C#练习题答案: 我最小码解释器(又名Brainf ** K)【难度:3级】--景越C#经典编程题库,1000道C#基础练习题等你来挑战

我最小码解释器(又名Brainf ** K)【难度:3级】:

答案1:

using System;
using System.Collections.Generic;
using System.Linq;

public static class Kata
{
  public static string BrainLuck(string code, string input)
  {
    return new Interpreter(code, input).Execute();
  }
}

public class Interpreter
{
  private Dictionary<char, Action> commands = new Dictionary<char, Action>();
  private List<dataByte> data = new List<dataByte>();
  private string validCode;
  private int pointer;
  private string output;
  private string input;
  private int codeLoc;
  
  public Interpreter(string code, string input)
  {
    output = String.Empty;
    commands.Add('<', Backward);
    commands.Add('>', Forward);
    commands.Add('+', Increment);
    commands.Add('-', Decrement);
    commands.Add('.', AddToOutput);
    commands.Add(',', TakeInput);
    commands.Add('[', Jump);
    commands.Add(']', Jump);
    this.input = input;
    validCode = new string(code.Where(commands.ContainsKey).ToArray());
    data.Add(new dataByte());
  }
  
  private void Forward() => MovePointerForward();
  private void Backward() => pointer = pointer == 0 ? 0 : pointer -1;
  private void Increment() => data.ElementAt(pointer).dataVal += 1;
  private void Decrement() => data.ElementAt(pointer).dataVal -= 1;
  private void TakeInput() => TakeIn();
  private void AddToOutput() => output += (char)data.ElementAt(pointer).dataVal;
  private void Jump() => JumpCheck(validCode[codeLoc]);
  
  private void JumpCheck(char command)
  {
    if (command == '[' &amp;&amp; data.ElementAt(pointer).dataVal == 0) jumpIndex(1, '[', ']');
    if (command == ']' &amp;&amp; data.ElementAt(pointer).dataVal != 0) jumpIndex(-1, ']', '[');
  }
  
  private void jumpIndex(int addValue, char match, char stop)
  {
    var count = 1;
    while (count > 0)
    {
      codeLoc += addValue;
      if (validCode[codeLoc] == match)
      {
        count += 1;
      }
      if (validCode[codeLoc] == stop)
      {
        count -= 1;
      }
    }    
  }
  
  private void MovePointerForward()
  {
    pointer++;
    if (pointer >= data.Count())
    {
      data.Add(new dataByte());
    }
  }
  
  private void TakeIn()
  {
    data.ElementAt(pointer).dataVal = input[0];
    input = input.Remove(0, 1);
  }
  
  public string Execute()
  {
    var codeBound = validCode.Length;
    while (codeLoc < codeBound)
    {
      var act = commands[validCode[codeLoc]];
      act();
      codeLoc++;
    }
    return output;
  }
}

public class dataByte
{
  private int val;
  public int dataVal
  {
    get {return val;}
    set
    {
      val = value;
      if (val > 255) val = 0;
      if (val < 0) val = 255;
    }
  }
}

答案2:

using System;
using System.Collections.Generic;
using System.Linq;

