diff --git a/2017/day08/main.go b/2017/day08/main.go new file mode 100644 index 0000000..124fc54 --- /dev/null +++ b/2017/day08/main.go @@ -0,0 +1,96 @@ +package main + +import ( + "flag" + "fmt" + "math" + "strings" + + "github.com/alexchao26/advent-of-code-go/mathutil" + + "github.com/alexchao26/advent-of-code-go/util" +) + +func main() { + var part int + flag.IntVar(&part, "part", 1, "part 1 or 2") + flag.Parse() + fmt.Println("Running part", part) + + ans := calcRegisters(util.ReadFile("./input.txt"), part) + util.CopyToClipboard(fmt.Sprintf("%v", ans)) + fmt.Println("Output:", ans) +} + +func calcRegisters(input string, part int) int { + instructions := parseInput(input) + + registers := map[string]int{} + var highestEverRegister int // for part 2 + for _, inst := range instructions { + registerVal := registers[inst.conditional[0]] + compareVal := mathutil.StrToInt(inst.conditional[2]) + var conditionalResult bool + switch inst.conditional[1] { + case "==": + conditionalResult = registerVal == compareVal + case "!=": + conditionalResult = registerVal != compareVal + case "<": + conditionalResult = registerVal < compareVal + case ">": + conditionalResult = registerVal > compareVal + case "<=": + conditionalResult = registerVal <= compareVal + case ">=": + conditionalResult = registerVal >= compareVal + default: + panic("unhandled operator") + } + if conditionalResult { + registers[inst.registerName] += inst.diff + } + highestEverRegister = mathutil.MaxInt(highestEverRegister, registers[inst.registerName]) + } + + largestFinalRegister := -math.MaxInt32 + for _, v := range registers { + largestFinalRegister = mathutil.MaxInt(largestFinalRegister, v) + } + + if part == 1 { + return largestFinalRegister + } + return highestEverRegister +} + +type instruction struct { + registerName string // register to modify + diff int // if instruction is a dec, multiply by -1 + conditional [3]string // contains all 3 parts @ end of each instruction +} +type compareFunc func(value int) bool + +func parseInput(input string) []instruction { + lines := strings.Split(input, "\n") + var instructions []instruction + + for _, l := range lines { + parts := strings.Split(l, " ") + if len(parts) != 7 { + panic("parts len to seven") + } + inst := instruction{ + registerName: parts[0], + diff: mathutil.StrToInt(parts[2]), + conditional: [3]string{parts[4], parts[5], parts[6]}, + } + if parts[1] == "dec" { + inst.diff *= -1 + } + + instructions = append(instructions, inst) + } + + return instructions +} diff --git a/2017/day08/main_test.go b/2017/day08/main_test.go new file mode 100644 index 0000000..c057930 --- /dev/null +++ b/2017/day08/main_test.go @@ -0,0 +1,33 @@ +package main + +import ( + "testing" + + "github.com/alexchao26/advent-of-code-go/util" +) + +var example = `b inc 5 if a > 1 +a inc 1 if b < 5 +c dec -10 if a >= 1 +c inc -20 if c == 10` + +func Test_calcRegisters(t *testing.T) { + tests := []struct { + name string + input string + part int + want int + }{ + {"example-part1", example, 1, 1}, + {"actual-part1", util.ReadFile("input.txt"), 1, 4066}, + {"example-part2", example, 2, 10}, + {"actual-part2", util.ReadFile("input.txt"), 2, 4829}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := calcRegisters(tt.input, tt.part); got != tt.want { + t.Errorf("part1() = %v, want %v", got, tt.want) + } + }) + } +}