2021 - Day 24

This commit is contained in:
Dreaded_X 2021-12-25 20:49:47 +01:00
parent 43263c0368
commit 96f2bcbcbc
6 changed files with 863 additions and 631 deletions

View File

@ -1,331 +1,130 @@
package main package main
import ( import (
aoc "AoC/2021/common"
"bufio"
"fmt" "fmt"
"strconv"
"strings"
) )
type Operator byte func step(w int, z int, a int, b int, pop bool) int {
const ( temp := z
INP Operator = iota
ADD
ADDR
MUL
MULR
DIV
DIVR
MOD
MODR
EQL
EQLR
)
func (op Operator) String() string { if pop {
switch op { // Pop value from stack
case INP: z /= 26
return "INP"
case ADD, ADDR:
return "ADD"
case MUL, MULR:
return "MUL"
case DIV, DIVR:
return "DIV"
case MOD, MODR:
return "MOD"
case EQL, EQLR:
return "EQL"
default:
return fmt.Sprintf("%d", int(op))
}
} }
type Instruction struct { if (temp%26)+a != w {
op Operator // Push new value to stack
a int z *= 26
b int z += w + b
} }
func (i Instruction) String() string { return z
if i.op == INP {
return fmt.Sprintf("%v\t[%s]", i.op, registerToString(i.a))
}
if i.op % 2 == 0 {
return fmt.Sprintf("%v\t[%s],\t[%s]", i.op, registerToString(i.a), registerToString(i.b))
}
return fmt.Sprintf("%v\t[%s],\t %d", i.op, registerToString(i.a), i.b)
}
type Memory [4]int
func (m Memory) String() string {
return fmt.Sprintf("w: %d, x: %d, y: %d, z: %d", m[0], m[1], m[2], m[3])
}
type Stream struct {
stream []int
counter int
}
func (s *Stream) Get() int {
if s.counter == len(s.stream) {
panic("End of stream reached")
}
val := s.stream[s.counter]
s.counter++
return val
}
func NewStream(input string) Stream {
var s Stream
s.stream = make([]int, len(input))
for i, b := range input {
n, err := strconv.Atoi(string(b))
if err != nil {
panic(err)
}
if n == 0 {
panic("0 is not a valid input")
}
s.stream[i] = n
}
return s
}
type Program []Instruction
func (p Program) Execute(input string) Memory {
stream := NewStream(input)
var mem Memory
for _, i := range p {
switch i.op {
case INP:
mem[i.a] = stream.Get()
case ADD:
mem[i.a] += i.b
case ADDR:
mem[i.a] += mem[i.b]
case MUL:
mem[i.a] *= i.b
case MULR:
mem[i.a] *= mem[i.b]
case DIV:
mem[i.a] /= i.b
case DIVR:
mem[i.a] /= mem[i.b]
case MOD:
mem[i.a] %= i.b
case MODR:
mem[i.a] %= mem[i.b]
case EQL:
val := 0
if mem[i.a] == i.b {
val = 1
}
mem[i.a] = val
case EQLR:
val := 0
if mem[i.a] == mem[i.b] {
val = 1
}
mem[i.a] = val
default:
panic("Unknown operator")
}
// fmt.Println(mem)
}
return mem
}
func Compile(input *bufio.Scanner) Program {
var program Program
for input.Scan() {
line := input.Text()
inst := strings.Split(line, " ")
var instruction Instruction
// Parse the operator
switch inst[0] {
case "inp":
instruction.op = INP
case "add":
instruction.op = ADD
case "mul":
instruction.op = MUL
case "div":
instruction.op = DIV
case "mod":
instruction.op = MOD
case "eql":
instruction.op = EQL
default:
panic("Unknown instruction")
}
// Parse the first parameter, this is always a register
instruction.a = parseRegister(inst[1])
// All instructions, except INP, require a second parameter
if instruction.op != INP {
b := inst[2]
if val, err := strconv.Atoi(b); err == nil {
// If the parameter is a number we use that as the second parameter
instruction.b = val
} else {
// Otherwise the parameter is a register, so we parse it and set it to the register
instruction.b = parseRegister(b)
// We also increment the operator by one to indicate that the second parameter is a register
instruction.op++
}
}
program = append(program, instruction)
}
return program
}
func (p Program) Optimize() Program {
// previous := len(p)
for counter := 0; counter < 4; counter++ {
fmt.Printf("PRECOMP %d\n", counter)
p = p.precomp()
fmt.Printf("QUASI %d\n", counter)
p = p.quasi()
// if previous == len(p) {
// fmt.Println("Done optimizing")
// break
// }
// previous = len(p)
}
return p
} }
func main() { func main() {
challenge := aoc.New(2021, 24) // for w1 := 1; w1 <= 9; w1++ {
// z1 := step(w1, 0, 14, 1, false)
// for w2 := 1; w2 <= 9; w2++ {
// z2 := step(w2, z1, 15, 7, false)
// for w3 := 1; w3 <= 9; w3++ {
// z3 := step(w3, z2, 15, 13, false)
// for w4 := 1; w4 <= 9; w4++ {
// z4 := step(w4, z3, -6, 10, true)
// for w5 := 1; w5 <= 9; w5++ {
// fmt.Println(w1, w2, w3, w4, w5)
// z5 := step(w5, z4, 14, 0, false)
// for w6 := 1; w6 <= 9; w6++ {
// z6 := step(w6, z5, -4, 13, true)
// for w7 := 1; w7 <= 9; w7++ {
// z7 := step(w7, z6, 15, 11, false)
// for w8 := 1; w8 <= 9; w8++ {
// z8 := step(w8, z7, 15, 6, false)
// for w9 := 1; w9 <= 9; w9++ {
// z9 := step(w9, z8, 11, 1, false)
// for w10 := 1; w10 <= 9; w10++ {
// z10 := step(w10, z9, 0, 7, true)
// for w11 := 1; w11 <= 9; w11++ {
// z11 := step(w11, z10, 0, 11, true)
// for w12 := 1; w12 <= 9; w12++ {
// z12 := step(w12, z11, -3, 14, true)
// for w13 := 1; w13 <= 9; w13++ {
// z13 := step(w13, z12, -9, 4, true)
// challenge.Test(`inp x // w14 := z13 - 9
// mul x -1`, []int{-1, -1}) // if w14 <= 0 || w14 > 9 {
// continue
// }
// challenge.Test(`inp z // z14 := step(w14, z13, -9, 10, true)
// inp x
// mul z 3
// eql z x`, []int{-1, -1})
// challenge.Test(`inp w // if z14 == 0 {
// add z w // fmt.Println("SOLUTION FOUND:", w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14)
// mod z 2 // return
// div w 2 // }
// add y w // }
// mod y 2 // }
// div w 2 // }
// add x w // }
// mod x 2 // }
// div w 2 // }
// mod w 2`, []int{-1, -1}) // }
// }
// }
// }
// }
// }
// }
challenge.Test(`inp w for w1 := 1; w1 <= 9; w1++ {
mul x 0 z1 := step(w1, 0, 14, 1, false)
add x z for w2 := 1; w2 <= 9; w2++ {
mod x 26 z2 := step(w2, z1, 15, 7, false)
div z 1 for w3 := 1; w3 <= 9; w3++ {
add x 14 z3 := step(w3, z2, 15, 13, false)
eql x w for w4 := 1; w4 <= 9; w4++ {
eql x 0 z4 := step(w4, z3, -6, 10, true)
mul y 0 for w5 := 1; w5 <= 9; w5++ {
add y 25 fmt.Println(w1, w2, w3, w4, w5)
mul y x z5 := step(w5, z4, 14, 0, false)
add y 1 for w6 := 1; w6 <= 9; w6++ {
mul z y z6 := step(w6, z5, -4, 13, true)
mul y 0 for w7 := 1; w7 <= 9; w7++ {
add y w z7 := step(w7, z6, 15, 11, false)
add y 1 for w8 := 1; w8 <= 9; w8++ {
mul y x z8 := step(w8, z7, 15, 6, false)
add z y`, []int{-1, -1}) for w9 := 1; w9 <= 9; w9++ {
z9 := step(w9, z8, 11, 1, false)
for w10 := 1; w10 <= 9; w10++ {
z10 := step(w10, z9, 0, 7, true)
for w11 := 1; w11 <= 9; w11++ {
z11 := step(w11, z10, 0, 11, true)
for w12 := 1; w12 <= 9; w12++ {
z12 := step(w12, z11, -3, 14, true)
for w13 := 1; w13 <= 9; w13++ {
z13 := step(w13, z12, -9, 4, true)
challenge.Test(`inp w w14 := z13 - 9
mul x 0 if w14 <= 0 || w14 > 9 {
add x z continue
mod x 26
div z 1
add x 14
eql x w
eql x 0
mul y 0
add y 25
mul y x
add y 1
mul z y
mul y 0
add y w
add y 1
mul y x
add z y
inp w
mul x 0
add x z
mod x 26
div z 1
add x 15
eql x w
eql x 0
mul y 0
add y 25
mul y x
add y 1
mul z y
mul y 0
add y w
add y 7
mul y x
add z y`, []int{-1, -1})
// challenge.Test(``, []int{-1, -1})
challenge.Solution(1, func (input *bufio.Scanner) int {
program := Compile(input)
fmt.Println("ORIGINAL")
for _, i := range program {
fmt.Printf("%v\n", i)
} }
fmt.Println(len(program))
fmt.Println("OPTIMIZED") z14 := step(w14, z13, -9, 10, true)
opti := program.Optimize()
for _, i := range opti { if z14 == 0 {
fmt.Printf("%v\n", i) fmt.Println("SOLUTION FOUND:", w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14)
return
}
}
}
}
}
}
}
}
}
}
}
}
}
} }
fmt.Println(len(opti))
str := "25579246899999"
fmt.Println(program.Execute(str))
fmt.Println(opti.Execute(str))
// fmt.Println(mem)
return 0
})
challenge.Solution(2, func (input *bufio.Scanner) int {
return 0
})
} }

