day18, another example working

This commit is contained in:
efim 2023-12-18 19:37:17 +00:00
parent 86c9ad7653
commit 6dabe8bc66
2 changed files with 152 additions and 31 deletions

View File

@ -12,8 +12,8 @@ import (
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/example2" filename := "day18/example"
instructions := ReadInstructionas2(filename) instructions := ReadInstructionas(filename)
h, w := calcHeightWidth(instructions) h, w := calcHeightWidth(instructions)
log.Printf("read %+v instructions", instructions) log.Printf("read %+v instructions", instructions)
@ -21,7 +21,7 @@ func Run() int {
fmt.Println(field.String()) fmt.Println(field.String())
borderAmount := field.digByInstructions(instructions) borderAmount := field.digByInstructions(instructions)
// log.Println("created field", field.BorderCellCols) log.Println(">>> created field", field.BordersFromLeft)
fmt.Println(field.String()) fmt.Println(field.String())
// WriteToFile("borders.txt", field.String()) // WriteToFile("borders.txt", field.String())
@ -208,17 +208,25 @@ type Cell struct {
ToBeDug bool ToBeDug bool
Coord Coord Coord Coord
} }
type BorderSymbol rune
// '' always left to right
const (Vertical BorderSymbol = '|'
ToDown BorderSymbol = '7'
ToUp BorderSymbol = 'J'
FromUp BorderSymbol = 'F'
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
// TODO - make this map[int]map[int]any (for the set) BordersFromLeft map[int]map[int]BorderSymbol
BorderCellCols map[int][]int // known row -> col
} }
func (f *Field)confirmCoord(c Coord) { func (f *Field)confirmCoord(c Coord) {
// log.Printf("configming coord %+v", c) // log.Printf("configming coord %+v", c)
f.BorderCellCols[c.Row] = append(f.BorderCellCols[c.Row], c.Col)
if c.Row - 3 < f.MinRow { if c.Row - 3 < f.MinRow {
f.MinRow = c.Row - 3 f.MinRow = c.Row - 3
@ -238,11 +246,25 @@ 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),
BorderCellCols: make(map[int][]int), BordersFromLeft: make(map[int]map[int]BorderSymbol),
} }
} }
func PutSymbIntoMMMMap(mmmap map[int]map[int]BorderSymbol, row, col int, symb BorderSymbol) {
rowMap := mmmap[row]
if rowMap == nil {
rowMap = make(map[int]BorderSymbol)
mmmap[row] = rowMap
}
rowMap[col] = symb
}
func (f *Field) digByInstructions(instructions []Instruction) (borderAmount int) { func (f *Field) digByInstructions(instructions []Instruction) (borderAmount int) {
// for the last turn
instructions = append(instructions, instructions[0])
// but also don't overcount the border
borderAmount -= instructions[0].Steps
runnerCoord := Coord{Col: 0, Row: 0} runnerCoord := Coord{Col: 0, Row: 0}
f.Cells[runnerCoord] = &Cell{ f.Cells[runnerCoord] = &Cell{
IsDug: true, IsDug: true,
@ -250,8 +272,19 @@ func (f *Field) digByInstructions(instructions []Instruction) (borderAmount int)
// f.confirmCoord(runnerCoord) // should be confirmed when the cycle is closed on last step // f.confirmCoord(runnerCoord) // should be confirmed when the cycle is closed on last step
// borderAmount += 1 // borderAmount += 1
var prevInstruction Instruction
firstInstruction := true
for _, instruction := range instructions { for _, instruction := range instructions {
fmt.Printf("starting instruction %+v", instruction) log.Printf("starting new instruction %+v", instruction)
if !firstInstruction {
turn := getTurnAsIfGoingFromLeft(prevInstruction.Direction, instruction.Direction)
for _, theTurn := range turn {
log.Printf(">> putting turn %s", string(turn))
PutSymbIntoMMMMap(f.BordersFromLeft, runnerCoord.Row, runnerCoord.Col, theTurn)
}
}
firstInstruction = false
log.Printf("starting instruction %+v", instruction)
for i := 0; i < instruction.Steps; i++ { for i := 0; i < instruction.Steps; i++ {
runnerCoord = runnerCoord.applyDirection(instruction.Direction) runnerCoord = runnerCoord.applyDirection(instruction.Direction)
f.Cells[runnerCoord] = &Cell{ f.Cells[runnerCoord] = &Cell{
@ -259,22 +292,77 @@ func (f *Field) digByInstructions(instructions []Instruction) (borderAmount int)
} }
f.confirmCoord(runnerCoord) f.confirmCoord(runnerCoord)
borderAmount += 1 borderAmount += 1
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]
if !alreadyCountedTurn {
PutSymbIntoMMMMap(f.BordersFromLeft, runnerCoord.Row, runnerCoord.Col, Vertical)
} }
} }
}
prevInstruction = instruction
}
return return
} }
func getTurnAsIfGoingFromLeft(directionFrom, directionTo Direction) []BorderSymbol {
log.Printf("getTurnAsIfGoingFromLeft from %s to %s", directionFrom.String(), directionTo.String())
var symbol BorderSymbol
if directionTo == Rightward && directionFrom == Upward {
symbol = FromUp
}
if directionTo == Rightward && directionFrom == Downward {
symbol = FromDown
}
if directionTo == Leftward && directionFrom == Upward {
symbol = ToDown
}
if directionTo == Leftward && directionFrom == Downward {
symbol = ToUp
}
if directionFrom == Rightward && directionTo == Upward {
symbol = ToUp
}
if directionFrom == Rightward && directionTo == Downward {
symbol = ToDown
}
if directionFrom == Leftward && directionTo == Upward {
symbol = FromDown
}
if directionFrom == Leftward && directionTo == Downward {
symbol = FromUp
}
// panic(fmt.Sprint("got strange from %s to %s", directionFrom.String(), directionTo.String()))
return []BorderSymbol{symbol}
}
func (f *Field) String() string { 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]
if rowBords != nil {
bord, exists := rowBords[col]
if exists {
rowChars[col - f.MinCol] = rune(bord)
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 {
@ -293,34 +381,64 @@ func (f *Field) digInsides() (countInside int) {
if row % 10000 == 0 { if row % 10000 == 0 {
log.Printf("processed rows %d out of %d", row, f.MaxRow) log.Printf("processed rows %d out of %d", row, f.MaxRow)
} }
thisRowBorderCols := f.BorderCellCols[row] specialBorders := f.BordersFromLeft[row]
slices.Sort(thisRowBorderCols) if len(specialBorders) == 0 {
// log.Printf("cols for row %d are %+v", row, thisRowBorderCols)
if len(thisRowBorderCols) == 0 {
continue continue
} }
isInside := true type BorderItem struct {
prevCol := thisRowBorderCols[0] border BorderSymbol
for _, col := range thisRowBorderCols[1:] { col int
gap := (col - prevCol - 1) }
if gap == 0 { rowBorders := make([]BorderItem, 0)
prevCol = col 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 {
bordersCrossed += 1
prevBorder = specialBorder
continue continue
} }
// log.Printf("found gap in row %d. is inside %t. between col %d and %d of length %d", if specialBorder.border == ToDown && prevBorder.border == FromDown {
// row, isInside, col, prevCol, gap) bordersCrossed += 1
if isInside { prevBorder = specialBorder
for coll := prevCol+1; coll < col; coll++ { continue
f.Cells[Coord{Col: coll, Row: row}] = &Cell{ }
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, ToBeDug: true,
} }
} }
countInside += gap countInside += diff
} }
isInside = !isInside if specialBorder.border == Vertical {
prevCol = col bordersCrossed += 1
}
prevBorder = specialBorder
} }
} }
return return

View File

@ -19,9 +19,12 @@ when there's a jump - compare counts, to make decision on whether to switch 'isI
** no. just because they are long doesn't mean they won't ever get one near another ** no. just because they are long doesn't mean they won't ever get one near another
* another idea is to save | and corners, as if we're going from left to right * another idea is to save | and corners, as if we're going from left to right
this seems reasonable. this seems reasonable.
** TODO i guess []SpecialSymbol which has Col and Symbol ** DONE i guess []SpecialSymbol which has Col and Symbol
** DONE no, let's make it map. yes will have to init, but yuck anyway
** TODO then different logic on border building. ** TODO then different logic on border building.
if U \ D - on all but last add '|' if U \ D - on all but last add '|'
on last - calc with the next turn, what should be saved 'as if traversing from the left' on last - calc with the next turn, what should be saved 'as if traversing from the left'
for L \ R - on last - calc what the turn was for L \ R - on last - calc what the turn was
** TODO !! between last and first movement the corner is unknown.
so, copy the first instruction to the end?