@@ -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 }
0 commit comments