Created
March 10, 2019 23:28
-
-
Save Oppodelldog/eddf321ded9315d514e84d5c2427d62a to your computer and use it in GitHub Desktop.
boolfuck interpreter (codewars kata, SPOILER)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package kata | |
import ( | |
"strings" | |
) | |
// Boolfuck entry point for codewars kata | |
func Boolfuck(code string, input string) string { | |
return NewBookFuckInterpreter().Run(code, input) | |
} | |
const initialBufferSize = 30000 | |
type operation rune | |
const ( | |
write operation = ';' | |
flip = '+' | |
moveRight = '>' | |
moveLeft = '<' | |
read = ',' | |
doIfTrue = '[' | |
repeatIfTrue = ']' | |
) | |
func NewBookFuckInterpreter() *BoolFuckInterpreter { | |
return &BoolFuckInterpreter{ | |
decoder: new(BoolFuckDecoder), | |
encoder: new(BoolFuckEncoder), | |
jumpBackPosStack: NewStack(), | |
} | |
} | |
type BoolFuckInterpreter struct { | |
in []bool | |
out []bool | |
buf []bool | |
code string | |
inputPointerPos int | |
bufferPointerPos int | |
codePos int | |
jumpBackPosStack *IntStack | |
decoder *BoolFuckDecoder | |
encoder *BoolFuckEncoder | |
} | |
func (bf *BoolFuckInterpreter) Run(boolFuckSourceCode string, input string) string { | |
bf.code = boolFuckSourceCode | |
bf.in = bf.decoder.Decode(input) | |
bf.buf = make([]bool, initialBufferSize) | |
for bf.codePos = 0; bf.codePos < len(bf.code); bf.codePos++ { | |
switch operation(bf.code[bf.codePos]) { | |
case write: | |
bf.write() | |
case flip: | |
bf.checkForTapeExpansion() | |
bf.flip() | |
case moveRight: | |
bf.moveRight() | |
bf.checkForTapeExpansion() | |
case moveLeft: | |
bf.moveLeft() | |
bf.checkForTapeExpansion() | |
case read: | |
bf.read(); | |
case doIfTrue: | |
bf.doIfTrueOrSkipBlock() | |
case repeatIfTrue: | |
bf.repeatIfTrue() | |
default: | |
continue | |
} | |
} | |
return bf.encoder.Encode(bf.out) | |
} | |
func (bf *BoolFuckInterpreter) repeatIfTrue() { | |
iNew := bf.jumpBackPosStack.Pop() | |
if bf.buf[bf.bufferPointerPos] == true { | |
bf.codePos = iNew - 1 | |
} | |
} | |
func (bf *BoolFuckInterpreter) flip() { | |
bf.buf[bf.bufferPointerPos] = !bf.buf[bf.bufferPointerPos] | |
} | |
func (bf *BoolFuckInterpreter) moveLeft() { | |
bf.bufferPointerPos-- | |
} | |
func (bf *BoolFuckInterpreter) moveRight() { | |
bf.bufferPointerPos++ | |
} | |
func (bf *BoolFuckInterpreter) checkForTapeExpansion() { | |
const tapeExpansionBoolBits = 1024 | |
if bf.bufferPointerPos < 0 { | |
newBuf := make([]bool, tapeExpansionBoolBits) | |
newBuf = append(newBuf, bf.buf...) | |
bf.buf = newBuf | |
bf.bufferPointerPos = bf.bufferPointerPos + tapeExpansionBoolBits | |
} | |
if bf.bufferPointerPos >= len(bf.buf) { | |
newBuf := make([]bool, len(bf.buf)+tapeExpansionBoolBits) | |
copy(newBuf, bf.buf) | |
bf.buf = newBuf | |
} | |
} | |
func (bf *BoolFuckInterpreter) write() { | |
bf.out = append(bf.out, bf.buf[bf.bufferPointerPos]) | |
} | |
func (bf *BoolFuckInterpreter) read() { | |
if bf.inputPointerPos < 0 || bf.inputPointerPos >= len(bf.in) { | |
bf.buf[bf.bufferPointerPos] = false | |
} else { | |
bf.buf[bf.bufferPointerPos] = bf.in[bf.inputPointerPos] | |
} | |
bf.inputPointerPos++ | |
} | |
func (bf *BoolFuckInterpreter) doIfTrueOrSkipBlock() { | |
if bf.buf[bf.bufferPointerPos] == false { | |
bf.codePos = bf.skipBlock(bf.code, bf.codePos) | |
} else { | |
bf.jumpBackPosStack.Push(bf.codePos) | |
} | |
} | |
func (bf *BoolFuckInterpreter) skipBlock(code string, i int) int { | |
open := 1 | |
i++ | |
for open != 0 { | |
if code[i] == '[' { | |
open++ | |
} | |
if code[i] == ']' { | |
open-- | |
if open == 0 { | |
return i | |
} | |
} | |
i++ | |
} | |
panic("Syntax error") | |
} | |
type IntStack struct { | |
s []int | |
} | |
func NewStack() *IntStack { | |
return &IntStack{make([]int, 0),} | |
} | |
func (s *IntStack) Push(v int) { | |
s.s = append(s.s, v) | |
} | |
func (s *IntStack) Pop() int { | |
l := len(s.s) | |
if l == 0 { | |
panic("stack is empty") | |
} | |
res := s.s[l-1] | |
s.s = s.s[:l-1] | |
return res | |
} | |
type BoolFuckEncoder struct{} | |
func (enc *BoolFuckEncoder) Encode(bb []bool) string { | |
sb := new(strings.Builder) | |
for i := 0; i < len(bb); i += 8 { | |
sb.WriteByte(enc.boolFuckBoolsToByte(bb[i : i+8])) | |
} | |
return sb.String() | |
} | |
func (enc *BoolFuckEncoder) boolFuckBoolsToByte(boolfuckBools []bool) byte { | |
for left, right := 0, len(boolfuckBools)-1; left < right; left, right = left+1, right-1 { | |
boolfuckBools[left], boolfuckBools[right] = boolfuckBools[right], boolfuckBools[left] | |
} | |
return enc.boolsToByte(boolfuckBools) | |
} | |
func (enc *BoolFuckEncoder) boolsToByte(byteBools []bool) byte { | |
var r byte | |
for i := 0; i < len(byteBools); i++ { | |
byteBool := byteBools[i] | |
b := byte(0x0); | |
if byteBool { | |
b = 0x1; | |
} | |
r ^= b | |
if i < len(byteBools)-1 { | |
r = r << 1 | |
} | |
} | |
return r | |
} | |
type BoolFuckDecoder struct{} | |
func (dec *BoolFuckDecoder) Decode(s string) []bool { | |
var bfb []bool | |
for _, r := range []byte(s) { | |
b := byte(r) | |
bfb = append(bfb, dec.byteToBoolFuckBools(b)...) | |
} | |
return bfb | |
} | |
func (dec *BoolFuckDecoder) byteToBoolFuckBools(b byte) []bool { | |
boolFuckBooleans := dec.byteToBools(b) | |
for left, right := 0, len(boolFuckBooleans)-1; left < right; left, right = left+1, right-1 { | |
boolFuckBooleans[left], boolFuckBooleans[right] = boolFuckBooleans[right], boolFuckBooleans[left] | |
} | |
return boolFuckBooleans | |
} | |
func (dec *BoolFuckDecoder) byteToBools(b byte) []bool { | |
var booleans []bool | |
for i := 0; i < 8; i++ { | |
if b&128 == 128 { | |
booleans = append(booleans, true) | |
} else { | |
booleans = append(booleans, false) | |
} | |
b = b << 1 | |
} | |
return booleans | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package kata | |
import ( | |
"reflect" | |
"testing" | |
) | |
const ( | |
helloWorld = ";;;+;+;;+;+;\n+;+;+;+;;+;;+;\n;;+;;+;+;;+;\n;;+;;+;+;;+;\n+;;;;+;+;;+;\n;;+;;+;+;+;;\n;;;;;+;+;;\n+;;;+;+;;;+;\n+;;;;+;+;;+;\n;+;+;;+;;;+;\n;;+;;+;+;;+;\n;;+;+;;+;;+;\n+;+;;;;+;+;;\n;+;+;+;" | |
multiply = ">,>,>,>,>,>,>,>,>>,>,>,>,>,>,>,>,<<<<<<<<+<<<<<<<<+[>+]<[<]>>>>>>>>>[+<<<<<<<<[>]+<[+<]>>>>>>>>>>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+<<<<<<<<[>]+<[+<]>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]>[>]+<[+<]>>>>>>>>>[+]>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<<<<<<<<<<+<<<<<<<<+[>+]<[<]>>>>>>>>>]<[+<]>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+<<<<<<<<[>]+<[+<]>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<<<<<<<<<<<<<<<<<<[>]+<[+<]>>>>>>>>>[+]>>>>>>>>>>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>]<[+<]<<<<<<<<<<<<<<<<<<+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]+<<<<<<<<+[>+]<[<]>>>>>>>>>]<[+<]>>>>>>>>>>>>>>>>>>>;>;>;>;>;>;>;>;<<<<<<<<" | |
catFF = ">,>,>,>,>,>,>,>,<<<<<<<[>]+<[+<]>>>>>>>>>[+]+<<<<<<<<+[>+]<[<]>>>>>>>>>[+<<<<<<<<[>]+<[+<]>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<;>;>;>;>;>;>;>;<<<<<<<,>,>,>,>,>,>,>,<<<<<<<[>]+<[+<]>>>>>>>>>[+]+<<<<<<<<+[>+]<[<]>>>>>>>>>]<[+<]" | |
cat00 = ">,>,>,>,>,>,>,>,>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+<<<<<<<<[>]+<[+<]>;>;>;>;>;>;>;>;>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+<<<<<<<<[>]+<[+<]>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]+<<<<<<<<+[>+]<[<]>>>>>>>>>]<[+<]>,>,>,>,>,>,>,>,>+<<<<<<<<+[>+]<[<]>>>>>>>>>]<[+<]" | |
helloWorld2 = ">>>>>>>>>>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+<<<<<<<<[>]+<[+<]>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>]<[+<]<<<<<<<<<>;>;>;>;>;>;>;>;<<<<<<<<>>>>>>>>>>>>>>>>>>>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+<<<<<<<<[>]+<[+<]>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>]<[+<]>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+<<<<<<<<[>]+<[+<]>>>>>>>>>>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+<<<<<<<<[>]+<[+<]>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<<<<<<<<<<<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>]<[+<]<<<<<<<<<<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>]<[+<]>>>>>>>>>>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>;>;>;>;>;>;>;>;<<<<<<<<>>>>>>>>>>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>;>;>;>;>;>;>;>;<<<<<<<<>;>;>;>;>;>;>;>;<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>;>;>;>;>;>;>;>;<<<<<<<<>>>>>>>>>>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>;>;>;>;>;>;>;>;<<<<<<<<<<<<<<<<<<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+<<<<<<<<[>]+<[+<]>>>>>>>>>>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+<<<<<<<<[>]+<[+<]>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>]<[+<]>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>]<[+<]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>;>;>;>;>;>;>;>;<<<<<<<<>>>>>>>>>>>>>>>>>>>;>;>;>;>;>;>;>;<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>;>;>;>;>;>;>;>;<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>;>;>;>;>;>;>;>;<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>;>;>;>;>;>;>;>;<<<<<<<<>>>>>>>>>>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>;>;>;>;>;>;>;>;<<<<<<<<>>>>>>>>>>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>;>;>;>;>;>;>;>;<<<<<<<<" | |
expandTape = ">>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<<<<<<<<<<<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+<<<<<<<<[>]+<[+<]>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+<<<<<<<<[>]+<[+<]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>]<[+<]>>>>>>>>>>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>]<[+<]<<<<<<<<<<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>;>;>;>;>;>;>;>;<<<<<<<<<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>;>;>;>;>;>;>;>;<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>;>;>;>;>;>;>;>;<<<<<<<<>;>;>;>;>;>;>;>;<<<<<<<<<<<<<<<<<<<<<<<<<<>;>;>;>;>;>;>;>;<<<<<<<<<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>;>;>;>;>;>;>;>;<<<<<<<<>>>>>>>>>>>>>>>>>>>;>;>;>;>;>;>;>;<<<<<<<<>>>>>>>>>>>>>>>>>>>;>;>;>;>;>;>;>;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>;>;>;>;>;>;>;>;<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>;>;>;>;>;>;>;>;<<<<<<<<>>>>>>>>>>>>>>>>>>>;>;>;>;>;>;>;>;<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<<>;>;>;>;>;>;>;>;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<<>;>;>;>;>;>;>;>;<<<<<<<<" | |
expandTape2 = "<<<<<<<<<<<<<<<<<<<<<<<<<<;;;+;+;;+;+;\n+;+;+;+;;+;;+;\n;;+;;+;+;;+;\n;;+;;+;+;;+;\n+;;;;+;+;;+;\n;;+;;+;+;+;;\n;;;;;+;+;;\n+;;;+;+;;;+;\n+;;;;+;+;;+;\n;+;+;;+;;;+;\n;;+;;+;+;;+;\n;;+;+;;+;;+;\n+;+;;;;+;+;;\n;+;+;+;" | |
expandTape3 = "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<;;;+;+;;+;+;\n+;+;+;+;;+;;+;\n;;+;;+;+;;+;\n;;+;;+;+;;+;\n+;;;;+;+;;+;\n;;+;;+;+;+;;\n;;;;;+;+;;\n+;;;+;+;;;+;\n+;;;;+;+;;+;\n;+;+;;+;;;+;\n;;+;;+;+;;+;\n;;+;+;;+;;+;\n+;+;;;;+;+;;\n;+;+;+;" | |
expandTape4 = ";;;+;+;;+;+;\n+;+;+;+;;+;;+;\n;;+;;+;+;;+;\n;;+;;+;+;;+;\n+;;;;+;+;;+;\n;;+;;+;+;+;;\n;;;;;+;+;;\n+;;;+;+;;;+;\n+;;;;+;+;;+;\n;+;+;;+;;;+;\n;;+;;+;+;;+;\n;;+;+;;+;;+;\n+;+;;;;+;+;;\n;+;+;+;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" | |
) | |
func TestBoolFuck(t *testing.T) { | |
type args struct { | |
code string | |
input string | |
} | |
tests := []struct { | |
name string | |
args args | |
want string | |
skip bool | |
}{ | |
{ | |
name: "Hello World", | |
args: args{code: helloWorld}, | |
want: "Hello, world!\n", | |
}, | |
{ | |
name: "Hello World 2", | |
args: args{code: helloWorld2}, | |
want: "Hello World!\n", | |
}, | |
{ | |
name: "Multiply", | |
args: args{code: multiply, input: "\x08\x09"}, | |
want: "\x48", | |
}, | |
{ | |
name: "catFF", | |
args: args{code: catFF, input: "Codewars\xff"}, | |
want: "Codewars", | |
}, | |
{ | |
name: "cat00", | |
args: args{code: cat00, input: "Codewars\x00"}, | |
want: "Codewars", | |
}, | |
{ | |
name: "expandTape", | |
args: args{code: expandTape, input: ""}, | |
want: "Hello, World!", | |
}, | |
{ | |
name: "expandTape2", | |
args: args{code: expandTape2, input: ""}, | |
want: "Hello, world!\n", | |
}, | |
{ | |
name: "expandTape3", | |
args: args{code: expandTape3, input: ""}, | |
want: "Hello, world!\n", | |
}, | |
{ | |
name: "expandTape4", | |
args: args{code: expandTape4, input: ""}, | |
want: "Hello, world!\n", | |
}, | |
} | |
for _, tt := range tests { | |
t.Run(tt.name, func(t *testing.T) { | |
if tt.skip { | |
t.SkipNow() | |
} | |
if got := Boolfuck(tt.args.code, tt.args.input); got != tt.want { | |
t.Errorf("Boolfuck() = %v, want %v", got, tt.want) | |
} | |
}) | |
} | |
} | |
func Test_boolFuckBitBufferToString(t *testing.T) { | |
H := []bool{false, false, false, true, false, false, true, false} // 'H' 0b01001000 inverted | |
e := []bool{true, false, true, false, false, true, true, false} // 'e' 0b01100101 inverted | |
l := []bool{false, false, true, true, false, true, true, false} // 'l' 0b01101100 inverted | |
o := []bool{true, true, true, true, false, true, true, false} // 'o' 0b01101111 inverted | |
var input []bool | |
input = append(input, H...) | |
input = append(input, e...) | |
input = append(input, l...) | |
input = append(input, l...) | |
input = append(input, o...) | |
expected := "Hello" | |
enc := new(BoolFuckEncoder) | |
r := enc.Encode(input) | |
if expected != r { | |
t.Fatalf("expected %v, but got %v", expected, r) | |
} | |
} | |
func Test_boolFuckBoolsToByte(t *testing.T) { | |
input := []bool{true, false, true, false, false, true, true, false} // 'e' 0b01100101 inverted | |
expected := byte('e') | |
enc := new(BoolFuckEncoder) | |
r := enc.boolFuckBoolsToByte(input) | |
if expected != r { | |
t.Fatalf("expected %v, but got %v", expected, r) | |
} | |
} | |
func Test_boolsToByte(t *testing.T) { | |
bools := []bool{false, true, true, false, false, true, false, true} //0b01100101 -> dec 101 -> ascii 'e' | |
expected := byte('e') | |
enc := new(BoolFuckEncoder) | |
r := enc.boolsToByte(bools) | |
if expected != r { | |
t.Fatalf("expected %v, but got %v", expected, r) | |
} | |
} | |
func Test_stringToBoolFuckBits(t *testing.T) { | |
H := []bool{false, false, false, true, false, false, true, false} | |
e := []bool{true, false, true, false, false, true, true, false} | |
l := []bool{false, false, true, true, false, true, true, false} | |
o := []bool{true, true, true, true, false, true, true, false} | |
C := []bool{true, true, false, false, false, false, true, false} | |
d := []bool{false, false, true, false, false, true, true, false} | |
w := []bool{true, true, true, false, true, true, true, false} | |
a := []bool{true, false, false, false, false, true, true, false} | |
r := []bool{false, true, false, false, true, true, true, false} | |
s := []bool{true, true, false, false, true, true, true, false} | |
xFF := []bool{true, true, true, true, true, true, true, true} | |
x00 := []bool{false, false, false, false, false, false, false, false} | |
testDataSet := map[string]struct { | |
intput string | |
expected func() []bool | |
}{ | |
"Hello": { | |
intput: "Hello", | |
expected: func() []bool { | |
var expected []bool | |
expected = append(expected, H...) | |
expected = append(expected, e...) | |
expected = append(expected, l...) | |
expected = append(expected, l...) | |
expected = append(expected, o...) | |
return expected | |
}, | |
}, | |
"Codewars\xff": { | |
intput: "Codewars\xff", | |
expected: func() []bool { | |
var expected []bool | |
expected = append(expected, C...) | |
expected = append(expected, o...) | |
expected = append(expected, d...) | |
expected = append(expected, e...) | |
expected = append(expected, w...) | |
expected = append(expected, a...) | |
expected = append(expected, r...) | |
expected = append(expected, s...) | |
expected = append(expected, xFF...) | |
return expected | |
}, | |
}, | |
"Codewars\x00": { | |
intput: "Codewars\x00", | |
expected: func() []bool { | |
var expected []bool | |
expected = append(expected, C...) | |
expected = append(expected, o...) | |
expected = append(expected, d...) | |
expected = append(expected, e...) | |
expected = append(expected, w...) | |
expected = append(expected, a...) | |
expected = append(expected, r...) | |
expected = append(expected, s...) | |
expected = append(expected, x00...) | |
return expected | |
}, | |
}, | |
} | |
dec := new(BoolFuckDecoder) | |
for testName, testData := range testDataSet { | |
t.Run(testName, func(t *testing.T) { | |
r := dec.Decode(testData.intput) | |
expected := testData.expected() | |
if !reflect.DeepEqual(expected, r) { | |
t.Fatalf("expected %v, but got %v", expected, r) | |
} | |
}) | |
} | |
} | |
func Test_byteToBoolFuckBools(t *testing.T) { | |
input := byte('e') | |
expected := []bool{true, false, true, false, false, true, true, false} // 'e' 0b01100101 inverted | |
dec := new(BoolFuckDecoder) | |
r := dec.byteToBoolFuckBools(input) | |
if !reflect.DeepEqual(expected, r) { | |
t.Fatalf("expected %v, but got %v", expected, r) | |
} | |
} | |
func Test_byteToBools(t *testing.T) { | |
input := byte('e') | |
expected := []bool{false, true, true, false, false, true, false, true} //0b01100101 -> dec 101 -> ascii 'e' | |
dec := new(BoolFuckDecoder) | |
r := dec.byteToBools(input) | |
if !reflect.DeepEqual(expected, r) { | |
t.Fatalf("expected %v, but got %v", expected, r) | |
} | |
} | |
func Test_skipBlock(t *testing.T) { | |
type args struct { | |
code string | |
pos int | |
} | |
testDataSet := map[string]struct { | |
intput args | |
expectedPos int | |
}{ | |
"1": {intput: args{code: "[]", pos: 0}, expectedPos: 1}, | |
"2": {intput: args{code: "[12345]", pos: 0}, expectedPos: 6}, | |
"3": {intput: args{code: "[[]]", pos: 0}, expectedPos: 3}, | |
"4": {intput: args{code: "[[x]]", pos: 0}, expectedPos: 4}, | |
"5": {intput: args{code: "[y[x]y]", pos: 0}, expectedPos: 6}, | |
"6": {intput: args{code: "[[[[[[]]]]]]", pos: 0}, expectedPos: 11}, | |
} | |
bf := NewBookFuckInterpreter() | |
for testName, testData := range testDataSet { | |
t.Run(testName, func(t *testing.T) { | |
r := bf.skipBlock(testData.intput.code, testData.intput.pos) | |
if testData.expectedPos != r { | |
t.Fatalf("expected %v, but got %v", testData.expectedPos, r) | |
} | |
}) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment