diff options
author | Hunky Jimpjorps <thechairman@thechairman.info> | 2024-02-02 17:05:12 -0500 |
---|---|---|
committer | Hunky Jimpjorps <thechairman@thechairman.info> | 2024-02-02 17:05:12 -0500 |
commit | 48e35ad3b0b0c62f936784e4aca70b17c3b0e3f9 (patch) | |
tree | f59a13e0b5e80ab925220b4488c6e36b1bec660a /aoc2023/src/day5/solve.gleam | |
parent | 87e9ab25ff70e215b537939a4bc23ab101f41dbe (diff) | |
download | gleam_aoc-48e35ad3b0b0c62f936784e4aca70b17c3b0e3f9.tar.gz gleam_aoc-48e35ad3b0b0c62f936784e4aca70b17c3b0e3f9.zip |
renaming
Diffstat (limited to 'aoc2023/src/day5/solve.gleam')
-rw-r--r-- | aoc2023/src/day5/solve.gleam | 167 |
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 - } -} |