Code for the Advent of Code event
aoc
advent-of-code
1use aoc::{cli, registry};
2
3// Import modules to ensure they're compiled and their solutions are registered
4#[allow(unused_imports)]
5use aoc::y2024;
6use clap::Parser;
7use std::fs;
8use std::path::Path;
9use std::time::Instant;
10
11fn main() {
12 let cli = cli::Cli::parse();
13
14 match cli.command {
15 cli::Commands::Run {
16 year,
17 day,
18 part,
19 all,
20 } => {
21 if all {
22 run_all_solutions();
23 } else {
24 run_solutions(year, day, part);
25 }
26 }
27 cli::Commands::List { year, day } => {
28 list_solutions(year, day);
29 }
30 }
31}
32
33fn load_input(year: u32, day: u32) -> Option<String> {
34 let input_path = format!("data/aoc/{}/{:02}/input", year, day);
35
36 if Path::new(&input_path).exists() {
37 fs::read_to_string(&input_path).ok()
38 } else {
39 eprintln!("Warning: Input file not found at {}", input_path);
40 None
41 }
42}
43
44fn run_solutions(year: Option<u32>, day: Option<u32>, part: Option<u32>) {
45 match (year, day, part) {
46 (Some(y), Some(d), Some(p)) => {
47 // Run specific solution
48 if let Some(solution) = registry::REGISTRY.get_solution(y, d, p) {
49 run_single_solution(&solution);
50 } else {
51 eprintln!("Solution not found for {}/{}/part{}", y, d, p);
52 }
53 }
54 (Some(y), Some(d), None) => {
55 // Run all parts for a specific day
56 let solutions = registry::REGISTRY.get_day_solutions(y, d);
57 if solutions.is_empty() {
58 eprintln!("No solutions found for {}/day{}", y, d);
59 } else {
60 for solution in solutions {
61 run_single_solution(&solution);
62 }
63 }
64 }
65 (Some(y), None, None) => {
66 // Run all solutions for a year
67 let mut solutions = registry::REGISTRY.get_year_solutions(y);
68 solutions.sort_by_key(|s| (s.day, s.part));
69
70 if solutions.is_empty() {
71 eprintln!("No solutions found for year {}", y);
72 } else {
73 for solution in solutions {
74 run_single_solution(&solution);
75 }
76 }
77 }
78 _ => {
79 eprintln!("Invalid combination of arguments. Use --help for usage information.");
80 }
81 }
82}
83
84fn run_all_solutions() {
85 let mut solutions = registry::REGISTRY.get_all_solutions();
86 solutions.sort_by_key(|s| (s.year, s.day, s.part));
87
88 if solutions.is_empty() {
89 eprintln!("No solutions found!");
90 return;
91 }
92
93 for solution in solutions {
94 run_single_solution(&solution);
95 }
96}
97
98fn run_single_solution(solution: ®istry::Solution) {
99 println!(
100 "\n=== {} Day {} Part {} ===",
101 solution.year, solution.day, solution.part
102 );
103
104 if let Some(input) = load_input(solution.year, solution.day) {
105 let start = Instant::now();
106 let result = (solution.function)(&input);
107 let duration = start.elapsed();
108
109 println!("Result: {}", result);
110 println!("Time: {:?}", duration);
111 } else {
112 println!("Skipping due to missing input file");
113 }
114}
115
116fn list_solutions(year: Option<u32>, day: Option<u32>) {
117 match (year, day) {
118 (Some(y), Some(d)) => {
119 let solutions = registry::REGISTRY.get_day_solutions(y, d);
120 if solutions.is_empty() {
121 println!("No solutions found for {}/day{}", y, d);
122 } else {
123 println!("Solutions for {}/day{}:", y, d);
124 for solution in solutions {
125 println!(" - Part {} ({})", solution.part, solution.name);
126 }
127 }
128 }
129 (Some(y), None) => {
130 let days = registry::REGISTRY.get_days(y);
131 if days.is_empty() {
132 println!("No solutions found for year {}", y);
133 } else {
134 println!("Available days for {}:", y);
135 for d in days {
136 let solutions = registry::REGISTRY.get_day_solutions(y, d);
137 let parts: Vec<u32> = solutions.iter().map(|s| s.part).collect();
138 println!(" - Day {} (parts: {:?})", d, parts);
139 }
140 }
141 }
142 (None, None) => {
143 let years = registry::REGISTRY.get_years();
144 if years.is_empty() {
145 println!("No solutions found!");
146 } else {
147 println!("Available years:");
148 for y in years {
149 let days = registry::REGISTRY.get_days(y);
150 println!(" - {} ({} days)", y, days.len());
151 }
152 }
153 }
154 (None, Some(_)) => {
155 eprintln!("Cannot specify day without year");
156 }
157 }
158}