322
2021/24/old/main.go Normal file
View File

@ -0,0 +1,322 @@
package main
import (
aoc "AoC/2021/common"
"bufio"
"fmt"
"strconv"
"strings"
)
type Operator byte
const (
INP Operator = iota
ADD
ADDR
MUL
MULR
DIV
DIVR
MOD
MODR
EQL
EQLR
)
func (op Operator) String() string {
switch op {
case INP:
return "INP"
case ADD, ADDR:
return "ADD"
case MUL, MULR:
return "MUL"
case DIV, DIVR:
return "DIV"
case MOD, MODR:
return "MOD"
case EQL, EQLR:
return "EQL"
default:
return fmt.Sprintf("%d", int(op))
}
}
type Instruction struct {
op Operator
a int
b int
}
func (i Instruction) String() string {
if i.op == INP {
return fmt.Sprintf("%v\t[%s]", i.op, registerToString(i.a))
}
if i.op % 2 == 0 {
return fmt.Sprintf("%v\t[%s],\t[%s]", i.op, registerToString(i.a), registerToString(i.b))
}
return fmt.Sprintf("%v\t[%s],\t %d", i.op, registerToString(i.a), i.b)
}
type Memory [4]int
func (m Memory) String() string {
return fmt.Sprintf("w: %d, x: %d, y: %d, z: %d", m[0], m[1], m[2], m[3])
}
type Stream struct {
stream []int
counter int
}
func (s *Stream) Get() int {
if s.counter == len(s.stream) {
panic("End of stream reached")
}
val := s.stream[s.counter]
s.counter++
return val
}
func NewStream(input string) Stream {
var s Stream
s.stream = make([]int, len(input))
for i, b := range input {
n, err := strconv.Atoi(string(b))
if err != nil {
panic(err)
}
if n == 0 {
panic("0 is not a valid input")
}
s.stream[i] = n
}
return s
}
type Program []Instruction
func (p Program) ExecuteMem(input string, mem Memory) Memory {
stream := NewStream(input)
for _, i := range p {
switch i.op {
case INP:
mem[i.a] = stream.Get()
case ADD:
mem[i.a] += i.b
case ADDR:
mem[i.a] += mem[i.b]
case MUL:
mem[i.a] *= i.b
case MULR:
mem[i.a] *= mem[i.b]
case DIV:
mem[i.a] /= i.b
case DIVR:
mem[i.a] /= mem[i.b]
case MOD:
mem[i.a] %= i.b
case MODR:
mem[i.a] %= mem[i.b]
case EQL:
val := 0
if mem[i.a] == i.b {
val = 1
}
mem[i.a] = val
case EQLR:
val := 0
if mem[i.a] == mem[i.b] {
val = 1
}
mem[i.a] = val
default:
panic("Unknown operator")
}
// fmt.Println(mem)
}
return mem
}
func (p Program) Execute(input string) Memory {
var mem Memory
return p.ExecuteMem(input, mem)
}
func Compile(input *bufio.Scanner) Program {
var program Program
for input.Scan() {
line := input.Text()
inst := strings.Split(line, " ")
var instruction Instruction
// Parse the operator
switch inst[0] {
case "inp":
instruction.op = INP
case "add":
instruction.op = ADD
case "mul":
instruction.op = MUL
case "div":
instruction.op = DIV
case "mod":
instruction.op = MOD
case "eql":
instruction.op = EQL
default:
panic("Unknown instruction")
}
// Parse the first parameter, this is always a register
instruction.a = parseRegister(inst[1])
// All instructions, except INP, require a second parameter
if instruction.op != INP {
b := inst[2]
if val, err := strconv.Atoi(b); err == nil {
// If the parameter is a number we use that as the second parameter
instruction.b = val
} else {
// Otherwise the parameter is a register, so we parse it and set it to the register
instruction.b = parseRegister(b)
// We also increment the operator by one to indicate that the second parameter is a register
instruction.op++
}
}
program = append(program, instruction)
}
return program
}
func (p Program) Optimize() Program {
fmt.Printf("QUASI\n")
p, _ = p.quasi(false)
fmt.Printf("PRECOMP\n")
p = p.precomp()
return p
}
// func (p Program) Solver() {
// // There should be a total of 14 blocks
// mem := [4]int{3, 0, 0, 0}
// for i := range p {
// if p[i].op == INP {
// end := len(p)
// for j := i+1; j < len(p); j++ {
// if p[j].op == INP {
// end = j
// break
// }
// }
// tp := p[i+1:end]
// tp.Execute("", [4]int{w, 0, 0, 0}))
// break
// }
// }
// }
func step(w int, z int, a int, b int, pop bool) int {
temp := z
if pop {
// Pop value from stack
z /= 26
}
if (temp % 26) + a != w {
// Push new value to stack
z *= 26
z += w+b
}
return z
}
func reverse(w int, z int, a int, b int, pop bool) []int {
var valid []int
for zc := 0; zc < 1000; zc++ {
res := step(w, zc, a, b, pop)
if res == z {
valid = append(valid, zc)
}
}
return valid
}
func main() {
challenge := aoc.New(2021, 24)
challenge.Solution(1, func (input *bufio.Scanner) int {
program := Compile(input)
mem := program.Execute("13579246899999")
fmt.Println(mem)
w := []int{1, 3, 5, 7, 9, 2, 4, 6, 8, 9, 9, 9, 9, 9}
z := step(w[0], 0, 14, 1, false)
z = step(w[1], z, 15, 7, false)
z = step(w[2], z, 15, 13, false)
z = step(w[3], z, -6, 10, true)
z = step(w[4], z, 14, 0, false)
z = step(w[5], z, -4, 13, true)
z = step(w[6], z, 15, 11, false)
z = step(w[7], z, 15, 6, false)
z = step(w[8], z, 11, 1, false)
z = step(w[9], z, 0, 7, true)
z = step(w[10], z, 0, 11, true)
z = step(w[11], z, -3, 14, true)
z = step(w[12], z, -9, 4, true)
z = step(w[13], z, -9, 10, true)
fmt.Println(z)
// solution := make(map[int]int)
for w := 1; w <= 9; w++ {
valid := reverse(w, 0, -9, 10, true)
fmt.Println(w, valid)
for _, v := range valid {
check := step(w, v, -9, 10, true)
if check != 0 {
panic("CHECK FAILED")
}
}
}
for w := 1; w <= 9; w++ {
fmt.Println(w, reverse(w, w+9, -9, 4, true))
}
// for _, i := range program {
// fmt.Println(i)
// }
return -1
})
challenge.Solution(2, func (input *bufio.Scanner) int {
return 0
})
}

