diff --git a/2023/src/framework/data.go b/2023/src/framework/data.go index 5812fa3..6ced4b3 100644 --- a/2023/src/framework/data.go +++ b/2023/src/framework/data.go @@ -1,6 +1,15 @@ package framework -import "strings" +import ( + "github.com/samber/lo" + "strings" +) + +func CharLines(data string) [][]rune { + return lo.Map(strings.Split(data, "\n"), func(item string, index int) []rune { + return []rune(item) + }) +} func Lines(data string) []string { return strings.Split(data, "\n") diff --git a/2023/src/tasks/day14/tasks.go b/2023/src/tasks/day14/tasks.go index c209892..975d9c6 100644 --- a/2023/src/tasks/day14/tasks.go +++ b/2023/src/tasks/day14/tasks.go @@ -2,30 +2,124 @@ package day14 import ( "2023/src/framework" + "github.com/samber/lo" ) func Task1(data string) (result framework.Result[int]) { - lines := framework.Lines(data) + rocks := framework.CharLines(data) - result.Value = calculateLoad(lines) + moveNorth(&rocks) + result.Value = calculateLoad(&rocks) return } -func calculateLoad(lines []string) (result int) { - height := len(lines) - highest := framework.Range(height, len(lines[0]), 0) +func Task2(data string) (result framework.Result[int]) { + rocks := framework.CharLines(data) - for y, line := range lines { - for x, char := range line { - switch char { + lo.RepeatBy(1000, func(index int) bool { + moveNorth(&rocks) + moveWest(&rocks) + moveSouth(&rocks) + moveEast(&rocks) + return true + }) + result.Value = calculateLoad(&rocks) + + return +} + +func calculateLoad(data *[][]rune) (result int) { + height := len(*data) + + for y, line := range *data { + for _, char := range line { + if char == 'O' { + result += height - y + } + } + } + return +} + +func moveNorth(data *[][]rune) { + width := len((*data)[0]) + height := len(*data) + limits := make([]int, width) + + for y := 0; y < height; y++ { + for x := 0; x < width; x++ { + switch (*data)[y][x] { case 'O': - result += highest[x] - highest[x] -= 1 + (*data)[y][x] = '.' + (*data)[limits[x]][x] = 'O' + limits[x] += 1 case '#': - highest[x] = height - y - 1 + limits[x] = y + 1 + } + } + } +} + +func moveWest(data *[][]rune) { + width := len((*data)[0]) + height := len(*data) + limits := make([]int, height) + + for x := 0; x < width; x++ { + for y := 0; y < height; y++ { + switch (*data)[y][x] { + case 'O': + (*data)[y][x] = '.' + (*data)[y][limits[y]] = 'O' + limits[y] += 1 + case '#': + limits[y] = x + 1 + } + } + } +} + +func moveSouth(data *[][]rune) { + width := len((*data)[0]) + height := len(*data) + limits := make([]int, width) + for i := 0; i < width; i++ { + limits[i] = height - 1 + } + + for y := height - 1; y >= 0; y-- { + for x := 0; x < width; x++ { + switch (*data)[y][x] { + case 'O': + (*data)[y][x] = '.' + (*data)[limits[x]][x] = 'O' + limits[x] -= 1 + case '#': + limits[x] = y - 1 + } + } + } +} + +func moveEast(data *[][]rune) { + width := len((*data)[0]) + height := len(*data) + limits := make([]int, height) + for i := 0; i < height; i++ { + limits[i] = width - 1 + } + + for x := width - 1; x >= 0; x-- { + for y := 0; y < height; y++ { + switch (*data)[y][x] { + case 'O': + (*data)[y][x] = '.' + (*data)[y][limits[y]] = 'O' + limits[y] -= 1 + case '#': + limits[y] = x - 1 } } } - return } diff --git a/2023/src/tasks/day14/tasks_test.go b/2023/src/tasks/day14/tasks_test.go index c92892b..a5f85b7 100644 --- a/2023/src/tasks/day14/tasks_test.go +++ b/2023/src/tasks/day14/tasks_test.go @@ -13,6 +13,13 @@ var taskDefinitions = []_testing.TaskDefinition[int]{ {"day14", 113525, _testing.RealData}, }, }, + { + Task: Task2, + Tests: []_testing.TestDefinition[int]{ + {"data", 64, _testing.TestData}, + {"day14", 101292, _testing.RealData}, + }, + }, } func TestDay13(t *testing.T) {