Skip to content

Commit 588a279

Browse files
committed
Refactoring 2024-06 Scala 2
1 parent 1af0dbb commit 588a279

File tree

6 files changed

+88
-24
lines changed

6 files changed

+88
-24
lines changed

rust/Cargo.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/common/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ num-traits.workspace = true
1616
num-derive.workspace = true
1717
itertools.workspace = true
1818
md5.workspace = true
19+
bit-set.workspace = true

rust/y2024/Cargo.toml

-1
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,3 @@ advent-of-code-common = { path = "../common" }
1414
chumsky.workspace = true
1515
itertools.workspace = true
1616
regex.workspace = true
17-
bit-set.workspace = true

scala2/src/main/scala/jurisk/adventofcode/Advent00.scala

+5-4
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,20 @@ import org.scalatest.matchers.should.Matchers._
88

99
object Advent00 {
1010
type Input = List[Command]
11+
type N = Long
1112

1213
sealed trait Command extends Product with Serializable
1314
object Command {
1415
case object Noop extends Command
1516
final case class Something(
16-
values: List[Int]
17+
values: List[N]
1718
) extends Command
1819
final case class Other(value: String) extends Command
1920

2021
def parse(s: String): Command =
2122
s match {
2223
case "noop" => Noop
23-
case s"something $rem" => Something(rem.extractIntList)
24+
case s"something $rem" => Something(rem.extractLongList)
2425
case s if s.nonEmpty => Other(s)
2526
case _ => s.failedToParse
2627
}
@@ -29,10 +30,10 @@ object Advent00 {
2930
def parse(input: String): Input =
3031
input.parseLines(Command.parse)
3132

32-
def part1(data: Input): Int =
33+
def part1(data: Input): N =
3334
0
3435

35-
def part2(data: Input): Int =
36+
def part2(data: Input): N =
3637
0
3738

3839
def parseFile(fileName: String): Input =

scala2/src/main/scala/jurisk/adventofcode/y2024/Advent06.scala

+22-18
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package jurisk.adventofcode.y2024
33
import cats.implicits._
44
import jurisk.adventofcode.y2024.Advent06.Block.Empty
55
import jurisk.adventofcode.y2024.Advent06.Block.Wall
6+
import jurisk.collections.mutable.BitSetKey
7+
import jurisk.collections.mutable.MutableBitSet
68
import jurisk.geometry.Coords2D
79
import jurisk.geometry.Direction2D
810
import jurisk.geometry.Direction2D.CardinalDirection2D
@@ -21,11 +23,6 @@ object Advent06 {
2123

2224
type Input = (Coords2D, Field2D[Block])
2325

24-
final private case class GuardWithVisitedLog(
25-
guard: Guard,
26-
visited: Set[Coords2D],
27-
)
28-
2926
final private case class Guard(
3027
location: Coords2D,
3128
direction: CardinalDirection2D,
@@ -57,24 +54,30 @@ object Advent06 {
5754
(location, field)
5855
}
5956

60-
private def guardsPath(data: Input): Set[Coords2D] = {
61-
// TODO: Try a BitSet instead of a Set?
62-
57+
private def guardsPath(data: Input): MutableBitSet[Coords2D] = {
6358
val (location, field) = data
64-
val state =
65-
GuardWithVisitedLog(Guard(location, Direction2D.N), Set(location))
59+
60+
implicit val key: BitSetKey[Coords2D] = new BitSetKey[Coords2D] {
61+
def toInt(value: Coords2D): Int = value.x + value.y * field.width
62+
def fromInt(value: Int): Coords2D =
63+
Coords2D(value % field.width, value / field.width)
64+
}
65+
66+
val visited = MutableBitSet[Coords2D](location)
67+
68+
val state = Guard(location, Direction2D.N)
6669

6770
Simulation.run(state) { s =>
68-
s.guard.next(field) match {
71+
s.next(field) match {
6972
case Some(next) =>
70-
s.copy(
71-
guard = next,
72-
visited = s.visited + next.location,
73-
).asRight
73+
visited.add(next.location)
74+
next.asRight
7475
case None =>
75-
s.visited.asLeft
76+
().asLeft
7677
}
7778
}
79+
80+
visited
7881
}
7982

8083
def part1(data: Input): Int =
@@ -94,8 +97,9 @@ object Advent06 {
9497
val (location, field) = data
9598

9699
guardsPath(data)
97-
.filterNot(_ == location)
98-
.count(c => wouldLoop(location, field.updatedAtUnsafe(c, Wall)))
100+
.count(c =>
101+
c != location && wouldLoop(location, field.updatedAtUnsafe(c, Wall))
102+
)
99103
}
100104

101105
def parseFile(fileName: String): Input =
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package jurisk.collections.mutable
2+
3+
import jurisk.collections.mutable.BitSetKeySyntax.BitSetKeyOps1
4+
import jurisk.collections.mutable.BitSetKeySyntax.BitSetKeyOps2
5+
6+
import scala.collection.mutable
7+
8+
trait BitSetKey[T] {
9+
def toInt(value: T): Int
10+
def fromInt(value: Int): T
11+
}
12+
13+
object BitSetKeyInstances {
14+
implicit val intBitSetKey: BitSetKey[Int] = new BitSetKey[Int] {
15+
def toInt(value: Int): Int = value
16+
def fromInt(value: Int): Int = value
17+
}
18+
}
19+
20+
object BitSetKeySyntax {
21+
implicit class BitSetKeyOps1[T](value: T)(implicit ev: BitSetKey[T]) {
22+
def toInt: Int = ev.toInt(value)
23+
}
24+
25+
implicit class BitSetKeyOps2[T](value: Int)(implicit ev: BitSetKey[T]) {
26+
def fromInt: T = ev.fromInt(value)
27+
}
28+
}
29+
30+
final class MutableBitSet[T: BitSetKey](
31+
private val underlying: mutable.BitSet
32+
) {
33+
private def this() =
34+
this(mutable.BitSet.empty)
35+
36+
def add(value: T): Boolean =
37+
underlying.add(value.toInt)
38+
39+
def size: Int =
40+
underlying.size
41+
42+
def filterNot(
43+
predicate: T => Boolean
44+
): MutableBitSet[T] =
45+
new MutableBitSet(underlying.filterNot(x => predicate(x.fromInt)))
46+
47+
def count(
48+
predicate: T => Boolean
49+
): Int =
50+
underlying.count(x => predicate(x.fromInt))
51+
}
52+
53+
object MutableBitSet {
54+
def apply[T: BitSetKey](values: T*): MutableBitSet[T] = {
55+
val result = new MutableBitSet[T]()
56+
values.foreach(result.add)
57+
result
58+
}
59+
}

0 commit comments

Comments
 (0)