mirror of
https://github.com/Threnklyn/advent-of-code-go.git
synced 2026-06-07 12:45:10 +02:00
2017-day25: 2017 finished! this one seems worse than it is because of the parsing
This commit is contained in:
@@ -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
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user