diff --git a/day18/example2 b/day18/example2 new file mode 100644 index 0000000..82cff39 --- /dev/null +++ b/day18/example2 @@ -0,0 +1,8 @@ +R 6 (#70c710) +D 5 (#0dc571) +L 2 (#5713f0) +U 2 (#d2c081) +L 2 (#59c680) +D 2 (#411b91) +L 2 (#8ceee2) +U 5 (#d2c081) diff --git a/day18/lagoon.go b/day18/lagoon.go index d25062a..1b58d72 100644 --- a/day18/lagoon.go +++ b/day18/lagoon.go @@ -12,21 +12,22 @@ import ( func Run() int { log.Println("hello day 18") log.Println("problem of lagoon bgins") - filename := "day18/example" - instructions := ReadInstructionas(filename) + filename := "day18/example2" + instructions := ReadInstructionas2(filename) h, w := calcHeightWidth(instructions) log.Printf("read %+v instructions", instructions) field := CreateField(h, w) - log.Println("created field") - // fmt.Println(field.String()) + fmt.Println(field.String()) borderAmount := field.digByInstructions(instructions) + // log.Println("created field", field.BorderCellCols) fmt.Println(field.String()) // WriteToFile("borders.txt", field.String()) // convert -size 3000x6000 xc:white -font "FreeMono" -pointsize 13 -fill black -draw @borders.txt borders.png + log.Printf("starting dig inside for cols %d-%d and rows %d-%d ", field.MinCol, field.MaxCol, field.MinRow, field.MaxRow) insideAmount := field.digInsides() log.Printf("border is %d; inside is %d", borderAmount, insideAmount) @@ -212,8 +213,13 @@ type Field struct { // Cells [][]*Cell Cells map[Coord]*Cell MinRow, MaxRow, MinCol, MaxCol int + // TODO - make this map[int]map[int]any (for the set) + BorderCellCols map[int][]int // known row -> col } func (f *Field)confirmCoord(c Coord) { + // log.Printf("configming coord %+v", c) + f.BorderCellCols[c.Row] = append(f.BorderCellCols[c.Row], c.Col) + if c.Row - 3 < f.MinRow { f.MinRow = c.Row - 3 } @@ -232,6 +238,7 @@ func CreateField(height, width int) Field { return Field{ Height: height, Width: width, Cells: make(map[Coord]*Cell), + BorderCellCols: make(map[int][]int), } } @@ -240,11 +247,11 @@ func (f *Field) digByInstructions(instructions []Instruction) (borderAmount int) f.Cells[runnerCoord] = &Cell{ IsDug: true, } - f.confirmCoord(runnerCoord) + // f.confirmCoord(runnerCoord) // should be confirmed when the cycle is closed on last step // borderAmount += 1 for _, instruction := range instructions { - log.Printf("starting instruction %+v", instruction) + fmt.Printf("starting instruction %+v", instruction) for i := 0; i < instruction.Steps; i++ { runnerCoord = runnerCoord.applyDirection(instruction.Direction) f.Cells[runnerCoord] = &Cell{ @@ -281,44 +288,86 @@ func (f *Field) String() string { s += "\"" return s } - func (f *Field) digInsides() (countInside int) { for row := f.MinRow; row < f.MaxRow; row++ { - isInside := false - seenUp, seenDown := false, false // for detecting L---7 walls - for col := f.MinCol; col < f.MaxCol; col++ { - rightCellIsDug := f.isCellDug(row, col+1) - if f.isCellDug(row, col) { - upCellIsDug := f.isCellDug(row-1, col) - downCellIsDug := f.isCellDug(row+1, col) - if !rightCellIsDug { - if (upCellIsDug && seenDown) || (downCellIsDug && seenUp) { - isInside = !isInside - } - seenUp, seenDown = false, false - } - } else { - // not a dug out cell, maybe inside and needs to be dug out - if isInside { - // f.Cells[Coord{col, row}] = &Cell{ - // ToBeDug: true, - // } - - countInside += 1 - log.Printf("tick count inside for %d %d", row, col) - // cellPtr.ToBeDug = true - } - if rightCellIsDug { - seenUp = f.isCellDug(row-1, col+1) - seenDown = f.isCellDug(row+1, col+1) - } - + if row % 10000 == 0 { + log.Printf("processed rows %d out of %d", row, f.MaxRow) + } + thisRowBorderCols := f.BorderCellCols[row] + slices.Sort(thisRowBorderCols) + // log.Printf("cols for row %d are %+v", row, thisRowBorderCols) + if len(thisRowBorderCols) == 0 { + continue + } + isInside := true + prevCol := thisRowBorderCols[0] + for _, col := range thisRowBorderCols[1:] { + gap := (col - prevCol - 1) + if gap == 0 { + prevCol = col + continue } + // log.Printf("found gap in row %d. is inside %t. between col %d and %d of length %d", + // row, isInside, col, prevCol, gap) + if isInside { + for coll := prevCol+1; coll < col; coll++ { + f.Cells[Coord{Col: coll, Row: row}] = &Cell{ + ToBeDug: true, + } + + } + countInside += gap + } + + isInside = !isInside + prevCol = col } } return } +// func (f *Field) digInsides() (countInside int) { +// for row := f.MinRow; row < f.MaxRow; row++ { +// if row % 10000 == 0 { +// log.Printf("processed rows %d out of %d", row, f.MaxRow) +// } +// isInside := false +// seenUp, seenDown := false, false // for detecting L---7 walls +// for col := f.MinCol; col < f.MaxCol; col++ { +// // TODO next optimization - for each row, store indices of cols with border cells +// // so that count of inside would be done by many at a time +// rightCellIsDug := f.isCellDug(row, col+1) +// if f.isCellDug(row, col) { +// upCellIsDug := f.isCellDug(row-1, col) +// downCellIsDug := f.isCellDug(row+1, col) +// if !rightCellIsDug { +// if (upCellIsDug && seenDown) || (downCellIsDug && seenUp) { +// isInside = !isInside +// } +// seenUp, seenDown = false, false +// } +// } else { +// // not a dug out cell, maybe inside and needs to be dug out +// if isInside { +// // f.Cells[Coord{col, row}] = &Cell{ +// // ToBeDug: true, +// // } + +// countInside += 1 +// // log.Printf("tick count inside for %d %d", row, col) +// // cellPtr.ToBeDug = true +// } +// if rightCellIsDug { +// seenUp = f.isCellDug(row-1, col+1) +// seenDown = f.isCellDug(row+1, col+1) +// } + +// } +// } +// } +// return +// } + func (f *Field) isCellDug(row, col int) bool { cell := f.Cells[Coord{col, row}] return cell != nil && cell.IsDug diff --git a/day18/notes.org b/day18/notes.org new file mode 100644 index 0000000..a29e128 --- /dev/null +++ b/day18/notes.org @@ -0,0 +1,27 @@ +#+title: Notes +* part 2 and i'm struggling. +maybe i need to mark 'inside' cells while i dig? +i don't know which is 'outside' from the getgo? + +if i mark 'all the rightside', will that help to calculate inside? +* well, if we dont' have instruction with steps:1 i can just count points above and belove the line +without more complicated things + +just count 'seenUp' and 'seenDown' if equal - then we changed side + +and - we shouldn't have 'step1' because all numbers are soooo big. + +ok. let's do that? with maps of cols. +** CANCELLED add map[row]map[col]any +** CANCELLED separate method to set it up after we have all of the BorderCellCols +** CANCELLED during digInsides on each consecutive - check above and below and count +when there's a jump - compare counts, to make decision on whether to switch 'isInside' +** 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 +this seems reasonable. +** TODO i guess []SpecialSymbol which has Col and Symbol +** TODO then different logic on border building. +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' + +for L \ R - on last - calc what the turn was