diff options
author | HJ <thechairman@thechairman.info> | 2023-12-18 08:43:44 -0500 |
---|---|---|
committer | HJ <thechairman@thechairman.info> | 2023-12-18 08:43:44 -0500 |
commit | ee8001fe861ddb62b042a5904cfb57b5c511d2e7 (patch) | |
tree | 0cd13b5fddce0e05862297d1ef89bb538fa4ab9d | |
parent | d782a6118d7c48371912d52c1839014d0309ff5a (diff) | |
download | gleam_aoc-ee8001fe861ddb62b042a5904cfb57b5c511d2e7.tar.gz gleam_aoc-ee8001fe861ddb62b042a5904cfb57b5c511d2e7.zip |
day 18 gleam complete
-rw-r--r-- | aoc2023/src/day18/.gitignore | 1 | ||||
-rw-r--r-- | aoc2023/src/day18/solve.gleam | 113 | ||||
-rw-r--r-- | aoc2023/test/day18/day18_test.gleam | 74 |
3 files changed, 188 insertions, 0 deletions
diff --git a/aoc2023/src/day18/.gitignore b/aoc2023/src/day18/.gitignore new file mode 100644 index 0000000..ae40cea --- /dev/null +++ b/aoc2023/src/day18/.gitignore @@ -0,0 +1 @@ +input.txt
\ No newline at end of file diff --git a/aoc2023/src/day18/solve.gleam b/aoc2023/src/day18/solve.gleam new file mode 100644 index 0000000..2c000f9 --- /dev/null +++ b/aoc2023/src/day18/solve.gleam @@ -0,0 +1,113 @@ +import adglent.{First, Second} +import gleam/io +import gleam/int +import gleam/list +import gleam/option.{Some} +import gleam/regex.{type Match, Match} +import gleam/string + +type Coord { + Coord(x: Int, y: Int) +} + +type Direction { + Up + Right + Down + Left +} + +type Dig { + Dig(dir: Direction, dist: Int) +} + +fn to_direction(c: String) { + case c { + "R" | "0" -> Right + "D" | "1" -> Down + "L" | "2" -> Left + "U" | "3" -> Up + _ -> panic + } +} + +fn parse_front(line: String) { + let assert Ok(re) = regex.from_string("(.) (.*) \\(.*\\)") + let assert [Match(submatches: [Some(dir), Some(dist)], ..)] = + regex.scan(with: re, content: line) + let assert Ok(n) = int.parse(dist) + Dig(to_direction(dir), n) +} + +fn parse_hex(line: String) { + let assert Ok(re) = regex.from_string("\\(#(.....)(.)\\)") + let assert [Match(submatches: [Some(dist), Some(dir)], ..)] = + regex.scan(with: re, content: line) + let assert Ok(n) = int.base_parse(dist, 16) + Dig(to_direction(dir), n) +} + +fn go(current: Coord, dig: Dig) { + case dig { + Dig(Up, n) -> Coord(current.x, current.y + n) + Dig(Right, n) -> Coord(current.x + n, current.y) + Dig(Down, n) -> Coord(current.x, current.y - n) + Dig(Left, n) -> Coord(current.x - n, current.y) + } +} + +fn double_triangle(c1: Coord, c2: Coord) { + { c1.x * c2.y } - { c2.x * c1.y } +} + +fn start_dig(digs: List(Dig)) { + do_next_dig(digs, Coord(0, 0), 0, 0) +} + +fn do_next_dig( + digs: List(Dig), + current: Coord, + area: Int, + perimeter: Int, +) -> Int { + case digs { + [] -> int.absolute_value(area) / 2 + { perimeter / 2 } + 1 + [dig, ..rest] -> { + let next = go(current, dig) + let area = area + double_triangle(current, next) + let perimeter = perimeter + dig.dist + do_next_dig(rest, next, area, perimeter) + } + } +} + +fn solve_with(input, f) { + input + |> string.split("\n") + |> list.map(f) + |> start_dig + |> string.inspect +} + +pub fn part1(input: String) { + solve_with(input, parse_front) +} + +pub fn part2(input: String) { + solve_with(input, parse_hex) +} + +pub fn main() { + let assert Ok(part) = adglent.get_part() + let assert Ok(input) = adglent.get_input("18") + case part { + First -> + part1(input) + |> adglent.inspect + |> io.println + Second -> + part2(input) + |> adglent.inspect + |> io.println + } +} diff --git a/aoc2023/test/day18/day18_test.gleam b/aoc2023/test/day18/day18_test.gleam new file mode 100644 index 0000000..7b510c8 --- /dev/null +++ b/aoc2023/test/day18/day18_test.gleam @@ -0,0 +1,74 @@ +import gleam/list +import showtime/tests/should +import adglent.{type Example, Example} +import day18/solve + +type Problem1AnswerType = + String + +type Problem2AnswerType = + String + +/// Add examples for part 1 here: +/// ```gleam +///const part1_examples: List(Example(Problem1AnswerType)) = [Example("some input", "")] +/// ``` +const part1_examples: List(Example(Problem1AnswerType)) = [ + Example( + "R 6 (#70c710) +D 5 (#0dc571) +L 2 (#5713f0) +D 2 (#d2c081) +R 2 (#59c680) +D 2 (#411b91) +L 5 (#8ceee2) +U 2 (#caa173) +L 1 (#1b58a2) +U 2 (#caa171) +R 2 (#7807d2) +U 3 (#a77fa3) +L 2 (#015232) +U 2 (#7a21e3)", + "62", + ), +] + +/// Add examples for part 2 here: +/// ```gleam +///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")] +/// ``` +const part2_examples: List(Example(Problem2AnswerType)) = [ + Example( + "R 6 (#70c710) +D 5 (#0dc571) +L 2 (#5713f0) +D 2 (#d2c081) +R 2 (#59c680) +D 2 (#411b91) +L 5 (#8ceee2) +U 2 (#caa173) +L 1 (#1b58a2) +U 2 (#caa171) +R 2 (#7807d2) +U 3 (#a77fa3) +L 2 (#015232) +U 2 (#7a21e3)", + "952408144115", + ), +] + +pub fn part1_test() { + part1_examples + |> should.not_equal([]) + use example <- list.map(part1_examples) + solve.part1(example.input) + |> should.equal(example.answer) +} + +pub fn part2_test() { + part2_examples + |> should.not_equal([]) + use example <- list.map(part2_examples) + solve.part2(example.input) + |> should.equal(example.answer) +} |