Advent of Code solutions
at main 233 lines 5.3 kB view raw
1extern crate proc_macro; 2 3use proc_macro::TokenStream; 4 5fn make_day_mods(days: usize) -> String { 6 (1..=days) 7 .map(|day| format!("pub mod day_{day};", day = day)) 8 .collect::<Vec<_>>() 9 .join("\n") 10} 11 12fn make_use_days(days: usize) -> String { 13 (1..=days) 14 .map(|day| format!("use day_{day}::Day{day};", day = day)) 15 .collect::<Vec<_>>() 16 .join("\n") 17} 18 19fn make_day_match(inner: &str, days: usize) -> String { 20 (1..=days) 21 .map(|day| format!("{day} => {},", inner.replace("{day}", &day.to_string()))) 22 .collect::<Vec<_>>() 23 .join("\n") 24} 25 26fn make_day_tests(days: usize) -> String { 27 (1..=days) 28 .map(|day| { 29 format!( 30 " 31 #[test] 32 fn test_day_{day}_part_1() {{ 33 Day{day}::assert_part_1(); 34 }} 35 36 #[test] 37 fn test_day_{day}_part_2() {{ 38 Day{day}::assert_part_2(); 39 }}" 40 ) 41 }) 42 .collect::<Vec<_>>() 43 .join("\n") 44} 45 46fn get_solve_day(days: usize) -> String { 47 let inner = make_day_match("Day{day}::run_part(part, input)", days); 48 let inner2 = make_day_match("{Day{day}::bench_part(part, input);}", days); 49 format!( 50 " 51 fn solve_day(day: usize, part: usize, input: Option<&str>) -> Option<String> {{ 52 match day {{ 53 {inner} 54 _ => None, 55 }} 56 }} 57 fn bench_day(day: usize, part: usize, input: Option<&str>) {{ 58 match day {{ 59 {inner2} 60 _ => panic!(\"Invalid Day\"), 61 }} 62 }}" 63 ) 64} 65 66fn get_solve_day_both_parts(days: usize) -> String { 67 let inner = make_day_match("Day{day}::run_all_parts(extra_indent)", days); 68 format!( 69 " 70 fn solve_day_both_parts(day: usize, extra_indent: &str) {{ 71 match day {{ 72 {inner} 73 _ => (), 74 }} 75 }}", 76 inner = inner 77 ) 78} 79 80fn make_year_struct(year: &str, days: usize) -> String { 81 format!( 82 " 83 pub struct Year{year}; 84 85 impl Year for Year{year} {{ 86 const YEAR: usize = {year}; 87 88 {solve_day} 89 90 {solve_day_both_parts} 91 }}", 92 solve_day = get_solve_day(days), 93 solve_day_both_parts = get_solve_day_both_parts(days) 94 ) 95} 96 97fn make_tests(days: usize) -> String { 98 format!( 99 " 100 #[cfg(test)] 101 mod tests {{ 102 use super::*; 103 use advent_core::{{Day, Year}}; 104 105 {day_tests} 106 }}", 107 day_tests = make_day_tests(days) 108 ) 109} 110 111#[proc_macro] 112pub fn year(item: TokenStream) -> TokenStream { 113 let year = item.to_string(); 114 115 let days = if year == "2024" { 25 } else { 12 }; 116 117 let mods = make_day_mods(days); 118 let uses = make_use_days(days); 119 120 let year_struct = make_year_struct(&year, days); 121 122 let tests = make_tests(days); 123 124 format!( 125 " 126 {mods} 127 128 use advent_core::{{Year, Day}}; 129 {uses} 130 131 {year_struct} 132 133 {tests} 134 " 135 ) 136 .parse::<TokenStream>() 137 .unwrap() 138} 139 140#[proc_macro] 141pub fn year_runner(item: TokenStream) -> TokenStream { 142 let year = item.to_string(); 143 144 format!( 145 " 146 use advent_core::{{Year, get_dp_and_input}}; 147 148 use y_{year}::Year{year}; 149 150 fn main() {{ 151 let (dp, input) = get_dp_and_input(); 152 Year{year}::run_dp(input.as_deref(), dp); 153 }}" 154 ) 155 .parse::<TokenStream>() 156 .unwrap() 157} 158 159fn make_year_match(years: &[&str], inner: &str) -> String { 160 years 161 .iter() 162 .map(|year| format!("{year} => {},", inner.replace("{year}", year.as_ref()))) 163 .collect::<Vec<_>>() 164 .join("\n") 165} 166 167fn make_year_uses(years: &[&str]) -> String { 168 years 169 .iter() 170 .map(|year| format!("use y_{year}::Year{year};", year = year)) 171 .collect::<Vec<_>>() 172 .join("\n") 173} 174 175fn make_run_all_years(years: &[&str]) -> String { 176 years 177 .iter() 178 .map(|year| { 179 format!( 180 "Year{year}::run_dp(input.as_deref(), dp.clone());", 181 year = year 182 ) 183 }) 184 .collect::<Vec<_>>() 185 .join("\n") 186} 187 188fn make_run_year(years: &[&str]) -> String { 189 let inner = make_year_match(years, "Year{year}::run_dp(input.as_deref(), dp)"); 190 let inner2 = make_year_match(years, "Year{year}::bench_dp(input.as_deref(), dp)"); 191 format!( 192 " 193 fn run_year(year: usize, dp: DP, input: Option<&str>) {{ 194 match year {{ 195 {inner} 196 _ => {{ 197 println!(\"Unknown year: {{year}}\"); 198 }} 199 }} 200 }} 201 fn bench_year(year: usize, dp: DP, input: Option<&str>) {{ 202 match year {{ 203 {inner2} 204 _ => {{ 205 println!(\"Unknown year: {{year}}\"); 206 }} 207 }} 208 }}" 209 ) 210} 211 212#[proc_macro] 213pub fn global_runner(item: TokenStream) -> TokenStream { 214 let item = item.to_string(); 215 let years = item.split(',').map(|s| s.trim()).collect::<Vec<_>>(); 216 217 let year_uses = make_year_uses(&years); 218 let run_all_years = make_run_all_years(&years); 219 let run_year = make_run_year(&years); 220 221 format!( 222 " 223 {year_uses} 224 225 {run_year} 226 227 fn run_all_years(dp: &DP, input: Option<String>) {{ 228 {run_all_years} 229 }}" 230 ) 231 .parse::<TokenStream>() 232 .unwrap() 233}