View File

@ -1,5 +1,7 @@
package main package main
// import "fmt"
type RegisterState struct { type RegisterState struct {
value int value int
last int last int
@ -18,49 +20,61 @@ func (p Program) precomp() Program {
} }
for _, i := range p { for _, i := range p {
// fmt.Println(i)
switch i.op { switch i.op {
case INP: case INP:
r[i.a].known = false r[i.a].known = false
np = append(np, i) np = append(np, i)
// fmt.Printf("- \t%v\n", np[len(np)-1])
case ADD: case ADD:
if r[i.a].known { if r[i.a].known {
r[i.a].value += i.b r[i.a].value += i.b
// fmt.Printf("- \t%v\n", r)
continue continue
} }
np = append(np, i) np = append(np, i)
// fmt.Printf("- \t%v\n", np[len(np)-1])
case ADDR: case ADDR:
if r[i.a].known && r[i.b].known { if r[i.a].known && r[i.b].known {
r[i.a].value += r[i.b].value r[i.a].value += r[i.b].value
// fmt.Printf("- \t%v\n", r)
continue continue
} }
if r[i.a].known { if r[i.a].known {
np = append(np, Instruction{MUL, i.a, 0}) if r[i.a].value - r[i.a].last != 0 {
if r[i.b].value != 0 { np = append(np, Instruction{ADD, i.a, r[i.a].value - r[i.a].last})
np = append(np, Instruction{ADD, i.b, r[i.a].value}) r[i.a].last = r[i.a].value
// fmt.Printf("- \t%v\n", np[len(np)-1])
} }
} }
if r[i.b].known { if r[i.b].known {
np = append(np, Instruction{MUL, i.b, 0}) if r[i.b].value - r[i.b].last != 0 {
if r[i.b].value != 0 { np = append(np, Instruction{ADD, i.b, r[i.b].value - r[i.b].last})
np = append(np, Instruction{ADD, i.b, r[i.b].value}) r[i.b].last = r[i.b].value
// fmt.Printf("- \t%v\n", np[len(np)-1])
} }
} }
r[i.a].known = false r[i.a].known = false
// fmt.Printf("- \t%v\n", r)
np = append(np, i) np = append(np, i)
// fmt.Printf("- \t%v\n", np[len(np)-1])
case MUL: case MUL:
if i.b == 0 { if i.b == 0 {
r[i.a].value = 0 r[i.a].value = 0
if !r[i.a].known { if !r[i.a].known {
r[i.a].value = 0 r[i.a].value = 0
r[i.a].last = 0
r[i.a].known = true r[i.a].known = true
np = append(np, Instruction{MUL, i.a, 0}) np = append(np, Instruction{MUL, i.a, 0})
// fmt.Printf("- \t%v\n", np[len(np)-1])
} }
// fmt.Printf("- \t%v\n", r)
continue continue
} }
@ -70,14 +84,17 @@ func (p Program) precomp() Program {
if r[i.a].known { if r[i.a].known {
r[i.a].value *= i.b r[i.a].value *= i.b
// fmt.Printf("- \t%v\n", r)
continue continue
} }
np = append(np, i) np = append(np, i)
// fmt.Printf("- \t%v\n", np[len(np)-1])
case MULR: case MULR:
if r[i.a].known && r[i.a].value == 0 { if r[i.a].known && r[i.a].value == 0 {
r[i.a].value = 0 r[i.a].value = 0
// fmt.Printf("- \t%v\n", r)
continue continue
} }
@ -85,9 +102,12 @@ func (p Program) precomp() Program {
r[i.a].value = 0 r[i.a].value = 0
if !r[i.a].known { if !r[i.a].known {
r[i.a].value = 0 r[i.a].value = 0
r[i.a].last = 0
r[i.a].known = true r[i.a].known = true
np = append(np, Instruction{MUL, i.a, 0}) np = append(np, Instruction{MUL, i.a, 0})
// fmt.Printf("- \t%v\n", np[len(np)-1])
} }
// fmt.Printf("- \t%v\n", r)
continue continue
} }
@ -97,25 +117,30 @@ func (p Program) precomp() Program {
if r[i.a].known && r[i.b].known { if r[i.a].known && r[i.b].known {
r[i.a].value *= r[i.b].value r[i.a].value *= r[i.b].value
// fmt.Printf("- \t%v\n", r)
continue continue
} }
if r[i.a].known { if r[i.a].known {
np = append(np, Instruction{MUL, i.a, 0}) if r[i.a].value - r[i.a].last != 0 {
if r[i.b].value != 0 { np = append(np, Instruction{ADD, i.a, r[i.a].value - r[i.a].last})
np = append(np, Instruction{ADD, i.b, r[i.a].value}) r[i.a].last = r[i.a].value
// fmt.Printf("- \t%v\n", np[len(np)-1])
} }
} }
if r[i.b].known { if r[i.b].known {
np = append(np, Instruction{MUL, i.b, 0}) if r[i.b].value - r[i.b].last != 0 {
if r[i.b].value != 0 { np = append(np, Instruction{ADD, i.b, r[i.b].value - r[i.b].last})
np = append(np, Instruction{ADD, i.b, r[i.b].value}) r[i.b].last = r[i.b].value
// fmt.Printf("- \t%v\n", np[len(np)-1])
} }
} }
r[i.a].known = false r[i.a].known = false
// fmt.Printf("- \t%v\n", r)
np = append(np, i) np = append(np, i)
// fmt.Printf("- \t%v\n", np[len(np)-1])
case DIV: case DIV:
if i.b == 1 { if i.b == 1 {
@ -124,14 +149,17 @@ func (p Program) precomp() Program {
if r[i.a].known { if r[i.a].known {
r[i.a].value /= i.b r[i.a].value /= i.b
// fmt.Printf("- \t%v\n", r)
continue continue
} }
np = append(np, i) np = append(np, i)
// fmt.Printf("- \t%v\n", np[len(np)-1])
case DIVR: case DIVR:
if r[i.a].known && r[i.a].value == 0 { if r[i.a].known && r[i.a].value == 0 {
r[i.a].value = 0 r[i.a].value = 0
// fmt.Printf("- \t%v\n", r)
continue continue
} }
@ -141,34 +169,42 @@ func (p Program) precomp() Program {
if r[i.a].known && r[i.b].known { if r[i.a].known && r[i.b].known {
r[i.a].value /= r[i.b].value r[i.a].value /= r[i.b].value
// fmt.Printf("- \t%v\n", r)
continue continue
} }
if r[i.a].known { if r[i.a].known {
np = append(np, Instruction{MUL, i.a, 0}) if r[i.a].value - r[i.a].last != 0 {
if r[i.b].value != 0 { np = append(np, Instruction{ADD, i.a, r[i.a].value - r[i.a].last})
np = append(np, Instruction{ADD, i.b, r[i.a].value}) r[i.a].last = r[i.a].value
// fmt.Printf("- \t%v\n", np[len(np)-1])
} }
} }
if r[i.b].known { if r[i.b].known {
np = append(np, Instruction{MUL, i.b, 0}) if r[i.b].value - r[i.b].last != 0 {
if r[i.b].value != 0 { np = append(np, Instruction{ADD, i.b, r[i.b].value - r[i.b].last})
np = append(np, Instruction{ADD, i.b, r[i.b].value}) r[i.b].last = r[i.b].value
// fmt.Printf("- \t%v\n", np[len(np)-1])
} }
} }
r[i.a].known = false r[i.a].known = false
// fmt.Printf("- \t%v\n", r)
np = append(np, i) np = append(np, i)
// fmt.Printf("- \t%v\n", np[len(np)-1])
case MOD: case MOD:
if i.b == -1 { if i.b == -1 {
r[i.a].value = 0 r[i.a].value = 0
if !r[i.a].known { if !r[i.a].known {
r[i.a].value = 0 r[i.a].value = 0
r[i.a].last = 0
r[i.a].known = true r[i.a].known = true
np = append(np, Instruction{MUL, i.a, 0}) np = append(np, Instruction{MUL, i.a, 0})
// fmt.Printf("- \t%v\n", np[len(np)-1])
} }
// fmt.Printf("- \t%v\n", r)
continue continue
} }
@ -176,22 +212,28 @@ func (p Program) precomp() Program {
r[i.a].value = 0 r[i.a].value = 0
if !r[i.a].known { if !r[i.a].known {
r[i.a].value = 0 r[i.a].value = 0
r[i.a].last = 0
r[i.a].known = true r[i.a].known = true
np = append(np, Instruction{MUL, i.a, 0}) np = append(np, Instruction{MUL, i.a, 0})
// fmt.Printf("- \t%v\n", np[len(np)-1])
} }
// fmt.Printf("- \t%v\n", r)
continue continue
} }
if r[i.a].known { if r[i.a].known {
r[i.a].value %= i.b r[i.a].value %= i.b
// fmt.Printf("- \t%v\n", r)
continue continue
} }
np = append(np, i) np = append(np, i)
// fmt.Printf("- \t%v\n", np[len(np)-1])
case MODR: case MODR:
if r[i.a].known && r[i.a].value == 0 { if r[i.a].known && r[i.a].value == 0 {
r[i.a].value = 0 r[i.a].value = 0
// fmt.Printf("- \t%v\n", r)
continue continue
} }
@ -199,9 +241,12 @@ func (p Program) precomp() Program {
r[i.a].value = 0 r[i.a].value = 0
if !r[i.a].known { if !r[i.a].known {
r[i.a].value = 0 r[i.a].value = 0
r[i.a].last = 0
r[i.a].known = true r[i.a].known = true
np = append(np, Instruction{MUL, i.a, 0}) np = append(np, Instruction{MUL, i.a, 0})
// fmt.Printf("- \t%v\n", np[len(np)-1])
} }
// fmt.Printf("- \t%v\n", r)
continue continue
} }
@ -209,33 +254,41 @@ func (p Program) precomp() Program {
r[i.a].value = 0 r[i.a].value = 0
if !r[i.a].known { if !r[i.a].known {
r[i.a].value = 0 r[i.a].value = 0
r[i.a].last = 0
r[i.a].known = true r[i.a].known = true
np = append(np, Instruction{MUL, i.a, 0}) np = append(np, Instruction{MUL, i.a, 0})
// fmt.Printf("- \t%v\n", np[len(np)-1])
} }
// fmt.Printf("- \t%v\n", r)
continue continue
} }
if r[i.a].known && r[i.b].known { if r[i.a].known && r[i.b].known {
r[i.a].value %= r[i.b].value r[i.a].value %= r[i.b].value
// fmt.Printf("- \t%v\n", r)
continue continue
} }
if r[i.a].known { if r[i.a].known {
np = append(np, Instruction{MUL, i.a, 0}) if r[i.a].value - r[i.a].last != 0 {
if r[i.b].value != 0 { np = append(np, Instruction{ADD, i.a, r[i.a].value - r[i.a].last})
np = append(np, Instruction{ADD, i.b, r[i.a].value}) r[i.a].last = r[i.a].value
// fmt.Printf("- \t%v\n", np[len(np)-1])
} }
} }
if r[i.b].known { if r[i.b].known {
np = append(np, Instruction{MUL, i.b, 0}) if r[i.b].value - r[i.b].last != 0 {
if r[i.b].value != 0 { np = append(np, Instruction{ADD, i.b, r[i.b].value - r[i.b].last})
np = append(np, Instruction{ADD, i.b, r[i.b].value}) r[i.b].last = r[i.b].value
// fmt.Printf("- \t%v\n", np[len(np)-1])
} }
} }
r[i.a].known = false r[i.a].known = false
// fmt.Printf("- \t%v\n", r)
np = append(np, i) np = append(np, i)
// fmt.Printf("- \t%v\n", np[len(np)-1])
case EQL: case EQL:
if r[i.a].known { if r[i.a].known {
@ -244,19 +297,24 @@ func (p Program) precomp() Program {
val = 1 val = 1
} }
r[i.a].value = val r[i.a].value = val
// fmt.Printf("- \t%v\n", r)
continue continue
} }
np = append(np, i) np = append(np, i)
// fmt.Printf("- \t%v\n", np[len(np)-1])
case EQLR: case EQLR:
if i.a == i.b { if i.a == i.b {
r[i.a].value = 1 r[i.a].value = 1
if !r[i.a].known { if !r[i.a].known {
r[i.a].value = 0 r[i.a].value = 0
r[i.a].last = 0
r[i.a].known = true r[i.a].known = true
np = append(np, Instruction{MUL, i.a, 0}) np = append(np, Instruction{MUL, i.a, 0})
// fmt.Printf("- \t%v\n", np[len(np)-1])
} }
// fmt.Printf("- \t%v\n", r)
continue continue
} }
@ -266,25 +324,30 @@ func (p Program) precomp() Program {
val = 1 val = 1
} }
r[i.a].value = val r[i.a].value = val
// fmt.Printf("- \t%v\n", r)
continue continue
} }
if r[i.a].known { if r[i.a].known {
np = append(np, Instruction{MUL, i.a, 0}) if r[i.a].value - r[i.a].last != 0 {
if r[i.b].value != 0 { np = append(np, Instruction{ADD, i.a, r[i.a].value - r[i.a].last})
np = append(np, Instruction{ADD, i.b, r[i.a].value}) r[i.a].last = r[i.a].value
// fmt.Printf("- \t%v\n", np[len(np)-1])
} }
} }
if r[i.b].known { if r[i.b].known {
np = append(np, Instruction{MUL, i.b, 0}) if r[i.b].value - r[i.b].last != 0 {
if r[i.b].value != 0 { np = append(np, Instruction{ADD, i.b, r[i.b].value - r[i.b].last})
np = append(np, Instruction{ADD, i.b, r[i.b].value}) r[i.b].last = r[i.b].value
// fmt.Printf("- \t%v\n", np[len(np)-1])
} }
} }
r[i.a].known = false r[i.a].known = false
// fmt.Printf("- \t%v\n", r)
np = append(np, i) np = append(np, i)
// fmt.Printf("- \t%v\n", np[len(np)-1])
} }
} }

