Solve day 7
This commit is contained in:
16
day7/example.txt
Normal file
16
day7/example.txt
Normal file
@@ -0,0 +1,16 @@
|
||||
.......S.......
|
||||
...............
|
||||
.......^.......
|
||||
...............
|
||||
......^.^......
|
||||
...............
|
||||
.....^.^.^.....
|
||||
...............
|
||||
....^.^...^....
|
||||
...............
|
||||
...^.^...^.^...
|
||||
...............
|
||||
..^...^.....^..
|
||||
...............
|
||||
.^.^.^.^.^...^.
|
||||
...............
|
||||
145
day7/main.go
Normal file
145
day7/main.go
Normal file
@@ -0,0 +1,145 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"slices"
|
||||
)
|
||||
|
||||
func main() {
|
||||
debug := flag.Bool("debug", false, "Debug.")
|
||||
flag.Parse()
|
||||
|
||||
f := os.Stdin
|
||||
if flag.NArg() > 0 && flag.Arg(0) != "-" {
|
||||
var err error
|
||||
f, err = os.Open(flag.Arg(0))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer f.Close()
|
||||
}
|
||||
|
||||
diagram, err := readDiagram(f)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
splits := diagram.Propagate()
|
||||
var timelines int
|
||||
for _, row := range slices.Backward(diagram) {
|
||||
for _, c := range row {
|
||||
if c.Marker != BeamMarker {
|
||||
continue
|
||||
}
|
||||
timelines += c.WaysToReach
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
if *debug {
|
||||
for _, row := range diagram {
|
||||
for _, c := range row {
|
||||
if c.Marker == BeamMarker {
|
||||
if c.WaysToReach < 10 {
|
||||
fmt.Print(c.WaysToReach)
|
||||
} else {
|
||||
b := 'A' + c.WaysToReach - 10
|
||||
if b > 'Z' {
|
||||
b = int(c.Marker)
|
||||
}
|
||||
fmt.Printf("%c", b)
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("%c", c.Marker)
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("beam split", splits, "times into", timelines, "timelines")
|
||||
}
|
||||
|
||||
type Marker byte
|
||||
|
||||
const (
|
||||
BeamEmitterMarker Marker = 'S'
|
||||
BeamMarker Marker = '|'
|
||||
SplitterMarker Marker = '^'
|
||||
EmptyMarker Marker = '.'
|
||||
)
|
||||
|
||||
type Cell struct {
|
||||
Marker Marker
|
||||
WaysToReach int
|
||||
}
|
||||
|
||||
type diagram [][]Cell
|
||||
|
||||
func (d diagram) Propagate() (splits int) {
|
||||
splitoff := func(x, y, dx int) {
|
||||
x1 := x + dx
|
||||
if x1 < 0 || x1 >= len(d[y]) {
|
||||
return // out of range
|
||||
}
|
||||
switch d[y][x1].Marker {
|
||||
case EmptyMarker:
|
||||
d[y][x1] = Cell{
|
||||
Marker: BeamMarker,
|
||||
WaysToReach: d[y-1][x].WaysToReach,
|
||||
}
|
||||
case BeamMarker:
|
||||
d[y][x1].WaysToReach += d[y-1][x].WaysToReach
|
||||
}
|
||||
}
|
||||
|
||||
propagateCell := func(x, y int) {
|
||||
switch d[y-1][x].Marker {
|
||||
case BeamEmitterMarker:
|
||||
d[y-1][x].WaysToReach = 1
|
||||
case BeamMarker:
|
||||
default:
|
||||
return
|
||||
}
|
||||
// we have a beam above
|
||||
|
||||
switch d[y][x].Marker {
|
||||
case EmptyMarker:
|
||||
d[y][x] = Cell{
|
||||
Marker: BeamMarker,
|
||||
WaysToReach: d[y-1][x].WaysToReach,
|
||||
}
|
||||
case BeamMarker:
|
||||
d[y][x].WaysToReach += d[y-1][x].WaysToReach
|
||||
case SplitterMarker:
|
||||
splitoff(x, y, -1)
|
||||
splitoff(x, y, +1)
|
||||
splits++
|
||||
}
|
||||
}
|
||||
|
||||
for y := 1; y < len(d); y++ {
|
||||
for x := range d[y] {
|
||||
propagateCell(x, y)
|
||||
}
|
||||
}
|
||||
return splits
|
||||
}
|
||||
|
||||
func readDiagram(r io.Reader) (diagram, error) {
|
||||
var diagram diagram
|
||||
sc := bufio.NewScanner(r)
|
||||
for sc.Scan() {
|
||||
cells := make([]Cell, 0, len(sc.Bytes()))
|
||||
for _, b := range sc.Bytes() {
|
||||
cells = append(cells, Cell{Marker: Marker(b)})
|
||||
}
|
||||
diagram = append(diagram, cells)
|
||||
}
|
||||
return diagram, sc.Err()
|
||||
}
|
||||
Reference in New Issue
Block a user