aboutsummaryrefslogtreecommitdiff
path: root/main.go
blob: 6b2ad0976ac3626d779ca32b5b93f8018b79a2b6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package main

import (
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"unicode"
)

type Memory [59049]int // 3^10

func ReadProg(in io.Reader) Memory {
	var m Memory
	buf, err := ioutil.ReadAll(in)
	if err != nil {
		log.Fatal(err)
	}
	var n int
	for _, v := range buf {
		if !unicode.IsSpace(rune(v)) {
			m[n] = int(v)
			n++
		}
	}
	for n < len(m) {
		m[n] = Crazy(m[n-2], m[n-1])
		n++
	}
	return m
}

func Eval(mem Memory) {
	var A, C, D int
	for {
		switch (mem[C] + C) % 94 {
		case 4: // jmp [d]
			C = mem[D]
		case 5: // out a
			fmt.Printf("%c", byte(A))
		case 23: // in a
			fmt.Scanf("%c", &A)
		case 39: // rotr [d]; mov a, [d]
			mem[D] = RotR(mem[D])
			A = mem[D]
		case 40: // mov d, [d]
			D = mem[D]
		case 62: // crz [d], a; mov a, [d]
			mem[D] = Crazy(mem[D], A)
			A = mem[D]
		case 68: // nop
		case 81: // end
			return
		}
		mem[C] = Encrypt(mem[C])
		C = (C + 1) % len(mem)
		D = (D + 1) % len(mem)
	}
}

func RotR(x int) int {
	return x/3 + (x%3)*19683
}

//		crz	Input 2
//			0	1	2
// Input 1	0	1	0	0
//		1	1	0	2
//		2	2	2	1

func Crazy(x, y int) (ret int) {
	o := [][]int{
		{4, 3, 3, 1, 0, 0, 1, 0, 0},
		{4, 3, 5, 1, 0, 2, 1, 0, 2},
		{5, 5, 4, 2, 2, 1, 2, 2, 1},
		{4, 3, 3, 1, 0, 0, 7, 6, 6},
		{4, 3, 5, 1, 0, 2, 7, 6, 8},
		{5, 5, 4, 2, 2, 1, 8, 8, 7},
		{7, 6, 6, 7, 6, 6, 4, 3, 3},
		{7, 6, 8, 7, 6, 8, 4, 3, 5},
		{8, 8, 7, 8, 8, 7, 5, 5, 4},
	}
	for _, v := range []int{1, 9, 81, 729, 6561} {
		ret += o[x/v%9][y/v%9] * v
	}
	return
}

func Encrypt(x int) int {
	e := []int{
		57, 109, 60, 46, 84, 86, 97, 99, 96, 117,
		89, 42, 77, 75, 39, 88, 126, 120, 68, 108,
		125, 82, 69, 111, 107, 78, 58, 35, 63, 71,
		34, 105, 64, 53, 122, 93, 38, 103, 113, 116,
		121, 102, 114, 36, 40, 119, 101, 52, 123, 87,
		80, 41, 72, 45, 90, 110, 44, 91, 37, 92,
		51, 100, 76, 43, 81, 59, 62, 85, 33, 112,
		74, 83, 55, 50, 70, 104, 79, 65, 49, 67,
		66, 54, 118, 94, 61, 73, 95, 48, 47, 56,
		124, 106, 115, 98,
	}
	return e[x%94]
}

func main() {
	file := flag.String("file", "", "malbolge program file")
	flag.Parse()

	fd, err := os.Open(*file)
	if err != nil {
		log.Fatal(err)
	}
	defer fd.Close()

	Eval(ReadProg(fd))
}