|
@@ -114,6 +114,108 @@ func part1(lines []string) int {
|
|
|
return result
|
|
|
}
|
|
|
|
|
|
+type Point struct {
|
|
|
+ x, y int
|
|
|
+}
|
|
|
+
|
|
|
+func digitsFromLine(line string, start int, end int, y int) []Point {
|
|
|
+ var points []Point
|
|
|
+ reading := false
|
|
|
+ for i := start; i <= end; i++ {
|
|
|
+ if isDigit(line[i]) {
|
|
|
+ if !reading {
|
|
|
+ points = append(points, Point{x: i, y: y})
|
|
|
+ reading = true
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ reading = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return points
|
|
|
+}
|
|
|
+
|
|
|
+func getDigits(lines []string, height int, width int, y int, x int) []Point {
|
|
|
+ var points []Point
|
|
|
+
|
|
|
+ start := x - 1
|
|
|
+ if start < 0 {
|
|
|
+ start = x
|
|
|
+ }
|
|
|
+
|
|
|
+ end := x + 1
|
|
|
+ if end >= width {
|
|
|
+ end = x
|
|
|
+ }
|
|
|
+
|
|
|
+ if y-1 >= 0 {
|
|
|
+ points = append(points, digitsFromLine(lines[y-1], start, end, y-1)...)
|
|
|
+ }
|
|
|
+
|
|
|
+ if y+1 < height {
|
|
|
+ points = append(points, digitsFromLine(lines[y+1], start, end, y+1)...)
|
|
|
+ }
|
|
|
+
|
|
|
+ points = append(points, digitsFromLine(lines[y], start, end, y)...)
|
|
|
+
|
|
|
+ return points
|
|
|
+}
|
|
|
+
|
|
|
+func numberFromPoint(lines []string, width int, point Point) int {
|
|
|
+ start := point.x
|
|
|
+ end := point.x
|
|
|
+ var haveStart, haveEnd bool
|
|
|
+ for {
|
|
|
+ if haveStart && haveEnd {
|
|
|
+ break
|
|
|
+ }
|
|
|
+
|
|
|
+ if !haveStart && start-1 >= 0 && isDigit(lines[point.y][start-1]) {
|
|
|
+ start--
|
|
|
+ } else {
|
|
|
+ haveStart = true
|
|
|
+ }
|
|
|
+
|
|
|
+ if !haveEnd && end+1 < width && isDigit(lines[point.y][end+1]) {
|
|
|
+ end++
|
|
|
+ } else {
|
|
|
+ haveEnd = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ end++
|
|
|
+
|
|
|
+ var d int
|
|
|
+ n, err := fmt.Sscanf(lines[point.y][start:end], "%d", &d)
|
|
|
+ if n != 1 || err != nil {
|
|
|
+ log.Fatalf("Wrong input: %s\n%s", lines[point.y][start:end], err)
|
|
|
+ }
|
|
|
+
|
|
|
+ return d
|
|
|
+}
|
|
|
+
|
|
|
+func part2(lines []string) int {
|
|
|
+ height := len(lines)
|
|
|
+ width := len(lines[0])
|
|
|
+ var result int
|
|
|
+ for i := range lines {
|
|
|
+ for j := range lines[i] {
|
|
|
+ if lines[i][j] == '*' {
|
|
|
+ digits := getDigits(lines, height, width, i, j)
|
|
|
+ if len(digits) == 2 {
|
|
|
+ prod := 1
|
|
|
+ for k := range digits {
|
|
|
+ prod *= numberFromPoint(lines, width, digits[k])
|
|
|
+ }
|
|
|
+
|
|
|
+ result += prod
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return result
|
|
|
+}
|
|
|
+
|
|
|
func main() {
|
|
|
if len(os.Args) < 2 {
|
|
|
log.Fatal("You need to specify a file!")
|
|
@@ -128,4 +230,5 @@ func main() {
|
|
|
|
|
|
lines := readInput(file)
|
|
|
fmt.Println("Part1:", part1(lines))
|
|
|
+ fmt.Println("Part2:", part2(lines))
|
|
|
}
|