aboutsummaryrefslogtreecommitdiff
path: root/aoc2023/src/day5/solve.gleam
diff options
context:
space:
mode:
authorHunky Jimpjorps <thechairman@thechairman.info>2024-02-02 17:05:12 -0500
committerHunky Jimpjorps <thechairman@thechairman.info>2024-02-02 17:05:12 -0500
commit48e35ad3b0b0c62f936784e4aca70b17c3b0e3f9 (patch)
treef59a13e0b5e80ab925220b4488c6e36b1bec660a /aoc2023/src/day5/solve.gleam
parent87e9ab25ff70e215b537939a4bc23ab101f41dbe (diff)
downloadgleam_aoc-48e35ad3b0b0c62f936784e4aca70b17c3b0e3f9.tar.gz
gleam_aoc-48e35ad3b0b0c62f936784e4aca70b17c3b0e3f9.zip
renaming
Diffstat (limited to 'aoc2023/src/day5/solve.gleam')
-rw-r--r--aoc2023/src/day5/solve.gleam167
1 files changed, 0 insertions, 167 deletions
diff --git a/aoc2023/src/day5/solve.gleam b/aoc2023/src/day5/solve.gleam
deleted file mode 100644
index 58e2ae0..0000000
--- a/aoc2023/src/day5/solve.gleam
+++ /dev/null
@@ -1,167 +0,0 @@
-import adglent.{First, Second}
-import gleam/io
-import gleam/string
-import gleam/result
-import gleam/list.{Continue, Stop}
-import gleam/int
-import gleam/function
-
-// Types -------------------------------------------------------------------------------------------
-
-pub type Almanac {
- Almanac(seeds: List(Int), mappers: List(Mapper))
-}
-
-pub type MappingRange {
- MRange(start: Int, end: Int, offset: Int)
-}
-
-pub type SeedRange {
- SRange(start: Int, end: Int)
-}
-
-type Mapper =
- List(MappingRange)
-
-// Parsing -----------------------------------------------------------------------------------------
-
-fn parse_input(input: String) {
- let assert ["seeds: " <> raw_seeds, ..raw_mappers] =
- string.split(input, on: "\n\n")
-
- let seeds = string_to_int_list(raw_seeds)
- let mappers =
- list.map(
- raw_mappers,
- function.compose(string.split(_, on: "\n"), parse_mapper),
- )
- Almanac(seeds, mappers)
-}
-
-fn string_to_int_list(str: String) {
- str
- |> string.split(on: " ")
- |> list.map(int.parse)
- |> result.values
-}
-
-fn parse_mapper(strs: List(String)) -> Mapper {
- let assert [_, ..raw_ranges] = strs
- list.map(raw_ranges, parse_mrange)
- |> list.sort(fn(a, b) { int.compare(a.start, b.start) })
-}
-
-fn parse_mrange(str: String) -> MappingRange {
- let assert [destination, source, range_width] = string_to_int_list(str)
- MRange(source, source + range_width - 1, destination - source)
-}
-
-// Part 1 ------------------------------------------------------------------------------------------
-
-pub fn part1(input: String) {
- let Almanac(seeds, mappers) = parse_input(input)
-
- list.map(seeds, list.fold(over: mappers, from: _, with: correspond))
- |> list.reduce(int.min)
- |> result.unwrap(0)
- |> string.inspect
-}
-
-fn correspond(n: Int, mapper: Mapper) {
- use acc, mrange <- list.fold_until(over: mapper, from: n)
- case mrange.start <= acc && acc <= mrange.end {
- True -> Stop(acc + mrange.offset)
- False -> Continue(acc)
- }
-}
-
-// Part 2 ------------------------------------------------------------------------------------------
-
-pub fn part2(input: String) {
- let Almanac(seeds, mappers) = parse_input(input)
-
- let assert [SRange(answer, _), ..] =
- seeds
- |> list.sized_chunk(into: 2)
- |> list.map(fn(chunk) {
- let assert [start, length] = chunk
- [SRange(start, start + length - 1)]
- |> remap_all_seed_ranges(mappers)
- })
- |> list.flatten()
- |> list.sort(fn(a, b) { int.compare(a.start, b.start) })
-
- string.inspect(answer)
-}
-
-fn remap_all_seed_ranges(srs: List(SeedRange), mappers: List(Mapper)) {
- case mappers {
- [] -> srs
- [mapper, ..rest] ->
- list.flat_map(srs, remap_range(_, mapper))
- |> remap_all_seed_ranges(rest)
- }
-}
-
-fn remap_range(r: SeedRange, mapper: Mapper) -> List(SeedRange) {
- do_remap_range(r, mapper, [])
-}
-
-fn transform_range(r: SeedRange, mapper: MappingRange) -> SeedRange {
- SRange(r.start + mapper.offset, r.end + mapper.offset)
-}
-
-fn do_remap_range(r: SeedRange, mapper: Mapper, acc: List(SeedRange)) {
- case mapper {
- // no more mappings -> no mapping covers this range
- [] -> [r, ..acc]
- // range is to the left of current mapping -> no mapping covers this range
- [m, ..] if r.end < m.start -> [r, ..acc]
- // range is to the right of current mapping -> move to next mapping
- [m, ..ms] if r.start > m.end -> do_remap_range(r, ms, acc)
- // range is fully inside mapping -> range is transformed
- [m, ..] if r.start >= m.start && r.end <= m.end -> [
- transform_range(r, m),
- ..acc
- ]
- // range overlaps start but not end -> left side not transformed, right side transformed
- [m, ..] if r.start < m.start && r.end <= m.end -> [
- SRange(r.start, m.start - 1),
- transform_range(SRange(m.start, r.end), m),
- ..acc
- ]
- // range overlaps end but not start -> left side transformed, right side moves to next mapping
- [m, ..ms] if r.start >= m.start && r.end > m.end ->
- do_remap_range(
- SRange(m.end + 1, r.end),
- ms,
- [transform_range(SRange(r.start, m.end), m), ..acc],
- )
- // mapping is fully inside range -> left not transformed, middle transformed, right to next
- [m, ..ms] ->
- do_remap_range(
- SRange(m.end + 1, r.end),
- ms,
- [
- SRange(r.start, m.start - 1),
- transform_range(SRange(m.start, m.end), m),
- ..acc
- ],
- )
- }
-}
-
-pub fn main() {
- let assert Ok(part) = adglent.get_part()
- let assert Ok(input) = adglent.get_input("5")
- case part {
- First ->
- part1(input)
- |> adglent.inspect
- |> io.println
- Second ->
- part2(input)
- |> adglent.inspect
- |> io.println
- }
-}