package main import ( "fmt" "regexp" "strings" helpers "git.bullercodeworks.com/brian/adventofcode/helpers" ) func main() { inp := helpers.StdinToString() part1(inp) part2(inp) } func part1(inp string) { mulCmds := regexp.MustCompile(`mul\(\d\d?\d?,\d\d?\d?\)`) cmds := mulCmds.FindAllString(inp, -1) var total int for _, v := range cmds { var num1, num2 int fmt.Sscanf(v, "mul(%d,%d)", &num1, &num2) total = total + (num1 * num2) } fmt.Println("# Part 1") fmt.Printf("Total: %d\n\n", total) } func part2(inp string) { var total int do, run := true, true for run { var cmd Command prev := inp cmd, inp = getNextCommand(inp) if prev == inp { panic("Remainder didn't change") } run = len(inp) > 0 switch cmd.Name { case "mul": if do { total = total + cmd.Run() } case "do": do = true case "don't": do = false } } fmt.Println("# Part 2") fmt.Printf("Total: %d\n", total) } type Command struct { Name string Values []int } func (c *Command) Run() int { if c.Name == "mul" { return c.Values[0] * c.Values[1] } return 0 } func (c Command) String() string { switch c.Name { case "mul": return fmt.Sprintf("%s(%d,%d)", c.Name, c.Values[0], c.Values[1]) default: return fmt.Sprintf("%s()", c.Name) } } func getNextCommand(inp string) (Command, string) { c := Command{ Values: make([]int, 2), } for i := range inp { switch inp[i] { case 'm': if _, err := fmt.Sscanf(inp[i:], "mul(%d,%d)", &c.Values[0], &c.Values[1]); err == nil { c.Name = "mul" return c, inp[i+len(c.String()):] } case 'd': if strings.HasPrefix(inp[i:], "do()") { c.Name = "do" return c, strings.TrimPrefix(inp[i:], "do()") } else if strings.HasPrefix(inp[i:], "don't()") { c.Name = "don't" return c, strings.TrimPrefix(inp[i:], "don't()") } } } return Command{}, "" }