public static class Kata
    {
        public static string BrainLuck(string code, string input)
        {
            code = string.Concat(code.Where(ch => new char[] { '>', '<', '+', '-', ',', '.', '[', ']' }.Contains(ch)));
            List<byte> memory = new List<byte>();
            string output = "";

            int codePtr = 0;
            int inputPtr = 0;
            int memoryPtr = 0; memory.Add(0);

            while (codePtr < code.Length)
            {
                switch (code[codePtr])
                {
                    case '>':
                        if (++memoryPtr >= memory.Count)
                            memory.Add(0);
                        break;
                    case '<':
                        if (memoryPtr == 0)
                            memory.Insert(0, 0);
                        else
                            --memoryPtr;
                        break;
                    case '+':
                        memory[memoryPtr] = memory[memoryPtr] < 255 ? ++memory[memoryPtr] : (byte)0;
                        break;
                    case '-':
                        memory[memoryPtr] = memory[memoryPtr] > 0 ? --memory[memoryPtr] : (byte)255;
                        break;
                    case ',':
                        memory[memoryPtr] = (byte)input[inputPtr];
                        ++inputPtr;
                        break;
                    case '.':
                        output += (char)memory[memoryPtr];
                        break;

                    case '[':
                        if (memory[memoryPtr] == 0) // zero means to jump from loop
                        {
                            int cnt = 1;
                            while (cnt != 0)
                            {
                                ++codePtr;
                                if (code[codePtr] == '[') ++cnt;
                                else if (code[codePtr] == ']') --cnt;
                            }
                        }
                        break;

                    case ']':
                        if (memory[memoryPtr] != 0)
                        {
                            int cnt = 1;
                            while (cnt != 0)
                            {
                                --codePtr;
                                if (code[codePtr] == ']') ++cnt;
                                else if (code[codePtr] == '[') --cnt;
                            }
                        }
                        break;
                }
                ++codePtr;
            }
            return output;
        }
    }

答案3:

using System;
using System.Collections.Generic;
using System.IO;

public static class Kata
{
    public static string BrainLuck(string code, string input)
    {
        if (code == null)
        {
            throw new ArgumentNullException(nameof(code));
        }
        if (input == null)
        {
            throw new ArgumentNullException(nameof(input));
        }

        using (var inputStream = new MemoryStream(GetBytes(input)))
        using (var outputStream = new MemoryStream())
        {
            var data = new List<byte>() { 0 };
            var pointer = 0;

            for (int pc = 0; pc < code.Length; ++pc)
            {
                switch (code[pc])
                {
                    case '>':
                        if (++pointer == data.Count)
                        {
                            data.Add(0);
                        }
                        break;
                    case '<':
                        if (pointer == 0)
                        {
                            throw new InvalidOperationException("Can't decrement data pointer at start of data.");
                        }
                        --pointer;
                        break;
                    case '+':
                        ++data[pointer];
                        break;
                    case '-':
                        --data[pointer];
                        break;
                    case '.':
                        outputStream.WriteByte(data[pointer]);
                        break;
                    case ',':
                        data[pointer] = (byte)inputStream.ReadByte();
                        break;
                    case '[':
                        if (data[pointer] == 0 &amp;&amp; (pc = FindClosing(code, pc)) == -1)
                        {
                            throw new ArgumentException("Unmatched '['.", nameof(code));
                        }
                        break;
                    case ']':
                        if (data[pointer] != 0 &amp;&amp; (pc = FindOpening(code, pc)) == -1)
                        {
                            throw new ArgumentException("Unmatched ']'.", nameof(code));
                        }
                        break;
                    default:
                        throw new ArgumentException("Unknown instruction.", nameof(code));
                }
            }

            return GetString(outputStream.ToArray());
        }
    }

    private static byte[] GetBytes(string s)
    {
        return Array.ConvertAll(s.ToCharArray(), c => (byte)c);
    }

    private static string GetString(byte[] bytes)
    {
        return new string(Array.ConvertAll(bytes, b => (char)b));
    }

    private static int FindClosing(string s, int startIndex)
    {
        int level = 1;

        for (int index = startIndex + 1; index < s.Length; ++index)
        {
            switch (s[index])
            {
                case '[':
                    ++level;
                    break;
                case ']':
                    if (--level == 0)
                    {
                        return index;
                    }
                    break;
            }
        }

        return -1;
    }

    private static int FindOpening(string s, int startIndex)
    {
        int level = 1;

        for (int index = startIndex - 1; index >= 0; --index)
        {
            switch (s[index])
            {
                case ']':
                    ++level;
                    break;
                case '[':
                    if (--level == 0)
                    {
                        return index;
                    }
                    break;
            }
        }

        return -1;
    }
}

答案4:

using System.Collections.Generic;

