看到一个有趣的问题
用不超过512个字符的brainfuck语言代码,输出一个尽可能大的数?2 关注 · 2 回答问题https://www.zhihu.com/question/622572410
看了下brainfuck的语法,极其简单。
尝试写了一个解释器,顺便测试了下,挺有趣的。
package main
import (
"os"
"reflect"
"strconv"
"unsafe"
)
func BytesToString(data []byte) string {
return *(*string)(unsafe.Pointer(&data))
}
func StringToReadBytes(data string) []byte {
stringHeader := (*reflect.StringHeader)(unsafe.Pointer(&data))
byteHeader := reflect.SliceHeader{
Data: stringHeader.Data,
Len: stringHeader.Len,
Cap: stringHeader.Len,
}
return *(*[]byte)(unsafe.Pointer(&byteHeader))
}
type Stack struct {
Data []int
Count int
}
func (this *Stack) Push(n int) {
if len(this.Data) <= this.Count {
this.Data = append(this.Data, 0)
}
this.Data[this.Count] = n
this.Count++
}
func (this *Stack) Pop() int {
if this.Count == 0 {
return 0
}
this.Count--
return this.Data[this.Count]
}
func main() {
args := os.Args
dataMaxLen := 10240
code := "-[>-[>+++++++[>++++++++<-]>.[-]<<-]<-]" //测试code
codeIndex := 0
outMaxLen := 1024
input := []uint8{}
inputIndex := 0
argsNum := len(args)
if argsNum >= 2 {
code = args[1]
}
if argsNum >= 3 {
input = StringToReadBytes(args[2])
}
if argsNum >= 4 {
tmpNum, err := strconv.ParseUint(args[3], 10, 64)
if err == nil {
dataMaxLen = int(tmpNum)
}
}
if argsNum >= 5 {
tmpNum, err := strconv.ParseUint(args[4], 10, 64)
if err == nil {
outMaxLen = int(tmpNum)
}
}
data := make([]uint8, dataMaxLen)
dataIndex := dataMaxLen / 2
stack := &Stack{}
out := make([]uint8, outMaxLen)
outIndex := 0
println("code:", code, ";input:", BytesToString(input))
for codeIndex < len(code) {
switch code[codeIndex] {
case '>':
dataIndex++
if dataIndex >= dataMaxLen {
print("data index:", dataIndex, " out")
return
}
codeIndex++
break
case '<':
dataIndex--
if dataIndex < 0 {
print("data index:", dataIndex, " out")
return
}
codeIndex++
break
case '+':
data[dataIndex]++
codeIndex++
break
case '-':
data[dataIndex]--
codeIndex++
break
case '.':
if outIndex < outMaxLen {
out[outIndex] = data[dataIndex]
outIndex++
}
codeIndex++
break
case ',':
if inputIndex < len(input) {
data[dataIndex] = input[inputIndex]
inputIndex++
} else {
data[dataIndex] = 0
}
codeIndex++
break
case '[':
if data[dataIndex] != 0 { //进入循环体
stack.Push(codeIndex)
codeIndex++
} else { //跳出
left := 0
for codeIndex < len(code) {
if code[codeIndex] == '[' {
left++
} else if code[codeIndex] == ']' {
left--
if left == 0 {
codeIndex++
break
}
}
codeIndex++
}
}
break
case ']':
if stack.Count == 0 {
codeIndex++
break
}
codeIndex = stack.Pop()
break
default:
codeIndex++
break
}
}
//把输出内容一次性输出
print(BytesToString(out[:outIndex]))
}