Skip to content

Commit 25fae8a

Browse files
committed
Solve 2024 day 9 part 2
1 parent a61a75e commit 25fae8a

File tree

2 files changed

+76
-28
lines changed

2 files changed

+76
-28
lines changed

src/main/scala/eu/sim642/adventofcode2024/Day9.scala

Lines changed: 62 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,6 @@ object Day9 {
1313

1414
type Filesystem = Vector[Block]
1515

16-
def defragment(filesystem: Filesystem): Filesystem = {
17-
18-
@tailrec
19-
def helper(filesystem: Filesystem, acc: Filesystem): Filesystem = {
20-
filesystem match {
21-
case (file@File(_, _)) +: newFilesystem => helper(newFilesystem, file +: acc)
22-
case (newFileSystem@Free(_) +: _) :+ Free(_) => helper(newFileSystem, acc)
23-
case Free(freeSize) +: newFileSystem :+ (file@File(id, fileSize)) =>
24-
if (freeSize == fileSize)
25-
helper(newFileSystem, file +: acc)
26-
else if (freeSize > fileSize)
27-
helper(Free(freeSize - fileSize) +: newFileSystem, file +: acc)
28-
else // freeSize < fileSize
29-
helper(newFileSystem :+ File(id, fileSize - freeSize), File(id, freeSize) +: acc)
30-
case Seq(Free(_)) | Seq() => acc.reverse
31-
}
32-
}
33-
34-
helper(filesystem, Vector.empty)
35-
}
36-
3716
def checksum(filesystem: Filesystem): Long = {
3817
filesystem.foldLeft((0L, 0))({ case ((acc, i), block) =>
3918
block match {
@@ -43,7 +22,66 @@ object Day9 {
4322
})._1
4423
}
4524

46-
def defragmentChecksum(filesystem: Filesystem): Long = checksum(defragment(filesystem))
25+
trait Part {
26+
def defragment(filesystem: Filesystem): Filesystem
27+
28+
def defragmentChecksum(filesystem: Filesystem): Long = checksum(defragment(filesystem))
29+
}
30+
31+
object Part1 extends Part {
32+
override def defragment(filesystem: Filesystem): Filesystem = {
33+
34+
@tailrec
35+
def helper(filesystem: Filesystem, acc: Filesystem): Filesystem = {
36+
filesystem match {
37+
case (file@File(_, _)) +: newFilesystem => helper(newFilesystem, file +: acc)
38+
case (newFileSystem@Free(_) +: _) :+ Free(_) => helper(newFileSystem, acc)
39+
case Free(freeSize) +: newFileSystem :+ (file@File(id, fileSize)) =>
40+
if (freeSize == fileSize)
41+
helper(newFileSystem, file +: acc)
42+
else if (freeSize > fileSize)
43+
helper(Free(freeSize - fileSize) +: newFileSystem, file +: acc)
44+
else // freeSize < fileSize
45+
helper(newFileSystem :+ File(id, fileSize - freeSize), File(id, freeSize) +: acc)
46+
case Seq(Free(_)) | Seq() => acc.reverse
47+
}
48+
}
49+
50+
helper(filesystem, Vector.empty)
51+
}
52+
}
53+
54+
object Part2 extends Part {
55+
override def defragment(filesystem: Filesystem): Filesystem = {
56+
57+
@tailrec
58+
def helper(filesystem: Filesystem, acc: Filesystem): Filesystem = {
59+
filesystem match {
60+
case newFilesystem :+ (free@Free(_)) => helper(newFilesystem, free +: acc)
61+
case newFilesystem :+ (file@File(id, fileSize)) =>
62+
val moveIndex = newFilesystem.indexWhere({
63+
case Free(freeSize) => freeSize >= fileSize
64+
case File(_, _) => false
65+
})
66+
if (moveIndex >= 0) {
67+
val (before, Free(freeSize) +: after) = newFilesystem.splitAt(moveIndex): @unchecked // TODO: return from indexWhere?
68+
val replace =
69+
if (freeSize == fileSize)
70+
Vector(file)
71+
else
72+
Vector(file, Free(freeSize - fileSize))
73+
helper(before ++ replace ++ after, Free(fileSize) +: acc)
74+
}
75+
else
76+
helper(newFilesystem, file +: acc)
77+
case Seq() => acc
78+
}
79+
}
80+
81+
helper(filesystem, Vector.empty)
82+
}
83+
}
84+
4785

4886
def parseFilesystem(input: String): Filesystem = {
4987
input.view.zipWithIndex.map({ case (size, i) =>
@@ -57,7 +95,8 @@ object Day9 {
5795
lazy val input: String = scala.io.Source.fromInputStream(getClass.getResourceAsStream("day9.txt")).mkString.trim
5896

5997
def main(args: Array[String]): Unit = {
60-
println(defragmentChecksum(parseFilesystem(input)))
98+
println(Part1.defragmentChecksum(parseFilesystem(input)))
99+
println(Part2.defragmentChecksum(parseFilesystem(input)))
61100

62101
// part 1: 1368861652 - too low (Int overflowed in checksum)
63102
}

src/test/scala/eu/sim642/adventofcode2024/Day9Test.scala

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,22 @@ class Day9Test extends AnyFunSuite {
99
val exampleInput2 = "2333133121414131402"
1010

1111
test("Part 1 examples") {
12-
//assert(defragmentChecksum(parseFilesystem(exampleInput)) == ???)
13-
//println(defragment(parseFilesystem(exampleInput)))
14-
//println(defragment(parseFilesystem(exampleInput2)))
15-
assert(defragmentChecksum(parseFilesystem(exampleInput2)) == 1928)
12+
//assert(Part1.defragmentChecksum(parseFilesystem(exampleInput)) == ???)
13+
//println(Part1.defragment(parseFilesystem(exampleInput)))
14+
//println(Part1.defragment(parseFilesystem(exampleInput2)))
15+
assert(Part1.defragmentChecksum(parseFilesystem(exampleInput2)) == 1928)
1616
}
1717

1818
test("Part 1 input answer") {
19-
assert(defragmentChecksum(parseFilesystem(input)) == 6310675819476L)
19+
assert(Part1.defragmentChecksum(parseFilesystem(input)) == 6310675819476L)
20+
}
21+
22+
test("Part 2 examples") {
23+
//println(Part2.defragment(parseFilesystem(exampleInput2)))
24+
assert(Part2.defragmentChecksum(parseFilesystem(exampleInput2)) == 2858)
25+
}
26+
27+
test("Part 2 input answer") {
28+
assert(Part2.defragmentChecksum(parseFilesystem(input)) == 6335972980679L)
2029
}
2130
}

0 commit comments

Comments
 (0)