package main import ( "bufio" "fmt" "io" "strconv" "strings" ) func isdigit(b byte) bool { return b >= 48 && b <= 57 } type enginepart struct { value int pos int raw string } func engineparts(buf *bufio.Reader) []enginepart { parts := make([]enginepart, 0, 150) outer: for pos := 0; ; pos++ { head, err := buf.ReadByte() if err != nil { return parts } if isdigit(head) { // start recording digits b := make([]byte, 0, 10) b = append(b, head) // continue reading until number is exhausted for { digit, err := buf.ReadByte() if !isdigit(digit) { value, _ := strconv.Atoi(string(b)) for range b { parts = append(parts, enginepart{value: value, pos: pos, raw: string(b)}) } pos += len(b) - 1 if err == io.EOF { return parts } buf.UnreadByte() continue outer } b = append(b, digit) } } else if head != '.' { // head is a symbol parts = append(parts, enginepart{value: -1, pos: pos, raw: string(head)}) } else { // head is a '.' parts = append(parts, enginepart{value: 0, pos: pos, raw: string(head)}) } } } type day03 struct{} func (d day03) solve1(r io.Reader) string { sum := 0 parts := make([][]enginepart, 0, 100) scanner := bufio.NewScanner(r) for scanner.Scan() { line := scanner.Text() buf := bufio.NewReader(strings.NewReader(line)) lineparts := engineparts(buf) parts = append(parts, lineparts) } for row := range parts { for item := range parts[row] { if sym := parts[row][item]; sym.value == -1 { for i := -1; i < 2; i++ { for j := -1; j < 2; { x := row + i y := item + j if x >= 0 && y >= 0 && x < len(parts) && y < len(parts[row]) { part := parts[x][y] if part.value > 0 { sum += part.value j += (part.pos + len(part.raw) - y) } else { j++ } } } } } } } return fmt.Sprintf("%d", sum) } func (d day03) solve2(r io.Reader) string { return "incomplete" }