day21: saturation logic, but removing points to early
This commit is contained in:
parent
840773fd16
commit
4cb35dca33
|
@ -39,3 +39,52 @@ my input is 131 chars of width.
|
||||||
so neighboring are necessarily of different phase.
|
so neighboring are necessarily of different phase.
|
||||||
could compute phase of (0,0)
|
could compute phase of (0,0)
|
||||||
and adjust from that
|
and adjust from that
|
||||||
|
** TODO remake 'ReachableBySteps' into 'CountReachableBySteps' returning int
|
||||||
|
** TODO make it take 'isInitialCountOdd' - to know phase of {0,0} field
|
||||||
|
current phase can be determined by initial phase and current N
|
||||||
|
|
||||||
|
if initial count is odd, and now it's odd number, we made even iterations, so (0,0) is in even state
|
||||||
|
if initial count is even, and now it's even number, we made even iterations, so (0,0) is in even state
|
||||||
|
|
||||||
|
** DONE make neighbors take set of saturated fields
|
||||||
|
and not produce points on those fields
|
||||||
|
** DONE for field calculate what would be amount of points in each phase
|
||||||
|
...........
|
||||||
|
.....###.#.
|
||||||
|
.###.##..#.
|
||||||
|
..#.#...#..
|
||||||
|
....#.#....
|
||||||
|
.##..S####.
|
||||||
|
.##..#...#.
|
||||||
|
.......##..
|
||||||
|
.##.#.####.
|
||||||
|
.##..##.##.
|
||||||
|
...........
|
||||||
|
*** getting 39 and 42
|
||||||
|
let's check
|
||||||
|
42 is even?
|
||||||
|
*** hmmm
|
||||||
|
EOEOEOEOEOE
|
||||||
|
OEOEO###O#O
|
||||||
|
E###E##OE#E
|
||||||
|
OE#E#EOE#EO
|
||||||
|
EOEO#O#OEOE
|
||||||
|
O##EOE####O
|
||||||
|
E##OE#EOE#E
|
||||||
|
OEOEOEO##EO
|
||||||
|
E##O#O####E
|
||||||
|
O##EO##E##O
|
||||||
|
EOEOEOEOEOE
|
||||||
|
*** yes, sounds good
|
||||||
|
|
||||||
|
|
||||||
|
** TODO after getting all new points. get coords of all fields we're working on.
|
||||||
|
( there already should be no points in saturated fields )
|
||||||
|
for each such field, check if it is saturated.
|
||||||
|
|
||||||
|
- can be done by comparing the phase with amount of points on saturated
|
||||||
|
|
||||||
|
if field saturated - add the coord into set
|
||||||
|
and remove all the points
|
||||||
|
** TODO on the last step, when n is 0
|
||||||
|
return len(startingAt) + (all saturated fields) * (amount of elems in their phase)
|
||||||
|
|
|
@ -7,12 +7,15 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Run() int {
|
func Run() (result int) {
|
||||||
fmt.Print("hello day21")
|
fmt.Print("hello day21")
|
||||||
filename := "day21/example"
|
filename := "day21/example"
|
||||||
field := ReadField(filename)
|
field := ReadField(filename)
|
||||||
log.Print(field)
|
log.Print(field)
|
||||||
|
|
||||||
|
initialSaturatedFields := make(map[Coord]any)
|
||||||
|
log.Print(initialSaturatedFields)
|
||||||
|
|
||||||
// for i := 6; i <= 10; i++ {
|
// for i := 6; i <= 10; i++ {
|
||||||
// reachableBySteps := field.ReachableBySteps(i, map[Coord]any{
|
// reachableBySteps := field.ReachableBySteps(i, map[Coord]any{
|
||||||
// Coord{Row: field.RowStart, Col: field.ColStart}: struct{}{},
|
// Coord{Row: field.RowStart, Col: field.ColStart}: struct{}{},
|
||||||
|
@ -22,14 +25,19 @@ func Run() int {
|
||||||
// field.PrintCoord(reachableBySteps, 1)
|
// field.PrintCoord(reachableBySteps, 1)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
steps := 100
|
steps := 50
|
||||||
reachableBySteps := field.ReachableBySteps(steps, map[FieldPoint]any{
|
reachableBySteps := field.ReachableBySteps(
|
||||||
FieldPoint{
|
steps,
|
||||||
InField: Coord{Row: field.RowStart, Col: field.ColStart},
|
map[FieldPoint]any{
|
||||||
}: struct{}{},
|
FieldPoint{
|
||||||
})
|
InField: Coord{Row: field.RowStart, Col: field.ColStart},
|
||||||
|
}: struct{}{}},
|
||||||
|
make(map[Coord]any),
|
||||||
|
steps)
|
||||||
|
result = reachableBySteps
|
||||||
|
log.Print("reachable after steps : ", steps, result)
|
||||||
|
|
||||||
return len(reachableBySteps)
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// let's do dijkstra?
|
// let's do dijkstra?
|
||||||
|
@ -38,8 +46,9 @@ func Run() int {
|
||||||
// OR. just breath first traversal
|
// OR. just breath first traversal
|
||||||
|
|
||||||
type Field struct {
|
type Field struct {
|
||||||
RowStart, ColStart int
|
RowStart, ColStart int
|
||||||
symbols [][]rune
|
symbols [][]rune
|
||||||
|
SaturatedEvenCount, SaturatedOddCount int
|
||||||
}
|
}
|
||||||
|
|
||||||
type Coord struct {
|
type Coord struct {
|
||||||
|
@ -51,31 +60,86 @@ type FieldPoint struct {
|
||||||
MetaField Coord
|
MetaField Coord
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f Field) ReachableBySteps(n int, startingAt map[FieldPoint]any) map[FieldPoint]any {
|
func (f Field) ReachableBySteps(n int, startingAt map[FieldPoint]any, saturatedFields map[Coord]any, initialSteps int) (countReachable int) {
|
||||||
if n%100 == 0 {
|
if n%100 == 0 {
|
||||||
log.Println("going step: ", n)
|
log.Println("going step: ", n)
|
||||||
}
|
}
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return startingAt
|
sizeOfUnsaturated := len(startingAt)
|
||||||
|
sizeOfSaturated := 0
|
||||||
|
// log.Printf("> before adding saturated fields. central is in even %t\n", CentralFieldIsInEven(initialSteps, n))
|
||||||
|
for saturatedField := range saturatedFields {
|
||||||
|
isEven := FieldIsInEven(initialSteps, n, saturatedField)
|
||||||
|
// log.Printf("> adding saturated field %+v. it is in even %t\n", saturatedField, isEven)
|
||||||
|
if isEven {
|
||||||
|
sizeOfSaturated += f.SaturatedEvenCount
|
||||||
|
} else {
|
||||||
|
sizeOfSaturated += f.SaturatedOddCount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sizeOfUnsaturated
|
||||||
}
|
}
|
||||||
// else collect directly available
|
// else collect directly available
|
||||||
|
|
||||||
oneStepExpanded := make(map[FieldPoint]any)
|
oneStepExpanded := make(map[FieldPoint]any)
|
||||||
for cur := range startingAt {
|
for cur := range startingAt {
|
||||||
for _, neighbor := range f.Neighbors(cur) {
|
for _, neighbor := range f.Neighbors(cur, saturatedFields) {
|
||||||
oneStepExpanded[neighbor] = struct{}{}
|
oneStepExpanded[neighbor] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if n < 4 {
|
metaFields := make(map[Coord]int)
|
||||||
log.Print("reachable after steps : ", n, len(oneStepExpanded))
|
for next := range oneStepExpanded {
|
||||||
f.PrintCoord(oneStepExpanded, 5)
|
metaFields[next.MetaField] += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
return f.ReachableBySteps(n-1, oneStepExpanded)
|
for workedUponFieldCoord, amount := range metaFields {
|
||||||
|
isEven := FieldIsInEven(initialSteps, n, workedUponFieldCoord)
|
||||||
|
if workedUponFieldCoord.Col == 0 && workedUponFieldCoord.Row == 0 {
|
||||||
|
log.Printf("checking %+v : %d as worked fields for saturation. isEven %t", workedUponFieldCoord, amount, isEven)
|
||||||
|
}
|
||||||
|
if isEven && amount == f.SaturatedEvenCount {
|
||||||
|
log.Printf(">>> adding %+v to saturated, with amount %d\n", workedUponFieldCoord, amount)
|
||||||
|
saturatedFields[workedUponFieldCoord] = struct{}{}
|
||||||
|
}
|
||||||
|
if !isEven && amount == f.SaturatedOddCount {
|
||||||
|
log.Printf(">>> adding %+v to saturated, with amount %d\n", workedUponFieldCoord, amount)
|
||||||
|
saturatedFields[workedUponFieldCoord] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for point := range oneStepExpanded {
|
||||||
|
_, fromSaturated := saturatedFields[point.MetaField]
|
||||||
|
if fromSaturated {
|
||||||
|
delete(oneStepExpanded, point)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if n < 4 {
|
||||||
|
// log.Print("reachable after steps : ", n, len(oneStepExpanded))
|
||||||
|
// f.PrintCoord(oneStepExpanded, 5)
|
||||||
|
// }
|
||||||
|
|
||||||
|
return f.ReachableBySteps(n-1, oneStepExpanded, saturatedFields, initialSteps)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f Field) Neighbors(c FieldPoint) (resut []FieldPoint) {
|
func CentralFieldIsInEven(initialSteps, currentSteps int) bool {
|
||||||
|
// off by one here because on initial step we first do 'neighbors' then comparicons
|
||||||
|
return (initialSteps-currentSteps)%2 != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func FieldIsInEven(initialSteps, currentSteps int, metaCoord Coord) bool {
|
||||||
|
centralIsInEven := CentralFieldIsInEven(initialSteps, currentSteps)
|
||||||
|
fieldIsInSyncWithCentral := (metaCoord.Col+metaCoord.Row)%2 == 0
|
||||||
|
if fieldIsInSyncWithCentral {
|
||||||
|
return centralIsInEven
|
||||||
|
} else {
|
||||||
|
return !centralIsInEven
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f Field) Neighbors(c FieldPoint, saturatedFields map[Coord]any) (resut []FieldPoint) {
|
||||||
closeCoords := []FieldPoint{
|
closeCoords := []FieldPoint{
|
||||||
{InField: Coord{Row: c.InField.Row + 1, Col: c.InField.Col}, MetaField: c.MetaField},
|
{InField: Coord{Row: c.InField.Row + 1, Col: c.InField.Col}, MetaField: c.MetaField},
|
||||||
{InField: Coord{Row: c.InField.Row - 1, Col: c.InField.Col}, MetaField: c.MetaField},
|
{InField: Coord{Row: c.InField.Row - 1, Col: c.InField.Col}, MetaField: c.MetaField},
|
||||||
|
@ -111,11 +175,10 @@ func (f Field) Neighbors(c FieldPoint) (resut []FieldPoint) {
|
||||||
for _, close := range closeCoords {
|
for _, close := range closeCoords {
|
||||||
if f.ValidCoord(close.InField.Row, close.InField.Col) {
|
if f.ValidCoord(close.InField.Row, close.InField.Col) {
|
||||||
symb := f.symbols[close.InField.Row][close.InField.Col]
|
symb := f.symbols[close.InField.Row][close.InField.Col]
|
||||||
if symb == '.' || symb == 'S' {
|
_, fieldIsAlreadySaturated := saturatedFields[close.MetaField]
|
||||||
|
if (symb == '.' || symb == 'S') && !fieldIsAlreadySaturated {
|
||||||
resut = append(resut, close)
|
resut = append(resut, close)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,6 +226,9 @@ func ReadField(filename string) (result Field) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.symbols = rows
|
result.symbols = rows
|
||||||
|
odd, even := result.PointsInEachPhase()
|
||||||
|
result.SaturatedEvenCount = even
|
||||||
|
result.SaturatedOddCount = odd
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,3 +259,30 @@ func (f Field) PrintCoord(coords map[FieldPoint]any, expandByField int) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if the field is fully saturated, what is amount of 'visited' points?
|
||||||
|
// odd - meaning one step around 'S', even - meaning with standing on 'S'
|
||||||
|
func (f Field) PointsInEachPhase() (pointsIfOddPhase, pointsIfEvenPhase int) {
|
||||||
|
remainderOfEvenPhase := (f.RowStart + f.ColStart) % 2
|
||||||
|
text := "\n"
|
||||||
|
for i, row := range f.symbols {
|
||||||
|
for j, cell := range row {
|
||||||
|
if cell != '#' {
|
||||||
|
if (i+j)%2 == remainderOfEvenPhase {
|
||||||
|
pointsIfEvenPhase += 1
|
||||||
|
text += "E"
|
||||||
|
} else {
|
||||||
|
pointsIfOddPhase += 1
|
||||||
|
text += "O"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
text += "#"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
text += "\n"
|
||||||
|
}
|
||||||
|
fmt.Println(text)
|
||||||
|
log.Printf("calculating points in even and odd phases", pointsIfEvenPhase, pointsIfOddPhase)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue