From 83399a45c2cc26ecf92dd5449130715f66600fe7 Mon Sep 17 00:00:00 2001 From: onyx-and-iris Date: Thu, 26 Dec 2024 20:09:19 +0000 Subject: [PATCH] refactor using graph struct and adjacency function --- day-04/internal/one/direction.go | 4 +- day-04/internal/one/graph.go | 17 ++++++++ day-04/internal/one/neighbours.go | 64 +++++-------------------------- day-04/internal/one/point.go | 10 +++++ day-04/internal/one/solve.go | 30 +++++++-------- day-04/internal/one/util.go | 21 ++++++++++ day-04/internal/two/direction.go | 4 +- day-04/internal/two/graph.go | 17 ++++++++ day-04/internal/two/neighbours.go | 52 +++---------------------- day-04/internal/two/point.go | 10 +++++ day-04/internal/two/solve.go | 30 +++++++-------- day-04/internal/two/util.go | 21 ++++++++++ day-04/internal/util/util.go | 21 ---------- 13 files changed, 147 insertions(+), 154 deletions(-) create mode 100644 day-04/internal/one/graph.go create mode 100644 day-04/internal/one/point.go create mode 100644 day-04/internal/one/util.go create mode 100644 day-04/internal/two/graph.go create mode 100644 day-04/internal/two/point.go create mode 100644 day-04/internal/two/util.go delete mode 100644 day-04/internal/util/util.go diff --git a/day-04/internal/one/direction.go b/day-04/internal/one/direction.go index 0a27b34..d501d07 100644 --- a/day-04/internal/one/direction.go +++ b/day-04/internal/one/direction.go @@ -1,7 +1,9 @@ package one +type direction int + const ( - N = iota + N direction = iota NE E SE diff --git a/day-04/internal/one/graph.go b/day-04/internal/one/graph.go new file mode 100644 index 0000000..d86588e --- /dev/null +++ b/day-04/internal/one/graph.go @@ -0,0 +1,17 @@ +package one + +type graph struct { + data []string +} + +func newGraph() *graph { + return &graph{} +} + +func (g *graph) valueAt(p point) rune { + return rune(g.data[p.y][p.x]) +} + +func (g *graph) isOutOfBounds(p point) bool { + return p.x < 0 || p.y < 0 || p.y >= len(g.data) || p.x >= len(g.data[p.y]) +} diff --git a/day-04/internal/one/neighbours.go b/day-04/internal/one/neighbours.go index b4fa1a3..7b7d2c9 100644 --- a/day-04/internal/one/neighbours.go +++ b/day-04/internal/one/neighbours.go @@ -1,58 +1,14 @@ package one -type neighbour struct { - x int - y int - direction int -} - -func newNeighbour(direction, x, y int) neighbour { - switch direction { - case N: - return neighbour{x, y + 1, direction} - case NE: - return neighbour{x + 1, y + 1, direction} - case E: - return neighbour{x + 1, y, direction} - case SE: - return neighbour{x + 1, y - 1, direction} - case S: - return neighbour{x, y - 1, direction} - case SW: - return neighbour{x - 1, y - 1, direction} - case W: - return neighbour{x - 1, y, direction} - case NW: - return neighbour{x - 1, y + 1, direction} - default: - return neighbour{} +func neighbours(p point) [8]point { + return [8]point{ + {y: p.y - 1, x: p.x, direction: N}, + {y: p.y - 1, x: p.x + 1, direction: NE}, + {y: p.y, x: p.x + 1, direction: E}, + {y: p.y + 1, x: p.x + 1, direction: SE}, + {y: p.y + 1, x: p.x, direction: S}, + {y: p.y + 1, x: p.x - 1, direction: SW}, + {y: p.y, x: p.x - 1, direction: W}, + {y: p.y - 1, x: p.x - 1, direction: NW}, } } - -type neighbours struct { - N neighbour - NE neighbour - E neighbour - SE neighbour - S neighbour - SW neighbour - W neighbour - NW neighbour -} - -func newNeighbours(x, y int) neighbours { - return neighbours{ - newNeighbour(N, x, y), - newNeighbour(NE, x, y), - newNeighbour(E, x, y), - newNeighbour(SE, x, y), - newNeighbour(S, x, y), - newNeighbour(SW, x, y), - newNeighbour(W, x, y), - newNeighbour(NW, x, y), - } -} - -func (n neighbours) all() [8]neighbour { - return [8]neighbour{n.N, n.NE, n.E, n.SE, n.S, n.SW, n.W, n.NW} -} diff --git a/day-04/internal/one/point.go b/day-04/internal/one/point.go new file mode 100644 index 0000000..4e8b857 --- /dev/null +++ b/day-04/internal/one/point.go @@ -0,0 +1,10 @@ +package one + +type point struct { + x, y int + direction direction +} + +func newPoint(x, y int) point { + return point{x: x, y: y} +} diff --git a/day-04/internal/one/solve.go b/day-04/internal/one/solve.go index 0e9031d..b70faef 100644 --- a/day-04/internal/one/solve.go +++ b/day-04/internal/one/solve.go @@ -3,30 +3,28 @@ package one import ( "bytes" - "github.com/onyx-and-iris/aoc2024/day-04/internal/util" - log "github.com/sirupsen/logrus" ) func Solve(buf []byte) (int, error) { r := bytes.NewReader(buf) - lines, err := util.ReadLines(r) + graph, err := readLines(r) if err != nil { return 0, err } var sum int - for i := 0; i < len(lines); i++ { - for j := 0; j < len(lines[i]); j++ { - neighbours := newNeighbours(j, i) - for _, n := range neighbours.all() { - if n.x < 0 || n.y < 0 || n.y >= len(lines) || n.x >= len(lines[i]) { - continue - } + for i := 0; i < len(graph.data); i++ { + for j := 0; j < len(graph.data[i]); j++ { + current := newPoint(j, i) + if graph.valueAt(current) == 'X' { + for _, n := range neighbours(current) { + if graph.isOutOfBounds(n) { + continue + } - if lines[i][j] == 'X' { - if checkNeighbours(n, "MAS", lines) { + if checkNeighbours(graph, n, "MAS") { sum++ } } @@ -37,19 +35,19 @@ func Solve(buf []byte) (int, error) { return sum, nil } -func checkNeighbours(n neighbour, word string, lines []string) bool { +func checkNeighbours(graph *graph, n point, word string) bool { if len(word) == 0 { log.Debug("we found a full XMAS") return true } - if n.x < 0 || n.y < 0 || n.y >= len(lines) || n.x >= len(lines[n.y]) { + if graph.isOutOfBounds(n) { return false } - if lines[n.y][n.x] != word[0] { + if graph.valueAt(n) != rune(word[0]) { return false } - return checkNeighbours(newNeighbour(n.direction, n.x, n.y), word[1:], lines) + return checkNeighbours(graph, neighbours(n)[n.direction], word[1:]) } diff --git a/day-04/internal/one/util.go b/day-04/internal/one/util.go new file mode 100644 index 0000000..f405d3d --- /dev/null +++ b/day-04/internal/one/util.go @@ -0,0 +1,21 @@ +package one + +import ( + "bufio" + "io" +) + +func readLines(r io.Reader) (*graph, error) { + graph := newGraph() + + scanner := bufio.NewScanner(r) + for scanner.Scan() { + graph.data = append(graph.data, scanner.Text()) + } + + if err := scanner.Err(); err != nil { + return nil, err + } + + return graph, nil +} diff --git a/day-04/internal/two/direction.go b/day-04/internal/two/direction.go index e8580d2..d566b4a 100644 --- a/day-04/internal/two/direction.go +++ b/day-04/internal/two/direction.go @@ -1,7 +1,9 @@ package two +type direction int + const ( - NW = iota + NW direction = iota NE SE SW diff --git a/day-04/internal/two/graph.go b/day-04/internal/two/graph.go new file mode 100644 index 0000000..7b49b9d --- /dev/null +++ b/day-04/internal/two/graph.go @@ -0,0 +1,17 @@ +package two + +type graph struct { + data []string +} + +func newGraph() *graph { + return &graph{} +} + +func (g *graph) valueAt(p point) rune { + return rune(g.data[p.y][p.x]) +} + +func (g *graph) isOutOfBounds(p point) bool { + return p.x < 0 || p.y < 0 || p.y >= len(g.data) || p.x >= len(g.data[p.y]) +} diff --git a/day-04/internal/two/neighbours.go b/day-04/internal/two/neighbours.go index d47d1df..2490887 100644 --- a/day-04/internal/two/neighbours.go +++ b/day-04/internal/two/neighbours.go @@ -1,50 +1,10 @@ package two -type neighbour struct { - x int - y int - direction int -} - -func newNeighbour(direction, x, y int) neighbour { - switch direction { - case NW: - return neighbour{x - 1, y + 1, direction} - case NE: - return neighbour{x + 1, y + 1, direction} - case SE: - return neighbour{x + 1, y - 1, direction} - case SW: - return neighbour{x - 1, y - 1, direction} - default: - return neighbour{} +func neighbours(p point) [4]point { + return [4]point{ + {p.x - 1, p.y - 1, NW}, + {p.x + 1, p.y - 1, NE}, + {p.x + 1, p.y + 1, SE}, + {p.x - 1, p.y + 1, SW}, } } - -func (n neighbour) outOfBounds(lines []string) bool { - return n.x < 0 || n.y < 0 || n.y >= len(lines) || n.x >= len(lines[0]) -} - -func (n neighbour) value(lines []string) rune { - return rune(lines[n.y][n.x]) -} - -type neighbours struct { - NW neighbour - NE neighbour - SE neighbour - SW neighbour -} - -func newNeighbours(x, y int) neighbours { - return neighbours{ - newNeighbour(NW, x, y), - newNeighbour(NE, x, y), - newNeighbour(SE, x, y), - newNeighbour(SW, x, y), - } -} - -func (n neighbours) all() [4]neighbour { - return [4]neighbour{n.NW, n.NE, n.SE, n.SW} -} diff --git a/day-04/internal/two/point.go b/day-04/internal/two/point.go new file mode 100644 index 0000000..d5cd726 --- /dev/null +++ b/day-04/internal/two/point.go @@ -0,0 +1,10 @@ +package two + +type point struct { + x, y int + direction direction +} + +func newPoint(x, y int) point { + return point{x: x, y: y} +} diff --git a/day-04/internal/two/solve.go b/day-04/internal/two/solve.go index 15e2c74..6b0ef88 100644 --- a/day-04/internal/two/solve.go +++ b/day-04/internal/two/solve.go @@ -3,29 +3,28 @@ package two import ( "bytes" "slices" - - "github.com/onyx-and-iris/aoc2024/day-04/internal/util" ) func Solve(buf []byte) (int, error) { r := bytes.NewReader(buf) - lines, err := util.ReadLines(r) + graph, err := readLines(r) if err != nil { return 0, err } var sum int - for i := 0; i < len(lines); i++ { - for j := 0; j < len(lines[i]); j++ { - if lines[i][j] == 'A' { - neighbours := newNeighbours(j, i) + for i := 0; i < len(graph.data); i++ { + for j := 0; j < len(graph.data[i]); j++ { + current := newPoint(j, i) + if graph.valueAt(current) == 'A' { if func() bool { - for _, n := range neighbours.all() { - if n.outOfBounds(lines) { + for _, n := range neighbours(current) { + if graph.isOutOfBounds(n) { return true } - if !slices.Contains([]rune{'M', 'S'}, n.value(lines)) { + + if !slices.Contains([]rune{'M', 'S'}, graph.valueAt(n)) { return true } } @@ -34,12 +33,13 @@ func Solve(buf []byte) (int, error) { continue } + ns := neighbours(current) matrix := newMatrix( - rune(lines[i][j]), - neighbours.NW.value(lines), - neighbours.NE.value(lines), - neighbours.SE.value(lines), - neighbours.SW.value(lines), + graph.valueAt(current), + graph.valueAt(ns[NW]), + graph.valueAt(ns[NE]), + graph.valueAt(ns[SE]), + graph.valueAt(ns[SW]), ) if matrix.validate() { diff --git a/day-04/internal/two/util.go b/day-04/internal/two/util.go new file mode 100644 index 0000000..18ec18f --- /dev/null +++ b/day-04/internal/two/util.go @@ -0,0 +1,21 @@ +package two + +import ( + "bufio" + "io" +) + +func readLines(r io.Reader) (*graph, error) { + graph := newGraph() + + scanner := bufio.NewScanner(r) + for scanner.Scan() { + graph.data = append(graph.data, scanner.Text()) + } + + if err := scanner.Err(); err != nil { + return nil, err + } + + return graph, nil +} diff --git a/day-04/internal/util/util.go b/day-04/internal/util/util.go deleted file mode 100644 index ab3f61a..0000000 --- a/day-04/internal/util/util.go +++ /dev/null @@ -1,21 +0,0 @@ -package util - -import ( - "bufio" - "io" -) - -func ReadLines(r io.Reader) ([]string, error) { - lines := []string{} - - scanner := bufio.NewScanner(r) - for scanner.Scan() { - lines = append(lines, scanner.Text()) - } - - if err := scanner.Err(); err != nil { - return []string{}, err - } - - return lines, nil -}