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}