Skip to content

Commit c103610

Browse files
committed
Day 4: part 1
1 parent f14ece9 commit c103610

File tree

2 files changed

+56
-13
lines changed

2 files changed

+56
-13
lines changed

src/main/scala/Day04.scala

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1+
import Day04.Grid.*
12
import cats.data.Store
23
import cats.syntax.all.*
34

45
object Day04:
56

67
case class Word(s: String):
78
val length: Int = s.length
8-
val toOptionChars: List[Option[Char]] = s.toList.map(Some.apply)
9+
val toOptionalChars: List[Option[Char]] = s.toList.map(_.some)
10+
def reverse: Word = Word(s.reverse)
911

1012
case class Pos(row: Int, col: Int)
1113

@@ -21,28 +23,58 @@ object Day04:
2123

2224
val toVectors: Vector[Vector[Char]] = rows.map(_.toVector).toVector
2325

24-
def toStore: StoreGrid = Store(
26+
val toStore: StoreGrid = Store(
2527
p => toVectors.get(p.row).flatMap(_.get(p.col)),
2628
s = Pos.zero
2729
)
2830

29-
def allPositions: List[Pos] =
31+
val allPositions: List[Pos] =
3032
rows.zipWithIndex.flatMap((row, rowIndex) => row.zipWithIndex.map((_, colIndex) => Pos(rowIndex, colIndex)))
3133

34+
def allWordChecks(w: Word): List[WordCheckResult] =
35+
toStore
36+
.coflatMap(s =>
37+
List(
38+
horizontalPositions,
39+
verticalPositions,
40+
ascDiagonalPositions,
41+
descDiagonalPositions
42+
).map(wordCheck(_)(w, s))
43+
)
44+
.experiment(_ => allPositions)
45+
.flatten
46+
47+
def allOccurrences(s: String): Int =
48+
val w = Word(s)
49+
(allWordChecks(w) ++ allWordChecks(w.reverse)).foldMap {
50+
case WordCheckResult.Found => 1
51+
case WordCheckResult.NotFound => 0
52+
}
53+
3254
object Grid:
3355

3456
def parse(rows: List[String]): Option[Grid] = Grid(rows = rows.map(_.toList)).some
3557

58+
def wordCheck(positions: Word => Pos => List[Pos])(w: Word, store: StoreGrid): WordCheckResult =
59+
if w.toOptionalChars == store.experiment(positions(w)) then WordCheckResult.Found else WordCheckResult.NotFound
60+
3661
/*
3762
XMAS
3863
....
3964
....
4065
....
4166
*/
42-
def topLeftPositions(w: Word)(from: Pos): List[Pos] =
67+
def horizontalPositions(w: Word)(from: Pos): List[Pos] =
4368
List.range(start = from.col, end = from.col + w.length).map(col => Pos(from.row, col))
4469

45-
def wordCheckTopLeft(w: Word, store: StoreGrid): WordCheckResult = wordCheck(topLeftPositions, w, store)
70+
/*
71+
X...
72+
M...
73+
A...
74+
S...
75+
*/
76+
def verticalPositions(w: Word)(from: Pos): List[Pos] =
77+
List.range(start = from.row, end = from.row + w.length).map(row => Pos(row, from.col))
4678

4779
/*
4880
...S
@@ -53,8 +85,6 @@ object Day04:
5385
def ascDiagonalPositions(w: Word)(from: Pos): List[Pos] =
5486
List.range(start = 0, end = w.length).reverse.map(i => Pos(row = i + from.row, col = w.length - i - 1 + from.col))
5587

56-
def wordCheckAscDiagonal(w: Word, store: StoreGrid): WordCheckResult = wordCheck(ascDiagonalPositions, w, store)
57-
5888
/*
5989
X...
6090
.M..
@@ -63,8 +93,3 @@ object Day04:
6393
*/
6494
def descDiagonalPositions(w: Word)(from: Pos): List[Pos] =
6595
List.range(start = 0, end = w.length).map(i => Pos(row = i + from.row, col = i + from.col))
66-
67-
def wordCheckDescDiagonal(w: Word, store: StoreGrid): WordCheckResult = wordCheck(descDiagonalPositions, w, store)
68-
69-
def wordCheck(positions: Word => Pos => List[Pos], w: Word, store: StoreGrid): WordCheckResult =
70-
if w.toOptionChars == store.experiment(positions(w)) then WordCheckResult.Found else WordCheckResult.NotFound

src/test/scala/Day04Suite.scala

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class Day04Suite extends ScalaCheckSuite:
3434

3535
test("topLeftPositions example"):
3636
assertEquals(
37-
Grid.topLeftPositions(Word("XYZ"))(from = Pos(row = 2, col = 4)),
37+
Grid.horizontalPositions(Word("XYZ"))(from = Pos(row = 2, col = 4)),
3838
List(
3939
Pos(row = 2, col = 4),
4040
Pos(row = 2, col = 5),
@@ -62,6 +62,24 @@ class Day04Suite extends ScalaCheckSuite:
6262
)
6363
)
6464

65+
test("small input contains 18 occurrences of \"XMAS\""):
66+
val smallInput = List(
67+
"MMMSXXMASM",
68+
"MSAMXMSMSA",
69+
"AMXSXMAAMM",
70+
"MSAMASMSMX",
71+
"XMASAMXAMM",
72+
"XXAMMXXAMA",
73+
"SMSMSASXSS",
74+
"SAXAMASAAA",
75+
"MAMMMXMMMM",
76+
"MXMXAXMASX"
77+
)
78+
assertEquals(Grid.parse(smallInput).map(_.allOccurrences("XMAS")), 18.some)
79+
80+
test("big input contains 2_578 occurrences of \"XMAS\""):
81+
assertEquals(Grid.parse(bigInput).map(_.allOccurrences("XMAS")), 2_578.some)
82+
6583
object Day04Suite:
6684

6785
val bigInput: List[String] = getLinesFromFile("src/test/scala/day04_input.txt")

0 commit comments

Comments
 (0)