diff --git a/03/main.go b/03/main.go index 0d3fbc3..7b081ac 100644 --- a/03/main.go +++ b/03/main.go @@ -33,18 +33,176 @@ func makeScanner(test bool) *bufio.Scanner { return bufio.NewScanner(reader) } +type schematic map[string]entry + +type entry struct { + num string + symb string +} + +func key(row, col int) string { + return fmt.Sprintf("%d.%d", row, col) +} + +func isSymbol(s schematic, row, col int) bool { + if c, ok := s[key(row, col)]; ok { + return c.symb != "" + } + return false +} + func partOne() { scanner := makeScanner(false) + row := 0 + schematic := schematic{} + // read the whole thing in for scanner.Scan() { - // line := scanner.Text() + line := scanner.Text() + i := struct { + tmp []rune + col int + }{} + for col, c := range line { + switch c { + case '.': + if len(i.tmp) != 0 { + schematic[key(row, i.col)] = entry{num: string(i.tmp)} + i.tmp = []rune{} + } + continue + case '1', '2', '3', '4', '5', '6', '7', '8', '9', '0': + if len(i.tmp) == 0 { + i.tmp = append(i.tmp, c) + i.col = col + } else { + i.tmp = append(i.tmp, c) + } + continue + default: + if len(i.tmp) != 0 { + schematic[key(row, i.col)] = entry{num: string(i.tmp)} + i.tmp = []rune{} + } + schematic[key(row, col)] = entry{symb: string(c)} + continue + } + } + // check if we have a number still to save but ran out of line + if len(i.tmp) != 0 { + schematic[key(row, i.col)] = entry{num: string(i.tmp)} + i.tmp = []rune{} + } + row++ } + sum := 0 + // now, map back over the schematics and find the parts + for row := 0; row <= 139; row++ { + for col := 0; col <= 139; col++ { + if num, ok := schematic[key(row, col)]; ok && num.num != "" { + part := mustAtoi(num.num) + if isSymbol(schematic, row, col-1) { + // look behind + sum += part + } else if isSymbol(schematic, row, col+len(num.num)) { + // look ahead + sum += part + } else { + for i := -1; i < len(num.num)+1; i++ { + // check row above and below + if isSymbol(schematic, row-1, col+i) { + sum += part + break + } else if isSymbol(schematic, row+1, col+i) { + sum += part + break + } + } + } + } + } + } + fmt.Println(sum) } func partTwo() { scanner := makeScanner(false) + row := 0 + schematic := schematic{} + // read the whole thing in for scanner.Scan() { - // line := scanner.Text() + line := scanner.Text() + i := struct { + tmp []rune + col int + }{} + for col, c := range line { + switch c { + case '1', '2', '3', '4', '5', '6', '7', '8', '9', '0': + if len(i.tmp) == 0 { + i.tmp = append(i.tmp, c) + i.col = col + } else { + i.tmp = append(i.tmp, c) + } + continue + default: + if len(i.tmp) != 0 { + schematic[key(row, i.col)] = entry{num: string(i.tmp)} + i.tmp = []rune{} + } + if c == '*' { // no longer care about other symbols + schematic[key(row, col)] = entry{symb: string(c)} + } + continue + } + } + // check if we have a number still to save but ran out of line + if len(i.tmp) != 0 { + schematic[key(row, i.col)] = entry{num: string(i.tmp)} + i.tmp = []rune{} + } + row++ } + gears := map[string][]int{} + // map back over the schematics and find the gears + for row := 0; row <= 139; row++ { + for col := 0; col <= 139; col++ { + if num, ok := schematic[key(row, col)]; ok && num.num != "" { + part := mustAtoi(num.num) + if isSymbol(schematic, row, col-1) { + if schematic[key(row, col-1)].symb == "*" { + gears[key(row, col-1)] = append(gears[key(row, col-1)], part) + } + } else if isSymbol(schematic, row, col+len(num.num)) { + if schematic[key(row, col+len(num.num))].symb == "*" { + gears[key(row, col+len(num.num))] = append(gears[key(row, col+len(num.num))], part) + } + } else { + for i := -1; i < len(num.num)+1; i++ { + // check row above and below + if isSymbol(schematic, row-1, col+i) { + if schematic[key(row-1, col+i)].symb == "*" { + gears[key(row-1, col+i)] = append(gears[key(row-1, col+i)], part) + } + break + } else if isSymbol(schematic, row+1, col+i) { + if schematic[key(row+1, col+i)].symb == "*" { + gears[key(row+1, col+i)] = append(gears[key(row+1, col+i)], part) + } + break + } + } + } + } + } + } + sum := 0 + for _, g := range gears { + if len(g) == 2 { + sum += g[0] * g[1] + } + } + fmt.Println(sum) }