Day 23 Complete

This commit is contained in:
Brian Buller 2016-12-23 13:20:07 -06:00
parent 99e36b8912
commit 54a91e53c7
3 changed files with 212 additions and 56 deletions

View File

@ -6,6 +6,7 @@ import (
"strings"
"time"
"github.com/fatih/color"
termbox "github.com/nsf/termbox-go"
"../../"
@ -18,9 +19,10 @@ var regs = map[string]int{
"d": 0,
}
var instructions []string
var curr int
var pause bool
var instructions, lastInst []string
var curr, cursor int
var pause, step, skip bool
var breakpoints []int
func main() {
var debug bool
@ -54,70 +56,107 @@ func main() {
var ins []string
for curr < len(instructions) || done {
if debug {
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
}
}
lastInst = ins
}
ins = strings.Fields(instructions[curr])
curr++
if len(ins) == 0 {
break
}
// Optimize multiplication
/*
// TODO:
> cpy b c
inc a
dec c
jnz c -2
dec d
jnz d -5
== mlt b d a
and curr += 5
== add (b * d) to a
set c & d to 0
curr += 5
*/
if ins[0] == "cpy" {
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
if len(instructions) >= curr+6 {
ins1 := strings.Fields(instructions[curr+1])
ins2 := strings.Fields(instructions[curr+2])
ins3 := strings.Fields(instructions[curr+3])
ins4 := strings.Fields(instructions[curr+4])
ins5 := strings.Fields(instructions[curr+5])
// Make sure all "c"s are correct
if ins[2] != ins2[1] && ins[2] != ins3[1] {
allGood = false
}
if allGood {
// Make sure all "b"s are correct
if ins[1] == ins1[1] || ins[1] == ins2[1] || ins[1] == ins4[1] {
allGood = false
if ins1[0] == "inc" && ins2[0] == "dec" && ins3[0] == "jnz" && ins4[0] == "dec" && ins5[0] == "jnz" {
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
}
if allGood {
regs[dst] += (regs[src1] * regs[src2])
curr += 6
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] {
case "jnz":
// If we have a jnz c -2 it could be moving all of c into another register
@ -211,6 +250,8 @@ func main() {
}
}
PrintState()
fmt.Println("Press any key to exit")
termbox.PollEvent()
}
// Fancy State Printing
@ -229,11 +270,21 @@ func PrintRegs() {
func PrintInstructionState() {
for pi := range instructions {
if pi == curr {
fmt.Print("> ")
fmt.Print(">")
} 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])
}
@ -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
View 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

View File

@ -1,7 +0,0 @@
cpy 2 a
tgl a
tgl a
tgl a
cpy 1 a
dec a
dec a