adventofcode/2017/day25/day25.go

148 lines
2.9 KiB
Go

package main
import (
"bufio"
"errors"
"fmt"
"log"
"os"
"strconv"
"strings"
)
var currState string
var diagAfterSteps, currStep, currPos int
var allStates map[string]State
var tape map[int]bool
func main() {
inp := StdinToStrings()
tape = make(map[int]bool)
allStates = make(map[string]State)
// Parse 'Begin' line
pts := strings.Split(inp[0], " ")
st := pts[len(pts)-1]
currState = st[:len(st)-1]
pts = strings.Split(inp[1], " ")
// Parse 'Diagnostic' line
diagAfterSteps = Atoi(pts[5])
// Parse all of the 'state' lines
for i := 3; i < len(inp); i += 10 {
if state, err := NewState(inp[i:]); err == nil {
allStates[state.Name] = state
}
}
fmt.Println("Beginning in State", currState)
fmt.Println("Diagnostic After", diagAfterSteps)
for i := 0; i < diagAfterSteps; i++ {
//fmt.Printf("Steps: %d; State %s; Diag: %d; Tape: %s\n", i, currState, RunDiagnostic(), GetTapeString())
currState = allStates[currState].Process()
}
fmt.Println("Diagnostic Checksum:", RunDiagnostic())
}
func GetTapeString() string {
ret := "[ "
min, max := 0, 0
for k := range tape {
if k < min {
min = k
}
if k > max {
max = k
}
}
for i := min; i < max; i++ {
ret += fmt.Sprint("(", i, tape[i], ") ")
}
return ret + "]"
}
func RunDiagnostic() int {
var chk int
for _, v := range tape {
if v {
chk++
}
}
return chk
}
type State struct {
Name string
State1Ins Instruction
State0Ins Instruction
}
// NewState takes a slice of strings and returns a state built from the _next_ description found
func NewState(inp []string) (State, error) {
if len(inp) < 9 {
return State{}, errors.New("Invalid state instructions")
}
ret := State{}
// The first line should have the state name
ln := inp[0]
ret.Name = ln[len(ln)-2 : len(ln)-1]
ret.State0Ins = NewInstruction(inp[2:5])
ret.State1Ins = NewInstruction(inp[6:9])
return ret, nil
}
// Process makes the needed changes to the tape and returns the
// next state
func (s State) Process() string {
ins := s.State0Ins
if tape[currPos] {
ins = s.State1Ins
}
tape[currPos] = ins.WriteValue
currPos += ins.Move
return ins.NextState
}
type Instruction struct {
WriteValue bool
Move int
NextState string
}
func NewInstruction(inp []string) Instruction {
ret := Instruction{}
tmp := strings.Split(strings.TrimSpace(inp[0]), " ")
ret.WriteValue = (tmp[4][len(tmp[4])-2] == '1')
tmp = strings.Split(strings.TrimSpace(inp[1]), " ")
ret.Move = 1
if tmp[6] == "left." {
ret.Move = -1
}
tmp = strings.Split(strings.TrimSpace(inp[2]), " ")
state := tmp[len(tmp)-1]
ret.NextState = state[len(state)-2 : len(state)-1]
return ret
}
func Atoi(i string) int {
var ret int
var err error
if ret, err = strconv.Atoi(i); err != nil {
log.Fatal("Invalid Atoi")
}
return ret
}
func StdinToStrings() []string {
var input []string
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
input = append(input, scanner.Text())
}
return input
}