diff options
author | Tomasz Chojnacki <tomaszchojnacki2001@gmail.com> | 2023-02-19 20:42:51 +0100 |
---|---|---|
committer | Tomasz Chojnacki <tomaszchojnacki2001@gmail.com> | 2023-02-19 20:42:51 +0100 |
commit | c4372e5b3d64d1b08cf9b00d0845141bbee753f6 (patch) | |
tree | 43c410dedf2088730b41079adc9e1b299844c619 /aoc-2020-gleam | |
parent | c74bb3862190e866a8764bf0781f60b248b64876 (diff) | |
download | gleam_aoc2020-c4372e5b3d64d1b08cf9b00d0845141bbee753f6.tar.gz gleam_aoc2020-c4372e5b3d64d1b08cf9b00d0845141bbee753f6.zip |
Finish day 3
Diffstat (limited to 'aoc-2020-gleam')
-rw-r--r-- | aoc-2020-gleam/src/aoc_2020_gleam.gleam | 2 | ||||
-rw-r--r-- | aoc-2020-gleam/src/days/day03.gleam | 99 | ||||
-rw-r--r-- | aoc-2020-gleam/src/ext/iteratorx.gleam | 14 | ||||
-rw-r--r-- | aoc-2020-gleam/src/util/parser.gleam | 2 |
4 files changed, 116 insertions, 1 deletions
diff --git a/aoc-2020-gleam/src/aoc_2020_gleam.gleam b/aoc-2020-gleam/src/aoc_2020_gleam.gleam index a208bfc..d39707b 100644 --- a/aoc-2020-gleam/src/aoc_2020_gleam.gleam +++ b/aoc-2020-gleam/src/aoc_2020_gleam.gleam @@ -2,12 +2,14 @@ import gleam/io import util/runner import days/day01 import days/day02 +import days/day03 pub fn main() -> Nil { use day <- runner.with_day() case day { 1 -> day01.run() 2 -> day02.run() + 3 -> day03.run() _ -> io.println("Day not found!") } } diff --git a/aoc-2020-gleam/src/days/day03.gleam b/aoc-2020-gleam/src/days/day03.gleam new file mode 100644 index 0000000..da67658 --- /dev/null +++ b/aoc-2020-gleam/src/days/day03.gleam @@ -0,0 +1,99 @@ +import gleam/string +import gleam/list +import gleam/function +import gleam/io +import gleam/iterator as iter +import gleam/int +import gleam/set.{Set} +import ext/resultx +import ext/iteratorx as iterx +import util/input_util + +type Pos = + #(Int, Int) + +const starting_pos = #(0, 0) + +const base_slope = #(3, 1) + +const all_slopes = [#(1, 1), base_slope, #(5, 1), #(7, 1), #(1, 2)] + +fn add(p1: Pos, p2: Pos) -> Pos { + #(p1.0 + p2.0, p1.1 + p2.1) +} + +type Area { + Area(trees: Set(Pos), cycle: Int, height: Int) +} + +fn parse_area(from text: String) -> Area { + let lines = string.split(text, on: "\n") + + let trees = + list.index_fold( + over: lines, + from: set.new(), + with: fn(prev, line, y) { + line + |> string.to_graphemes + |> list.index_map(with: fn(x, grapheme) { + case grapheme { + "#" -> Ok(#(x, y)) + _ -> Error(Nil) + } + }) + |> list.filter_map(with: function.identity) + |> set.from_list + |> set.union(prev) + }, + ) + let cycle = + lines + |> list.first + |> resultx.force_unwrap + |> string.length + let height = list.length(lines) + + Area(trees, cycle, height) +} + +fn has_tree(in area: Area, at pos: Pos) -> Bool { + set.contains(area.trees, #(pos.0 % area.cycle, pos.1)) +} + +fn is_valid(pos: Pos, in area: Area) -> Bool { + 0 <= pos.1 && pos.1 < area.height +} + +fn tree_count(in area: Area, with slope: Pos) -> Int { + starting_pos + |> iter.iterate(with: add(_, slope)) + |> iter.take_while(satisfying: is_valid(_, in: area)) + |> iterx.count(satisfying: has_tree(in: area, at: _)) +} + +fn part1(text: String) -> Int { + text + |> parse_area + |> tree_count(with: base_slope) +} + +fn part2(text: String) -> Int { + let area = parse_area(from: text) + + all_slopes + |> list.map(with: tree_count(in: area, with: _)) + |> int.product +} + +pub fn run() -> Nil { + let test = input_util.read_text("test03") + assert 7 = part1(test) + assert 336 = part2(test) + + let input = input_util.read_text("day03") + io.debug(part1(input)) + io.debug(part2(input)) + + Nil +} diff --git a/aoc-2020-gleam/src/ext/iteratorx.gleam b/aoc-2020-gleam/src/ext/iteratorx.gleam new file mode 100644 index 0000000..456c1d1 --- /dev/null +++ b/aoc-2020-gleam/src/ext/iteratorx.gleam @@ -0,0 +1,14 @@ +import gleam/iterator.{Iterator} as iter +import gleam/list + +pub fn length(iterator: Iterator(a)) -> Int { + iterator + |> iter.to_list + |> list.length +} + +pub fn count(iterator: Iterator(a), satisfying predicate: fn(a) -> Bool) -> Int { + iterator + |> iter.filter(for: predicate) + |> length +} diff --git a/aoc-2020-gleam/src/util/parser.gleam b/aoc-2020-gleam/src/util/parser.gleam index d6e35d5..cad8b35 100644 --- a/aoc-2020-gleam/src/util/parser.gleam +++ b/aoc-2020-gleam/src/util/parser.gleam @@ -7,7 +7,7 @@ import ext/intx // Heavily inspired by https://fsharpforfunandprofit.com/posts/understanding-parser-combinators/ -const eof: String = "end of input" +const eof = "end of input" pub type ParseError { InvalidInput(expected: String, found: String) |