day9, example
This commit is contained in:
parent
77d7355eb7
commit
554a3cb389
|
@ -0,0 +1,203 @@
|
|||
package day9
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Run() int {
|
||||
log.Println("hello day 9")
|
||||
filename := "day9/example"
|
||||
bytes, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintln("error reading file: ", err))
|
||||
}
|
||||
result := 0
|
||||
for _, line := range strings.Split(string(bytes), "\n") {
|
||||
seq := CreateSequence(line)
|
||||
next := seq.Next()
|
||||
result += next
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
type Cell struct {
|
||||
IsCached bool
|
||||
Value func() int
|
||||
SavedValue int
|
||||
}
|
||||
|
||||
func (c Cell) String() string {
|
||||
if c.IsCached {
|
||||
return fmt.Sprint(c.SavedValue)
|
||||
}
|
||||
return "*"
|
||||
}
|
||||
|
||||
func CachedCell(val int) Cell {
|
||||
valFunction := func() int {
|
||||
return val
|
||||
}
|
||||
cell := Cell{
|
||||
IsCached: true,
|
||||
Value: valFunction,
|
||||
SavedValue: val,
|
||||
}
|
||||
return cell
|
||||
|
||||
}
|
||||
|
||||
// so top row is 0. botton row is unknown before pre-processing
|
||||
type Coord struct {
|
||||
Row, Col int
|
||||
}
|
||||
func (c Coord)Equal(other Coord) bool {
|
||||
return c.Col == other.Col && c.Row == other.Row
|
||||
}
|
||||
|
||||
type Sequence struct {
|
||||
values map[Coord]Cell
|
||||
lastKnownRow int
|
||||
lastReadTop int
|
||||
zeroRowIndex int
|
||||
constRowVal int
|
||||
}
|
||||
|
||||
func (s *Sequence)Next() int {
|
||||
log.Printf(">>>> trying to get next. current last known top %d\n", s.lastReadTop)
|
||||
result := s.Get(s.lastReadTop + 1)
|
||||
s.lastReadTop += 1
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *Sequence) String() string {
|
||||
lines := ""
|
||||
for i := 0; i < s.lastKnownRow-1; i++ {
|
||||
// log.Printf("converting row %d to str\n", i)
|
||||
line := ""
|
||||
j := 0
|
||||
cell := s.GetAny(Coord{i, j})
|
||||
for cell.IsCached {
|
||||
// log.Printf("looking at cell %+v coord %d %d", cell, i, j)
|
||||
line += fmt.Sprintf("%s\t", cell)
|
||||
j += 1
|
||||
cell = s.GetAny(Coord{i, j})
|
||||
}
|
||||
lines += line
|
||||
lines += "\n"
|
||||
}
|
||||
lines += fmt.Sprintf("(%d)", s.constRowVal)
|
||||
return lines
|
||||
}
|
||||
|
||||
// TODO if zeroRowIndex == -1 would be better to return error, you know
|
||||
func (s *Sequence) GetAny(coord Coord) Cell {
|
||||
// time.Sleep(time.Millisecond * 300)
|
||||
cell, found := s.values[coord]
|
||||
row, col := coord.Row, coord.Col
|
||||
if !found {
|
||||
if row == (s.zeroRowIndex - 1) {
|
||||
log.Printf("new visit to Const\n")
|
||||
return CachedCell(s.constRowVal)
|
||||
}
|
||||
|
||||
log.Printf("creating new uncashed at %d %d\n", row, col)
|
||||
cell = Cell{
|
||||
IsCached: false,
|
||||
Value: func() int {
|
||||
if cell.IsCached {
|
||||
return cell.SavedValue
|
||||
}
|
||||
log.Printf("calc value for %d %d cell\n", row, col)
|
||||
simplerCell := s.GetAny(Coord{row + 1, col - 1})
|
||||
prevCell := s.GetAny(Coord{row, col - 1})
|
||||
value := simplerCell.Value() + prevCell.Value()
|
||||
cell.IsCached = true
|
||||
cell.SavedValue = value
|
||||
return value
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("in seq GetAny for %+v, got %+v", coord, cell)
|
||||
return cell
|
||||
}
|
||||
|
||||
func (s *Sequence) Get(n int) int {
|
||||
nCell := s.GetAny(Coord{0, n})
|
||||
return nCell.Value()
|
||||
}
|
||||
|
||||
func CreateSequence(line string) Sequence {
|
||||
seq := ReadTopRow(line)
|
||||
SetupLowerRows(&seq)
|
||||
return seq
|
||||
}
|
||||
|
||||
func ReadTopRow(line string) Sequence {
|
||||
cells := make(map[Coord]Cell)
|
||||
|
||||
maxRead := 0
|
||||
for i, numStr := range strings.Fields(line) {
|
||||
num, err := strconv.Atoi(numStr)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("error reading top row %s, value %s to int\n", line, numStr))
|
||||
}
|
||||
cell := CachedCell(num)
|
||||
cells[Coord{0, i}] = cell
|
||||
maxRead = i
|
||||
}
|
||||
|
||||
return Sequence{
|
||||
values: cells,
|
||||
zeroRowIndex: -1,
|
||||
lastReadTop: maxRead,
|
||||
}
|
||||
}
|
||||
|
||||
func SetupLowerRows(s *Sequence) {
|
||||
// need to get 'zeroValRowIndex'
|
||||
// need to get 'constRowValue'
|
||||
// and maybe don't need to get all of the intermediate? only enough to determine this
|
||||
|
||||
// after having top row, go down to row of all zeroes
|
||||
// well actually row with just 2 zeroes one after another should be it
|
||||
|
||||
// so? how just iterate
|
||||
foundZeroRow := false
|
||||
zeroRow := -1
|
||||
for i := 1; !foundZeroRow; i++ {
|
||||
// log.Printf("attempting to calc row %d\n", i)
|
||||
allZeroes := true
|
||||
|
||||
inRowCalculation:
|
||||
for j := 0; true; j++ {
|
||||
log.Printf("in row %d for index %d\n", i, j)
|
||||
topRight := s.GetAny(Coord{i-1, j+1})
|
||||
topLeft := s.GetAny(Coord{i-1, j})
|
||||
|
||||
if !topRight.IsCached || !topLeft.IsCached {
|
||||
break inRowCalculation
|
||||
}
|
||||
|
||||
calculatedValue := topRight.SavedValue - topLeft.SavedValue
|
||||
cell := CachedCell(calculatedValue)
|
||||
if calculatedValue != 0 {
|
||||
allZeroes = false
|
||||
}
|
||||
s.values[Coord{i,j}] = cell
|
||||
}
|
||||
|
||||
if allZeroes {
|
||||
foundZeroRow = true
|
||||
zeroRow = i
|
||||
}
|
||||
}
|
||||
|
||||
s.zeroRowIndex = zeroRow
|
||||
s.lastKnownRow = zeroRow
|
||||
s.constRowVal = s.GetAny(Coord{zeroRow-1, 0}).SavedValue
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
0 3 6 9 12 15
|
||||
1 3 6 10 15 21
|
||||
10 13 16 21 30 45
|
17
main.go
17
main.go
|
@ -3,12 +3,23 @@ package main
|
|||
import (
|
||||
"log"
|
||||
|
||||
"sunshine.industries/aoc2023/day8"
|
||||
"sunshine.industries/aoc2023/day9"
|
||||
)
|
||||
|
||||
func main() {
|
||||
log.Print("> starting run:")
|
||||
result := day8.Run()
|
||||
log.Printf("day8 result: %d\n****\n", result)
|
||||
|
||||
// line := "0 3 6 9 12 15"
|
||||
// line := "1 3 6 10 15 21"
|
||||
// line := "10 13 16 21 30 45"
|
||||
// seq := day9.CreateSequence(line)
|
||||
// fmt.Println(seq.String())
|
||||
|
||||
// fmt.Printf("got %+v \n", seq)
|
||||
// fmt.Printf("%s\n", seq.String())
|
||||
|
||||
// fmt.Printf("next value is %d\n", seq.Next())
|
||||
|
||||
result := day9.Run()
|
||||
log.Printf("day9 result: %d\n****\n", result)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue