diff options
Diffstat (limited to 'day12/main.go')
-rw-r--r-- | day12/main.go | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/day12/main.go b/day12/main.go new file mode 100644 index 0000000..60b0ecd --- /dev/null +++ b/day12/main.go @@ -0,0 +1,181 @@ +package main + +import ( + "bufio" + "fmt" + "os" + "strings" +) + +func main() { + fmt.Println("Part 1") + fmt.Println(part1(readData("example1.txt")), 140) + fmt.Println(part1(readData("example2.txt")), 772) + fmt.Println(part1(readData("example3.txt")), 1930) + fmt.Println(part1(readData("data.txt"))) + fmt.Println() + fmt.Println("Part 2") + fmt.Println(part2(readData("example1.txt")), 80) + fmt.Println(part2(readData("example2.txt")), 436) + fmt.Println(part2(readData("example3.txt")), 1206) + fmt.Println(part2(readData("example4.txt")), 236) + fmt.Println(part2(readData("example5.txt")), 368) + fmt.Println(part2(readData("data.txt"))) +} + +func part2(plots [][]byte) (totalPrice int) { + visited := make([][]int, len(plots)) + for i, line := range plots { + visited[i] = make([]int, len(line)) + } + + nextPlotId := 1 + areas := make([]int, 1) + for y := range len(plots) { + for x := range len(plots[y]) { + if visited[y][x] > 0 { + continue + } + area := visitPlot2(plots, visited, nextPlotId, x, y) + areas = append(areas, area) + nextPlotId += 1 + } + } + + sides := make([]int, len(areas)) + + for y := range len(plots) + 1 { + p0, p1 := 0, 0 + for x := range len(plots[0]) + 1 { + p0Next := getPlotIdOrZero(visited, x, y-1) + p1Next := getPlotIdOrZero(visited, x, y) + scanSides(visited, sides, p0, p1, p0Next, p1Next) + p0, p1 = p0Next, p1Next + } + } + + for x := range len(plots[0]) + 1 { + p0, p1 := 0, 0 + for y := range len(plots) + 1 { + p0Next := getPlotIdOrZero(visited, x-1, y) + p1Next := getPlotIdOrZero(visited, x, y) + scanSides(visited, sides, p0, p1, p0Next, p1Next) + p0, p1 = p0Next, p1Next + } + } + + for i := range areas { + totalPrice += areas[i] * sides[i] + } + + return +} + +func scanSides(visited [][]int, sides []int, p0, p1, p0Next, p1Next int) { + if p0Next != p1Next { + if p0 == p1 { + sides[p0Next] += 1 + sides[p1Next] += 1 + } else { + if p0 != p0Next { + sides[p0Next] += 1 + } + if p1 != p1Next { + sides[p1Next] += 1 + } + } + } +} + +var DIR = [4][2]int{{0, -1}, {-1, 0}, {0, 1}, {1, 0}} + +func visitPlot2(plots [][]byte, visited [][]int, plotId int, x, y int) (area int) { + if visited[y][x] > 0 { + return + } + + visited[y][x] = plotId + area += 1 + + p := plots[y][x] + + for _, dir := range DIR { + other := getPlotOrZero(plots, x+dir[0], y+dir[1]) + if other == p { + area += visitPlot2(plots, visited, plotId, x+dir[0], y+dir[1]) + } + } + + return +} + +func getPlotOrZero(plots [][]byte, x, y int) byte { + if x < 0 || y < 0 || y >= len(plots) || x >= len(plots[y]) { + return 0 + } else { + return plots[y][x] + } +} + +func getPlotIdOrZero(plots [][]int, x, y int) int { + if x < 0 || y < 0 || y >= len(plots) || x >= len(plots[y]) { + return 0 + } else { + return plots[y][x] + } +} + +func part1(plots [][]byte) (totalPrice int) { + visited := make([][]bool, len(plots)) + for i, line := range plots { + visited[i] = make([]bool, len(line)) + } + + for y := range len(plots) { + for x := range len(plots[y]) { + area, perimeter := visitPlot1(plots, visited, x, y) + totalPrice += area * perimeter + } + } + + return +} + +func visitPlot1(plots [][]byte, visited [][]bool, x, y int) (area, perimeter int) { + if visited[y][x] { + return + } + + visited[y][x] = true + area += 1 + + p := plots[y][x] + + for _, dir := range DIR { + other := getPlotOrZero(plots, x+dir[0], y+dir[1]) + + if other == p { + otherArea, otherPerimeter := visitPlot1(plots, visited, x+dir[0], y+dir[1]) + area += otherArea + perimeter += otherPerimeter + } else { + perimeter += 1 + } + } + + return +} + +func readData(fileName string) (plots [][]byte) { + fp, err := os.Open(fileName) + if err != nil { + panic(err) + } + + scanner := bufio.NewScanner(fp) + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + plots = append(plots, []byte(line)) + } + return +} |