day18, another example working
This commit is contained in:
parent
86c9ad7653
commit
6dabe8bc66
178
day18/lagoon.go
178
day18/lagoon.go
|
@ -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{
|
}
|
||||||
ToBeDug: true,
|
if specialBorder.border == ToUp && prevBorder.border == FromDown {
|
||||||
}
|
prevBorder = specialBorder
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
countInside += gap
|
if specialBorder.border == ToDown && prevBorder.border == FromUp {
|
||||||
|
prevBorder = specialBorder
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
isInside = !isInside
|
if bordersCrossed % 2 == 1 { // is in
|
||||||
prevCol = col
|
for col := prevBorder.col+1; col < specialBorder.col; col++ {
|
||||||
|
f.Cells[Coord{Col: col, Row: row}] = &Cell{
|
||||||
|
ToBeDug: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
countInside += diff
|
||||||
|
}
|
||||||
|
|
||||||
|
if specialBorder.border == Vertical {
|
||||||
|
bordersCrossed += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
prevBorder = specialBorder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
|
@ -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?
|
||||||
|
|
Loading…
Reference in New Issue