Day 23 Complete
This commit is contained in:
parent
99e36b8912
commit
54a91e53c7
@ -6,6 +6,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/fatih/color"
|
||||||
termbox "github.com/nsf/termbox-go"
|
termbox "github.com/nsf/termbox-go"
|
||||||
|
|
||||||
"../../"
|
"../../"
|
||||||
@ -18,9 +19,10 @@ var regs = map[string]int{
|
|||||||
"d": 0,
|
"d": 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
var instructions []string
|
var instructions, lastInst []string
|
||||||
var curr int
|
var curr, cursor int
|
||||||
var pause bool
|
var pause, step, skip bool
|
||||||
|
var breakpoints []int
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var debug bool
|
var debug bool
|
||||||
@ -54,70 +56,107 @@ func main() {
|
|||||||
var ins []string
|
var ins []string
|
||||||
for curr < len(instructions) || done {
|
for curr < len(instructions) || done {
|
||||||
if debug {
|
if debug {
|
||||||
lastInst := ins
|
lastInst = ins
|
||||||
// print state and wait for user to step
|
|
||||||
PrintState()
|
|
||||||
fmt.Println("Last Instruction:", lastInst)
|
|
||||||
//PrintInstructionState()
|
|
||||||
fmt.Println("(q): quit (space): pause/unpause")
|
|
||||||
ev := <-eventChan
|
|
||||||
if ev.Type == termbox.EventKey {
|
|
||||||
if ev.Key == termbox.KeySpace {
|
|
||||||
pause = !pause
|
|
||||||
}
|
|
||||||
if ev.Ch == 'q' {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ins = strings.Fields(instructions[curr])
|
ins = strings.Fields(instructions[curr])
|
||||||
curr++
|
if len(ins) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
// Optimize multiplication
|
// Optimize multiplication
|
||||||
/*
|
/*
|
||||||
// TODO:
|
|
||||||
> cpy b c
|
> cpy b c
|
||||||
inc a
|
inc a
|
||||||
dec c
|
dec c
|
||||||
jnz c -2
|
jnz c -2
|
||||||
dec d
|
dec d
|
||||||
jnz d -5
|
jnz d -5
|
||||||
== mlt b d a
|
== add (b * d) to a
|
||||||
and curr += 5
|
set c & d to 0
|
||||||
|
curr += 5
|
||||||
*/
|
*/
|
||||||
if ins[0] == "cpy" {
|
if ins[0] == "cpy" {
|
||||||
|
if len(instructions) >= curr+6 {
|
||||||
if strings.HasPrefix(instructions[curr+1], "inc") && strings.HasPrefix(instructions[curr+2], "dec") && strings.HasPrefix(instructions[curr+3], "jnz") && strings.HasPrefix(instructions[curr+4], "dec") && strings.HasPrefix(instructions[curr+5], "jnz") {
|
|
||||||
|
|
||||||
allGood := true
|
|
||||||
// The right instruction set, make sure the arguments match up
|
|
||||||
ins1 := strings.Fields(instructions[curr+1])
|
ins1 := strings.Fields(instructions[curr+1])
|
||||||
ins2 := strings.Fields(instructions[curr+2])
|
ins2 := strings.Fields(instructions[curr+2])
|
||||||
ins3 := strings.Fields(instructions[curr+3])
|
ins3 := strings.Fields(instructions[curr+3])
|
||||||
ins4 := strings.Fields(instructions[curr+4])
|
ins4 := strings.Fields(instructions[curr+4])
|
||||||
ins5 := strings.Fields(instructions[curr+5])
|
ins5 := strings.Fields(instructions[curr+5])
|
||||||
// Make sure all "c"s are correct
|
if ins1[0] == "inc" && ins2[0] == "dec" && ins3[0] == "jnz" && ins4[0] == "dec" && ins5[0] == "jnz" {
|
||||||
if ins[2] != ins2[1] && ins[2] != ins3[1] {
|
allGood := true
|
||||||
|
if allGood {
|
||||||
|
// Do the multiplication
|
||||||
|
// ins[1] * ins4[1]
|
||||||
|
// add that value to ins1[1]
|
||||||
|
// set ins[2] to 0
|
||||||
|
// set ins4[1] to 0
|
||||||
|
// Then add 5 to the pc
|
||||||
|
src1 := ins[1]
|
||||||
|
src2 := ins4[1]
|
||||||
|
dst := ins1[1]
|
||||||
|
if _, ok := regs[dst]; !ok {
|
||||||
|
// Invalid destination register
|
||||||
|
allGood = false
|
||||||
|
}
|
||||||
|
if _, ok := regs[src1]; !ok {
|
||||||
|
// Invalid source register
|
||||||
|
allGood = false
|
||||||
|
}
|
||||||
|
if _, ok := regs[src2]; !ok {
|
||||||
allGood = false
|
allGood = false
|
||||||
}
|
}
|
||||||
if allGood {
|
if allGood {
|
||||||
// Make sure all "b"s are correct
|
regs[dst] += (regs[src1] * regs[src2])
|
||||||
if ins[1] == ins1[1] || ins[1] == ins2[1] || ins[1] == ins4[1] {
|
curr += 6
|
||||||
allGood = false
|
skip = true
|
||||||
}
|
|
||||||
}
|
|
||||||
if allGood {
|
|
||||||
// Make sure all "d"s are correct
|
|
||||||
if (ins[1] == ins4[1] || ins[2] == ins4[1]) || ins4[1] != ins5[1] {
|
|
||||||
allGood = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if allGood {
|
|
||||||
// Go ahead and change the instruction
|
|
||||||
ins = []string{"mult", ins[1], ins4[1], ins1[1]}
|
|
||||||
curr += 5
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if debug {
|
||||||
|
if isBreakpoint(curr + 1) {
|
||||||
|
pause = true
|
||||||
|
step = false
|
||||||
|
}
|
||||||
|
for pause && !step {
|
||||||
|
// print state and wait for user to step
|
||||||
|
PrintState()
|
||||||
|
fmt.Println("Last Instruction:", lastInst)
|
||||||
|
PrintInstructionState()
|
||||||
|
fmt.Println("(q): quit (space): pause/unpause (s): step (b): toggle breakpoint")
|
||||||
|
ev := <-eventChan
|
||||||
|
if ev.Type == termbox.EventKey {
|
||||||
|
switch {
|
||||||
|
case ev.Key == termbox.KeySpace:
|
||||||
|
pause = !pause
|
||||||
|
case ev.Ch == 'q':
|
||||||
|
done = true
|
||||||
|
case ev.Ch == 'b':
|
||||||
|
toggleBreakpoint(cursor)
|
||||||
|
case ev.Ch == 's':
|
||||||
|
step = true
|
||||||
|
case ev.Key == termbox.KeyArrowUp:
|
||||||
|
if cursor > 0 {
|
||||||
|
cursor--
|
||||||
|
}
|
||||||
|
case ev.Key == termbox.KeyArrowDown:
|
||||||
|
if cursor < len(instructions)-1 {
|
||||||
|
cursor++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
step = false
|
||||||
|
}
|
||||||
|
if done {
|
||||||
|
// User hit 'q'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if skip {
|
||||||
|
skip = false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
curr++
|
||||||
switch ins[0] {
|
switch ins[0] {
|
||||||
case "jnz":
|
case "jnz":
|
||||||
// If we have a jnz c -2 it could be moving all of c into another register
|
// If we have a jnz c -2 it could be moving all of c into another register
|
||||||
@ -211,6 +250,8 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
PrintState()
|
PrintState()
|
||||||
|
fmt.Println("Press any key to exit")
|
||||||
|
termbox.PollEvent()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fancy State Printing
|
// Fancy State Printing
|
||||||
@ -229,12 +270,22 @@ func PrintRegs() {
|
|||||||
func PrintInstructionState() {
|
func PrintInstructionState() {
|
||||||
for pi := range instructions {
|
for pi := range instructions {
|
||||||
if pi == curr {
|
if pi == curr {
|
||||||
fmt.Print("> ")
|
fmt.Print(">")
|
||||||
} else {
|
} else {
|
||||||
fmt.Print(" ")
|
fmt.Print(" ")
|
||||||
}
|
}
|
||||||
|
if isBreakpoint(pi) {
|
||||||
|
fmt.Print("B")
|
||||||
|
} else {
|
||||||
|
fmt.Print(" ")
|
||||||
|
}
|
||||||
|
if cursor == pi {
|
||||||
|
cursor := color.New(color.FgBlack).Add(color.BgWhite)
|
||||||
|
cursor.Println(instructions[pi])
|
||||||
|
} else {
|
||||||
fmt.Println(instructions[pi])
|
fmt.Println(instructions[pi])
|
||||||
}
|
}
|
||||||
|
}
|
||||||
fmt.Println(instructions[curr])
|
fmt.Println(instructions[curr])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,3 +303,22 @@ func sendNoneEvent(e chan termbox.Event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func toggleBreakpoint(pos int) {
|
||||||
|
for i := 0; i < len(breakpoints); i++ {
|
||||||
|
if breakpoints[i] == pos {
|
||||||
|
breakpoints = append(breakpoints[:i], breakpoints[i+1:]...)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
breakpoints = append(breakpoints, pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isBreakpoint(pos int) bool {
|
||||||
|
for i := 0; i < len(breakpoints); i++ {
|
||||||
|
if breakpoints[i] == pos {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
93
2016/day23/problem
Normal file
93
2016/day23/problem
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
Advent of Code
|
||||||
|
|
||||||
|
--- Day 23: Safe Cracking ---
|
||||||
|
|
||||||
|
This is one of the top floors of the nicest tower in EBHQ. The Easter Bunny's private office is here, complete with
|
||||||
|
a safe hidden behind a painting, and who wouldn't hide a star in a safe behind a painting?
|
||||||
|
|
||||||
|
The safe has a digital screen and keypad for code entry. A sticky note attached to the safe has a password hint on
|
||||||
|
it: "eggs". The painting is of a large rabbit coloring some eggs. You see 7.
|
||||||
|
|
||||||
|
When you go to type the code, though, nothing appears on the display; instead, the keypad comes apart in your
|
||||||
|
hands, apparently having been smashed. Behind it is some kind of socket - one that matches a connector in your
|
||||||
|
prototype computer! You pull apart the smashed keypad and extract the logic circuit, plug it into your computer,
|
||||||
|
and plug your computer into the safe.
|
||||||
|
|
||||||
|
Now, you just need to figure out what output the keypad would have sent to the safe. You extract the assembunny
|
||||||
|
code from the logic chip (your puzzle input).
|
||||||
|
|
||||||
|
The code looks like it uses almost the same architecture and instruction set that the monorail computer used! You
|
||||||
|
should be able to use the same assembunny interpreter for this as you did there, but with one new instruction:
|
||||||
|
|
||||||
|
tgl x toggles the instruction x away (pointing at instructions like jnz does: positive means forward; negative
|
||||||
|
means backward):
|
||||||
|
|
||||||
|
• For one-argument instructions, inc becomes dec, and all other one-argument instructions become inc.
|
||||||
|
• For two-argument instructions, jnz becomes cpy, and all other two-instructions become jnz.
|
||||||
|
• The arguments of a toggled instruction are not affected.
|
||||||
|
• If an attempt is made to toggle an instruction outside the program, nothing happens.
|
||||||
|
• If toggling produces an invalid instruction (like cpy 1 2) and an attempt is later made to execute that
|
||||||
|
instruction, skip it instead.
|
||||||
|
• If tgl toggles itself (for example, if a is 0, tgl a would target itself and become inc a), the resulting
|
||||||
|
instruction is not executed until the next time it is reached.
|
||||||
|
|
||||||
|
For example, given this program:
|
||||||
|
|
||||||
|
cpy 2 a
|
||||||
|
tgl a
|
||||||
|
tgl a
|
||||||
|
tgl a
|
||||||
|
cpy 1 a
|
||||||
|
dec a
|
||||||
|
dec a
|
||||||
|
|
||||||
|
• cpy 2 a initializes register a to 2.
|
||||||
|
• The first tgl a toggles an instruction a (2) away from it, which changes the third tgl a into inc a.
|
||||||
|
• The second tgl a also modifies an instruction 2 away from it, which changes the cpy 1 a into jnz 1 a.
|
||||||
|
• The fourth line, which is now inc a, increments a to 3.
|
||||||
|
• Finally, the fifth line, which is now jnz 1 a, jumps a (3) instructions ahead, skipping the dec a instructions.
|
||||||
|
|
||||||
|
In this example, the final value in register a is 3.
|
||||||
|
|
||||||
|
The rest of the electronics seem to place the keypad entry (the number of eggs, 7) in register a, run the code, and
|
||||||
|
then send the value left in register a to the safe.
|
||||||
|
|
||||||
|
What value should be sent to the safe?
|
||||||
|
|
||||||
|
Your puzzle answer was ________.
|
||||||
|
|
||||||
|
--- Part Two ---
|
||||||
|
|
||||||
|
The safe doesn't open, but it does make several angry noises to express its frustration.
|
||||||
|
|
||||||
|
You're quite sure your logic is working correctly, so the only other thing is... you check the painting again. As
|
||||||
|
it turns out, colored eggs are still eggs. Now you count 12.
|
||||||
|
|
||||||
|
As you run the program with this new input, the prototype computer begins to overheat. You wonder what's taking so
|
||||||
|
long, and whether the lack of any instruction more powerful than "add one" has anything to do with it. Don't
|
||||||
|
bunnies usually multiply?
|
||||||
|
|
||||||
|
Anyway, what value should actually be sent to the safe?
|
||||||
|
|
||||||
|
Your puzzle answer was ____________.
|
||||||
|
|
||||||
|
References
|
||||||
|
|
||||||
|
Visible links
|
||||||
|
. http://adventofcode.com/
|
||||||
|
. http://adventofcode.com/2016/about
|
||||||
|
. http://adventofcode.com/2016/support
|
||||||
|
. http://adventofcode.com/2016/events
|
||||||
|
. http://adventofcode.com/2016/settings
|
||||||
|
. http://adventofcode.com/2016/auth/logout
|
||||||
|
. http://adventofcode.com/2016
|
||||||
|
. http://adventofcode.com/2016
|
||||||
|
. http://adventofcode.com/2016/leaderboard
|
||||||
|
. http://adventofcode.com/2016/stats
|
||||||
|
. http://adventofcode.com/2016/sponsors
|
||||||
|
. http://adventofcode.com/2016/sponsors
|
||||||
|
. http://adventofcode.com/2016/day/11
|
||||||
|
. http://adventofcode.com/2016/day/12
|
||||||
|
. http://adventofcode.com/2016/day/12
|
||||||
|
. http://adventofcode.com/2016
|
||||||
|
. http://adventofcode.com/2016/day/23/input
|
@ -1,7 +0,0 @@
|
|||||||
cpy 2 a
|
|
||||||
tgl a
|
|
||||||
tgl a
|
|
||||||
tgl a
|
|
||||||
cpy 1 a
|
|
||||||
dec a
|
|
||||||
dec a
|
|
Loading…
Reference in New Issue
Block a user