package main import ( "fmt" "os" "strings" ) func main() { content, err := os.ReadFile("data.txt") if err != nil { panic(err) } fmt.Println(part1("xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))")) fmt.Println(part1(string(content))) fmt.Println(part2("xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))")) fmt.Println(part2(string(content))) } func part1(s string) (result int) { for { index := strings.Index(s, "mul(") if index < 0 { return } s = s[index+4:] op1, opLength := parseOperand(&s) if opLength < 1 || opLength > 3 { continue } if !expectChar(&s, ',') { continue } op2, opLength := parseOperand(&s) if opLength < 1 || opLength > 3 { continue } if !expectChar(&s, ')') { continue } result += op1 * op2 } } func part2(s string) (result int) { for { dont_index := strings.Index(s, "don't()") if dont_index < 0 { result += part1(s) return } result += part1(s[:dont_index]) s = s[dont_index+7:] do_index := strings.Index(s, "do()") if do_index < 0 { return } s = s[do_index+4:] } return } func expectChar(s *string, r byte) bool { if len(*s) == 0 || (*s)[0] != r { return false } else { *s = (*s)[1:] return true } } func parseOperand(s *string) (operand int, length int) { for len(*s) > 0 { c := (*s)[0] if c < '0' || c > '9' { return } operand = operand*10 + int(c-'0') *s = (*s)[1:] length++ } return }