Day 8
This commit is contained in:
parent
6281ce178c
commit
2e5bda14ab
12 changed files with 1224 additions and 27 deletions
54
.github/README.md
vendored
54
.github/README.md
vendored
|
@ -10,33 +10,33 @@ Go solutions are near direct copies of the Python solutions and may be added a f
|
|||
|
||||
<!-- PARSE START -->
|
||||
|
||||
| Day | | Python | Go |
|
||||
| --------------------------- | ----------------------------- | ------------------------------------- | --------------------------------- |
|
||||
| [1](/01-reportRepair) | ![Completed][check] | [Link](/01-reportRepair/python) | [Link](/01-reportRepair/go) |
|
||||
| [2](/02-passwordPhilosophy) | ![Completed][check] | [Link](/02-passwordPhilosophy/python) | [Link](/02-passwordPhilosophy/go) |
|
||||
| [3](/03-tobogganTrajectory) | ![Completed][check] | [Link](/03-tobogganTrajectory/python) | [Link](/03-tobogganTrajectory/go) |
|
||||
| [4](/04-passportProcessing) | ![Completed][check] | [Link](/04-passportProcessing/python) | [Link](/04-passportProcessing/go) |
|
||||
| [5](/05-binaryBoarding) | ![Completed][check] | [Link](/05-binaryBoarding/python) | [Link](/05-binaryBoarding/go) |
|
||||
| [6](/06-customCustoms) | ![Completed][check] | [Link](/06-customCustoms/python) | [Link](/06-customCustoms/go) |
|
||||
| [7](/07-handyHaversacks) | ![Completed][check] | [Link](/07-handyHaversacks/python) | [Link](/07-handyHaversacks/go) |
|
||||
| 8 | ![Not yet attempted][pending] | | |
|
||||
| 9 | | | |
|
||||
| 10 | | | |
|
||||
| 11 | | | |
|
||||
| 12 | | | |
|
||||
| 13 | | | |
|
||||
| 14 | | | |
|
||||
| 15 | | | |
|
||||
| 16 | | | |
|
||||
| 17 | | | |
|
||||
| 18 | | | |
|
||||
| 19 | | | |
|
||||
| 20 | | | |
|
||||
| 21 | | | |
|
||||
| 22 | | | |
|
||||
| 23 | | | |
|
||||
| 24 | | | |
|
||||
| 25 | | | |
|
||||
| Day | | Python | Go |
|
||||
| --------------------------- | ------------------- | ------------------------------------- | --------------------------------- |
|
||||
| [1](/01-reportRepair) | ![Completed][check] | [Link](/01-reportRepair/python) | [Link](/01-reportRepair/go) |
|
||||
| [2](/02-passwordPhilosophy) | ![Completed][check] | [Link](/02-passwordPhilosophy/python) | [Link](/02-passwordPhilosophy/go) |
|
||||
| [3](/03-tobogganTrajectory) | ![Completed][check] | [Link](/03-tobogganTrajectory/python) | [Link](/03-tobogganTrajectory/go) |
|
||||
| [4](/04-passportProcessing) | ![Completed][check] | [Link](/04-passportProcessing/python) | [Link](/04-passportProcessing/go) |
|
||||
| [5](/05-binaryBoarding) | ![Completed][check] | [Link](/05-binaryBoarding/python) | [Link](/05-binaryBoarding/go) |
|
||||
| [6](/06-customCustoms) | ![Completed][check] | [Link](/06-customCustoms/python) | [Link](/06-customCustoms/go) |
|
||||
| [7](/07-handyHaversacks) | ![Completed][check] | [Link](/07-handyHaversacks/python) | [Link](/07-handyHaversacks/go) |
|
||||
| [8](/08-handheldHalting) | ![Completed][check] | [Link](/08-handheldHalting/python) | [Link](/08-handheldHalting/go) |
|
||||
| 9 | | | |
|
||||
| 10 | | | |
|
||||
| 11 | | | |
|
||||
| 12 | | | |
|
||||
| 13 | | | |
|
||||
| 14 | | | |
|
||||
| 15 | | | |
|
||||
| 16 | | | |
|
||||
| 17 | | | |
|
||||
| 18 | | | |
|
||||
| 19 | | | |
|
||||
| 20 | | | |
|
||||
| 21 | | | |
|
||||
| 22 | | | |
|
||||
| 23 | | | |
|
||||
| 24 | | | |
|
||||
| 25 | | | |
|
||||
|
||||
<!-- PARSE END -->
|
||||
|
||||
|
|
125
08-handheldHalting/README.md
Normal file
125
08-handheldHalting/README.md
Normal file
|
@ -0,0 +1,125 @@
|
|||
# [Day 8: Handheld Halting](https://adventofcode.com/2020/day/8)
|
||||
|
||||
<details><summary>Challenge description</summary>
|
||||
|
||||
*Description (c) [Eric Wastl](https://twitter.com/ericwastl)*
|
||||
|
||||
## Part One
|
||||
|
||||
Your flight to the major airline hub reaches cruising altitude without incident. While you consider checking the in-flight menu for one of those drinks that come with a little umbrella, you are interrupted by the kid sitting next to you.
|
||||
|
||||
Their [handheld game console](https://en.wikipedia.org/wiki/Handheld_game_console) won't turn on! They ask if you can take a look.
|
||||
|
||||
You narrow the problem down to a strange _infinite loop_ in the <span title="A trendy new line of encrypted footwear?">boot code</span> (your puzzle input) of the device. You should be able to fix it, but first you need to be able to run the code in isolation.
|
||||
|
||||
The boot code is represented as a text file with one _instruction_ per line of text. Each instruction consists of an _operation_ (`acc`, `jmp`, or `nop`) and an _argument_ (a signed number like `+4` or `-20`).
|
||||
|
||||
* `acc` increases or decreases a single global value called the _accumulator_ by the value given in the argument. For example, `acc +7` would increase the accumulator by 7\. The accumulator starts at `0`. After an `acc` instruction, the instruction immediately below it is executed next.
|
||||
* `jmp` _jumps_ to a new instruction relative to itself. The next instruction to execute is found using the argument as an _offset_ from the `jmp` instruction; for example, `jmp +2` would skip the next instruction, `jmp +1` would continue to the instruction immediately below it, and `jmp -20` would cause the instruction 20 lines above to be executed next.
|
||||
* `nop` stands for _No OPeration_ - it does nothing. The instruction immediately below it is executed next.
|
||||
|
||||
For example, consider the following program:
|
||||
|
||||
nop +0
|
||||
acc +1
|
||||
jmp +4
|
||||
acc +3
|
||||
jmp -3
|
||||
acc -99
|
||||
acc +1
|
||||
jmp -4
|
||||
acc +6
|
||||
|
||||
These instructions are visited in this order:
|
||||
|
||||
nop +0 | 1
|
||||
acc +1 | 2, 8(!)
|
||||
jmp +4 | 3
|
||||
acc +3 | 6
|
||||
jmp -3 | 7
|
||||
acc -99 |
|
||||
acc +1 | 4
|
||||
jmp -4 | 5
|
||||
acc +6 |
|
||||
|
||||
First, the `nop +0` does nothing. Then, the accumulator is increased from 0 to 1 (`acc +1`) and `jmp +4` sets the next instruction to the other `acc +1` near the bottom. After it increases the accumulator from 1 to 2, `jmp -4` executes, setting the next instruction to the only `acc +3`. It sets the accumulator to 5, and `jmp -3` causes the program to continue back at the first `acc +1`.
|
||||
|
||||
This is an _infinite loop_: with this sequence of jumps, the program will run forever. The moment the program tries to run any instruction a second time, you know it will never terminate.
|
||||
|
||||
Immediately _before_ the program would run an instruction a second time, the value in the accumulator is _`5`_.
|
||||
|
||||
Run your copy of the boot code. Immediately before any instruction is executed a second time, _what value is in the accumulator?_
|
||||
|
||||
Your puzzle answer was `1816`.
|
||||
|
||||
## Part Two
|
||||
|
||||
After some careful analysis, you believe that _exactly one instruction is corrupted_.
|
||||
|
||||
Somewhere in the program, _either_ a `jmp` is supposed to be a `nop`, _or_ a `nop` is supposed to be a `jmp`. (No `acc` instructions were harmed in the corruption of this boot code.)
|
||||
|
||||
The program is supposed to terminate by _attempting to execute an instruction immediately after the last instruction in the file_. By changing exactly one `jmp` or `nop`, you can repair the boot code and make it terminate correctly.
|
||||
|
||||
For example, consider the same program from above:
|
||||
|
||||
nop +0
|
||||
acc +1
|
||||
jmp +4
|
||||
acc +3
|
||||
jmp -3
|
||||
acc -99
|
||||
acc +1
|
||||
jmp -4
|
||||
acc +6
|
||||
|
||||
If you change the first instruction from `nop +0` to `jmp +0`, it would create a single-instruction infinite loop, never leaving that instruction. If you change almost any of the `jmp` instructions, the program will still eventually find another `jmp` instruction and loop forever.
|
||||
|
||||
However, if you change the second-to-last instruction (from `jmp -4` to `nop -4`), the program terminates! The instructions are visited in this order:
|
||||
|
||||
nop +0 | 1
|
||||
acc +1 | 2
|
||||
jmp +4 | 3
|
||||
acc +3 |
|
||||
jmp -3 |
|
||||
acc -99 |
|
||||
acc +1 | 4
|
||||
nop -4 | 5
|
||||
acc +6 | 6
|
||||
|
||||
After the last instruction (`acc +6`), the program terminates by attempting to run the instruction below the last instruction in the file. With this change, after the program terminates, the accumulator contains the value _`8`_ (`acc +1`, `acc +1`, `acc +6`).
|
||||
|
||||
Fix the program so that it terminates normally by changing exactly one `jmp` (to `nop`) or `nop` (to `jmp`). _What is the value of the accumulator after the program terminates?_
|
||||
|
||||
Your puzzle answer was `1149`.
|
||||
|
||||
</details>
|
||||
|
||||
<details><summary>Script output</summary>
|
||||
|
||||
```
|
||||
❯ python .\python\
|
||||
AoC 2020: day 8 - Handheld Halting
|
||||
Python 3.8.5
|
||||
|
||||
Test cases
|
||||
1.1 pass
|
||||
2.1 pass
|
||||
|
||||
Answers
|
||||
Part 1: 1816
|
||||
Part 2: 1149
|
||||
|
||||
❯ go run .\go\
|
||||
AoC 2020: day 8 - Handheld Halting
|
||||
Go go1.15.2
|
||||
|
||||
Test cases
|
||||
1.1 pass
|
||||
2.1 pass
|
||||
|
||||
Answers
|
||||
Part 1: 1816
|
||||
Part 2: 1149
|
||||
```
|
||||
|
||||
</details>
|
30
08-handheldHalting/go/challenge/common.go
Normal file
30
08-handheldHalting/go/challenge/common.go
Normal file
|
@ -0,0 +1,30 @@
|
|||
package challenge
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Instruction struct {
|
||||
Opcode string
|
||||
Operand int
|
||||
}
|
||||
|
||||
func NewInstruction(instr string) Instruction {
|
||||
icp := strings.Split(instr, " ")
|
||||
opc, err := strconv.Atoi(icp[1])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return Instruction{
|
||||
Opcode: icp[0],
|
||||
Operand: opc,
|
||||
}
|
||||
}
|
||||
|
||||
func parse(instr string) (o []Instruction) {
|
||||
for _, v := range strings.Split(strings.TrimSpace(instr), "\n") {
|
||||
o = append(o, NewInstruction(v))
|
||||
}
|
||||
return
|
||||
}
|
44
08-handheldHalting/go/challenge/partOne.go
Normal file
44
08-handheldHalting/go/challenge/partOne.go
Normal file
|
@ -0,0 +1,44 @@
|
|||
package challenge
|
||||
|
||||
func PartOne(instr string) int {
|
||||
instructions := parse(instr)
|
||||
|
||||
var (
|
||||
acc int
|
||||
pc int
|
||||
visited []int
|
||||
)
|
||||
|
||||
for {
|
||||
{
|
||||
var found bool
|
||||
for _, v := range visited {
|
||||
if v == pc {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if found {
|
||||
return acc
|
||||
} else {
|
||||
visited = append(visited, pc)
|
||||
}
|
||||
}
|
||||
|
||||
cir := instructions[pc]
|
||||
|
||||
if cir.Opcode == "jmp" {
|
||||
pc += cir.Operand
|
||||
} else {
|
||||
switch cir.Opcode {
|
||||
case "acc":
|
||||
acc += cir.Operand
|
||||
case "nop":
|
||||
}
|
||||
|
||||
pc += 1
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
82
08-handheldHalting/go/challenge/partTwo.go
Normal file
82
08-handheldHalting/go/challenge/partTwo.go
Normal file
|
@ -0,0 +1,82 @@
|
|||
package challenge
|
||||
|
||||
func execute(instructions []Instruction) (cleanExit bool, acc int) {
|
||||
var (
|
||||
pc int
|
||||
visited []int
|
||||
)
|
||||
|
||||
for {
|
||||
if pc >= len(instructions) {
|
||||
// Clean exit
|
||||
return true, acc
|
||||
}
|
||||
|
||||
{
|
||||
var found bool
|
||||
for _, v := range visited {
|
||||
if v == pc {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if found {
|
||||
return false, acc
|
||||
} else {
|
||||
visited = append(visited, pc)
|
||||
}
|
||||
}
|
||||
|
||||
cir := instructions[pc]
|
||||
|
||||
if cir.Opcode == "jmp" {
|
||||
pc += cir.Operand
|
||||
} else {
|
||||
switch cir.Opcode {
|
||||
case "acc":
|
||||
acc += cir.Operand
|
||||
case "nop":
|
||||
}
|
||||
|
||||
pc += 1
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func PartTwo(instr string) int {
|
||||
masterInstructions := parse(instr)
|
||||
|
||||
var switchSetLocations []int
|
||||
for idx, instruction := range masterInstructions {
|
||||
if instruction.Opcode == "jmp" || instruction.Opcode == "nop" {
|
||||
switchSetLocations = append(switchSetLocations, idx)
|
||||
}
|
||||
}
|
||||
|
||||
for _, slc := range switchSetLocations {
|
||||
// Copy instruction set
|
||||
instructions := make([]Instruction, len(masterInstructions))
|
||||
copy(instructions, masterInstructions)
|
||||
|
||||
// Swap instruction
|
||||
oldval := instructions[slc].Opcode
|
||||
var newval string
|
||||
if oldval == "jmp" {
|
||||
newval = "nop"
|
||||
} else if oldval == "nop" {
|
||||
newval = "jmp"
|
||||
}
|
||||
instructions[slc].Opcode = newval
|
||||
|
||||
// Execute
|
||||
cleanExit, acc := execute(instructions)
|
||||
if cleanExit {
|
||||
return acc
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
100
08-handheldHalting/go/main.go
Normal file
100
08-handheldHalting/go/main.go
Normal file
|
@ -0,0 +1,100 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"adventOfCode/08-handheldHalting/go/challenge"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var infoStruct info
|
||||
{
|
||||
inb, err := ioutil.ReadFile("info.json")
|
||||
if err != nil {
|
||||
fmt.Println("Error: could not open info.json")
|
||||
os.Exit(-1)
|
||||
}
|
||||
err = json.Unmarshal(inb, &infoStruct)
|
||||
if err != nil {
|
||||
fmt.Println("Error: could not parse info.json")
|
||||
os.Exit(-1)
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
year = infoStruct.Year
|
||||
day = infoStruct.Day
|
||||
title = infoStruct.Title
|
||||
)
|
||||
|
||||
fmt.Fprintf(color.Output, "%s: day %s - %s\n", color.YellowString("AoC "+year), color.BlueString(day), title)
|
||||
fmt.Fprintf(color.Output, "Go %s\n\n", color.BlueString(runtime.Version()))
|
||||
|
||||
var challengeInput string
|
||||
{
|
||||
inb, err := ioutil.ReadFile("input.txt")
|
||||
if err != nil {
|
||||
fmt.Println("Error: could not open input.txt")
|
||||
os.Exit(-1)
|
||||
}
|
||||
challengeInput = string(inb)
|
||||
}
|
||||
|
||||
runTests(infoStruct)
|
||||
|
||||
fmt.Println("Answers")
|
||||
fmt.Fprintf(color.Output, "Part %s: %s\n", color.BlueString("1"), color.BlueString(strconv.Itoa(challenge.PartOne(challengeInput))))
|
||||
fmt.Fprintf(color.Output, "Part %s: %s\n", color.BlueString("2"), color.BlueString(strconv.Itoa(challenge.PartTwo(challengeInput))))
|
||||
|
||||
}
|
||||
|
||||
type tc struct {
|
||||
Input string `json:"input"`
|
||||
Expected int `json:"expected"`
|
||||
}
|
||||
|
||||
type info struct {
|
||||
Year string `json:"year"`
|
||||
Day string `json:"day"`
|
||||
Title string `json:"title"`
|
||||
TestCases struct {
|
||||
One []tc `json:"one"`
|
||||
Two []tc `json:"two"`
|
||||
} `json:"testCases"`
|
||||
}
|
||||
|
||||
func runTests(infoStruct info) {
|
||||
|
||||
if len(infoStruct.TestCases.One) == 0 && len(infoStruct.TestCases.Two) == 0 {
|
||||
fmt.Println("Info: no test cases specified. Skipping tests")
|
||||
fmt.Println()
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("Test cases")
|
||||
|
||||
rt := func(tcs []tc, f func(string) int, n string) {
|
||||
for i, tc := range tcs {
|
||||
fmt.Fprintf(color.Output, "%s ", color.BlueString(n+"."+strconv.Itoa(i+1)))
|
||||
result := f(tc.Input)
|
||||
if result == tc.Expected {
|
||||
fmt.Fprintf(color.Output, "%s", color.GreenString("pass"))
|
||||
} else {
|
||||
fmt.Fprintf(color.Output, "%s (got %s, expected %s)", color.RedString("fail"), color.BlueString(strconv.Itoa(result)), color.BlueString(strconv.Itoa(tc.Expected)))
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
rt(infoStruct.TestCases.One, challenge.PartOne, "1")
|
||||
rt(infoStruct.TestCases.Two, challenge.PartTwo, "2")
|
||||
|
||||
fmt.Println()
|
||||
|
||||
}
|
19
08-handheldHalting/info.json
Normal file
19
08-handheldHalting/info.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"year": "2020",
|
||||
"day": "8",
|
||||
"title": "Handheld Halting",
|
||||
"testCases": {
|
||||
"one": [
|
||||
{
|
||||
"input": "nop +0\nacc +1\njmp +4\nacc +3\njmp -3\nacc -99\nacc +1\njmp -4\nacc +6",
|
||||
"expected": 5
|
||||
}
|
||||
],
|
||||
"two": [
|
||||
{
|
||||
"input": "nop +0\nacc +1\njmp +4\nacc +3\njmp -3\nacc -99\nacc +1\njmp -4\nacc +6",
|
||||
"expected": 8
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
626
08-handheldHalting/input.txt
Normal file
626
08-handheldHalting/input.txt
Normal file
|
@ -0,0 +1,626 @@
|
|||
jmp +149
|
||||
acc -11
|
||||
nop +95
|
||||
acc -6
|
||||
jmp +196
|
||||
acc +2
|
||||
acc -6
|
||||
acc +38
|
||||
acc +18
|
||||
jmp +246
|
||||
acc +43
|
||||
acc +37
|
||||
acc -1
|
||||
jmp +390
|
||||
acc +32
|
||||
acc -15
|
||||
jmp +487
|
||||
jmp +382
|
||||
jmp +71
|
||||
jmp +331
|
||||
acc -3
|
||||
acc -12
|
||||
acc +4
|
||||
jmp +417
|
||||
acc +30
|
||||
acc +20
|
||||
jmp +410
|
||||
acc +22
|
||||
acc +25
|
||||
acc +19
|
||||
acc +5
|
||||
jmp +405
|
||||
acc +15
|
||||
acc +33
|
||||
acc +7
|
||||
acc -18
|
||||
jmp +463
|
||||
acc +25
|
||||
acc +8
|
||||
acc +1
|
||||
jmp +64
|
||||
jmp +1
|
||||
jmp +562
|
||||
jmp +4
|
||||
acc +21
|
||||
acc +12
|
||||
jmp +467
|
||||
nop +197
|
||||
acc +32
|
||||
jmp +7
|
||||
acc +2
|
||||
jmp +352
|
||||
acc +15
|
||||
jmp +289
|
||||
acc +39
|
||||
jmp +448
|
||||
jmp +227
|
||||
acc +17
|
||||
acc +4
|
||||
jmp +326
|
||||
acc -1
|
||||
nop +167
|
||||
acc +30
|
||||
nop +471
|
||||
jmp +101
|
||||
acc +45
|
||||
nop +276
|
||||
acc +12
|
||||
jmp +215
|
||||
nop +80
|
||||
acc +23
|
||||
acc +31
|
||||
jmp +104
|
||||
acc +39
|
||||
acc +15
|
||||
jmp +40
|
||||
nop +433
|
||||
acc +21
|
||||
acc +22
|
||||
acc +37
|
||||
jmp +421
|
||||
acc +14
|
||||
jmp -30
|
||||
acc +42
|
||||
acc +38
|
||||
jmp +203
|
||||
acc -8
|
||||
acc +27
|
||||
jmp +102
|
||||
acc -5
|
||||
acc +0
|
||||
acc +18
|
||||
acc +26
|
||||
jmp +212
|
||||
acc +25
|
||||
acc +18
|
||||
jmp +209
|
||||
acc +18
|
||||
acc +44
|
||||
acc +47
|
||||
nop -40
|
||||
jmp +372
|
||||
acc +29
|
||||
jmp +384
|
||||
acc +39
|
||||
acc -11
|
||||
acc +43
|
||||
jmp +406
|
||||
acc +2
|
||||
nop +439
|
||||
jmp +343
|
||||
acc +29
|
||||
acc +18
|
||||
jmp +457
|
||||
jmp -31
|
||||
jmp +146
|
||||
acc +12
|
||||
acc +26
|
||||
nop +98
|
||||
jmp +125
|
||||
acc +6
|
||||
acc +35
|
||||
acc +48
|
||||
acc +44
|
||||
jmp +497
|
||||
acc +17
|
||||
acc -8
|
||||
jmp +223
|
||||
acc +47
|
||||
jmp +405
|
||||
jmp +212
|
||||
jmp +317
|
||||
acc -13
|
||||
acc -6
|
||||
jmp +94
|
||||
acc +47
|
||||
acc +50
|
||||
acc -16
|
||||
acc +38
|
||||
jmp +290
|
||||
jmp +383
|
||||
nop -44
|
||||
acc +38
|
||||
nop +418
|
||||
acc +42
|
||||
jmp +233
|
||||
nop -94
|
||||
acc +46
|
||||
jmp +413
|
||||
acc +10
|
||||
acc -6
|
||||
jmp +410
|
||||
acc +30
|
||||
jmp -93
|
||||
acc -13
|
||||
jmp +6
|
||||
acc -16
|
||||
acc +18
|
||||
nop +403
|
||||
acc +0
|
||||
jmp +68
|
||||
acc +45
|
||||
jmp +302
|
||||
acc +5
|
||||
jmp +26
|
||||
acc -5
|
||||
acc +49
|
||||
jmp +412
|
||||
acc +3
|
||||
acc +14
|
||||
jmp +278
|
||||
acc +6
|
||||
acc +4
|
||||
jmp -58
|
||||
acc +14
|
||||
jmp -60
|
||||
acc -12
|
||||
acc +23
|
||||
jmp +225
|
||||
acc +9
|
||||
acc +17
|
||||
acc -10
|
||||
acc -13
|
||||
jmp +216
|
||||
acc -8
|
||||
nop +363
|
||||
jmp +84
|
||||
nop +300
|
||||
acc -15
|
||||
jmp +415
|
||||
acc +17
|
||||
acc -11
|
||||
nop +96
|
||||
jmp +377
|
||||
nop +259
|
||||
acc +4
|
||||
jmp +327
|
||||
acc +0
|
||||
jmp +149
|
||||
jmp +12
|
||||
acc +23
|
||||
acc +43
|
||||
acc +2
|
||||
jmp +1
|
||||
jmp +400
|
||||
acc +24
|
||||
jmp +114
|
||||
acc +3
|
||||
acc -13
|
||||
jmp +149
|
||||
jmp +100
|
||||
jmp +1
|
||||
jmp +157
|
||||
acc +23
|
||||
acc -15
|
||||
jmp -139
|
||||
nop -85
|
||||
jmp +201
|
||||
acc -2
|
||||
acc +39
|
||||
acc +30
|
||||
nop -93
|
||||
jmp -11
|
||||
acc +46
|
||||
jmp +285
|
||||
jmp +1
|
||||
acc +41
|
||||
jmp +115
|
||||
acc +48
|
||||
acc -12
|
||||
acc -17
|
||||
jmp -15
|
||||
nop +82
|
||||
acc +25
|
||||
jmp -151
|
||||
acc +20
|
||||
acc -14
|
||||
acc +9
|
||||
acc -9
|
||||
jmp +284
|
||||
acc +27
|
||||
acc +38
|
||||
acc +50
|
||||
jmp +145
|
||||
nop +279
|
||||
jmp -55
|
||||
nop +245
|
||||
jmp +254
|
||||
acc +4
|
||||
jmp +368
|
||||
nop -119
|
||||
acc -11
|
||||
acc +16
|
||||
acc +19
|
||||
jmp -54
|
||||
nop -186
|
||||
nop -187
|
||||
acc +9
|
||||
acc +44
|
||||
jmp -222
|
||||
jmp +253
|
||||
nop -234
|
||||
acc +33
|
||||
acc +35
|
||||
acc -17
|
||||
jmp +11
|
||||
acc +2
|
||||
acc +41
|
||||
acc +47
|
||||
jmp +310
|
||||
acc +0
|
||||
acc -8
|
||||
acc +1
|
||||
jmp +55
|
||||
acc -1
|
||||
jmp -257
|
||||
acc +7
|
||||
acc +44
|
||||
nop +253
|
||||
acc +41
|
||||
jmp +302
|
||||
acc +16
|
||||
jmp -185
|
||||
jmp +140
|
||||
jmp +1
|
||||
nop +3
|
||||
acc +35
|
||||
jmp -267
|
||||
acc +6
|
||||
jmp -269
|
||||
jmp +211
|
||||
acc +30
|
||||
acc +14
|
||||
acc +16
|
||||
acc +41
|
||||
jmp -47
|
||||
jmp -192
|
||||
nop -21
|
||||
acc -1
|
||||
jmp +192
|
||||
acc -6
|
||||
acc +15
|
||||
acc +3
|
||||
nop -247
|
||||
jmp -88
|
||||
jmp +164
|
||||
acc +47
|
||||
nop +43
|
||||
acc +40
|
||||
jmp +151
|
||||
jmp +85
|
||||
jmp +1
|
||||
acc +40
|
||||
jmp -257
|
||||
acc +13
|
||||
acc +13
|
||||
jmp -256
|
||||
acc +25
|
||||
acc +39
|
||||
jmp +260
|
||||
acc +13
|
||||
acc -18
|
||||
acc -19
|
||||
acc -14
|
||||
jmp -10
|
||||
acc -16
|
||||
acc +9
|
||||
jmp -199
|
||||
nop +185
|
||||
acc +38
|
||||
jmp -261
|
||||
nop +200
|
||||
acc -18
|
||||
nop +115
|
||||
acc +36
|
||||
jmp -259
|
||||
acc +47
|
||||
acc -2
|
||||
acc +9
|
||||
jmp -139
|
||||
nop -117
|
||||
jmp -13
|
||||
jmp +1
|
||||
jmp +247
|
||||
acc +19
|
||||
acc +49
|
||||
jmp +177
|
||||
acc -1
|
||||
jmp +249
|
||||
jmp -218
|
||||
acc +12
|
||||
acc +33
|
||||
jmp +108
|
||||
jmp -48
|
||||
nop -205
|
||||
acc +32
|
||||
jmp -159
|
||||
jmp -129
|
||||
acc +32
|
||||
jmp +1
|
||||
jmp +249
|
||||
nop +75
|
||||
acc +17
|
||||
acc -16
|
||||
jmp +253
|
||||
acc -9
|
||||
jmp -12
|
||||
acc +15
|
||||
jmp -14
|
||||
acc +13
|
||||
acc -8
|
||||
nop -13
|
||||
jmp +27
|
||||
nop -336
|
||||
acc +33
|
||||
acc +10
|
||||
acc -1
|
||||
jmp -350
|
||||
nop -134
|
||||
acc -11
|
||||
jmp +5
|
||||
acc +10
|
||||
acc +13
|
||||
acc +13
|
||||
jmp -249
|
||||
acc +8
|
||||
jmp -215
|
||||
jmp +49
|
||||
acc +35
|
||||
acc +28
|
||||
jmp -54
|
||||
acc +14
|
||||
nop -264
|
||||
jmp +1
|
||||
jmp -166
|
||||
jmp -291
|
||||
acc +9
|
||||
acc +43
|
||||
jmp -301
|
||||
nop +149
|
||||
acc -9
|
||||
jmp -81
|
||||
jmp -287
|
||||
acc +9
|
||||
acc +35
|
||||
acc -12
|
||||
jmp -295
|
||||
acc +46
|
||||
jmp -394
|
||||
acc +29
|
||||
acc +19
|
||||
acc +9
|
||||
jmp -58
|
||||
acc +7
|
||||
acc +32
|
||||
nop -261
|
||||
acc +44
|
||||
jmp -365
|
||||
jmp +1
|
||||
jmp +120
|
||||
acc +37
|
||||
nop -177
|
||||
jmp +101
|
||||
acc +42
|
||||
acc +13
|
||||
acc +36
|
||||
jmp -343
|
||||
acc +45
|
||||
jmp -408
|
||||
acc +23
|
||||
acc +0
|
||||
jmp -66
|
||||
jmp +1
|
||||
acc +34
|
||||
acc +19
|
||||
jmp +104
|
||||
jmp +1
|
||||
acc +36
|
||||
jmp -141
|
||||
jmp -44
|
||||
acc +9
|
||||
acc +30
|
||||
acc +18
|
||||
acc +0
|
||||
jmp -303
|
||||
jmp +1
|
||||
acc +12
|
||||
jmp +66
|
||||
acc +0
|
||||
jmp +82
|
||||
acc +43
|
||||
acc +18
|
||||
jmp +49
|
||||
acc -16
|
||||
acc -3
|
||||
acc +0
|
||||
jmp -249
|
||||
acc -2
|
||||
nop +81
|
||||
jmp +40
|
||||
jmp +94
|
||||
acc -16
|
||||
acc +1
|
||||
jmp -445
|
||||
jmp +1
|
||||
acc +22
|
||||
jmp -130
|
||||
acc +44
|
||||
jmp -73
|
||||
acc +3
|
||||
acc +5
|
||||
jmp -121
|
||||
jmp -352
|
||||
jmp -163
|
||||
acc +15
|
||||
acc +47
|
||||
nop +141
|
||||
jmp +140
|
||||
acc -18
|
||||
nop -289
|
||||
acc +16
|
||||
jmp -476
|
||||
acc -19
|
||||
nop +134
|
||||
acc -10
|
||||
acc +37
|
||||
jmp -13
|
||||
jmp -359
|
||||
acc +32
|
||||
acc +14
|
||||
jmp -306
|
||||
acc +25
|
||||
acc +30
|
||||
jmp -441
|
||||
acc +44
|
||||
acc +14
|
||||
acc +12
|
||||
acc +19
|
||||
jmp -387
|
||||
jmp -12
|
||||
jmp -180
|
||||
jmp -113
|
||||
jmp -29
|
||||
acc +34
|
||||
acc -13
|
||||
acc -12
|
||||
nop +73
|
||||
jmp -263
|
||||
jmp -373
|
||||
jmp -360
|
||||
acc +38
|
||||
nop -123
|
||||
jmp -176
|
||||
nop -155
|
||||
acc -11
|
||||
acc +32
|
||||
nop +54
|
||||
jmp -461
|
||||
acc +31
|
||||
acc +10
|
||||
acc -7
|
||||
acc -19
|
||||
jmp -212
|
||||
acc +41
|
||||
acc +4
|
||||
nop -2
|
||||
jmp -483
|
||||
acc +16
|
||||
acc +42
|
||||
acc -15
|
||||
jmp -286
|
||||
jmp -122
|
||||
acc -4
|
||||
jmp -436
|
||||
acc +27
|
||||
jmp -508
|
||||
acc +38
|
||||
nop -309
|
||||
jmp +10
|
||||
acc +31
|
||||
acc +18
|
||||
acc +5
|
||||
jmp -119
|
||||
acc +8
|
||||
acc -7
|
||||
acc -16
|
||||
acc +18
|
||||
jmp -416
|
||||
acc -15
|
||||
acc +1
|
||||
acc +30
|
||||
acc +8
|
||||
jmp -476
|
||||
jmp -298
|
||||
acc +29
|
||||
acc +24
|
||||
acc -9
|
||||
acc +35
|
||||
jmp -438
|
||||
nop -5
|
||||
jmp -100
|
||||
acc +5
|
||||
acc +3
|
||||
acc +5
|
||||
acc -4
|
||||
jmp +14
|
||||
acc +43
|
||||
acc +3
|
||||
acc +40
|
||||
jmp -517
|
||||
acc +10
|
||||
acc +35
|
||||
acc +38
|
||||
jmp -120
|
||||
acc +1
|
||||
acc -18
|
||||
acc +0
|
||||
acc +42
|
||||
jmp -69
|
||||
jmp -101
|
||||
acc +1
|
||||
jmp -271
|
||||
acc +37
|
||||
acc +17
|
||||
jmp +1
|
||||
jmp -401
|
||||
acc +1
|
||||
acc +3
|
||||
acc -8
|
||||
jmp -392
|
||||
nop -99
|
||||
acc +2
|
||||
jmp -301
|
||||
acc +10
|
||||
acc +32
|
||||
acc +3
|
||||
jmp -286
|
||||
jmp +1
|
||||
jmp -444
|
||||
nop -364
|
||||
acc +46
|
||||
acc +30
|
||||
acc -2
|
||||
jmp -13
|
||||
nop -65
|
||||
acc +22
|
||||
jmp -292
|
||||
acc -13
|
||||
jmp -480
|
||||
acc +4
|
||||
acc -8
|
||||
nop -500
|
||||
jmp -113
|
||||
acc -16
|
||||
acc +40
|
||||
acc -18
|
||||
jmp -125
|
||||
jmp -482
|
||||
acc +28
|
||||
acc -5
|
||||
jmp -471
|
||||
acc +33
|
||||
acc +49
|
||||
acc +21
|
||||
acc +9
|
||||
jmp +1
|
66
08-handheldHalting/python/__main__.py
Normal file
66
08-handheldHalting/python/__main__.py
Normal file
|
@ -0,0 +1,66 @@
|
|||
import json
|
||||
import platform
|
||||
import sys
|
||||
|
||||
from rich import print
|
||||
|
||||
from partOne import partOne
|
||||
from partTwo import partTwo
|
||||
|
||||
|
||||
def run_tests(test_cases):
|
||||
do_tests = True
|
||||
if len(test_cases) == 0:
|
||||
do_tests = False
|
||||
elif len(test_cases["one"]) == 0 and len(test_cases["two"]) == 0:
|
||||
do_tests = False
|
||||
|
||||
if not do_tests:
|
||||
print("Info: no test cases specified. Skipping tests\n")
|
||||
return
|
||||
|
||||
print("Test cases")
|
||||
|
||||
def rt(tcs, f, n):
|
||||
for i, tc in enumerate(tcs):
|
||||
print(f"{n}.{i+1} ", end="")
|
||||
expectedInt = tc["expected"]
|
||||
result = f(str(tc["input"]))
|
||||
if result == expectedInt:
|
||||
print("[green]pass[/green]")
|
||||
else:
|
||||
print(f"[red]fail[/red] (got {result}, expected {expectedInt})")
|
||||
|
||||
rt(test_cases["one"], partOne, 1)
|
||||
rt(test_cases["two"], partTwo, 2)
|
||||
|
||||
print()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
info = open("info.json").read()
|
||||
except FileNotFoundError:
|
||||
print("Error: could not open info.json")
|
||||
sys.exit(-1)
|
||||
|
||||
info = json.loads(info)
|
||||
|
||||
year = info["year"]
|
||||
day = info["day"]
|
||||
title = info["title"]
|
||||
|
||||
print(f"[yellow]AoC {year}[/yellow]: day {day} - {title}")
|
||||
print(f"Python {platform.python_version()}\n")
|
||||
|
||||
try:
|
||||
challenge_input = open("input.txt").read()
|
||||
except FileNotFoundError:
|
||||
print("Error: could not open input.txt")
|
||||
sys.exit(-1)
|
||||
|
||||
run_tests(info["testCases"])
|
||||
|
||||
print("Answers")
|
||||
print("Part 1:", partOne(challenge_input))
|
||||
print("Part 2:", partTwo(challenge_input))
|
14
08-handheldHalting/python/common.py
Normal file
14
08-handheldHalting/python/common.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
from typing import List
|
||||
|
||||
|
||||
class Instruction:
|
||||
opcode: str
|
||||
operand: int
|
||||
|
||||
def __init__(self, instr: str) -> None:
|
||||
self.opcode, t = instr.split(" ")
|
||||
self.operand = int(t)
|
||||
|
||||
|
||||
def parse(instr: str) -> List[Instruction]:
|
||||
return [Instruction(x) for x in instr.strip().split("\n")]
|
28
08-handheldHalting/python/partOne.py
Normal file
28
08-handheldHalting/python/partOne.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
from common import *
|
||||
|
||||
|
||||
def partOne(instr: str) -> int:
|
||||
instructions = parse(instr)
|
||||
|
||||
acc = 0
|
||||
pc = 0
|
||||
|
||||
visited = [] # indexes of visited instructions
|
||||
|
||||
while True:
|
||||
|
||||
if pc in visited:
|
||||
return acc
|
||||
else:
|
||||
visited.append(pc)
|
||||
|
||||
cir = instructions[pc]
|
||||
|
||||
if cir.opcode == "jmp":
|
||||
pc += cir.operand
|
||||
else:
|
||||
if cir.opcode == "acc":
|
||||
acc += cir.operand
|
||||
elif cir.opcode == "nop":
|
||||
pass
|
||||
pc += 1
|
63
08-handheldHalting/python/partTwo.py
Normal file
63
08-handheldHalting/python/partTwo.py
Normal file
|
@ -0,0 +1,63 @@
|
|||
import copy
|
||||
from typing import List, Tuple
|
||||
|
||||
from common import *
|
||||
|
||||
|
||||
def execute(instructions: List[Instruction]) -> Tuple[bool, int]:
|
||||
# Returning false means a loop occured. Returning true means no loop occured.
|
||||
# The value of the accumulator is always returned
|
||||
|
||||
acc = 0
|
||||
pc = 0
|
||||
|
||||
visited = [] # indexes of visited instructions
|
||||
|
||||
while True:
|
||||
|
||||
if pc >= len(instructions):
|
||||
# Clean exit
|
||||
return True, acc
|
||||
|
||||
if pc in visited:
|
||||
# Loop is going to occur at some point
|
||||
return False, acc
|
||||
else:
|
||||
visited.append(pc)
|
||||
|
||||
cir = instructions[pc]
|
||||
|
||||
if cir.opcode == "jmp":
|
||||
pc += cir.operand
|
||||
else:
|
||||
if cir.opcode == "acc":
|
||||
acc += cir.operand
|
||||
elif cir.opcode == "nop":
|
||||
pass
|
||||
pc += 1
|
||||
|
||||
|
||||
def partTwo(instr: str) -> int:
|
||||
master_instructions = parse(instr)
|
||||
|
||||
# I imagine there's probably a smart way to do this... but I'm going to bruteforce it haha
|
||||
|
||||
# Build list of locations of instructions to be switched
|
||||
switch_set_locations = []
|
||||
for idx, instruction in enumerate(master_instructions):
|
||||
if instruction.opcode in ["jmp", "nop"]:
|
||||
switch_set_locations.append(idx)
|
||||
|
||||
for slc in switch_set_locations:
|
||||
instructions = copy.deepcopy(master_instructions)
|
||||
|
||||
# Switch instruction
|
||||
oldval = instructions[slc].opcode
|
||||
instructions[slc].opcode = "jmp" if oldval == "nop" else "nop"
|
||||
|
||||
# Execute
|
||||
clean_exit, acc = execute(instructions)
|
||||
if clean_exit:
|
||||
break
|
||||
|
||||
return acc
|
Loading…
Add table
Add a link
Reference in a new issue