public static class Kata {
  public static string BrainLuck(string code, string input) {
    var cells = new Dictionary<int, byte>() { {0,0} };
    var ptr = 0;
    var inputPtr = 0;
    var output = "";
    for (var i = 0; i < code.Length; i++) {
      switch (code[i]) {
        case '>': ptr++; break;
        case '<': ptr--; break;
        case '+': cells[ptr]++; break;
        case '-': cells[ptr]--; break;
        case '.': output += (char)cells[ptr]; break;
        case ',': cells[ptr] = (byte)input[inputPtr]; inputPtr++; break;
        case '[': if (cells[ptr] == 0) i = FindMatch(code, i); break;
        case ']': if (cells[ptr] != 0) i = FindMatch(code, i); break;
        default: break;
      }
      if (!cells.ContainsKey(ptr)) cells[ptr] = 0;
    }
    return output;
  }
  
  private static int FindMatch(string code, int index) {
    var start = code[index];
    var end = (start == '[') ? ']' : '[';
    var direction = (start == '[') ? 1 : -1;
    var depth = 0;
    for (var i = index + direction; i >= 0 &amp;&amp; i < code.Length; i += direction) {
      if (code[i] == start) {
        depth++;
      } else if (code[i] == end) {
        if (depth == 0) return i;
        depth--;
      }
    }
    return -1;
  }
}

答案5:

using System.Collections.Generic;
public static class Kata
{
  public static string BrainLuck(string code, string input, string outp = "")
  {
    var data = new byte[32];
    for(int i = 0, inP = 0, p = 0; i < code.Length; i++)
    {
      if (code[i] == '>')  p++;
      if (code[i] == '<')  p--;
      if (code[i] == '+')  data[p]++;
      if (code[i] == '-')  data[p]--;
      if (code[i] == '.')  outp += (char)data[p];
      if (code[i] == ',')  data[p] = (byte)input[inP++];
      if (code[i] == '[' &amp; data[p] == 0) i = BMatch(code, i, -1, 1,']');
      if (code[i] == ']' &amp; data[p] != 0) i = BMatch(code, i, 1, -1, '[');
    }
    return outp;
  }
  
  private static int BMatch(string s, int i, int b, int dir, char pair)
  {
    if (s[i] == pair &amp;&amp; b == 0) return i; 
    if (s[i] == '[') b++;
    if (s[i] == ']') b--;
    return BMatch(s, i+dir, b, dir, pair);
  }
}

答案6:

using System.Collections.Generic;
using System.Linq;

public static class Kata
{
  public static string BrainLuck(string code, string input)
  {
    var outp = new List<byte>();
    var data = new byte[9000];
    
    for(int i = 0, inP = 0, p = 0; i < code.Length; i++)
    {
      if (code[i] == '>')  p++;
      if (code[i] == '<')  p--;
      if (code[i] == '+')  data[p]++;
      if (code[i] == '-')  data[p]--;
      if (code[i] == '.')  outp.Add(data[p]);
      if (code[i] == ',')  data[p] = (byte)input[inP++];
      if (code[i] == '[' &amp; data[p] == 0) i = BMatch(code, i, -1, ']');
      if (code[i] == ']' &amp; data[p] != 0) i = BMatch(code, i,  1, '[');
    }
    return string.Concat(outp.Select(x => (char)x));
  }
  
  private static int BMatch(string s, int i, int d, char pair)
  {
    for (int b = d; (s[i] != pair || b != 0); i -= d)
    {
      if (s[i] == '[') b++;
      if (s[i] == ']') b--;
    }
    return i;
  }
}

答案7:

using System;
using System.Collections.Generic;
using System.Linq;

public static class Kata {

    public static string BrainLuck(string code, string input) {
        Dictionary<int, int> brackets = new Dictionary<int, int>();
        Stack<int> starts = new Stack<int>();
        byte[] mem = new byte[256];
        string output = "";
        int ptr = 0, read = 0;

        for (int i = 0; i < code.Length; i++) {
            if (code[i] == '[') starts.Push(i);
            if (code[i] == ']') brackets.Add(starts.Pop(), i);
        }
        foreach (var item in brackets.ToArray()) brackets.Add(item.Value, item.Key);

        for (int ip = 0; ip < code.Length; ip++) {
            if (code[ip] == '[' &amp;&amp; mem[ptr] == 0 || code[ip] == ']' &amp;&amp; mem[ptr] != 0) ip = brackets[ip];
            if (code[ip] == '>' || code[ip] == '<') ptr += code[ip] == '>' ? 1 : -1;
            if (code[ip] == '+' || code[ip] == '-') mem[ptr] = (byte)(mem[ptr] + (code[ip] == '+' ? 1 : -1));
            if (code[ip] == ',') mem[ptr] = (byte)input[read++];
            if (code[ip] == '.') output += (char)mem[ptr];
        }

        return output;
    }

}

