From 554a3cb389f33b366482cbd1df3eb9de01a9ae72 Mon Sep 17 00:00:00 2001 From: efim Date: Sat, 9 Dec 2023 15:57:51 +0000 Subject: [PATCH] day9, example --- day9/dayNine.go | 203 ++++++++++++++++++++++++++++++++++++++++++++++++ day9/example | 3 + main.go | 17 +++- 3 files changed, 220 insertions(+), 3 deletions(-) create mode 100644 day9/dayNine.go create mode 100644 day9/example diff --git a/day9/dayNine.go b/day9/dayNine.go new file mode 100644 index 0000000..778c3af --- /dev/null +++ b/day9/dayNine.go @@ -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 +} diff --git a/day9/example b/day9/example new file mode 100644 index 0000000..539a763 --- /dev/null +++ b/day9/example @@ -0,0 +1,3 @@ +0 3 6 9 12 15 +1 3 6 10 15 21 +10 13 16 21 30 45 diff --git a/main.go b/main.go index 3bdcc98..78074e9 100644 --- a/main.go +++ b/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) }