2017-day25: 2017 finished! this one seems worse than it is because of the parsing

This commit is contained in:
alexchao26
2020-12-20 22:07:35 -05:00
parent 8f8ffc86fa
commit fd9a076157
2 changed files with 122 additions and 0 deletions
+74
View File
@@ -0,0 +1,74 @@
package main
import (
"fmt"
"strings"
"github.com/alexchao26/advent-of-code-go/mathutil"
"github.com/alexchao26/advent-of-code-go/util"
)
func main() {
ans := part1(util.ReadFile("./input.txt"))
fmt.Println("Output:", ans)
}
func part1(input string) int {
steps, stateRules := parseInput(input)
// lazy, use a huge array and just start in the middle
bigArray := make([]int, steps)
index := steps / 2
currentStateName := "A"
for i := 0; i < steps; i++ {
currentVal := bigArray[index]
rulesToFollow := stateRules[currentStateName][currentVal]
// write
bigArray[index] = rulesToFollow.valToWrite
if rulesToFollow.direction == "left" {
index--
} else {
index++
}
currentStateName = rulesToFollow.nextState
}
return mathutil.SumIntSlice(bigArray)
}
type ruleset struct {
name string // for debugging only
valToWrite int
direction string
nextState string
}
// assume all programs start in state A for now, one less thing to parse...
func parseInput(input string) (steps int, states map[string][2]ruleset) {
// a manual parse here would be faster...
blocks := strings.Split(input, "\n\n")
fmt.Sscanf(strings.Split(blocks[0], "\n")[1], "Perform a diagnostic checksum after %d steps.", &steps)
states = map[string][2]ruleset{}
for _, block := range blocks[1:] {
lines := strings.Split(block, "\n")
var stateName string
fmt.Sscanf(lines[0], "In state %1s:", &stateName)
rulesIfZero := ruleset{name: stateName}
fmt.Sscanf(strings.Trim(lines[2], " -."), "Write the value %d", &rulesIfZero.valToWrite)
fmt.Sscanf(strings.Trim(lines[3], " -."), "Move one slot to the %s", &rulesIfZero.direction)
fmt.Sscanf(strings.Trim(lines[4], " -."), "Continue with state %1s", &rulesIfZero.nextState)
rulesIfOne := ruleset{name: stateName}
fmt.Sscanf(strings.Trim(lines[6], " -."), "Write the value %d", &rulesIfOne.valToWrite)
fmt.Sscanf(strings.Trim(lines[7], " -."), "Move one slot to the %s", &rulesIfOne.direction)
fmt.Sscanf(strings.Trim(lines[8], " -."), "Continue with state %1s", &rulesIfOne.nextState)
states[stateName] = [2]ruleset{rulesIfZero, rulesIfOne}
}
return steps, states
}
+48
View File
@@ -0,0 +1,48 @@
package main
import (
"testing"
"github.com/alexchao26/advent-of-code-go/util"
)
var example = `Begin in state A.
Perform a diagnostic checksum after 6 steps.
In state A:
If the current value is 0:
- Write the value 1.
- Move one slot to the right.
- Continue with state B.
If the current value is 1:
- Write the value 0.
- Move one slot to the left.
- Continue with state B.
In state B:
If the current value is 0:
- Write the value 1.
- Move one slot to the left.
- Continue with state A.
If the current value is 1:
- Write the value 1.
- Move one slot to the right.
- Continue with state A.`
func Test_part1(t *testing.T) {
tests := []struct {
name string
input string
want int
}{
{"example", example, 3},
{"actual", util.ReadFile("input.txt"), 5744},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := part1(tt.input); got != tt.want {
t.Errorf("part1() = %v, want %v", got, tt.want)
}
})
}
}