Skip to content

Commit

Permalink
Day 9 Part 1
Browse files Browse the repository at this point in the history
  • Loading branch information
kodfodrasz committed Jan 3, 2025
1 parent 9d06701 commit 79067f4
Show file tree
Hide file tree
Showing 4 changed files with 219 additions and 0 deletions.
84 changes: 84 additions & 0 deletions Kodfodrasz.AoC.Year2024.Tests/Day9Tests.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
module Kodfodrasz.AoC.Year2024.Tests.Day9Tests

open Xunit
open Swensen.Unquote.Assertions

open Kodfodrasz.AoC
open Kodfodrasz.AoC.Year2024
open Kodfodrasz.AoC.Year2024.Day9


let exampleInput = """
2333133121414131402
"""

[<Fact>]
let ``Parsing example input`` () =
let expected = [|
File (0, 2, 0)
Free (2, 3)
File (5, 3, 1)
Free (8, 3)
File (11, 1, 2)
Free (12, 3)
File (15, 3, 3)
Free (18, 1)
File (19, 2, 4)
Free (21, 1)
File (22, 4, 5)
Free (26, 1)
File (27, 4, 6)
Free (31, 1)
File (32, 3, 7)
Free (35, 1)
File (36, 4, 8)
Free (40, 0)
File (40, 2, 9)
|]

test
<@ let actual = parseInput exampleInput
actual = Ok expected @>


[<Fact>]
let ``Parsing example input for 12345`` () =
test
<@
let expected = Ok [|
File (0, 1, 0)
Free (1, 2)
File (3, 3, 1)
Free (6, 4)
File (10, 5, 2)
|]
let actual = parseInput "12345"
actual = expected
@>

[<Fact>]
let ``Answer 1 for example input for 12345`` () =
let blocks = parseInput "12345" |> Result.get
// BLOCKS BEFORE: 0..111....22222
// BLOCKS AFTER : 022111222
// POS : 0123456789
// CHECKSUM : 60 = 0 + 2 + 4 + 3 + 4 + 5 + 12 + 14 + 16
test <@ answer1 blocks = Ok 60L @>

[<Fact>]
let ``Answer 1 for example input`` () =
let input = parseInput exampleInput

test
<@ let actual = Result.bind answer1 input
let expected: Result<_, string> = Ok 1928L
actual = expected @>

[<Fact(Skip="TODO")>]
let ``Answer 2 for example input`` () =
let input = parseInput exampleInput

test
<@ let actual = Result.bind answer2 input
let expected: Result<_, string> = Ok 31L
actual = expected @>
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<Compile Include="Day6Tests.fs" />
<Compile Include="Day7Tests.fs" />
<Compile Include="Day8Tests.fs" />
<Compile Include="Day9Tests.fs" />
<Compile Include="Day10Tests.fs" />
<Compile Include="Day11Tests.fs" />
<Compile Include="Day13Tests.fs" />
Expand Down
133 changes: 133 additions & 0 deletions Kodfodrasz.AoC.Year2024/Day9.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
module Kodfodrasz.AoC.Year2024.Day9

open System
open System.Text.RegularExpressions
open Kodfodrasz.AoC
open System.Collections.Generic

type Block =
| File of pos : int * size : int * id : int
| Free of pos : int * size : int

let pos = function
| File(pos, _, _) -> pos
| Free(pos, _) -> pos

let size = function
| File(_, size, _) -> size
| Free(_, size) -> size

let fid = function
| File(_, _, _id) -> _id
| Free(_, _) -> failwith "Not a file"

type BlockPosComparer() =
interface IComparer<Block> with
member _.Compare(x, y) =
compare (pos x) (pos y)

type parsedInput = Block array
let parseInput (input: string): Result<parsedInput,string> =
let numbers =
input.Split('\n', StringSplitOptions.TrimEntries ||| StringSplitOptions.RemoveEmptyEntries)
|> Seq.collect(String.toCharArray)
|> Seq.map (string >> int)
|> Seq.toArray

let blocks =
numbers
|> Array.fold (fun (id, pos, l) n ->
match l with
| [] | Free _ :: _ ->
let f = File(pos, n, id)
(id + 1, pos + n, f :: l)
| File _ :: _->
let f = Free(pos, n)
(id, pos + n, f :: l)
) (0, 0, List.empty)
|> (fun (_, _, l) -> List.rev l)

blocks
|> List.toArray
|> Ok

let checksum blocks =
Seq.sumBy(function
| File(pos, size, id) ->
let mutable sum = 0L
for x in 0 .. size - 1 do
sum <- sum + int64(pos + x) * int64(id)
sum
| Free _ -> 0
) blocks

let defrag1 blocks : Block array =
let blocks = System.Collections.Generic.List<Block>(blocks :> Block seq)

let cmp = BlockPosComparer()
let mutable fragmented = true
while fragmented do
let firstFreeIdx = blocks.FindIndex(function
| Free (pos, size) -> size > 0
| _ -> false)
let lastFileIdx = blocks.FindLastIndex(function
| File(pos, size, id) -> true
| _ -> false)

fragmented <- firstFreeIdx >= 0 && lastFileIdx >= 0

if fragmented then
let free = blocks[firstFreeIdx]
let file = blocks[lastFileIdx]

if pos free > pos file then
blocks.RemoveAt(firstFreeIdx)
elif size free = size file then
blocks[firstFreeIdx] <- File(
pos free,
size file,
fid file)
blocks.RemoveAt(lastFileIdx)
elif size free > size file then
blocks[lastFileIdx] <- File(
pos free,
size file,
fid file)
blocks[firstFreeIdx] <- Free(
pos free + size file,
size free - size file)
else // file is bigger
blocks[firstFreeIdx] <- File(
pos free,
size free,
fid file)
blocks[lastFileIdx] <- File(
pos file,
size file - size free,
fid file)
blocks.Sort(cmp)

blocks.ToArray()

let answer1 (blocks : parsedInput) =
blocks
|> defrag1
|> checksum
|> Ok

let answer2 (data : parsedInput) =
failwith "TODO"

type Solver() =
inherit SolverBase("Disk Fragmenter")
with
override this.Solve input =
input
|>
this.DoSolve
(parseInput)
[
answer1;
answer2;
]

1 change: 1 addition & 0 deletions Kodfodrasz.AoC.Year2024/Kodfodrasz.AoC.Year2024.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<Compile Include="Day6.fs" />
<Compile Include="Day7.fs" />
<Compile Include="Day8.fs" />
<Compile Include="Day9.fs" />
<Compile Include="Day10.fs" />
<Compile Include="Day11.fs" />
<Compile Include="Day13.fs" />
Expand Down

0 comments on commit 79067f4

Please sign in to comment.