day 9
This commit is contained in:
parent
49134bff05
commit
e4d2bbeb49
2 changed files with 132 additions and 13 deletions
|
@ -22,25 +22,29 @@ fn calculate_checksum(filemap: Dict(Int, Int)) -> Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compact(filemap: Dict(Int, Int)) -> Dict(Int, Int) {
|
fn compact(filemap: Dict(Int, Int)) -> Dict(Int, Int) {
|
||||||
filemap
|
let keys =
|
||||||
|> dict.keys
|
filemap
|
||||||
|
|> dict.keys
|
||||||
|
|> list.sort(int.compare)
|
||||||
|
|
||||||
|
let to_move = keys |> list.reverse
|
||||||
|
|
||||||
|
keys
|
||||||
|> find_gaps
|
|> find_gaps
|
||||||
|> list.fold_until(filemap, fn(acc, gap) {
|
|> list.fold_until(#(filemap, to_move), fn(acc, gap) {
|
||||||
case
|
let #(fmap, fdata) = acc
|
||||||
acc
|
case fdata {
|
||||||
|> dict.keys
|
[x, ..] if x <= gap -> Stop(acc)
|
||||||
|> list.reverse
|
[x, ..rest] ->
|
||||||
|> list.first
|
case dict.get(fmap, x) {
|
||||||
{
|
Ok(val) ->
|
||||||
Ok(x) if x <= gap -> Stop(acc)
|
Continue(#(fmap |> dict.delete(x) |> dict.insert(gap, val), rest))
|
||||||
Ok(x) ->
|
|
||||||
case dict.get(acc, x) {
|
|
||||||
Ok(val) -> Continue(acc |> dict.delete(x) |> dict.insert(gap, val))
|
|
||||||
_ -> Stop(acc)
|
_ -> Stop(acc)
|
||||||
}
|
}
|
||||||
_ -> Stop(acc)
|
_ -> Stop(acc)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|> pair.first
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_gaps(nums: List(Int)) -> List(Int) {
|
fn find_gaps(nums: List(Int)) -> List(Int) {
|
||||||
|
|
115
src/day9_p2.gleam
Normal file
115
src/day9_p2.gleam
Normal 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
|
||||||
|
}
|
Loading…
Reference in a new issue