From 2e3c9db727f654bf623cd8bba7b85fd1fda15a21 Mon Sep 17 00:00:00 2001 From: oabrivard Date: Wed, 13 Dec 2023 20:17:26 +0100 Subject: [PATCH] Completed both parts of Day 13 puzzle with help to debug my code --- day13/day13.go | 527 ++++++++++++++++++ day13/day13_test.go | 294 ++++++++++ day13/input.txt | 1296 +++++++++++++++++++++++++++++++++++++++++++ utils/utils.go | 19 + 4 files changed, 2136 insertions(+) create mode 100644 day13/day13.go create mode 100644 day13/day13_test.go create mode 100644 day13/input.txt diff --git a/day13/day13.go b/day13/day13.go new file mode 100644 index 0000000..59574e1 --- /dev/null +++ b/day13/day13.go @@ -0,0 +1,527 @@ +package day13 + +import ( + "fmt" + + "gitea.paas.celticinfo.fr/oabrivard/aoc2023/utils" +) + +func isMirror(vector []int) bool { + if len(vector) == 0 { + return true + } + + if len(vector) == 1 { + return false + } + + return vector[0] == vector[len(vector)-1] && isMirror(vector[1:len(vector)-1]) +} + +func findMirrorPos(vector []int) int { + + for i := range vector { + if isMirror(vector[i:]) { + return i + (len(vector)-i)/2 + } + } + + for j := len(vector); j > 0; j-- { + if isMirror(vector[:j]) { + return j / 2 + } + } + + return -1 +} + +/* +func findMirror2(vector []int, start int, end int, skipFirst bool) int { + if start > end { + if start < len(vector) && vector[start] == vector[end] { + return end + } else { + return -1 + } + } + + if vector[start] == vector[end] { + result := -1 + for i := start + 1; i < end+1; i++ { + result = findMirror2(vector, i, end-1, skipFirst) + + if result != -1 { + break + } + } + return result + } else { + if skipFirst { + return findMirror2(vector, start+1, end, skipFirst) + } else { + return findMirror2(vector, start, end-1, skipFirst) + } + // skipFirstResult := findMirror(vector, start+1, end) + // if skipFirstResult > 0 { + // return skipFirstResult + // } else { + // skipLastResult := findMirror(vector, start, end+1) + // if skipLastResult > 0 { + // return skipLastResult + // } + // } + } +} +*/ + +func sumPatternLines(lines [][]byte) int { + result := 0 + height := len(lines) + width := len(lines[0]) + + matrix := make([][]byte, height) + vector := make([]int, width) + + for row, line := range lines { + matrix[row] = make([]byte, len(line)) + + for col, r := range line { + matrix[row][col] = r + + if r == '#' { + vector[col] += utils.Pow2(row) + } + } + + } + + /* + colCount := findMirror(vector, 0, width-1, true) + 1 + + if colCount > 0 { + //fmt.Println(vector) + fmt.Println("found vertical at", colCount) + } else { + colCount = findMirror(vector, 0, width-1, false) + 1 + if colCount > 0 { + //fmt.Println(vector) + fmt.Println("found vertical at", colCount) + } + } + */ + + colCount := findMirrorPos(vector) + if colCount > 0 { + result = colCount + + fmt.Println("found vertical at", colCount) + /* + for _, l := range lines { + fmt.Println(string(l)) + } + */ + } + + vector = make([]int, height) + + for col := 0; col < width; col++ { + for row := 0; row < height; row++ { + if matrix[row][col] == '#' { + vector[row] += utils.Pow2(col) + } + } + } + + /* + rowCount := findMirror(vector, 0, height-1, true) + 1 + + if rowCount > 0 { + //fmt.Println(vector) + fmt.Println("found horizontal at", rowCount) + } else { + rowCount = findMirror(vector, 0, height-1, false) + 1 + if rowCount > 0 { + //fmt.Println(vector) + fmt.Println("found horizontal at", rowCount) + } + } + */ + + rowCount := findMirrorPos(vector) + if rowCount > 0 { + result += rowCount * 100 + + fmt.Println("found horizontal at", rowCount) + /* + for _, l := range lines { + fmt.Println(string(l)) + } + */ + } + + return result + +} + +func SumMirrorLines(lines []string) int { + result := 0 + pattern := [][]byte{} + count := 0 + for _, line := range lines { + if line == "" { + fmt.Println("Analyzing pattern", count) + result += sumPatternLines(pattern) + pattern = [][]byte{} + count++ + } else { + pattern = append(pattern, []byte(line)) + } + } + return result +} + +func SumMirrorLinesWithSumdge(lines []string) int { + result := 0 + pattern := [][]byte{} + count := 0 + for _, line := range lines { + if line == "" { + fmt.Println("Analyzing pattern", count) + + sum := 0 + OuterLoop: + for row := range pattern { + for col := range pattern[row] { + saved := pattern[row][col] + + if saved == '.' { + pattern[row][col] = '#' + } else { + pattern[row][col] = '.' + } + + sum = sumPatternLines(pattern) + pattern[row][col] = saved + + if sum > 0 { + break OuterLoop + } + } + } + + result += sum + pattern = [][]byte{} + count++ + } else { + pattern = append(pattern, []byte(line)) + } + } + return result +} + +func findNextReflectionPoint(vector []int, first int, vector2 []int, smudge int) (bool, int) { + width := len(vector) + found := false + start := first + end := 0 + result := -1 + smudgeCount := 0 + for i := first; i < width-1; i++ { + if vector[i] == vector[i+1] { + found = true + result = i + start = i + end = i + 1 + break + } + + if smudgeCount < smudge && (vector2[i]+smudge == vector2[i+1] || vector2[i] == vector2[i+1]+smudge) { + smudgeCount++ + found = true + result = i + start = i + end = i + 1 + break + } + + } + + if !found { + return false, result + } + + for { + if vector[start] != vector[end] { + if smudgeCount >= smudge { + return false, result + } else { + if vector2[start]+smudge == vector2[end] || vector2[start] == vector2[end]+smudge { + smudgeCount++ + } else { + return false, result + } + } + } + if start == 0 { + if smudgeCount < smudge { + return false, result + } else { + return true, result + } + } + if end == width-1 { + if smudgeCount < smudge { + return false, result + } else { + return true, result + } + } + + start-- + end++ + } +} + +func getPatternSum(lines [][]byte, smudge int) (int, int) { + height := len(lines) + width := len(lines[0]) + + matrix := make([][]byte, height) + vector := make([]int, width) + vector2 := make([]int, width) + + for row, line := range lines { + matrix[row] = make([]byte, len(line)) + + for col, r := range line { + matrix[row][col] = r + + if r == '#' { + vector[col] += utils.Pow2(row) + vector2[col] += 1 + } + } + } + + success, colCount := findNextReflectionPoint(vector, 0, vector2, smudge) + colCount++ + for { + if success { + fmt.Println("found vertical at", colCount) + /* + for _, l := range lines { + fmt.Println(string(l)) + } + */ + break + } + + if colCount >= len(vector)-1 || colCount == 0 { + break + } + + success, colCount = findNextReflectionPoint(vector, colCount, vector2, smudge) + colCount++ + } + + vector = make([]int, height) + vector2 = make([]int, height) + + for col := 0; col < width; col++ { + for row := 0; row < height; row++ { + if matrix[row][col] == '#' { + vector[row] += utils.Pow2(col) + vector2[row] += 1 + } + } + } + + success, rowCount := findNextReflectionPoint(vector, 0, vector2, smudge) + rowCount++ + for { + if success { + fmt.Println("found horizontal at", rowCount) + /* + for _, l := range lines { + fmt.Println(string(l)) + } + */ + break + } + + if rowCount >= len(vector)-1 || rowCount == 0 { + break + } + + success, rowCount = findNextReflectionPoint(vector, rowCount, vector2, smudge) + rowCount++ + } + + return rowCount, colCount +} + +func SumMirrorLines2(lines []string, smudge int) int { + result := 0 + pattern := [][]byte{} + count := 0 + for _, line := range lines { + if line == "" { + fmt.Println("Analyzing pattern", count) + rowCount, colCount := getPatternSum(pattern, smudge) + result += rowCount*100 + colCount + pattern = [][]byte{} + count++ + } else { + pattern = append(pattern, []byte(line)) + } + } + return result +} + +func SumMirrorLinesWithSumdge2(lines []string) int { + result := 0 + pattern := [][]byte{} + count := 0 + for _, line := range lines { + if line == "" { + fmt.Println("Analyzing pattern", count) + rowBase, colBase := getPatternSum(pattern, 0) + + sum := 0 + OuterLoop: + for row := range pattern { + for col := range pattern[row] { + saved := pattern[row][col] + + if saved == '.' { + pattern[row][col] = '#' + } else { + pattern[row][col] = '.' + } + + rowCount, colCount := getPatternSum(pattern, 1) + if rowCount != rowBase && colBase != colCount { + for _, l := range pattern { + fmt.Println(string(l)) + } + fmt.Println(row, col) + sum += rowCount*100 + colCount + } + pattern[row][col] = saved + + if sum > 0 { + break OuterLoop + } + } + } + + result += sum + pattern = [][]byte{} + count++ + } else { + pattern = append(pattern, []byte(line)) + } + } + return result +} + +func vectorDiff(v1 []int, v2 []int) int { + sum := 0 + + for i, v := range v1 { + sum += utils.AbsInt(v - v2[i]) + } + + return sum +} + +// Only valid solution for both parts +func findReflectionPoint(matrix [][]int, smudge int) int { + width := len(matrix) + + // trouver la premiere paire de layouts a partir de 'first' + for first := 0; first < width-1; { + smudgeCount := smudge + start := -1 + end := -1 + + for i := first; i < width-1; i++ { + diff := vectorDiff(matrix[i], matrix[i+1]) + + if smudgeCount >= diff { + smudgeCount -= diff + start = i + end = i + 1 + break + } + } + + if start == -1 { + return -1 + } + + result := start + + for { + if start == 0 || end == width-1 { + if smudgeCount == 0 { + return result + } else { + first = result + 1 + break + } + } + + start-- + end++ + + diff := vectorDiff(matrix[start], matrix[end]) + smudgeCount -= diff + + if smudgeCount < 0 { + first = result + 1 + break + } + } + } + + return -1 +} + +// Only valid solution for both parts +func SumMirrorLines3(lines []string, smudge int) int { + result := 0 + matrix := [][]int{} + + count := 0 + for _, line := range lines { + if line == "" { + fmt.Println("Analyzing pattern", count) + + rowCount := findReflectionPoint(matrix, smudge) + 1 + + matrix2 := utils.Transpose[int](matrix) + colCount := findReflectionPoint(matrix2, smudge) + 1 + + fmt.Println("found horizontal at ", rowCount, "and vertical at ", colCount) + + result += rowCount*100 + colCount + matrix = [][]int{} + + count++ + } else { + vector := make([]int, len(line)) + + for j, b := range line { + if b == '.' { + vector[j] = 0 + } else { + vector[j] = 1 + } + } + + matrix = append(matrix, vector) + } + } + return result +} diff --git a/day13/day13_test.go b/day13/day13_test.go new file mode 100644 index 0000000..50f6b1e --- /dev/null +++ b/day13/day13_test.go @@ -0,0 +1,294 @@ +package day13 + +import ( + "testing" + + "gitea.paas.celticinfo.fr/oabrivard/aoc2023/utils" +) + +func TestSumMirrorLines(t *testing.T) { + lines := []string{ + "#.##..##.", + "..#.##.#.", + "##......#", + "##......#", + "..#.##.#.", + "..##..##.", + "#.#.##.#.", + "", + "#...##..#", + "#....#..#", + "..##..###", + "#####.##.", + "#####.##.", + "..##..###", + "#....#..#", + "", + } + + result := SumMirrorLines(lines) + + if result != 405 { + t.Fatalf("expected 405, got %v", result) + } +} + +func TestSumMirrorLinesDebug(t *testing.T) { + lines := []string{ + "#...#..#.", + "#...#..#.", + ".####..#.", + "..#..#..#", + "...#....#", + "##..###..", + "#...####.", + "#...####.", + "##..##...", + "...#....#", + "..#..#..#", + ".####..#.", + "#...#..#.", + "", + } + + result := SumMirrorLines(lines) + + if result != 100 { + t.Fatalf("expected 100, got %v", result) + } +} + +func TestSumMirrorLinesWithInput1(t *testing.T) { + lines := utils.ReadLines("input.txt") + + result := SumMirrorLines(lines) + + if result != 43614 { + t.Fatalf("expected 43614 %v", result) + } +} + +func TestSumMirrorLinesWithSmudge(t *testing.T) { + lines := []string{ + "#.##..##.", + "..#.##.#.", + "##......#", + "##......#", + "..#.##.#.", + "..##..##.", + "#.#.##.#.", + "", + "#...##..#", + "#....#..#", + "..##..###", + "#####.##.", + "#####.##.", + "..##..###", + "#....#..#", + "", + } + + result := SumMirrorLinesWithSumdge(lines) + + if result != 400 { + t.Fatalf("expected 400, got %v", result) + } +} + +func TestSumMirrorLinesWithSmudgeWithInput1(t *testing.T) { + lines := utils.ReadLines("input.txt") + + result := SumMirrorLinesWithSumdge(lines) + + if result != 43614 { + t.Fatalf("expected 43614 %v", result) + } +} + +func TestSumMirrorLines2(t *testing.T) { + lines := []string{ + "#.##..##.", + "..#.##.#.", + "##......#", + "##......#", + "..#.##.#.", + "..##..##.", + "#.#.##.#.", + "", + "#...##..#", + "#....#..#", + "..##..###", + "#####.##.", + "#####.##.", + "..##..###", + "#....#..#", + "", + } + + result := SumMirrorLines2(lines, 0) + + if result != 405 { + t.Fatalf("expected 405, got %v", result) + } +} + +func TestSumMirrorLines2WithInput1(t *testing.T) { + lines := utils.ReadLines("input.txt") + + result := SumMirrorLines2(lines, 0) + + if result != 43614 { + t.Fatalf("expected 43614 %v", result) + } +} + +func TestSumMirrorLines2Debug(t *testing.T) { + lines := []string{ + "...###...##", + "##....#..#.", + "###.#.#....", + "#..###.##.#", + "#..###.##.#", + "###.#......", + "##....#..#.", + "...###...##", + "...###...##", + "##....#..#.", + "###.#......", + "", + } + + result := SumMirrorLines2(lines, 0) + + if result != 800 { + t.Fatalf("expected 800, got %v", result) + } +} + +func TestSumMirrorLines2WithSmudge(t *testing.T) { + lines := []string{ + "#.##..##.", + "..#.##.#.", + "##......#", + "##......#", + "..#.##.#.", + "..##..##.", + "#.#.##.#.", + "", + "#...##..#", + "#....#..#", + "..##..###", + "#####.##.", + "#####.##.", + "..##..###", + "#....#..#", + "", + } + + result := SumMirrorLines2(lines, 1) + + if result != 405 { + t.Fatalf("expected 405, got %v", result) + } +} + +func TestSumMirrorLinesWithSmudge2(t *testing.T) { + lines := []string{ + "#.##..##.", + "..#.##.#.", + "##......#", + "##......#", + "..#.##.#.", + "..##..##.", + "#.#.##.#.", + "", + "#...##..#", + "#....#..#", + "..##..###", + "#####.##.", + "#####.##.", + "..##..###", + "#....#..#", + "", + } + + result := SumMirrorLinesWithSumdge2(lines) + + if result != 400 { + t.Fatalf("expected 400, got %v", result) + } +} + +func TestSumMirrorLines3(t *testing.T) { + lines := []string{ + "#.##..##.", + "..#.##.#.", + "##......#", + "##......#", + "..#.##.#.", + "..##..##.", + "#.#.##.#.", + "", + "#...##..#", + "#....#..#", + "..##..###", + "#####.##.", + "#####.##.", + "..##..###", + "#....#..#", + "", + } + + result := SumMirrorLines3(lines, 0) + + if result != 405 { + t.Fatalf("expected 405, got %v", result) + } +} + +func TestSumMirrorLines3WithInput1(t *testing.T) { + lines := utils.ReadLines("input.txt") + + result := SumMirrorLines3(lines, 0) + + if result != 43614 { + t.Fatalf("expected 43614 %v", result) + } +} + +func TestSumMirrorLines3WithSmudge(t *testing.T) { + lines := []string{ + "#.##..##.", + "..#.##.#.", + "##......#", + "##......#", + "..#.##.#.", + "..##..##.", + "#.#.##.#.", + "", + "#...##..#", + "#....#..#", + "..##..###", + "#####.##.", + "#####.##.", + "..##..###", + "#....#..#", + "", + } + + result := SumMirrorLines3(lines, 1) + + if result != 400 { + t.Fatalf("expected 400, got %v", result) + } +} + +func TestSumMirrorLines3WithSmudgeWithInput1(t *testing.T) { + lines := utils.ReadLines("input.txt") + + result := SumMirrorLines3(lines, 1) + + if result != 36771 { + t.Fatalf("expected 36771 %v", result) + } +} diff --git a/day13/input.txt b/day13/input.txt new file mode 100644 index 0000000..6c1e0cb --- /dev/null +++ b/day13/input.txt @@ -0,0 +1,1296 @@ +...#..##.####.# +##..##.###..### +#.#............ +#...#...#..#.#. +.#..###.#.##.#. +###.###.##..##. +.....##........ +##..#....#..#.. +#....#...#..#.. +#..##.#.#.##.#. +#..##.#.#.##.#. +#....#...#..#.. +##..#....#..#.. +.....##........ +###.###.##..##. + +...#.#.####.#.# +#..#..##.###..# +..#.##..##..##. +##...########.. +.####..####..## +.##............ +#...#.#.##.#.#. +.#..#.#.##.#.#. +.#.##..####..## +##..####..####. +##..####..####. +.#.##..####..## +.#..#.#.##.#.#. +#...#.#.##.#.#. +.##............ + +#...##. +####..# +....##. +..#.##. +#.##..# +.##.... +...#..# +..###.# +#..#### +#...##. +#...##. + +.#.#.######## +..#..####..## +#.#..####..## +.#.#.######## +...##.#.####. +.##.##...##.. +.#####.#....# +....#.#.#..#. +#..##..##..## +#...####....# +###...###..## +#.##....####. +#..#.#....... +##.##..#.##.# +##.###....... + +.#...## +#..#### +.##.... +..#.... +..#.#.. +#.#.#.. +..#.... +.##.... +#..#### +.#...## +#..#.## +#..#... +..#.### +..##### +.###... + +.####.##......# +...##.##..##..# +...##.##..##..# +.####.##......# +#.##.#..#.##.#. +..#####.##.###. +.#...#...#..#.. +#######.######. +.#.#...######## + +..#..#.## +##.#####. +.##.#..## +...#.##.. +..#...##. +....##..# +####.##.. +####.##.. +....##..# +..#...##. +...#.##.. + +#....#.#.#....#.# +#....###.#....#.# +.##.#....#.##.#.. +.###.###.#....#.# +.##.....##....##. +###.#.#..#.##.#.. +##...#.#.######.# +##..##.####..#### +#.#..###..#..#..# +.#####..#.#..#.#. +.#.##.#..#.##.#.. + +.##.##.## +#..####.# +#..####.# +.##.##.## +##.##.### +.##..###. +#..#.#... + +#...#..#. +#...#..#. +.####..#. +..#..#..# +...#....# +##..###.. +#...####. +#...####. +##..##... +...#....# +..#..#..# +.####..#. +#...#..#. + +#.##.#..#.##. +......##..... +..#.#.##.#.#. +###.#....#.## +..#...##...#. +......##..... +###.#....#.## + +...#..#.....##.## +...#........##.## +......###........ +..##....#...##### +##..###.######.#. +#.....#..##.###.# +#.#######.#...##. +#.###..#.##.##.#. +..##..#..##.####. +.#.#..###...##.## +###..##.###..##.# +#.##.##.##..##..# +#.##.##.##..##..# + +#..#....# +#..#....# +#....##.. +.###..#.# +.#.##...# +..#....## +..#....## +.#.##...# +.###..#.. + +...###...## +##....#..#. +###.#.#.... +#..###.##.# +#..###.##.# +###.#...... +##....#..#. +...###...## +...###...## +##....#..#. +###.#...... + +..#.#.###...##... +##.#...##.######. +##.#...##.######. +#.#.#.###...##... +.#...#..##.####.# +.###..#.####..### +#.##.#.#.#.#..#.# + +#..#.#..#...... +.####.....####. +.#.#####....... +#.#.#####.####. +##..#...##.##.# +...####...####. +.####.######### +....#..######## +...#.##...####. +...#.##...####. +....#..######## +.###..######### +...####...####. + +##.###.#. +#.#..#.#. +...#.#.## +...#.#.## +#.#..#.#. +##.###.#. +..#....#. +#..#.#### +..###.#.# +#####..#. +..#.####. +...###.#. +...###.#. +..#.####. +#####..#. +..###.#.# +#....#### + +##..#..#..# +#...#....#. +#.......##. +#.#...##..# +.#..#...##. +.########## +.#....##..# +.##.###.... +#.###..#..# +#.###..#..# +.##.###.... + +#.#.#.#.##.#. +.##.###.##.## +..#...#...##. +##.#....##... +##...###..### +#.##....##... +#.##....##... + +#.####.##..##.. +#.###..##..##.. +#.###..####.### +.#..#.#...###.. +...##..#..##... +##..#.#..#.#.## +.....#.##..#..# +.##....#.####.# +###.##.######## +#.....#..#...## +...##...#####.# +##....#..##.... +##....#..##.... +...##...#####.# +#.....#..#...## + +##..####..####. +##...##...####. +#.##.##.##.##.# +###.####.###### +.####..####..## +.#.#...##.#..#. +#..........##.. +....#..#....... +.##.#..#.##..## +#####..######## +...#....#...... + +###.#.#..#. +#..##.##### +.##.###..## +..#.#.####. +.#.#...##.. +##...###### +.#.....##.. +.#.....##.. +##...###### + +..#....#..... +##########..# +#........#..# +..........##. +#.#....#.#### +#....#...#### +.#.####.#.##. +#.##..##.#### +..........##. + +.#...#..#.. +#..#....#.. +#..#...##.. +##.#..#..## +.###...#### +#.#.#...#.. +.###.#.#... +###.#####.. +#.......... +.#....#.... +.#....#.#.. + +#...##.#...#.## +##...#.###..### +#....##..#.###. +.###..#.##..... +##.#..##.#.#.#. +####.#...#.#... +.#.....#..#...# +.#.....#..#...# +####.#...#.#... +##.#..##.#.#.#. +.###..#.##....# +#....##..#.###. +##...#.###..### +#...##.#...#.## +##..#...#.#.#.# +#...#.##.##.... +#...#.##.##.... + +#.#..####..#.##.# +..###....###....# +.##.#.##.#.##..## +...########...... +.###.####.###..## +.###..##..###..## +###..#..#..###### +...##.##.##...... +.#..##..##..#..#. +##...####...####. +..#.#.##.#.#....# +##..........####. +..#.######.#....# +..#.#.####.#....# +#.#..#..#..#.##.# +####.#..#.####### +.#...####...#..#. + +..#.##.#...#..# +.#..##..#.#..#. +#..####..##.##. +.#.#..#.#.##... +###########.... +#.#....#.#..#.. +.###..###.#...# +##.####.###..#. +.#..##..#...##. +#.######.#.#..# +##..###.####... +#........##.#.# +.########.#.... +.########.#.... +#........##.#.# + +###...##...## +#.#.##..##.#. +#.#.##..##.#. +###...##...## +#....####.... +##.##.##.##.# +.##........## +.#.#.#..#.#.# +##..#....#..# +#..##.##.##.# +.#.###..###.# +.##........## +..#...##...#. + +#..#....#..## +.##.#..#.##.. +...#.##.#.... +##...##...### +.#..#..#..#.. +#..##..##..## +.##......##.. +....####...## +...#.##.#.... +.##..##..##.. +.###.##.###.. +#....##....## +####....##### +#.#.####.#.## +###......#### +....#..#..... +#.#.#..#.#.## + +##.###..#....#..# +..###..#.###..... +##.#####...####.. +#...#.#.###..#.## +#...###.###..#.## +##.#####...####.. +..###..#.###..... +##.###..#....#..# +#.#....##...##### +#.#....##...##### +##.###..#....#..# + +#..#..#..#..#.. +####..######### +.##..#.#......# +#.#..#.#.####.# +..#...######### +#..####..#..#.. +..#..##.##..##. +##...##.#....#. +##.#.##.#....#. + +.#.##.##.#.##.. +###.##.####..#. +.#.#.#..####.## +.#.#.#..####.## +###.##.####..#. +.#.##.##.#.##.. +...##.###.###.# +.##....#.###.## +#..#.#.##.#..#. +.###.######.... +####...##.#.... +####...##.#.#.. +.###.######.... + +..##.#.## +##.#.#.## +###...... +#..#.##.. +.#..##.## +..###.#.. +#....#.## +#..##..## +##.#..#.. +..#.###.. +..#.##... +##.#..#.. +#..##..## +#....#.## +..###.#.. + +..#..#.##.# +.......##.. +####....... +.#...##..## +#.######### +..##.##..## +#.###...... + +....####.#.#.## +.##...##...#.## +####...###.##.. +#..###....#..#. +#..###....#..#. +####...###.#... +.##...##...#.## + +##....#...# +######..##. +##.#####.#. +.......#.#. +..##......# +..#........ +####.##.##. +.....#..### +...#####.## +...###.#.## +.....#..### + +##...#.###. +###.####.#. +###.#.....# +...###.#.#. +...#######. +##.....###. +##..##.#### +..####.#... +#####..#.## +##.....##.# +....##..#.. +###..###.#. +###...##.#. + +#...####.##.### +.#####.#...#### +#.#.#..#.#..##. +#.#.#..#.#..##. +.#####.#...#### +....####.##.### +###..###.###.#. +..##...#.#..#.# +#.#.#...###.### +.###..#...##..# +######.......#. +#...#####..##.# +#...#####..##.# +######.......#. +.###..#...##..# + +###.#.####.#. +.#####.##.##. +#.#..#.###.#. +#..####.#...# +#..####.#...# +#.#..#.###.#. +.#####.##.##. +###.#.####.#. +.##..#.#.#..# +.##..#.#.#..# +###.#.####.## +.#####.##.##. +#.#..#.###.#. + +#.####.####..#.## +.##..##..#.##.#.. +.........######.. +.##..##.#.####.#. +#..##..#.#....#.# +##.##.####....### +.#.##.#.##....##. +..####.....##.... +#.#..#.###.##.### +#......########## +#......#...##...# + +.#..#####.# +.#.#....#.# +......##.## +#.....##.## +.#.#....#.# +###.#...... +###.#...... +.#.#....#.# +#.....##.## +......##.## +.#.#....#.# + +#.##..##.#...##.# +#..#..#..##.##.## +##......##..##..# +#.##..##.#..#.### +#.##..##.#..#.### +##......##..##..# +#..#..#..##.##.## +#.##..##.#....#.# +.###..###..###... +##.####.##..###.# +#.#....#.###.###. +.#......#.#.##... +##..##..##.###.#. + +####...##..#. +##.#..#...... +##.#.####.### +...........#. +.##.##.#####. +..###..#.#... +..#..#.##.... +###..##....## +..##..#.#.### +..#..#.##.#.# +..#..#.##.#.# + +##.###### +..#.#..#. +..#..##.. +.#.#.##.# +##...##.. +..#...... +.##...... + +#..#.#.#.## +....#.#..#. +#..##.#..#. +#..##.#.##. +#..##..###. +#..#..###.. +.##.##..#.# +.##.##.##.# +#..#..###.. + +.#.#..#.... +.#.#..##... +.#.##...#.. +#...#.#..## +#...##.#### +..##....### +#...####.## + +####.####.#.### +####.####.#.### +..#...#####.##. +#.#.#...#..#... +#.###.#.#..#... +.....##.####### +.#..###...###.# +...###.##...#.. +...#.#.##...#.. + +.....#..###..#. +##...#...##.##. +###..#..####... +##..##....##.## +##.#..########. +###...#..#####. +..##.#..#.#.... +##..####...###. +###..#...#....# +####.##.#..##.. +####.####..##.. +###..#...#....# +##..####...###. + +.#.#.##.###.#.. +#..###.....#### +.....##.##..... +#.#..#...##.#.. +#..####...###.. +..######.#.#... +.##.#.#..##.#.. +.#...##.#...### +.#...##.#...### +.##.#.#..##.#.. +..######.#.#... +#..####...###.. +#.##.#...##.#.. + +##..##. +.....## +##..##. +..##... +##..##. +.####.. +......# +##..### +.####.# +#....## +######. +......# +#.##.## +#.##.#. +#.##.#. + +.#.##.#.#.##.## +##....###..##.. +#.#..#.#..####. +.######....##.. +#.####.###.##.. +#.####.###.##.. +.######....##.. +#.#..#.#..####. +##....###..##.. +.#.##.#.#.##.## +........####... +#..##..#....#.# +#......#.##.#.. +##....###.####. +.#.#..#..#.##.. + +#..........#. +.##...##...## +#.#...##...#. +...#.#..#.#.. +...###..###.. +.....#..#.... +..##.#..#.##. +.#..######..# +.#..######..# + +..#..###..... +..##.###..... +.....##.#.##. +.####..#.##.. +.##.#..##...# +#.#.#...#...# +......###.##. +.####..#####. +#..#.##..#.## +#..#.##..#.## +.####..#####. +......###.##. +#.#.#...#...# + +.#.###.## +..#.##### +#.####.## +#.#.#.##. +...#..#.. +#..##..## +##...#.## +.#...##.. +.#..#..## +.#..#..## +.#...##.. +##...#.## +#..##..## + +.#..####...#....# +.......##...##.## +.......##...##.## +.#..####...#....# +.#.###.###..##..# +.##.###.......... +#####.#.#.##.###. +.#.###.#######... +...##..##.#.##..# +.###.#.####.#...# +.###.#.####.#.#.# + +.#..#..#..#..#. +####....####### +#####..######## +...#....#...... +..##.##.##....# +#..#....#..##.. +...######...... +.###....###...# +.#..####..#..#. + +..##......#.# +###.###..#..# +######.#.#..# +######..##.## +#....#..##.#. +.####.#....#. +..##..####..# +##..####.##.. +##..####.##.. + +..#.##..##. +....#....#. +.##..#..#.. +#..#..##..# +.##..####.. +.##..#..#.. +#..###..### +.##.#.##.#. +#..##....## + +##.##.### +#.####.## +...##.... +.##..##.. +...##.... +#.####.## +#..##..## +##....### +#..##..## +...##.... +#.####.## +##....### +.##.###.. +#.####.## +#..##..## +#......## +..#..#... + +.####.###..#. +#....#...#.## +#....###.##.# +......#####.. +......#.###.# +.#..#..#.##.. +..##..##.##.# +......##.#.#. +..#......##.# +######...#### +.........#### +#.##.#.##.#.. +#.##.#.##.#.. +.........#### +######...#### + +..##.###.#. +###.###.##. +.#.##.##... +.#.##.##... +###.###.##. +..##.###.#. +###..##...# +...#.###.#. +#.##.##..#. +..#.....#.. +##.....#### +.#.###..### +####..#..## +####..#..## +.#.###..##. + +##..#..#....# +#.###.#.###.. +#.#..#.#...#. +####.#..###.. +.#..##.#.#..# +.#....####### +..#.####.##.# +..#.####.##.# +.#....####### +.#..##.#.#..# +####.#..###.. +#.#..#.#...#. +#.##..#.###.. +##..#..#....# +##..#..#....# + +##..#.##.## +##.##.#.#.. +#.#.####### +.##....#.#. +#.###..##.# +#.###..##.# +.##....#.#. +#.#.####### +##.##.#.#.. +##..#.##..# +..#..###.#. +#.##.#.#.## +#.##.#.#.## +..#..###.#. +##..#.##..# + +#.#............ +...##.##..##..# +.#..###.##.###. +####.#.#..#.#.# +..#.##......##. +#..#.#......#.# +..##.#......#.# +.#.#....##....# +#####........## +#..#..##..##..# +#..#..##..##..# +#####........## +.#.#....##....# +..##.#......#.# +#..#.#......#.# + +##.##.#.##.#..# +.##.#.#.#.###.# +....#.#......## +....#.#......## +.##.#.#.#.###.# +##.##.#.##.#..# +#..##..#....#.# +.###.#####...#. +.###.#####...#. +...##..#....#.# +##.##.#.##.#..# + +#.##.###. +.##.##... +.##.##... +#.##.###. +....#.### +##..#..## +..##.#.#. +...#.##.# +..####### +..######. +...#.##.# + +.#.#.####.....# +#....#....#.#.# +.#####.#.#..#.# +...#..###...### +..##...#.###### +###.#####..#### +....#....####.# +....#....####.# +###.#####..#### +..##...#.###### +...#..###...### +.#####.#.#..#.# +#....#....#.#.# +.#.#.####.....# +..##....#....## +##..#..#...###. +##..#..#...#.#. + +##.######## +##.######## +####.#..#.# +.#..##.###. +.##.######. +#..#......# +.#####..### +.###......# +.#.#.####.# +.....####.. +.....#..#.. +##..#.##.#. +.#...####.. + +.....###. +...#.##.. +.....###. +.....###. +...#.##.. +.....###. +####..... +#...###.# +#...###.# +####..#.. +.....###. + +##....### +.#....#.. +#..##..#. +##.##.#.# +#.#..#.#. +.##..##.. +#..##..#. +.######.# +##.##.##. +..#..#..# +##....### +##....##. +#.####.#. +#.####.#. +#.####.#. + +.##..#.##.#.. +#.###.#..#.## +......####... +#......##.... +.#.#.#....#.. +..#.#.####.#. +####..####..# +#.#..#....#.. +..#...####... +..#...####... +#.#..#....#.. +####..####..# +..#.#.####.#. + +.##.#..#..##.##.# +.###.#...###.##.# +.###...#.....##.. +.###..##.....##.. +.###.#...###.##.# +.##.#..#..##.##.# +..####....#...... +###...##..#..##.. +#...#...####.##.# +.####.#.###..##.. +##.#####..###..## + +###.#.##..... +.##...##..### +.##...##..### +###.#.##..... +.....###.##.. +##...###.#... +#####.#...... +.##.#..##.##. +.##.#..##.##. +#####.#..#... +##...###.#... +.....###.##.. +###.#.##..... + +...##.##.#. +####..##... +.##.##..#.. +.##...#.#.# +#..#.#...#. +##.#.#.#... +#.......##. +#........#. +##.#.#.#... +####.##...# +#.##.#.##.. +#.##.#.##.. +####.##...# +##.#.#.#... +#........#. +#.......##. +##.#.#.#... + +#.##.#.#.##.#.#.# +.......##..##.... +########.##.##### +.#..#.##....##.#. +.####..##..##..## +#######......#### +......########... +#.##.#.#.##.###.# +........#..#..... +..##..#.#..#.#..# +.####..######..## +#.##.###....###.# +.#..#..........#. +..##...#.##.#...# +......#......#... + +####..#..###### +#.#.#.##.##.##. +...###.#.#..... +...###.#.#..... +#.#.#.#####.##. +####..#..###### +.##.#...##.#.## +..###.####.##.. +#...##...#..#.# +.#.#..#.####### +......##.###..# +####...#.#####. +....###.#..#... +..####.######## +..####.######## + +.#####.#..#.### +..#.....##..... +######.####.### +##.##..####..## +##.##..####..## +######.####.### +..#.....##..... +.#####.#..#.### +.############## +.#..#...##...#. +...###.#.##.### +.##.#.#....#.#. +#####...##...## + +#...#..#### +#.#.#...##. +..##.###..# +#.#..#.#### +##.#.#..##. +##.#.#..##. +#.#..###### +..##.###..# +#.#.#...##. + +######.##.##. +...##.....##. +##....##.##.. +.######.#..#. +#.#..#.#.##.. +.######.#.#.. +#......##.### +###..###..... +###..###..... + +#.######### +####..##..# +.########## +#..###..### +..##..##..# +....##..##. +...#..##..# + +.##.##..# +....#.##. +.##.#.##. +.....#### +#..###..# +....#.##. +.##.#.##. +.#...#..# +.....#..# +####.#..# +.##.##..# +#..#..... +#..##.##. +.##...##. +######..# +####.#### +.##...##. + +#####.##...#. +..#......##.. +.###.#.#.##.. +####...#.##.# +#...#....#... +..###.####### +#.####..###.# +#.####..###.# +..###.####### +#...#....#... +####...#.##.# +.###.#.#.##.. +..#......##.. +#####..#...#. +#####..#...#. + +..#.###.##..# +######.#.#.#. +######.#.#.#. +..#.###.##..# +#...#..###.#. +############. +..##.####...# +#####.###.... +#...#####.... +##..#......#. +##..#......#. +#...#####.... +#####.###.... +..##.####...# +############. +#...#..###.## +..#.###.##..# + +#.#..#### +.##.##### +##.#.#... +##.#.#... +.##.##### +#....#### +##..#.#.. + +#####.#.. +#.#.##### +..##.##.. +.....#.## +..#####.# +..#####.# +.....#.## + +#..##.##. +###.#.### +#..####.# +.##...#.# +....##... +....#.##. +#..##..## +....####. +.##...#.# +.##...#.# +....####. +#..##..## +....#.##. + +##..####..##..##. +.#..#..#...#..#.. +##..##...##.##.## +##..###.#..####.. +.#..#......#..#.. +.......#.##.##.## +.......###......# +#######.###.##.## +#....##.##......# +##..###.#........ +##..###..#.####.# +.#..#.#.#.......# +##..#####..#..#.. +......##.######## +..##....#.######. + +.......#.#.#..#.. +.####.#.##.#..#.. +######.#####.#.## +######.#####.#.## +.####.#.##.#..#.. +.......#.#.#..#.# +##..##..#.#..##.. +#.##.#.#..#..#.## +.#..#.##..###...# + +#.#...... +...##..## +.##.####. +#..#....# +#..#....# +.##.####. +#..##..## + +.#..#.. +#....## +#....## +.#..#.. +..##... +..##..# +#.##.## +#....#. +##..##. +#....#. +##...## + +##.###... +..#.#...# +####.###. +##.#.##.# +..#...#.# +####..#.. +.......## +...#.#... +####.#... +...#.#..# +..#..#... +....#.#.# +..###..## +..##..... +..##..... +..###..#. +....#.#.# + +##.#.#.#.###...#. +.##.#...#.###.#.. +###.######..#.... +###.######..#.... +.##.#...#.###.#.. +##.#.#.#.###...#. +.##.#####.##..#.. +..##..###.#..#.## +###..####.##.#..# +###..####.##.#..# +..##..###.##.#.## + +#....#.## +#....#.#. +.#..#.### +..##..#.# +#....##.# +#.##.#... +#.##.#..# +.......#. +##..####. + +##.#..#.##..... +..........##.#. +.#.#..#.#.##... +###....######## +.########.###.# +.##....##.#.... +#.#....#.#.#.## +#.#....#.#.#.## +.##....##...... + +#.#.#.#..#. +..##....... +....##.##.# +##...###### +#####.####. +###..##..## +.....###### + +.....##...... +##..####.#### +..#..##..#... +..#.####.#... +#..#....#..## +##...##...### +.#..####..#.. +#.#......#.## +.#.#.##.#.#.. +..##....##... +##.##..##.### + +########. +......### +.####.##. +.#..#.##. +....#.### +#######.. +......### +##..##.## +.#..#.#.. +.#..#.#.. +##..##.## + +##.#......#.##. +###........#### +###..#..#..#### +.###..##..###.# +.#.###..###...# +.....####.....# +#.###.##.###.## +#............#. +..###.##.###..# +##.#.#..#.#.### +...#..##..#.... +##.#.####.#.##. +###.#.##.#.###. +....######..... +####......##### +####......##### +....######..... + +.....######..## +######.....##.. +..###.##..####. +.#..###.###..## +#..###..####### +.##..##.#.#..#. +.##.###.#.#..#. + +#..#..# +######. +.....#. +#..#### +.##.... +....### +#..##.# +#..###. +####.#. +.##.#.# +#..#.#. +....### +.###.#. +.##..#. +.##..#. + diff --git a/utils/utils.go b/utils/utils.go index 48e8ad9..5de6443 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -84,6 +84,10 @@ func Int64Pow(x int64, y int64) int64 { return result } +func Pow2(x int) int { + return 1 << x +} + // greatest common divisor (GCD) via Euclidean algorithm func GCD(a, b int) int { for b != 0 { @@ -133,3 +137,18 @@ func SplitNoBlank(s string, sep string) []string { return result } + +func Transpose[T any](slice [][]T) [][]T { + xl := len(slice[0]) + yl := len(slice) + result := make([][]T, xl) + for i := range result { + result[i] = make([]T, yl) + } + for i := 0; i < xl; i++ { + for j := 0; j < yl; j++ { + result[i][j] = slice[j][i] + } + } + return result +}