diff --git a/day16/floorWillBeLava.go b/day16/floorWillBeLava.go index 2dffc1d..b5bfd4e 100644 --- a/day16/floorWillBeLava.go +++ b/day16/floorWillBeLava.go @@ -3,6 +3,7 @@ package day16 import ( "fmt" "log" + "math" "os" "strings" "sync" @@ -11,13 +12,63 @@ import ( func Run() int { fmt.Println("hello from day 16") log.Println("starting") - field := ReadField("day16/input") - fmt.Println(field.String()) - field.StartTraversal() + filename := "day16/example" + field := ReadField(filename) + 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 @@ -53,7 +104,7 @@ type Field struct { cells [][]*Cell } -func (f *Field)isValid(mp MovementPoint) bool { +func (f *Field) isValid(mp MovementPoint) bool { if mp.Row < 0 || mp.Col < 0 { return false } @@ -75,7 +126,7 @@ func ReadField(filename string) Field { rowCells := make([]*Cell, 0) for _, symb := range line { rowCells = append(rowCells, &Cell{ - CellType: CellType(symb), + CellType: CellType(symb), KnownBeams: make(map[Direction]any), }) } @@ -84,7 +135,7 @@ func ReadField(filename string) Field { return result } -func (f *Field)String() string { +func (f *Field) String() string { result := "\n" for _, row := range f.cells { for _, cell := range row { @@ -95,7 +146,7 @@ func (f *Field)String() string { return result } -func (f *Field)ShowEnergyzed() string { +func (f *Field) ShowEnergyzed() string { result := "\n" for _, row := range f.cells { for _, cell := range row { @@ -117,14 +168,11 @@ type MovementPoint struct { Direction Direction } -func (f *Field)StartTraversal() { +func (f *Field) StartTraversal(startPoint MovementPoint) { reportedVisits := make(chan MovementPoint) var wg sync.WaitGroup go f.RecordVisits(reportedVisits) - startPoint := MovementPoint { - Row: 0, Col: 0, Direction: Rightward, - } wg.Add(1) go f.TraverseFrom(startPoint, reportedVisits, &wg) @@ -132,7 +180,7 @@ func (f *Field)StartTraversal() { close(reportedVisits) } -func (f *Field)CountEnergized() (result int) { +func (f *Field) CountEnergized() (result int) { for _, row := range f.cells { for _, cell := range row { if len(cell.KnownBeams) > 0 { @@ -143,7 +191,7 @@ func (f *Field)CountEnergized() (result int) { return } -func (f *Field)RecordVisits(reportedPoints <-chan MovementPoint) { +func (f *Field) RecordVisits(reportedPoints <-chan MovementPoint) { for point := range reportedPoints { 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) @@ -154,7 +202,7 @@ func (f *Field)RecordVisits(reportedPoints <-chan MovementPoint) { // starting at point, mark as visited // move (concurrently if required) into next points // 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) if !f.isValid(current) { 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) log.Printf("for current %+v next are: %+v\n", current, nextPoints) switch len(nextPoints) { - case 0: + case 0: wg.Done() return case 1: @@ -204,9 +252,9 @@ func NextPoints(f *Field, current MovementPoint) []MovementPoint { // value receiver, can safely modify incoming mp // doesn't know about Field dimentions -func (mp MovementPoint)ApplyDirection(d Direction) MovementPoint { +func (mp MovementPoint) ApplyDirection(d Direction) MovementPoint { switch d { - case Upward: + case Upward: mp.Row -= 1 case Downward: mp.Row += 1