This commit is contained in:
Hamcha 2024-12-09 17:49:48 +01:00
parent 49134bff05
commit e4d2bbeb49
2 changed files with 132 additions and 13 deletions

View file

@ -22,25 +22,29 @@ fn calculate_checksum(filemap: Dict(Int, Int)) -> Int {
}
fn compact(filemap: Dict(Int, Int)) -> Dict(Int, Int) {
filemap
|> dict.keys
let keys =
filemap
|> dict.keys
|> list.sort(int.compare)
let to_move = keys |> list.reverse
keys
|> find_gaps
|> list.fold_until(filemap, fn(acc, gap) {
case
acc
|> dict.keys
|> list.reverse
|> list.first
{
Ok(x) if x <= gap -> Stop(acc)
Ok(x) ->
case dict.get(acc, x) {
Ok(val) -> Continue(acc |> dict.delete(x) |> dict.insert(gap, val))
|> list.fold_until(#(filemap, to_move), fn(acc, gap) {
let #(fmap, fdata) = acc
case fdata {
[x, ..] if x <= gap -> Stop(acc)
[x, ..rest] ->
case dict.get(fmap, x) {
Ok(val) ->
Continue(#(fmap |> dict.delete(x) |> dict.insert(gap, val), rest))
_ -> Stop(acc)
}
_ -> Stop(acc)
}
})
|> pair.first
}
fn find_gaps(nums: List(Int)) -> List(Int) {

115
src/day9_p2.gleam Normal file
View file

@ -0,0 +1,115 @@
import gleam/int
import gleam/io
import gleam/iterator
import gleam/list.{fold, map}
import gleam/result
import gleam/string
import stdin.{stdin}
pub fn main() {
stdin()
|> read_input
|> compact
|> calculate_checksum
|> io.debug
}
fn calculate_checksum(filemap: List(Segment)) -> Int {
filemap
|> fold(0, fn(acc, next) {
case next {
File(pos, index, size) -> {
list.range(pos, pos + size - 1)
|> fold(acc, fn(total, x) { total + x * index })
}
_ -> acc
}
})
}
fn compact(filemap: List(Segment)) -> List(Segment) {
filemap
|> list.reverse
|> fold(filemap, fn(acc, next) {
case next {
File(pos, index, size) -> {
let next_gap =
list.find(acc, fn(x) {
case x {
Gap(gap_pos, gap_size) if gap_pos < pos && gap_size >= size ->
True
_ -> False
}
})
case next_gap {
Ok(Gap(gap_pos, _)) -> fill_gap(acc, gap_pos, index, size)
_ -> acc
}
}
_ -> acc
}
})
}
fn fill_gap(
segments: List(Segment),
gap_pos: Int,
file_index: Int,
file_size: Int,
) -> List(Segment) {
segments
|> fold([], fn(acc, s) {
case s {
Gap(pos, size) if pos == gap_pos && size == file_size -> [
File(pos, file_index, file_size),
..acc
]
Gap(pos, size) if pos == gap_pos -> [
Gap(pos + file_size, size - file_size),
File(pos, file_index, file_size),
..acc
]
File(pos, index, size) if file_index == index -> [Gap(pos, size), ..acc]
_ -> [s, ..acc]
}
})
|> list.reverse
}
pub type Segment {
File(position: Int, index: Int, size: Int)
Gap(position: Int, size: Int)
}
fn read_input(it: iterator.Iterator(String)) -> List(Segment) {
let assert Ok(numbers) =
it
|> iterator.to_list
|> map(fn(line) {
line
|> string.trim
|> string.to_graphemes
|> map(int.parse)
})
|> list.flatten
|> result.all
numbers
|> list.index_fold(#([], 0, 0), fn(acc, size, i) {
let #(segments, index, position) = acc
case i % 2 == 0 {
True -> #(
[File(position, index, size), ..segments],
index + 1,
position + size,
)
False -> #([Gap(position, size), ..segments], index, position + size)
}
})
|> fn(x) {
let #(segments, _, _) = x
segments
}
|> list.reverse
}