答案8:

using System;
using System.Collections.Generic;
using System.Linq;

public class BrainFuckInterpreter
{
    string instructions;
    string inputStream;
    int pntr;
    List<int> mem = new List<int>() {0};
    string outputString = "";
    int instPointer;

    private Dictionary<char, Action> ops;

    public BrainFuckInterpreter(string program, string input)
    {
        instructions = program;
        inputStream = input;
        ops = new Dictionary<char, Action>()
        {
            { '>',this.incPntr},
            { '<',this.decPntr},
            { '+',this.incByte},
            { '-',this.decByte},
            { '.',this.output},
            { ',',this.input},
            { '[',this.jmpIfZero},
            { ']',this.jmpIfNonZero},
        };
    }

    public string Run()
    {
        char op;
        while (instPointer < instructions.Length)
        {
            op = instructions[instPointer];
            if (ops.ContainsKey(op))
                ops[op]();
            else
                instPointer++;
        }
        return outputString;
    }

    private void incPntr()
    {
        pntr++;
        if (pntr >= mem.Count)
        {
            mem.Add(0);
        }
        instPointer++;
    }

    private void decPntr()
    {
        pntr--;
        if (pntr < 0)
        {
            pntr = 0;
            mem.Insert(0,0);
        }
        instPointer++;
    }

    private void incByte()
    {
        mem[pntr] = (mem[pntr] + 1)%256;
        instPointer++;
    }

    private void decByte()
    {
        mem[pntr]--;
        if (mem[pntr] == -1)
        {
            mem[pntr] = 255;
        }
        instPointer++;
    }

    private void output()
    {
        outputString += (char)mem[pntr];
        instPointer++;
    }

    private void input()
    {
        mem[pntr] = inputStream[0];
        inputStream = inputStream.Substring(1);
        instPointer++;
    }

    private void jmpIfZero()
    {
        if (mem[pntr] != 0)
        {
            instPointer++;
            return;
        }

        var matches = 1;
        do
        {
            instPointer++;
            if (instructions[instPointer] == '[')
                matches++;
            if (instructions[instPointer] == ']')
                matches--;
        } while (matches != 0);

        instPointer++;
    }

    private void jmpIfNonZero()
    {
        if (mem[pntr] == 0)
        {
            instPointer++;
            return;
        }

        var matches = 1;
        do
        {
            instPointer--;
            if (instructions[instPointer] == '[')
                matches--;
            if (instructions[instPointer] == ']')
                matches++;
        } while (matches != 0);

        instPointer++;
    }
}

public static class Kata
  {
      public static string BrainLuck(string code, string input)
      {
         return new BrainFuckInterpreter(code,input).Run();
      }
  }

答案9:

using System;
using System.Collections.Generic;

