Skip to content

Instantly share code, notes, and snippets.

@Oppodelldog
Created March 10, 2019 23:28
Show Gist options
  • Save Oppodelldog/eddf321ded9315d514e84d5c2427d62a to your computer and use it in GitHub Desktop.
Save Oppodelldog/eddf321ded9315d514e84d5c2427d62a to your computer and use it in GitHub Desktop.
boolfuck interpreter (codewars kata, SPOILER)
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
}
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