aoc.gleam

 1import argv
 2import compare
 3import gleam/int
 4import gleam/io
 5import gleam/list
 6import gleam/option.{type Option, None, Some}
 7import gleam/result
 8import gleam/string
 9import internal/mine/day01 as mine_day01
10import utils
11
12const available_days = [1]
13
14pub fn main() -> Nil {
15  let args = argv.load().arguments
16
17  case parse_args(args) {
18    Error(msg) -> io.println("Error: " <> msg)
19    Ok(#(day, example, cmp)) ->
20      case day {
21        Some(d) -> run_day(d, example, cmp)
22        None -> list.each(available_days, fn(d) { run_day(d, example, cmp) })
23      }
24  }
25}
26
27pub type Args {
28  Args(day: Option(Int), example: Bool, compare: Bool)
29}
30
31fn parse_args(
32  args: List(String),
33) -> Result(#(Option(Int), Bool, Bool), String) {
34  let example = list.contains(args, "--example") || list.contains(args, "-e")
35  let no_cmp =
36    list.contains(args, "--no-compare") || list.contains(args, "-n")
37  let day_args = list.filter(args, fn(a) { !string.starts_with(a, "-") })
38
39  use day <- result.try(case day_args {
40    [day_str, ..] ->
41      case int.parse(day_str) {
42        Ok(d) if d >= 1 && d <= 25 -> Ok(Some(d))
43        Ok(_) -> Error("day must be between 1 and 25")
44        Error(_) -> Error("invalid day number: " <> day_str)
45      }
46    [] -> Ok(None)
47  })
48
49  Ok(#(day, example, !no_cmp))
50}
51
52fn run_day(day: Int, example: Bool, cmp: Bool) -> Nil {
53  case utils.read_input(day, example) {
54    Error(e) -> io.println(e)
55    Ok(input) -> {
56      let mode = case example {
57        True -> " (example)"
58        False -> ""
59      }
60      io.println("=== Day " <> int.to_string(day) <> mode <> " ===")
61      case cmp {
62        True -> run_comparison(day, input)
63        False -> run_parts(day, input)
64      }
65    }
66  }
67}
68
69fn run_parts(day: Int, input: List(String)) -> Nil {
70  case day {
71    1 -> {
72      io.println("Part 1: " <> int.to_string(mine_day01.part1(input)))
73      io.println("Part 2: " <> int.to_string(mine_day01.part2(input)))
74    }
75    _ -> io.println("Day " <> int.to_string(day) <> " not implemented yet")
76  }
77}
78
79fn run_comparison(day: Int, input: List(String)) -> Nil {
80  case day {
81    1 -> compare.day01(input)
82    _ -> io.println("Day " <> int.to_string(day) <> " comparison not available")
83  }
84}