public static class Kata
    {
        class Data
    {
        List<short> d = new List<short>();
        public Data()
        {

        }
        public short get(int index)
        {
            if (index < d.Count) return d[index];
            else
            {
                d.AddRange(new short[index - d.Count + 1]);
                return 0;
            }
        }
        public void set(short val, int index)
        {
            if (index < d.Count) d[index] = val;
            else
            {
                d.AddRange(new short[index - d.Count + 1]);
                d[index] = val;
            }
        }
        public int len() { return d.Count; }
    }
    static int findMatchFwd(string code, int start)
    {
        int open = 1;
        for (int i = start + 1; i < code.Length; ++i)
        {
            if (code[i] == '[') open++;
            else if (code[i] == ']') open--;
            if (open == 0) return i;
        }
        return start + 1;
    }
    static int findMatchBwd(string code, int start)
    {
        int open = -1;
        for (int i = start - 1; i >= 0; --i)
        {
            if (code[i] == '[') open++;
            else if (code[i] == ']') open--;
            if (open == 0) return i;
        }
        return start + 1;
    }
    public static string BrainLuck(string code, string input)
    {
        int dataPtr = 0, instrPtr = 0, inputPtr = 0;
        Data d = new Data();
        string res = "";
        while (instrPtr < code.Length)
        {
            if (code[instrPtr] == ',')
            {
                if (inputPtr >= input.Length) break;
                d.set((short)input[inputPtr++], dataPtr);
                instrPtr++;
            }
            else if (code[instrPtr] == '.')
            {
                res += ((char)d.get(dataPtr)).ToString();
                instrPtr++;
            }
            else if (code[instrPtr] == '+')
            {
                short old = d.get(dataPtr);
                if (old == 255) old = 0;
                else old += 1;
                d.set(old, dataPtr);
                instrPtr++;
            }
            else if (code[instrPtr] == '-')
            {
                short old = d.get(dataPtr);
                if (old == 0) old = 255;
                else old -= 1;
                d.set(old, dataPtr);
                instrPtr++;
            }
            else if (code[instrPtr] == '>')
            {
                ++dataPtr;
                instrPtr++;
            }
            else if (code[instrPtr] == '<')
            {
                --dataPtr;
                instrPtr++;
            }
            else if (code[instrPtr] == '[')
            {
                short b = d.get(dataPtr);
                if (b != 0)
                    instrPtr++;
                else
                {
                    instrPtr = findMatchFwd(code, instrPtr) + 1;
                }
            }
            else if (code[instrPtr] == ']')
            {
                short b = d.get(dataPtr);
                if (b == 0)
                    instrPtr++;
                else
                {
                    instrPtr = findMatchBwd(code, instrPtr) + 1;
                }
            }
        }
        return res;
    }
    }

答案10:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public static class Kata
{
  public static string BrainLuck(string code, string input)
  {
    var output = new StringBuilder();
    
    var data = new List<byte>() { 0 };
    var dataPointer = 0;
    var inputPointer = 0;
    for(int i = 0;i < code.Length; ++i)
    {
      if(code[i] == '>')
      {
        ++dataPointer;
        if (dataPointer >= data.Count)
          data.Add(0);
      }
      else if(code[i] == '<')
      {
        --dataPointer;
      }
      else if(code[i] == '+')
      {
        ++data[dataPointer];
      }
      else if(code[i] == '-')
      {
        --data[dataPointer];
      }
      else if(code[i] == '.')
      {
        output.Append(Convert.ToChar(data[dataPointer]));
      }
      else if(code[i] == ',')
      {
        data[dataPointer] = Convert.ToByte(input[inputPointer++]);
      }
      else if(code[i] == '[')
      {
        if(data[dataPointer] == 0)
          i = FindMatchingClosingBracket(code, i);
      }
      else if(code[i] == ']')
      {
        if(data[dataPointer] != 0)
          i = FindMatchingOpeningBracket(code, i) - 1;
      }
    }
    return output.ToString();
  }
  
  private static int FindMatchingClosingBracket(string code, int start)
  {
    var openingBracketsCount = 0;
    for(int i = start + 1; i < code.Length; ++i)
    {
      if(code[i] == '[')
        ++openingBracketsCount;
      else if(code[i] == ']')
      {
        if(openingBracketsCount == 0)
          return i;
        else
          --openingBracketsCount;
      }
    }
    throw new Exception();
  }
  
  private static int FindMatchingOpeningBracket(string code, int start)
  {
    var closingBracketsCount = 0;
    for(int i = start - 1; i > -1; --i)
    {
      if(code[i] == ']')
        ++closingBracketsCount;
      else if(code[i] == '[')
      {
        if(closingBracketsCount == 0)
          return i;
        else
          --closingBracketsCount;
      }
    }
    throw new Exception();
  }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值