day18, example second parallel

This commit is contained in:
efim 2023-12-18 20:33:04 +00:00
parent 568fdd9a70
commit 6efd55ae6a
2 changed files with 126 additions and 79 deletions

View File

@ -7,12 +7,13 @@ import (
"slices" "slices"
"strconv" "strconv"
"strings" "strings"
"sync"
) )
func Run() int { func Run() int {
log.Println("hello day 18") log.Println("hello day 18")
log.Println("problem of lagoon bgins") log.Println("problem of lagoon bgins")
filename := "day18/example" filename := "day18/input"
instructions := ReadInstructionas2(filename) instructions := ReadInstructionas2(filename)
h, w := calcHeightWidth(instructions) h, w := calcHeightWidth(instructions)
log.Printf("read %+v instructions", instructions) log.Printf("read %+v instructions", instructions)
@ -210,34 +211,37 @@ type Cell struct {
} }
type BorderSymbol rune type BorderSymbol rune
// '' always left to right
const (Vertical BorderSymbol = '|' // ” always left to right
ToDown BorderSymbol = '7' const (
ToUp BorderSymbol = 'J' Vertical BorderSymbol = '|'
FromUp BorderSymbol = 'F' ToDown BorderSymbol = '7'
ToUp BorderSymbol = 'J'
FromUp BorderSymbol = 'F'
FromDown BorderSymbol = 'L' FromDown BorderSymbol = 'L'
) )
type Field struct { type Field struct {
Height, Width int Height, Width int
// Cells [][]*Cell // Cells [][]*Cell
Cells map[Coord]*Cell Cells map[Coord]*Cell
MinRow, MaxRow, MinCol, MaxCol int 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) // log.Printf("configming coord %+v", c)
if c.Row - 3 < f.MinRow { if c.Row-3 < f.MinRow {
f.MinRow = c.Row - 3 f.MinRow = c.Row - 3
} }
if c.Row + 3 > f.MaxRow { if c.Row+3 > f.MaxRow {
f.MaxRow = c.Row + 3 f.MaxRow = c.Row + 3
} }
if c.Col - 3 < f.MinCol { if c.Col-3 < f.MinCol {
f.MinCol = c.Col - 3 f.MinCol = c.Col - 3
} }
if c.Col + 3 > f.MaxCol { if c.Col+3 > f.MaxCol {
f.MaxCol = c.Col + 3 f.MaxCol = c.Col + 3
} }
} }
@ -245,7 +249,7 @@ func (f *Field)confirmCoord(c Coord) {
func CreateField(height, width int) Field { func CreateField(height, width int) Field {
return Field{ return Field{
Height: height, Width: width, Height: height, Width: width,
Cells: make(map[Coord]*Cell), Cells: make(map[Coord]*Cell),
BordersFromLeft: make(map[int]map[int]BorderSymbol), 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) // log.Printf("inside %+v updated border amount to %d", instruction, borderAmount)
if instruction.Direction == Upward || instruction.Direction == Downward { if instruction.Direction == Upward || instruction.Direction == Downward {
_, alreadyCountedTurn := f.BordersFromLeft[runnerCoord.Row][runnerCoord.Col] _, alreadyCountedTurn := f.BordersFromLeft[runnerCoord.Row][runnerCoord.Col]
if !alreadyCountedTurn { if !alreadyCountedTurn {
PutSymbIntoMMMMap(f.BordersFromLeft, runnerCoord.Row, runnerCoord.Col, Vertical) PutSymbIntoMMMMap(f.BordersFromLeft, runnerCoord.Row, runnerCoord.Col, Vertical)
} }
@ -307,7 +311,7 @@ func (f *Field) digByInstructions(instructions []Instruction) (borderAmount int)
return return
} }
func getTurnAsIfGoingFromLeft(directionFrom, directionTo Direction) []BorderSymbol { func getTurnAsIfGoingFromLeft(directionFrom, directionTo Direction) []BorderSymbol {
// log.Printf("getTurnAsIfGoingFromLeft from %s to %s", directionFrom.String(), directionTo.String()) // log.Printf("getTurnAsIfGoingFromLeft from %s to %s", directionFrom.String(), directionTo.String())
var symbol BorderSymbol var symbol BorderSymbol
@ -337,7 +341,6 @@ func getTurnAsIfGoingFromLeft(directionFrom, directionTo Direction) []BorderSym
symbol = FromUp symbol = FromUp
} }
// panic(fmt.Sprint("got strange from %s to %s", directionFrom.String(), directionTo.String())) // panic(fmt.Sprint("got strange from %s to %s", directionFrom.String(), directionTo.String()))
return []BorderSymbol{symbol} return []BorderSymbol{symbol}
} }
@ -346,27 +349,27 @@ func (f *Field) String() string {
s := "text 15,15 \"" s := "text 15,15 \""
for row := f.MinRow; row <= f.MaxRow; row++ { 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++ { for col := f.MinCol; col <= f.MaxCol; col++ {
rowBords := f.BordersFromLeft[row] rowBords := f.BordersFromLeft[row]
if rowBords != nil { if rowBords != nil {
bord, exists := rowBords[col] bord, exists := rowBords[col]
if exists { if exists {
rowChars[col - f.MinCol] = rune(bord) rowChars[col-f.MinCol] = rune(bord)
continue continue
} }
} }
cell := f.Cells[Coord{col, row}] cell := f.Cells[Coord{col, row}]
if cell != nil && cell.ToBeDug { if cell != nil && cell.ToBeDug {
rowChars[col - f.MinCol] = '@' rowChars[col-f.MinCol] = '@'
continue continue
} }
if f.isCellDug(row, col) { if f.isCellDug(row, col) {
rowChars[col - f.MinCol] = '#' rowChars[col-f.MinCol] = '#'
} else { } else {
rowChars[col - f.MinCol] = '.' rowChars[col-f.MinCol] = '.'
} }
} }
@ -376,72 +379,101 @@ func (f *Field) String() string {
s += "\"" s += "\""
return 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++ { for row := f.MinRow; row < f.MaxRow; row++ {
if row % 10000 == 0 { go func(row int){
log.Printf("processed rows %d out of %d", row, f.MaxRow) if row%10000 == 0 {
} log.Printf("processed rows %d out of %d", row, f.MaxRow)
specialBorders := f.BordersFromLeft[row] }
if len(specialBorders) == 0 { specialBorders := f.BordersFromLeft[row]
continue if len(specialBorders) == 0 {
} wg.Done()
type BorderItem struct { return
border BorderSymbol }
col int type BorderItem struct {
} border BorderSymbol
rowBorders := make([]BorderItem, 0) col int
for col, borderSymbol := range specialBorders { }
rowBorders = append(rowBorders, BorderItem{borderSymbol, col}) rowBorders := make([]BorderItem, 0)
} for col, borderSymbol := range specialBorders {
slices.SortFunc(rowBorders, func(a BorderItem, b BorderItem) int { rowBorders = append(rowBorders, BorderItem{borderSymbol, col})
return a.col - b.col }
}) slices.SortFunc(rowBorders, func(a BorderItem, b BorderItem) int {
return a.col - b.col
})
// log.Printf(">>>>>>> for row %d sorted %+v", row, rowBorders) // log.Printf(">>>>>>> for row %d sorted %+v", row, rowBorders)
prevBorder := rowBorders[0] prevBorder := rowBorders[0]
bordersCrossed := 0 bordersCrossed := 0
if prevBorder.border == Vertical { if prevBorder.border == Vertical {
bordersCrossed += 1
}
for _, specialBorder := range rowBorders[1:] {
diff := specialBorder.col - prevBorder.col - 1
if specialBorder.border == ToUp && prevBorder.border == FromUp {
bordersCrossed += 1 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 if specialBorder.border == ToUp && prevBorder.border == FromUp {
for col := prevBorder.col+1; col < specialBorder.col; col++ { bordersCrossed += 1
// f.Cells[Coord{Col: col, Row: row}] = &Cell{ prevBorder = specialBorder
// ToBeDug: true, 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 { wg.Done()
bordersCrossed += 1 }(row)
}
prevBorder = specialBorder
}
} }
return
<-done
return result
} }
// func (f *Field) digInsides() (countInside int) { // func (f *Field) digInsides() (countInside int) {

View File

@ -34,3 +34,18 @@ day18 result: 952408144115
952408144115 952408144115
*** YES. *** 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