2021 - Day 24
This commit is contained in:
322
2021/24/old/main.go
Normal file
322
2021/24/old/main.go
Normal 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
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user