View File

@ -7,6 +7,12 @@ type RegisterQuasiState struct {
max int max int
} }
type SubProgram struct {
program Program
min int
max int
}
func minv(a int, b int) int { func minv(a int, b int) int {
if a < b { if a < b {
return a return a
@ -22,16 +28,27 @@ func maxv(a int, b int) int {
} }
// This function will try to eliminate eql statements // This function will try to eliminate eql statements
func (p Program) quasi() Program { func (p Program) quasi(prnt bool) (Program, []SubProgram) {
var np Program var np Program
var sp []SubProgram
var r [4]RegisterQuasiState var r [4]RegisterQuasiState
counter1 := 0
counter2 := 0
broken := false broken := false
for _, i := range p { for index, i := range p {
if !broken { if !broken {
switch i.op { switch i.op {
case INP: case INP:
counter2 = counter1
counter1 = index
sp = append(sp, SubProgram{p[counter2:counter1], r[3].min, r[3].max})
if prnt {
fmt.Println("")
}
r[i.a].min = 1 r[i.a].min = 1
r[i.a].max = 9 r[i.a].max = 9
@ -60,13 +77,35 @@ func (p Program) quasi() Program {
r[i.a].min = minv(min1, minv(min2, minv(max1, max2))) r[i.a].min = minv(min1, minv(min2, minv(max1, max2)))
r[i.a].max = maxv(min1, maxv(min2, maxv(max1, max2))) r[i.a].max = maxv(min1, maxv(min2, maxv(max1, max2)))
case DIV:
r[i.a].min /= i.b
r[i.a].max /= i.b
if r[i.a].min > r[i.a].max {
r[i.a].min, r[i.a].max = r[i.a].max, r[i.a].min
}
case DIVR:
min1 := r[i.a].min / r[i.b].min
min2 := r[i.a].min / r[i.b].max
max1 := r[i.a].max / r[i.b].min
max2 := r[i.a].max / r[i.b].max
r[i.a].min = minv(min1, minv(min2, minv(max1, max2)))
r[i.a].max = maxv(min1, maxv(min2, maxv(max1, max2)))
case EQL: case EQL:
if i.b < r[i.a].min || i.b > r[i.a].max { if i.b < r[i.a].min || i.b > r[i.a].max {
r[i.a].min = 0 r[i.a].min = 0
r[i.a].max = 0 r[i.a].max = 0
if prnt {
fmt.Printf("- %v \t %v\n", i, r)
}
np = append(np, Instruction{MUL, i.a, 0}) np = append(np, Instruction{MUL, i.a, 0})
fmt.Println("\tReplace EQL with mul 0") if prnt {
fmt.Printf("+ %v\n", np[len(np)-1])
}
continue continue
} }
@ -79,9 +118,17 @@ func (p Program) quasi() Program {
r[i.a].min = val r[i.a].min = val
r[i.a].max = val r[i.a].max = val
if prnt {
fmt.Printf("- %v \t %v\n", i, r)
}
np = append(np, Instruction{MUL, i.a, 0}) np = append(np, Instruction{MUL, i.a, 0})
if prnt {
fmt.Printf("+ %v\n", np[len(np)-1])
}
np = append(np, Instruction{ADD, i.a, 1}) np = append(np, Instruction{ADD, i.a, 1})
fmt.Println("\tReplace EQL with mul 0, add 1") if prnt {
fmt.Printf("+ %v\n", np[len(np)-1])
}
continue continue
} }
@ -93,8 +140,13 @@ func (p Program) quasi() Program {
r[i.a].min = 0 r[i.a].min = 0
r[i.a].max = 0 r[i.a].max = 0
if prnt {
fmt.Printf("- %v \t %v\n", i, r)
}
np = append(np, Instruction{MUL, i.a, 0}) np = append(np, Instruction{MUL, i.a, 0})
fmt.Println("\tReplace EQLR with mul 0") if prnt {
fmt.Printf("+ %v\n", np[len(np)-1])
}
continue continue
} }
@ -107,9 +159,17 @@ func (p Program) quasi() Program {
r[i.a].min = val r[i.a].min = val
r[i.a].max = val r[i.a].max = val
if prnt {
fmt.Printf("- %v \t %v\n", i, r)
}
np = append(np, Instruction{MUL, i.a, 0}) np = append(np, Instruction{MUL, i.a, 0})
if prnt {
fmt.Printf("+ %v\n", np[len(np)-1])
}
np = append(np, Instruction{ADD, i.a, 1}) np = append(np, Instruction{ADD, i.a, 1})
fmt.Println("\tReplace EQLR with mul 0, add 1") if prnt {
fmt.Printf("+ %v\n", np[len(np)-1])
}
continue continue
} }
@ -117,8 +177,17 @@ func (p Program) quasi() Program {
r[i.a].max = 1 r[i.a].max = 1
case MOD: case MOD:
if r[i.a].max <= 0 || r[i.a].max >= i.b {
r[i.a].max = i.b - 1
}
if r[i.a].min <= 0 || r[i.a].min >= i.b {
r[i.a].min = 0 r[i.a].min = 0
r[i.a].max = i.b
}
// r[i.a].min = 0
// r[i.a].max = i.b-1
if r[i.a].min > r[i.a].max { if r[i.a].min > r[i.a].max {
r[i.a].min, r[i.a].max = r[i.a].max, r[i.a].min r[i.a].min, r[i.a].max = r[i.a].max, r[i.a].min
@ -126,15 +195,22 @@ func (p Program) quasi() Program {
default: default:
fmt.Println("\tBROKE") if prnt {
fmt.Printf("\tBROKE: %v\n", i.op)
}
broken = true broken = true
} }
} }
if prnt {
fmt.Printf("%v \t %v\n", i, r)
}
np = append(np, i) np = append(np, i)
} }
sp = append(sp, SubProgram{p[counter1:], r[3].min, r[3].max})
return np return np, sp[1:]
} }

View File

@ -1,26 +1,30 @@
PART1
inp w
add y w
add y 1
add z y
add x 1
PART2
INP [w]
ADD [y], [w]
ADD [y], 1
ADD [z], [y]
w = ? x = 1 y = ? z = ?
INP [w] INP [w]
MUL [x], 0 MUL [x], 0
ADD [x], [z] ADD [x], [z]
MOD [x], 26 MOD [x], 26
DIV [z], 1
ADD [x], 14
EQL [x], [w]
EQL [x], 0
MUL [y], 0
ADD [y], 25
MUL [y], [x]
ADD [y], 1
MUL [z], [y]
MUL [y], 0
ADD [y], [w]
ADD [y], 1
MUL [y], [x]
ADD [z], [y]
INP [w]
MUL [x], 0
ADD [x], [z]
MOD [x], 26
DIV [z], 1
ADD [x], 15 ADD [x], 15
MUL [x], 0 EQL [x], [w]
MUL [x], 0 EQL [x], 0
ADD [x], 1
MUL [y], 0 MUL [y], 0
ADD [y], 25 ADD [y], 25
MUL [y], [x] MUL [y], [x]
@ -32,262 +36,230 @@ ADD [y], 7
MUL [y], [x] MUL [y], [x]
ADD [z], [y] ADD [z], [y]
INP [w]
MUL [x], 0
ADD [x], [z]
MOD [x], 26
DIV [z], 1
ADD [x], 15
EQL [x], [w]
EQL [x], 0
MUL [y], 0
ADD [y], 25
MUL [y], [x]
ADD [y], 1
MUL [z], [y]
MUL [y], 0
ADD [y], [w]
ADD [y], 13
MUL [y], [x]
ADD [z], [y]
INP [w]
MUL [x], 0
ADD [x], [z]
MOD [x], 26
DIV [z], 26
ADD [x], -6
EQL [x], [w]
EQL [x], 0
MUL [y], 0
ADD [y], 25
MUL [y], [x]
ADD [y], 1
MUL [z], [y]
MUL [y], 0
ADD [y], [w]
ADD [y], 10
MUL [y], [x]
ADD [z], [y]
INP [w]
MUL [x], 0
ADD [x], [z]
MOD [x], 26
DIV [z], 1
ADD [x], 14
EQL [x], [w]
EQL [x], 0
MUL [y], 0
ADD [y], 25
MUL [y], [x]
ADD [y], 1
MUL [z], [y]
MUL [y], 0
ADD [y], [w]
ADD [y], 0
MUL [y], [x]
ADD [z], [y]
INP [w]
MUL [x], 0
ADD [x], [z]
MOD [x], 26
DIV [z], 26
ADD [x], -4
EQL [x], [w]
EQL [x], 0
MUL [y], 0
ADD [y], 25
MUL [y], [x]
ADD [y], 1
MUL [z], [y]
MUL [y], 0
ADD [y], [w]
ADD [y], 13
MUL [y], [x]
ADD [z], [y]
ORIGINAL INP [w]
inp w MUL [x], 0
mul x 0 ADD [x], [z]
add x z MOD [x], 26
mod x 26 DIV [z], 1
div z 1 ADD [x], 15
add x 14 EQL [x], [w]
eql x w EQL [x], 0
eql x 0 MUL [y], 0
mul y 0 ADD [y], 25
add y 25 MUL [y], [x]
mul y x ADD [y], 1
add y 1 MUL [z], [y]
mul z y MUL [y], 0
mul y 0 ADD [y], [w]
add y w ADD [y], 11
add y 1 MUL [y], [x]
mul y x ADD [z], [y]
add z y
inp w
mul x 0
add x z
mod x 26
div z 1
add x 15
eql x w
eql x 0
mul y 0
add y 25
mul y x
add y 1
mul z y
mul y 0
add y w
add y 7
mul y x
add z y
inp w
mul x 0
add x z
mod x 26
div z 1
add x 15
eql x w
eql x 0
mul y 0
add y 25
mul y x
add y 1
mul z y
mul y 0
add y w
add y 13
mul y x
add z y
inp w
mul x 0
add x z
mod x 26
div z 26
add x -6
eql x w
eql x 0
mul y 0
add y 25
mul y x
add y 1
mul z y
mul y 0
add y w
add y 10
mul y x
add z y
inp w
mul x 0
add x z
mod x 26
div z 1
add x 14
eql x w
eql x 0
mul y 0
add y 25
mul y x
add y 1
mul z y
mul y 0
add y w
add y 0
mul y x
add z y
inp w
mul x 0
add x z
mod x 26
div z 26
add x -4
eql x w
eql x 0
mul y 0
add y 25
mul y x
add y 1
mul z y
mul y 0
add y w
add y 13
mul y x
add z y
inp w
mul x 0
add x z
mod x 26
div z 1
add x 15
eql x w
eql x 0
mul y 0
add y 25
mul y x
add y 1
mul z y
mul y 0
add y w
add y 11
mul y x
add z y
inp w
mul x 0
add x z
mod x 26
div z 1
add x 15
eql x w
eql x 0
mul y 0
add y 25
mul y x
add y 1
mul z y
mul y 0
add y w
add y 6
mul y x
add z y
inp w
mul x 0
add x z
mod x 26
div z 1
add x 11
eql x w
eql x 0
mul y 0
add y 25
mul y x
add y 1
mul z y
mul y 0
add y w
add y 1
mul y x
add z y
inp w
mul x 0
add x z
mod x 26
div z 26
add x 0
eql x w
eql x 0
mul y 0
add y 25
mul y x
add y 1
mul z y
mul y 0
add y w
add y 7
mul y x
add z y
inp w
mul x 0
add x z
mod x 26
div z 26
add x 0
eql x w
eql x 0
mul y 0
add y 25
mul y x
add y 1
mul z y
mul y 0
add y w
add y 11
mul y x
add z y
inp w
mul x 0
add x z
mod x 26
div z 26
add x -3
eql x w
eql x 0
mul y 0
add y 25
mul y x
add y 1
mul z y
mul y 0
add y w
add y 14
mul y x
add z y
inp w
mul x 0
add x z
mod x 26
div z 26
add x -9
eql x w
eql x 0
mul y 0
add y 25
mul y x
add y 1
mul z y
mul y 0
add y w
add y 4
mul y x
add z y
inp w
mul x 0
add x z
mod x 26
div z 26
add x -9
eql x w
eql x 0
mul y 0
add y 25
mul y x
add y 1
mul z y
mul y 0
add y w
add y 10
mul y x
add z y
INP [w]
MUL [x], 0
ADD [x], [z]
MOD [x], 26
DIV [z], 1
ADD [x], 15
EQL [x], [w]
EQL [x], 0
MUL [y], 0
ADD [y], 25
MUL [y], [x]
ADD [y], 1
MUL [z], [y]
MUL [y], 0
ADD [y], [w]
ADD [y], 6
MUL [y], [x]
ADD [z], [y]
INP [w]
MUL [x], 0
ADD [x], [z]
MOD [x], 26
DIV [z], 1
ADD [x], 11
EQL [x], [w]
EQL [x], 0
MUL [y], 0
ADD [y], 25
MUL [y], [x]
ADD [y], 1
MUL [z], [y]
MUL [y], 0
ADD [y], [w]
ADD [y], 1
MUL [y], [x]
ADD [z], [y]
INP [w]
MUL [x], 0
ADD [x], [z]
MOD [x], 26
DIV [z], 26
ADD [x], 0
EQL [x], [w]
EQL [x], 0
MUL [y], 0
ADD [y], 25
MUL [y], [x]
ADD [y], 1
MUL [z], [y]
MUL [y], 0
ADD [y], [w]
ADD [y], 7
MUL [y], [x]
ADD [z], [y]
INP [w]
MUL [x], 0
ADD [x], [z]
MOD [x], 26
DIV [z], 26
ADD [x], 0
EQL [x], [w]
EQL [x], 0
MUL [y], 0
ADD [y], 25
MUL [y], [x]
ADD [y], 1
MUL [z], [y]
MUL [y], 0
ADD [y], [w]
ADD [y], 11
MUL [y], [x]
ADD [z], [y]
INP [w]
MUL [x], 0
ADD [x], [z]
MOD [x], 26
DIV [z], 26
ADD [x], -3
EQL [x], [w]
EQL [x], 0
MUL [y], 0
ADD [y], 25
MUL [y], [x]
ADD [y], 1
MUL [z], [y]
MUL [y], 0
ADD [y], [w]
ADD [y], 14
MUL [y], [x]
ADD [z], [y]
INP [w]
MUL [x], 0
ADD [x], [z]
MOD [x], 26
DIV [z], 26
ADD [x], -9
EQL [x], [w]
EQL [x], 0
MUL [y], 0
ADD [y], 25
MUL [y], [x]
ADD [y], 1
MUL [z], [y]
MUL [y], 0
ADD [y], [w]
ADD [y], 4
MUL [y], [x]
ADD [z], [y]
INP [w]
MUL [x], 0
ADD [x], [z]
MOD [x], 26
DIV [z], 26
ADD [x], -9
EQL [x], [w]
EQL [x], 0
MUL [y], 0
ADD [y], 25
MUL [y], [x]
ADD [y], 1
MUL [z], [y]
MUL [y], 0
ADD [y], [w]
ADD [y], 10
MUL [y], [x]
ADD [z], [y]