58 lines
1.3 KiB
Gleam
58 lines
1.3 KiB
Gleam
import gleam/int
|
|
import gleam/io
|
|
import gleam/iterator
|
|
import gleam/list
|
|
import gleam/pair
|
|
import gleam/result
|
|
import gleam/string
|
|
import stdin.{stdin}
|
|
|
|
type Report =
|
|
List(Int)
|
|
|
|
pub fn main() {
|
|
let reports = stdin() |> iterator.to_list() |> list.map(with: parse_report)
|
|
|
|
let part1 = list.count(reports, is_safe) |> int.to_string()
|
|
let part2 = list.count(reports, is_safe_with_damper) |> int.to_string()
|
|
|
|
io.print("Part 1: ")
|
|
io.println(part1)
|
|
io.print("Part 2: ")
|
|
io.println(part2)
|
|
}
|
|
|
|
fn is_safe(report: Report) -> Bool {
|
|
let diffs =
|
|
report
|
|
|> list.zip(with: list.drop(report, 1))
|
|
|> list.map(fn(p) { pair.first(p) - pair.second(p) })
|
|
|
|
list.all(diffs, fn(n) { 1 <= n && n <= 3 })
|
|
|| list.all(diffs, fn(n) { -3 <= n && n <= -1 })
|
|
}
|
|
|
|
fn is_safe_with_damper(report: Report) -> Bool {
|
|
is_safe(report)
|
|
|| report
|
|
|> reports_with_a_single_level_removed()
|
|
|> list.any(is_safe)
|
|
}
|
|
|
|
fn reports_with_a_single_level_removed(report: Report) -> List(Report) {
|
|
let len = list.length(report)
|
|
let idxs = list.range(0, len - 1)
|
|
|
|
use i <- list.map(idxs)
|
|
let assert #(head, [_, ..tail]) = list.split(report, i)
|
|
list.append(head, tail)
|
|
}
|
|
|
|
fn parse_report(str: String) -> Report {
|
|
str
|
|
|> string.trim()
|
|
|> string.split(" ")
|
|
|> list.map(int.parse)
|
|
|> result.all()
|
|
|> result.unwrap([])
|
|
}
|