From e85fc4d48476fe1edae0b99a0e5eab485b99fa3f Mon Sep 17 00:00:00 2001 From: Dmytro Spivakov Date: Thu, 31 Oct 2024 04:57:16 +0200 Subject: [PATCH] Day 14 --- README.md | 2 +- day14/day14.go | 137 ++++++++++++++++++++++++++++++++++++++------ day14/day14_test.go | 19 ++++++ 3 files changed, 138 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index bd35f45..b7d87b9 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ A small practice project created to get familiar with Go syntax. - [x] day 11 - [x] day 12 - [x] day 13 -- [ ] day 14 +- [x] day 14 - [ ] day 15 - [ ] day 16 - [ ] day 17 diff --git a/day14/day14.go b/day14/day14.go index fdca725..d666a93 100644 --- a/day14/day14.go +++ b/day14/day14.go @@ -2,8 +2,10 @@ package day14 import ( "bufio" + "fmt" "log" "os" + "strings" ) func Solution1(filepath string) int { @@ -12,37 +14,134 @@ func Solution1(filepath string) int { log.Fatalf("Failed to open the input file with: %v\n", err.Error()) } - var results []int - // { x: y } - maxAvailablePositon := make(map[int]int) + var m [][]string scanner := bufio.NewScanner(file) - y := 0 for scanner.Scan() { - for x, char := range scanner.Text() { - switch char { - case 'O': - results = append(results, maxAvailablePositon[x]) - maxAvailablePositon[x] = maxAvailablePositon[x] + 1 - case '#': - maxAvailablePositon[x] = y + 1 - } - } + m = append(m, strings.Split(scanner.Text(), "")) + } + if err = scanner.Err(); err != nil { + log.Fatalf("Error during input file read: %v\n", err.Error()) + } + + m = tiltNorth(m) + return calcWeight(m) +} + +func Solution2(filepath string) int { + file, err := os.Open(filepath) + if err != nil { + log.Fatalf("Failed to open the input file with: %v\n", err.Error()) + } - y++ + var m [][]string + scanner := bufio.NewScanner(file) + for scanner.Scan() { + m = append(m, strings.Split(scanner.Text(), "")) } if err = scanner.Err(); err != nil { log.Fatalf("Error during input file read: %v\n", err.Error()) } + return calcFinalWeight(m) +} + +func calcWeight(m [][]string) int { result := 0 - maxY := y - for _, r := range results { - result += maxY - r + for y := len(m) - 1; y >= 0; y-- { + for x := 0; x < len(m[y]); x++ { + if m[y][x] == "O" { + result += len(m) - y + } + } + } return result } -func Solution2(filepath string) int { - return -1 +// idea: +// implement the base 4 direction roll algorithm, +// then add logic to detect number of iterations required for the pattern to repeat (?ignore the initial state where boulders are placed randomly) +// once a repat is detected skip to (1000000000 - current number of cycles) % repeat length +func calcFinalWeight(m [][]string) int { + remaining := 1000000000 + + // { serializedMatrix: loop idx, ... } + loopMap := make(map[string]int) + var loopStart, loopEnd int + + for i := 1; i < 1000; i++ { + for j := 0; j <= 3; j++ { + m = tiltNorth(m) + m = rotateClockwise(m) + } + + remaining-- + currentCycle := fmt.Sprintf("%v", m) + if idx, ok := loopMap[currentCycle]; ok { + loopStart, loopEnd = idx, i + break + } else { + loopMap[currentCycle] = i + } + } + + loopLength := loopEnd - loopStart + remaining = remaining % loopLength + + result := 0 + for remaining > 0 { + for j := 0; j <= 3; j++ { + m = tiltNorth(m) + m = rotateClockwise(m) + } + result = calcWeight(m) + remaining-- + } + + return result +} + +func rotateClockwise(m [][]string) [][]string { + transposed := make([][]string, len(m[0])) + + for x := 0; x < len(m[0]); x++ { + for y := len(m) - 1; y >= 0; y-- { + transposed[x] = append(transposed[x], m[y][x]) + } + } + + return transposed +} + +func tiltNorth(m [][]string) [][]string { + availablePos := make(map[int]int) + + for y := 0; y < len(m); y++ { + for x := 0; x < len(m[y]); x++ { + char := m[y][x] + if char == "#" { + availablePos[x] = y + 1 + continue + } + if char == "O" { + newY := availablePos[x] + if y != newY && newY < len(m) { + m[newY][x] = "O" + m[y][x] = "." + } + availablePos[x] = availablePos[x] + 1 + } + } + } + + return m +} + +func printMatrix(m [][]string) { + fmt.Println("-----MATRIX START-----") + for _, row := range m { + fmt.Println(row) + } + fmt.Println("------MATRIX END------") } diff --git a/day14/day14_test.go b/day14/day14_test.go index 02a30d3..04d643f 100644 --- a/day14/day14_test.go +++ b/day14/day14_test.go @@ -20,3 +20,22 @@ func TestSolution1(t *testing.T) { } } } + +func TestSolution2(t *testing.T) { + cases := map[string]int{ + "test_input11": 64, + } + + for input, expectedResult := range cases { + result := Solution2(input) + + if result == expectedResult { + fmt.Printf("Solution2()=%d, OK\n", result) + } else { + t.Fatalf("Solution2()=%d, expecting %d, FAIL\n", result, expectedResult) + } + } +} + +func TestTranspose(t *testing.T) { +}