day13, example
This commit is contained in:
parent
4d346a23db
commit
adcb2417ff
|
@ -0,0 +1,205 @@
|
||||||
|
package day13
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Run() int {
|
||||||
|
filename := "day13/example"
|
||||||
|
fmt.Println("hello day 13.", filename)
|
||||||
|
bytes, err := os.ReadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("error reading file %s", filename))
|
||||||
|
}
|
||||||
|
allText := string(bytes)
|
||||||
|
fieldTexts := strings.Split(allText, "\n\n")
|
||||||
|
|
||||||
|
result := 0
|
||||||
|
for _, fieldText := range fieldTexts {
|
||||||
|
field := ReadField(fieldText)
|
||||||
|
result += Calc(field)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func Calc(field Field) int {
|
||||||
|
verticals, horizontals := field.initMirrors()
|
||||||
|
fmt.Println(field.String())
|
||||||
|
fmt.Printf("field width %d and height %d\n", len(field.Symbols[0]), len(field.Symbols))
|
||||||
|
|
||||||
|
for rowNum, row := range field.Symbols {
|
||||||
|
for colNum, symb := range row {
|
||||||
|
for _, horizontalMirrorUnderCheck := range horizontals {
|
||||||
|
mirroredRow, shouldCheck := horizontalMirrorUnderCheck.reflectCoord(rowNum)
|
||||||
|
if shouldCheck {
|
||||||
|
// log.Printf("checking horizontal mirror %+v", horizontalMirrorUnderCheck)
|
||||||
|
// log.Printf("in should check for row %d, col %d, mirrored row %d\n", rowNum, colNum, mirroredRow)
|
||||||
|
mirroredSymb := field.Symbols[mirroredRow][colNum]
|
||||||
|
isMirrored := symb == mirroredSymb
|
||||||
|
if !isMirrored {
|
||||||
|
// log.Printf("found not mirrored : %s != %s\n", string(symb), string(mirroredSymb))
|
||||||
|
horizontalMirrorUnderCheck.FailedLineChecks[rowNum] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// whole row got checked.
|
||||||
|
// let's mark successful line check for all that didn't fail this line check
|
||||||
|
for _, horizontalMirror := range horizontals {
|
||||||
|
_, failedCheckReported := horizontalMirror.FailedLineChecks[rowNum]
|
||||||
|
if !failedCheckReported {
|
||||||
|
horizontalMirror.SuccessfulLineChecks[rowNum] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rowsAboveHorizontals := 0
|
||||||
|
for _, mirr := range horizontals {
|
||||||
|
fmt.Println(mirr.String())
|
||||||
|
if mirr.isFullMirror() {
|
||||||
|
rowsAboveHorizontals += (mirr.Smaller + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for colNum, _ := range field.Symbols[0] {
|
||||||
|
for rowNum, row := range field.Symbols {
|
||||||
|
symb := row[colNum]
|
||||||
|
for _, verticalMirrorUnderCheck := range verticals {
|
||||||
|
mirroredCol, shouldCheck := verticalMirrorUnderCheck.reflectCoord(colNum)
|
||||||
|
if shouldCheck {
|
||||||
|
// log.Printf("checking vertical mirror %+v", horizontalMirrorUnderCheck)
|
||||||
|
// log.Printf("in should check for row %d, col %d, mirrored row %d\n", rowNum, colNum, mirroredRow)
|
||||||
|
mirroredSymb := field.Symbols[rowNum][mirroredCol]
|
||||||
|
isMirrored := symb == mirroredSymb
|
||||||
|
if !isMirrored {
|
||||||
|
// log.Printf("found not mirrored : %s != %s\n", string(symb), string(mirroredSymb))
|
||||||
|
verticalMirrorUnderCheck.FailedLineChecks[rowNum] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// whole row got checked.
|
||||||
|
// let's mark successful line check for all that didn't fail this line check
|
||||||
|
for _, verticalMirror := range verticals {
|
||||||
|
_, failedCheckReported := verticalMirror.FailedLineChecks[colNum]
|
||||||
|
if !failedCheckReported {
|
||||||
|
verticalMirror.SuccessfulLineChecks[colNum] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
colsToLeftOfHorizontals := 0
|
||||||
|
for _, mirr := range verticals {
|
||||||
|
fmt.Println(mirr.String())
|
||||||
|
if mirr.isFullMirror() {
|
||||||
|
colsToLeftOfHorizontals += (mirr.Smaller + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result := colsToLeftOfHorizontals + 100*rowsAboveHorizontals
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
type Field struct {
|
||||||
|
Symbols [][]rune
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadField(fieldText string) Field {
|
||||||
|
fieldText = strings.TrimSpace(fieldText)
|
||||||
|
lines := strings.Split(fieldText, "\n")
|
||||||
|
|
||||||
|
symbols := make([][]rune, len(lines))
|
||||||
|
for i, line := range lines {
|
||||||
|
symbols[i] = []rune(line)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Field{
|
||||||
|
Symbols: symbols,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Field) String() string {
|
||||||
|
text := "\n"
|
||||||
|
for _, row := range f.Symbols {
|
||||||
|
text += string(row)
|
||||||
|
text += "\n"
|
||||||
|
}
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Field) initMirrors() (vertical []Mirror, horizontal []Mirror) {
|
||||||
|
height := len(f.Symbols)
|
||||||
|
width := len(f.Symbols[0])
|
||||||
|
amountHorizontal := height - 1
|
||||||
|
amountVertical := width - 1
|
||||||
|
horizontal = make([]Mirror, amountHorizontal)
|
||||||
|
vertical = make([]Mirror, amountVertical)
|
||||||
|
|
||||||
|
for rowNum := 0; rowNum < amountHorizontal; rowNum++ {
|
||||||
|
maxDist := min(rowNum, height - 1 - (rowNum+1))
|
||||||
|
log.Println("maxDist ", maxDist, "for rowNum ", rowNum)
|
||||||
|
horizontal[rowNum] = Mirror{
|
||||||
|
Smaller: rowNum,
|
||||||
|
Bigger: rowNum + 1,
|
||||||
|
SuccessfulLineChecks: make(map[int]any),
|
||||||
|
FailedLineChecks: make(map[int]any),
|
||||||
|
MaxDistToCheck: maxDist,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for colNum := 0; colNum < amountVertical; colNum++ {
|
||||||
|
maxDist := min(colNum, width - 1 - (colNum+1))
|
||||||
|
vertical[colNum] = Mirror{
|
||||||
|
Smaller: colNum,
|
||||||
|
Bigger: colNum + 1,
|
||||||
|
SuccessfulLineChecks: make(map[int]any),
|
||||||
|
FailedLineChecks: make(map[int]any),
|
||||||
|
MaxDistToCheck: min(colNum, maxDist),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type Mirror struct {
|
||||||
|
// located between lines
|
||||||
|
Smaller, Bigger int
|
||||||
|
MaxDistToCheck int // how many steps from mirrow have to be checked to confirm
|
||||||
|
// i.e if mirror between 0 and 1 - only rows 0 & 1 have to be checked, row 2 is 'mirrored' outside of the field and 'ok'
|
||||||
|
// value 0 means one step from 'mirror' so rows 0 and 1
|
||||||
|
SuccessfulLineChecks map[int]any
|
||||||
|
FailedLineChecks map[int]any
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Mirror)isFullMirror() bool {
|
||||||
|
return len(m.FailedLineChecks) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Mirror)String() string {
|
||||||
|
return fmt.Sprintf("Mirror between %d and %d. successful lines: %+v ; failed lines: %+v. Max check dist: %d\n",
|
||||||
|
m.Smaller, m.Bigger, m.SuccessfulLineChecks, m.FailedLineChecks, m.MaxDistToCheck)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Mirror) reflectCoord(coord int) (reflected int, shouldCheck bool) {
|
||||||
|
dist := m.Smaller - coord
|
||||||
|
|
||||||
|
_, distFailed := m.FailedLineChecks[dist]
|
||||||
|
_, distConfirmed := m.SuccessfulLineChecks[dist]
|
||||||
|
if distFailed || distConfirmed {
|
||||||
|
return 0, false // either line already fully confirmed, or failed. no need for additional checks
|
||||||
|
}
|
||||||
|
|
||||||
|
reflected = m.Bigger + dist
|
||||||
|
if dist < 0 {
|
||||||
|
dist = coord - m.Bigger
|
||||||
|
reflected = m.Smaller - dist
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldCheck = dist <= m.MaxDistToCheck
|
||||||
|
|
||||||
|
return reflected, shouldCheck
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
#.##..##.
|
||||||
|
..#.##.#.
|
||||||
|
##......#
|
||||||
|
##......#
|
||||||
|
..#.##.#.
|
||||||
|
..##..##.
|
||||||
|
#.#.##.#.
|
||||||
|
|
||||||
|
#...##..#
|
||||||
|
#....#..#
|
||||||
|
..##..###
|
||||||
|
#####.##.
|
||||||
|
#####.##.
|
||||||
|
..##..###
|
||||||
|
#....#..#
|
|
@ -0,0 +1,7 @@
|
||||||
|
#.##..##.
|
||||||
|
..#.##.#.
|
||||||
|
##......#
|
||||||
|
##......#
|
||||||
|
..#.##.#.
|
||||||
|
..##..##.
|
||||||
|
#.#.##.#.
|
|
@ -0,0 +1,7 @@
|
||||||
|
#...##..#
|
||||||
|
#....#..#
|
||||||
|
..##..###
|
||||||
|
#####.##.
|
||||||
|
#####.##.
|
||||||
|
..##..###
|
||||||
|
#....#..#
|
6
main.go
6
main.go
|
@ -3,12 +3,12 @@ package main
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"sunshine.industries/aoc2023/day12"
|
"sunshine.industries/aoc2023/day13"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
log.Print("> starting run:")
|
log.Print("> starting run:")
|
||||||
|
|
||||||
result := day12.Run()
|
result := day13.Run()
|
||||||
log.Printf("day12 result: %d\n****\n", result)
|
log.Printf("day13 result: %d\n****\n", result)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue