From 53557adddb4f9a10605251ae2255170dc52c14f1 Mon Sep 17 00:00:00 2001 From: Gareth Date: Fri, 10 Jan 2025 19:59:49 +0000 Subject: [PATCH] Day10 --- 2024/gareth/day10/day10.go | 141 ++++++++++++++++++++++++++++++++ 2024/gareth/day10/day10_test.go | 31 +++++++ 2024/gareth/day10/input.txt | 45 ++++++++++ 2024/gareth/main.go | 8 +- 4 files changed, 221 insertions(+), 4 deletions(-) create mode 100644 2024/gareth/day10/day10.go create mode 100644 2024/gareth/day10/day10_test.go create mode 100644 2024/gareth/day10/input.txt diff --git a/2024/gareth/day10/day10.go b/2024/gareth/day10/day10.go new file mode 100644 index 0000000..ef1dda7 --- /dev/null +++ b/2024/gareth/day10/day10.go @@ -0,0 +1,141 @@ +package day10 + +import ( + "strings" +) + +var directions = [][2]int{ + {-1, 0}, + {1, 0}, + {0, -1}, + {0, 1}, +} + +func Part1(input string) int { + grid := ParseInput(input) + return CalculateTotalTrailheadScore(grid) +} + +func Part2(input string) int { + grid := ParseInput(input) + return CalculateTotalTrailheadRating(grid) +} + +func ParseInput(input string) [][]int { + lines := strings.Split(strings.TrimSpace(input), "\n") + grid := make([][]int, len(lines)) + for i, line := range lines { + grid[i] = make([]int, len(line)) + for j, char := range line { + grid[i][j] = int(char - '0') + } + } + return grid +} + +func IsValidPosition(x, y, rows, cols int) bool { + return x >= 0 && x < rows && y >= 0 && y < cols +} + +func DFS(grid [][]int, x, y, prevHeight int, visited [][]bool, reached9 map[[2]int]bool) { + rows := len(grid) + cols := len(grid[0]) + if !IsValidPosition(x, y, rows, cols) || visited[x][y] || grid[x][y] != prevHeight+1 { + return + } + + if grid[x][y] == 9 { + reached9[[2]int{x, y}] = true + return + } + + visited[x][y] = true + for _, dir := range directions { + nx, ny := x+dir[0], y+dir[1] + DFS(grid, nx, ny, grid[x][y], visited, reached9) + } + visited[x][y] = false +} + +func CalculateTrailheadScore(grid [][]int, x, y int) int { + rows := len(grid) + cols := len(grid[0]) + visited := make([][]bool, rows) + for i := range visited { + visited[i] = make([]bool, cols) + } + + reached9 := make(map[[2]int]bool) + DFS(grid, x, y, -1, visited, reached9) + return len(reached9) +} + +func DFSForRatings(grid [][]int, x, y, prevHeight int, visited [][]bool, trailCache map[[3]int]int) int { + rows := len(grid) + cols := len(grid[0]) + if !IsValidPosition(x, y, rows, cols) || visited[x][y] || grid[x][y] != prevHeight+1 { + return 0 + } + + if grid[x][y] == 9 { + return 1 + } + + cacheKey := [3]int{x, y, grid[x][y]} + if count, exists := trailCache[cacheKey]; exists { + return count + } + + visited[x][y] = true + totalTrails := 0 + for _, dir := range directions { + nx, ny := x+dir[0], y+dir[1] + totalTrails += DFSForRatings(grid, nx, ny, grid[x][y], visited, trailCache) + } + visited[x][y] = false + + trailCache[cacheKey] = totalTrails + return totalTrails +} + +func CalculateTrailheadRating(grid [][]int, x, y int) int { + rows := len(grid) + cols := len(grid[0]) + visited := make([][]bool, rows) + for i := range visited { + visited[i] = make([]bool, cols) + } + + trailCache := make(map[[3]int]int) + return DFSForRatings(grid, x, y, -1, visited, trailCache) +} + +func CalculateTotalTrailheadScore(grid [][]int) int { + rows := len(grid) + cols := len(grid[0]) + totalScore := 0 + for i := 0; i < rows; i++ { + for j := 0; j < cols; j++ { + if grid[i][j] == 0 { + score := CalculateTrailheadScore(grid, i, j) + totalScore += score + } + } + } + return totalScore +} + +func CalculateTotalTrailheadRating(grid [][]int) int { + rows := len(grid) + cols := len(grid[0]) + totalRating := 0 + for i := 0; i < rows; i++ { + for j := 0; j < cols; j++ { + if grid[i][j] == 0 { + rating := CalculateTrailheadRating(grid, i, j) + totalRating += rating + } + } + } + return totalRating +} diff --git a/2024/gareth/day10/day10_test.go b/2024/gareth/day10/day10_test.go new file mode 100644 index 0000000..547889b --- /dev/null +++ b/2024/gareth/day10/day10_test.go @@ -0,0 +1,31 @@ +package day10 + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestPart1(t *testing.T) { + r := Part1(`89010123 +78121874 +87430965 +96549874 +45678903 +32019012 +01329801 +10456732`) + assert.Equal(t, 36, r) +} + +func TestPart2(t *testing.T) { + r := Part2(`89010123 +78121874 +87430965 +96549874 +45678903 +32019012 +01329801 +10456732`) + assert.Equal(t, 81, r) +} diff --git a/2024/gareth/day10/input.txt b/2024/gareth/day10/input.txt new file mode 100644 index 0000000..a6f2793 --- /dev/null +++ b/2024/gareth/day10/input.txt @@ -0,0 +1,45 @@ +987123434330121232101001234730123456781067632 +876076576521010345692340349823212347892398701 +945087689432105676787659856714503210987445610 +332196576587654989801456787609654502376530923 +211543210298923215432321098128778901430121894 +300692340147210106523543210039569876589836765 +456781678236103267015693016543410231276745650 +576890549345234178106782187612320140345654321 +985098432100125089235493498109876056034765012 +834127102345456978340362569018765487123876678 +123236221976347869651251078729034398101985589 +014545340889298958707867897430120987012834432 +105965456770107843216950956541231276543124501 +896872378761016930345441019876501345678023670 +787901069654325321210332398545432330589012981 +107821543213034321089206787638901421432103210 +215430694102123475670115896129876548901210349 +126989780210014984308924925014578037654321458 +037878921001235675217833210123669123109452367 +549865438901045102346542106548754321278501476 +678954987432696201256430087239689870347699985 +230143006501787349961021298101236787656788014 +123272112981010458872787034010345691875107623 +054387623472129867763698125676210010961234510 +565694502561036789854567012980387121250129878 +676783411051045672343218763901296030343278569 +989872123432345891050109654812345145467303450 +012763094321056700891760345765432256958912341 +103450185789763211709851236876301967843211032 +814321276656854345612345654954101878701208983 +923434434565956745678036783063210989870345674 +874532345410345832989123192178981876781456564 +265101654323234901808765013265432185692387565 +103216765432101267814554323476501094501893474 +232109856321011876923601098789678923432102985 +343898707896540945498712367765672310567891078 +456789010987231234321203456894581455454986569 +556776125670102343100157654503490166303890432 +543895434894321765212348983212321876212761201 +432104898765010894301054581200110955211654300 +301256567656987105498765690341034567300563212 +434567430547896234787654785652123498456767843 +321798121032345375696543098743096567877854952 +210899021121036789781232143456787656928923761 +326765430110145678710123232109876543210010890 \ No newline at end of file diff --git a/2024/gareth/main.go b/2024/gareth/main.go index ef55304..256421d 100644 --- a/2024/gareth/main.go +++ b/2024/gareth/main.go @@ -1,7 +1,7 @@ package main import ( - "aoc2024/day19" + "aoc2024/day10" "fmt" "os" "time" @@ -9,9 +9,9 @@ import ( func main() { start := time.Now() - data, _ := os.ReadFile("day19/input.txt") - fmt.Printf("part 1: %d\n", day19.Part1(string(data))) - fmt.Printf("part 2: %d\n", day19.Part2(string(data))) + data, _ := os.ReadFile("day10/input.txt") + fmt.Printf("part 1: %d\n", day10.Part1(string(data))) + fmt.Printf("part 2: %d\n", day10.Part2(string(data))) elapsed := time.Since(start) fmt.Printf("Execution time: %s\n", elapsed) }