From 6efd55ae6a63a849f72d71e07c05638db37a36f5 Mon Sep 17 00:00:00 2001 From: efim Date: Mon, 18 Dec 2023 20:33:04 +0000 Subject: [PATCH] day18, example second parallel --- day18/lagoon.go | 190 ++++++++++++++++++++++++++++-------------------- day18/notes.org | 15 ++++ 2 files changed, 126 insertions(+), 79 deletions(-) diff --git a/day18/lagoon.go b/day18/lagoon.go index 0b7ab9c..74ddb7f 100644 --- a/day18/lagoon.go +++ b/day18/lagoon.go @@ -7,12 +7,13 @@ import ( "slices" "strconv" "strings" + "sync" ) func Run() int { log.Println("hello day 18") log.Println("problem of lagoon bgins") - filename := "day18/example" + filename := "day18/input" instructions := ReadInstructionas2(filename) h, w := calcHeightWidth(instructions) log.Printf("read %+v instructions", instructions) @@ -210,34 +211,37 @@ type Cell struct { } type BorderSymbol rune -// '' always left to right -const (Vertical BorderSymbol = '|' - ToDown BorderSymbol = '7' - ToUp BorderSymbol = 'J' - FromUp BorderSymbol = 'F' + +// ” always left to right +const ( + Vertical BorderSymbol = '|' + ToDown BorderSymbol = '7' + ToUp BorderSymbol = 'J' + FromUp BorderSymbol = 'F' FromDown BorderSymbol = 'L' ) type Field struct { Height, Width int // Cells [][]*Cell - Cells map[Coord]*Cell + Cells map[Coord]*Cell MinRow, MaxRow, MinCol, MaxCol int - BordersFromLeft map[int]map[int]BorderSymbol + BordersFromLeft map[int]map[int]BorderSymbol } -func (f *Field)confirmCoord(c Coord) { + +func (f *Field) confirmCoord(c Coord) { // log.Printf("configming coord %+v", c) - if c.Row - 3 < f.MinRow { + if c.Row-3 < f.MinRow { f.MinRow = c.Row - 3 } - if c.Row + 3 > f.MaxRow { + if c.Row+3 > f.MaxRow { f.MaxRow = c.Row + 3 } - if c.Col - 3 < f.MinCol { + if c.Col-3 < f.MinCol { f.MinCol = c.Col - 3 } - if c.Col + 3 > f.MaxCol { + if c.Col+3 > f.MaxCol { f.MaxCol = c.Col + 3 } } @@ -245,7 +249,7 @@ func (f *Field)confirmCoord(c Coord) { func CreateField(height, width int) Field { return Field{ Height: height, Width: width, - Cells: make(map[Coord]*Cell), + Cells: make(map[Coord]*Cell), BordersFromLeft: make(map[int]map[int]BorderSymbol), } } @@ -295,7 +299,7 @@ func (f *Field) digByInstructions(instructions []Instruction) (borderAmount int) // log.Printf("inside %+v updated border amount to %d", instruction, borderAmount) if instruction.Direction == Upward || instruction.Direction == Downward { - _, alreadyCountedTurn := f.BordersFromLeft[runnerCoord.Row][runnerCoord.Col] + _, alreadyCountedTurn := f.BordersFromLeft[runnerCoord.Row][runnerCoord.Col] if !alreadyCountedTurn { PutSymbIntoMMMMap(f.BordersFromLeft, runnerCoord.Row, runnerCoord.Col, Vertical) } @@ -307,7 +311,7 @@ func (f *Field) digByInstructions(instructions []Instruction) (borderAmount int) return } -func getTurnAsIfGoingFromLeft(directionFrom, directionTo Direction) []BorderSymbol { +func getTurnAsIfGoingFromLeft(directionFrom, directionTo Direction) []BorderSymbol { // log.Printf("getTurnAsIfGoingFromLeft from %s to %s", directionFrom.String(), directionTo.String()) var symbol BorderSymbol @@ -337,7 +341,6 @@ func getTurnAsIfGoingFromLeft(directionFrom, directionTo Direction) []BorderSym symbol = FromUp } - // panic(fmt.Sprint("got strange from %s to %s", directionFrom.String(), directionTo.String())) return []BorderSymbol{symbol} } @@ -346,27 +349,27 @@ func (f *Field) String() string { s := "text 15,15 \"" for row := f.MinRow; row <= f.MaxRow; row++ { - rowChars := make([]rune, f.MaxCol - f.MinCol + 1) + rowChars := make([]rune, f.MaxCol-f.MinCol+1) for col := f.MinCol; col <= f.MaxCol; col++ { rowBords := f.BordersFromLeft[row] if rowBords != nil { bord, exists := rowBords[col] if exists { - rowChars[col - f.MinCol] = rune(bord) + rowChars[col-f.MinCol] = rune(bord) continue } } cell := f.Cells[Coord{col, row}] if cell != nil && cell.ToBeDug { - rowChars[col - f.MinCol] = '@' + rowChars[col-f.MinCol] = '@' continue } if f.isCellDug(row, col) { - rowChars[col - f.MinCol] = '#' + rowChars[col-f.MinCol] = '#' } else { - rowChars[col - f.MinCol] = '.' + rowChars[col-f.MinCol] = '.' } } @@ -376,72 +379,101 @@ func (f *Field) String() string { s += "\"" return s } -func (f *Field) digInsides() (countInside int) { +func (f *Field) digInsides() (result int) { + lineSum := make(chan int) + + var wg sync.WaitGroup + rowsCount := f.MaxRow - f.MinRow + wg.Add(rowsCount) + + done := make(chan bool) + + go func() { + wg.Wait() + close(lineSum) + }() + + go func() { + for rowInternalCount := range lineSum { + result += rowInternalCount + } + close(done) + }() + for row := f.MinRow; row < f.MaxRow; row++ { - if row % 10000 == 0 { - log.Printf("processed rows %d out of %d", row, f.MaxRow) - } - specialBorders := f.BordersFromLeft[row] - if len(specialBorders) == 0 { - continue - } - type BorderItem struct { - border BorderSymbol - col int - } - rowBorders := make([]BorderItem, 0) - for col, borderSymbol := range specialBorders { - rowBorders = append(rowBorders, BorderItem{borderSymbol, col}) - } - slices.SortFunc(rowBorders, func(a BorderItem, b BorderItem) int { - return a.col - b.col - }) + go func(row int){ + if row%10000 == 0 { + log.Printf("processed rows %d out of %d", row, f.MaxRow) + } + specialBorders := f.BordersFromLeft[row] + if len(specialBorders) == 0 { + wg.Done() + return + } + type BorderItem struct { + border BorderSymbol + col int + } + rowBorders := make([]BorderItem, 0) + for col, borderSymbol := range specialBorders { + rowBorders = append(rowBorders, BorderItem{borderSymbol, col}) + } + slices.SortFunc(rowBorders, func(a BorderItem, b BorderItem) int { + return a.col - b.col + }) - // log.Printf(">>>>>>> for row %d sorted %+v", row, rowBorders) - prevBorder := rowBorders[0] - bordersCrossed := 0 - if prevBorder.border == Vertical { - bordersCrossed += 1 - } - for _, specialBorder := range rowBorders[1:] { - diff := specialBorder.col - prevBorder.col - 1 - - if specialBorder.border == ToUp && prevBorder.border == FromUp { + // log.Printf(">>>>>>> for row %d sorted %+v", row, rowBorders) + prevBorder := rowBorders[0] + bordersCrossed := 0 + if prevBorder.border == Vertical { bordersCrossed += 1 - prevBorder = specialBorder - continue - } - if specialBorder.border == ToDown && prevBorder.border == FromDown { - bordersCrossed += 1 - prevBorder = specialBorder - continue - } - if specialBorder.border == ToUp && prevBorder.border == FromDown { - prevBorder = specialBorder - continue - } - if specialBorder.border == ToDown && prevBorder.border == FromUp { - prevBorder = specialBorder - continue } + for _, specialBorder := range rowBorders[1:] { + diff := specialBorder.col - prevBorder.col - 1 - if bordersCrossed % 2 == 1 { // is in - for col := prevBorder.col+1; col < specialBorder.col; col++ { - // f.Cells[Coord{Col: col, Row: row}] = &Cell{ - // ToBeDug: true, - // } + if specialBorder.border == ToUp && prevBorder.border == FromUp { + bordersCrossed += 1 + prevBorder = specialBorder + continue } - countInside += diff + if specialBorder.border == ToDown && prevBorder.border == FromDown { + bordersCrossed += 1 + prevBorder = specialBorder + continue + } + if specialBorder.border == ToUp && prevBorder.border == FromDown { + prevBorder = specialBorder + continue + } + if specialBorder.border == ToDown && prevBorder.border == FromUp { + prevBorder = specialBorder + continue + } + + if bordersCrossed%2 == 1 { // is in + for col := prevBorder.col + 1; col < specialBorder.col; col++ { + // f.Cells[Coord{Col: col, Row: row}] = &Cell{ + // ToBeDug: true, + // } + } + lineSum <- diff + // countInside += diff + } + + if specialBorder.border == Vertical { + bordersCrossed += 1 + } + + prevBorder = specialBorder } - if specialBorder.border == Vertical { - bordersCrossed += 1 - } - - prevBorder = specialBorder - } + wg.Done() + }(row) } - return + + <-done + + return result } // func (f *Field) digInsides() (countInside int) { diff --git a/day18/notes.org b/day18/notes.org index 1824ce3..217e663 100644 --- a/day18/notes.org +++ b/day18/notes.org @@ -34,3 +34,18 @@ day18 result: 952408144115 952408144115 *** YES. +*** about 1M for 4 minutes +** so, my input is ~16M rows +3.5 seconds per 10k +** well, maybe i can parallel. +*** parallel example +day18 result: 952407566854 +*** and with separate done channel from the summing goroutine +952408144115 +**** YES +** and +2023/12/18 23:35:31 border is 195341588; inside is 148441957805559 +2023/12/18 23:35:31 + +day18 result: 148442153147147 +* i should have used a formula. maybe then it would taken less than 4 hours