Skip to content

Commit

Permalink
2023 13-2
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinVlaanderen committed Dec 13, 2023
1 parent e2b0b47 commit 512a804
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 49 deletions.
161 changes: 112 additions & 49 deletions 2023/src/tasks/day13/tasks.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,72 +3,135 @@ package day13
import (
"2023/src/framework"
"github.com/samber/lo"
lop "github.com/samber/lo/parallel"
)

func Task1(data string) (result framework.Result[int]) {
blocks := framework.LineBlocks(data)

horizontalIndices := make([]int, 0)
verticalIndices := make([]int, 0)
lop.ForEach(blocks, func(block []string, index int) {
direction, index := findReflection(block, false)
switch direction {
case Horizontal:
result.Value += index * 100
case Vertical:
result.Value += index
}
})

Block:
for _, block := range blocks {
width, height := len(block[0]), len(block)
return
}

rows := make([][]bool, height)
columns := make([][]bool, width)
func Task2(data string) (result framework.Result[int]) {
blocks := framework.LineBlocks(data)

for y, line := range block {
if rows[y] == nil {
rows[y] = make([]bool, width)
}
for x, char := range line {
if columns[x] == nil {
columns[x] = make([]bool, height)
}
rows[y][x] = char == '#'
columns[x][y] = char == '#'
}
lop.ForEach(blocks, func(block []string, index int) {
direction, index := findReflection(block, true)
switch direction {
case Horizontal:
result.Value += index * 100
case Vertical:
result.Value += index
}
})

rowHashes := lo.Map(rows, func(row []bool, index int) framework.Hash {
return framework.ComputeHash(row)
})
columnHashes := lo.Map(columns, func(column []bool, index int) framework.Hash {
return framework.ComputeHash(column)
})

MidX:
for mid := 0; mid < width-1; mid++ {
checkN := min(mid+1, width-mid-1)
for i := 0; i < checkN; i++ {
if columnHashes[mid-i] != columnHashes[mid+i+1] {
continue MidX
}
return
}

func findReflection(block []string, checkVariants bool) (Direction, int) {
rows, columns := parseBlock(block)

rowHashes := calculateHashes(rows, checkVariants)
columnHashes := calculateHashes(columns, checkVariants)

if found, index := reflectionFound(columnHashes, checkVariants); found {
return Vertical, index
}
if found, index := reflectionFound(rowHashes, checkVariants); found {
return Horizontal, index
}
panic("no reflection found")
}

func parseBlock(block []string) ([][]bool, [][]bool) {
width, height := len(block[0]), len(block)

rows := make([][]bool, height)
columns := make([][]bool, width)

for y, line := range block {
if rows[y] == nil {
rows[y] = make([]bool, width)
}
for x, char := range line {
if columns[x] == nil {
columns[x] = make([]bool, height)
}
verticalIndices = append(verticalIndices, mid+1)
continue Block
rows[y][x] = char == '#'
columns[x][y] = char == '#'
}
}
return rows, columns
}

func calculateHashes(data [][]bool, checkVariants bool) []HashGroup {
return lo.Map(data, func(item []bool, index int) (hashGroup HashGroup) {
hashGroup.original = framework.ComputeHash(item)
if checkVariants {
hashGroup.variants = lo.Map(item, func(_ bool, index int) framework.Hash {
newRow := make([]bool, len(item))
copy(newRow, item)
newRow[index] = !item[index]
return framework.ComputeHash(newRow)
})
}
return
})
}

func reflectionFound(hashes []HashGroup, checkVariants bool) (bool, int) {
size := len(hashes)

for mid := 0; mid < size-1; mid++ {
checkN := min(mid+1, size-mid-1)

MidY:
for mid := 0; mid < height-1; mid++ {
checkN := min(mid+1, height-mid-1)
for i := 0; i < checkN; i++ {
if rowHashes[mid-i] != rowHashes[mid+i+1] {
continue MidY
matchFound := true
variantUsed := false

for offset := 0; offset < checkN; offset++ {
if hashes[mid-offset].original == hashes[mid+offset+1].original {
continue
}
if checkVariants && !variantUsed {
if compareLeftRight(mid-offset, mid+offset+1, hashes) ||
compareLeftRight(mid+offset+1, mid-offset, hashes) {
variantUsed = true
continue
}
}
horizontalIndices = append(horizontalIndices, mid+1)
continue Block
matchFound = false
}
if matchFound && (!checkVariants || variantUsed) {
return true, mid + 1
}
}
return false, 0
}

for _, row := range horizontalIndices {
result.Value += row * 100
}
for _, column := range verticalIndices {
result.Value += column
}
func compareLeftRight(originalIndex, variantIndex int, hashes []HashGroup) bool {
return lo.ContainsBy(hashes[variantIndex].variants, func(variant framework.Hash) bool {
return variant == hashes[originalIndex].original
})
}

return
type HashGroup struct {
original framework.Hash
variants []framework.Hash
}

type Direction uint8

const (
Horizontal Direction = iota
Vertical
)
7 changes: 7 additions & 0 deletions 2023/src/tasks/day13/tasks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ var taskDefinitions = []_testing.TaskDefinition[int]{
{"day13", 30802, _testing.RealData},
},
},
{
Task: Task2,
Tests: []_testing.TestDefinition[int]{
{"data", 400, _testing.TestData},
{"day13", 37876, _testing.RealData},
},
},
}

func TestDay13(t *testing.T) {
Expand Down

0 comments on commit 512a804

Please sign in to comment.