day16, example two

This commit is contained in:
efim 2023-12-16 07:33:01 +00:00
parent 8436426d3a
commit ee9c2c1ca0
1 changed files with 67 additions and 19 deletions

View File

@ -3,6 +3,7 @@ package day16
import ( import (
"fmt" "fmt"
"log" "log"
"math"
"os" "os"
"strings" "strings"
"sync" "sync"
@ -11,13 +12,63 @@ import (
func Run() int { func Run() int {
fmt.Println("hello from day 16") fmt.Println("hello from day 16")
log.Println("starting") log.Println("starting")
field := ReadField("day16/input") filename := "day16/example"
fmt.Println(field.String()) field := ReadField(filename)
field.StartTraversal() startPoints := StartPoints(&field)
fmt.Println(field.ShowEnergyzed()) var startPointsWaitGroup sync.WaitGroup
startPointsWaitGroup.Add(len(startPoints))
return field.CountEnergized() results := make(chan int)
go func() {
startPointsWaitGroup.Wait()
close(results)
}()
for _, start := range startPoints {
go func(start MovementPoint) {
cleanField := ReadField(filename)
cleanField.StartTraversal(start)
thisResult := cleanField.CountEnergized()
results <- thisResult
startPointsWaitGroup.Done()
}(start)
}
max := math.MinInt
for energized := range results {
if energized > max {
max = energized
log.Println("found new max: ", max)
}
}
// fmt.Println(field.String())
// field.StartTraversal()
// fmt.Println(field.ShowEnergyzed())
return max
}
func StartPoints(f *Field) []MovementPoint {
result := make([]MovementPoint, 0)
for rowNum, row := range f.cells {
result = append(result,
MovementPoint{Row: rowNum, Col: 0, Direction: Rightward},
MovementPoint{Row: rowNum, Col: len(row) - 1, Direction: Leftward})
}
for colNum, _ := range f.cells[0] {
result = append(result,
MovementPoint{Row: 0, Col: colNum, Direction: Downward},
MovementPoint{Row: len(f.cells) - 1, Col: colNum, Direction: Upward})
}
return result
} }
// have shared field // have shared field
@ -53,7 +104,7 @@ type Field struct {
cells [][]*Cell cells [][]*Cell
} }
func (f *Field)isValid(mp MovementPoint) bool { func (f *Field) isValid(mp MovementPoint) bool {
if mp.Row < 0 || mp.Col < 0 { if mp.Row < 0 || mp.Col < 0 {
return false return false
} }
@ -75,7 +126,7 @@ func ReadField(filename string) Field {
rowCells := make([]*Cell, 0) rowCells := make([]*Cell, 0)
for _, symb := range line { for _, symb := range line {
rowCells = append(rowCells, &Cell{ rowCells = append(rowCells, &Cell{
CellType: CellType(symb), CellType: CellType(symb),
KnownBeams: make(map[Direction]any), KnownBeams: make(map[Direction]any),
}) })
} }
@ -84,7 +135,7 @@ func ReadField(filename string) Field {
return result return result
} }
func (f *Field)String() string { func (f *Field) String() string {
result := "\n" result := "\n"
for _, row := range f.cells { for _, row := range f.cells {
for _, cell := range row { for _, cell := range row {
@ -95,7 +146,7 @@ func (f *Field)String() string {
return result return result
} }
func (f *Field)ShowEnergyzed() string { func (f *Field) ShowEnergyzed() string {
result := "\n" result := "\n"
for _, row := range f.cells { for _, row := range f.cells {
for _, cell := range row { for _, cell := range row {
@ -117,14 +168,11 @@ type MovementPoint struct {
Direction Direction Direction Direction
} }
func (f *Field)StartTraversal() { func (f *Field) StartTraversal(startPoint MovementPoint) {
reportedVisits := make(chan MovementPoint) reportedVisits := make(chan MovementPoint)
var wg sync.WaitGroup var wg sync.WaitGroup
go f.RecordVisits(reportedVisits) go f.RecordVisits(reportedVisits)
startPoint := MovementPoint {
Row: 0, Col: 0, Direction: Rightward,
}
wg.Add(1) wg.Add(1)
go f.TraverseFrom(startPoint, reportedVisits, &wg) go f.TraverseFrom(startPoint, reportedVisits, &wg)
@ -132,7 +180,7 @@ func (f *Field)StartTraversal() {
close(reportedVisits) close(reportedVisits)
} }
func (f *Field)CountEnergized() (result int) { func (f *Field) CountEnergized() (result int) {
for _, row := range f.cells { for _, row := range f.cells {
for _, cell := range row { for _, cell := range row {
if len(cell.KnownBeams) > 0 { if len(cell.KnownBeams) > 0 {
@ -143,7 +191,7 @@ func (f *Field)CountEnergized() (result int) {
return return
} }
func (f *Field)RecordVisits(reportedPoints <-chan MovementPoint) { func (f *Field) RecordVisits(reportedPoints <-chan MovementPoint) {
for point := range reportedPoints { for point := range reportedPoints {
cell := f.cells[point.Row][point.Col] cell := f.cells[point.Row][point.Col]
log.Printf("recording visit %+v to %+v at row %d col %d\n", point, cell, point.Row, point.Col) log.Printf("recording visit %+v to %+v at row %d col %d\n", point, cell, point.Row, point.Col)
@ -154,7 +202,7 @@ func (f *Field)RecordVisits(reportedPoints <-chan MovementPoint) {
// starting at point, mark as visited // starting at point, mark as visited
// move (concurrently if required) into next points // move (concurrently if required) into next points
// ends - when out of the field, or if encountering a cycle // ends - when out of the field, or if encountering a cycle
func (f *Field)TraverseFrom(current MovementPoint, reportVisits chan<- MovementPoint, wg *sync.WaitGroup) { func (f *Field) TraverseFrom(current MovementPoint, reportVisits chan<- MovementPoint, wg *sync.WaitGroup) {
log.Printf("> starting traverse through %+v", current) log.Printf("> starting traverse through %+v", current)
if !f.isValid(current) { if !f.isValid(current) {
log.Println("invalid current ", current, " should be impossible") log.Println("invalid current ", current, " should be impossible")
@ -174,7 +222,7 @@ func (f *Field)TraverseFrom(current MovementPoint, reportVisits chan<- MovementP
nextPoints := NextPoints(f, current) nextPoints := NextPoints(f, current)
log.Printf("for current %+v next are: %+v\n", current, nextPoints) log.Printf("for current %+v next are: %+v\n", current, nextPoints)
switch len(nextPoints) { switch len(nextPoints) {
case 0: case 0:
wg.Done() wg.Done()
return return
case 1: case 1:
@ -204,9 +252,9 @@ func NextPoints(f *Field, current MovementPoint) []MovementPoint {
// value receiver, can safely modify incoming mp // value receiver, can safely modify incoming mp
// doesn't know about Field dimentions // doesn't know about Field dimentions
func (mp MovementPoint)ApplyDirection(d Direction) MovementPoint { func (mp MovementPoint) ApplyDirection(d Direction) MovementPoint {
switch d { switch d {
case Upward: case Upward:
mp.Row -= 1 mp.Row -= 1
case Downward: case Downward:
mp.Row += 1 mp.Row += 1