aoc-2021-rust

git clone https://git.sinitax.com/sinitax/aoc-2021-rust
Log | Files | Refs | README | sfeed.txt

commit c9479238ea02674b65fde86c1723427ee65834c9
parent 745524e95d34e597a62a3d0c8fdb5a16ef203dfb
Author: Louis Burda <quent.burda@gmail.com>
Date:   Sat, 18 Dec 2021 16:01:35 +0100

Refactor all repo structure

Diffstat:
Mlib/aoc/src/lib.rs | 38++++++++++++++++++++++++++++++++------
Msrc/01/src/main.rs | 16++++++++--------
Msrc/02/Cargo.toml | 4++--
Msrc/02/src/main.rs | 35+++++++++++++----------------------
Msrc/03/Cargo.toml | 4++--
Msrc/03/src/main.rs | 51++++++++++++++++++++++++---------------------------
Msrc/04/Cargo.toml | 4++--
Msrc/04/src/main.rs | 50++++++++++++++++++++++----------------------------
Msrc/05/Cargo.toml | 4++--
Msrc/05/src/main.rs | 34+++++++++++++---------------------
Msrc/06/Cargo.toml | 3++-
Msrc/06/src/main.rs | 38+++++++++++++-------------------------
Msrc/07/Cargo.toml | 3++-
Msrc/07/src/main.rs | 39+++++++++++++--------------------------
Msrc/08/Cargo.toml | 3++-
Msrc/08/src/main.rs | 84+++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/09/Cargo.toml | 3++-
Msrc/09/src/main.rs | 65+++++++++++++++++++++++++++++++++++------------------------------
Msrc/10/Cargo.toml | 3++-
Msrc/10/src/main.rs | 38+++++++++++++-------------------------
Msrc/11/Cargo.toml | 3++-
Msrc/11/src/main.rs | 36+++++++++++++-----------------------
Msrc/12/Cargo.toml | 4++--
Msrc/12/src/main.rs | 34++++++++++++----------------------
24 files changed, 274 insertions(+), 322 deletions(-)

diff --git a/lib/aoc/src/lib.rs b/lib/aoc/src/lib.rs @@ -2,19 +2,24 @@ use std::env; use std::fs; use std::process::exit; +#[derive(PartialEq, PartialOrd)] pub enum Loglvl { LogNone = 0, LogVerb, + LogDebug, LogAll } pub struct Info { - pub debug: Loglvl, + pub verbose: bool, + pub debug: bool, + pub filename: String, pub input: String, - pub solution: Option<String>, + pub part: u32, + + pub solution: Option<&'static str>, pub answer: Option<String>, - pub part: u32 } #[macro_export] @@ -25,6 +30,24 @@ macro_rules! die { } } +#[macro_export] +macro_rules! debug { + ($aoc:expr, $( $arg:expr ),*) => { + if $aoc.debug { + eprint!($( $arg ), *); + } + } +} + +#[macro_export] +macro_rules! verbose { + ($aoc:expr, $( $arg:expr ),*) => { + if $aoc.verbose { + eprint!($( $arg ), *); + } + } +} + pub fn to_loglvl(val: u32) -> Loglvl { match val { 0 => return Loglvl::LogNone, @@ -36,12 +59,13 @@ pub fn to_loglvl(val: u32) -> Loglvl { pub fn run(part1: fn(info: &mut Info), part2: fn(info: &mut Info)) { let mut info = Info { + verbose: false, + debug: false, filename: "input".to_string(), - debug: Loglvl::LogNone, input: "".to_string(), + part: 0, solution: None, answer: None, - part: 0 }; let input_file = env::var("AOCINPUT"); @@ -58,7 +82,9 @@ pub fn run(part1: fn(info: &mut Info), part2: fn(info: &mut Info)) { let debug = env::var("AOCDEBUG"); if debug.is_ok() { let num = debug.unwrap().parse::<u32>().unwrap(); - info.debug = to_loglvl(num); + let lvl = to_loglvl(num); + info.verbose = lvl >= Loglvl::LogVerb; + info.debug = lvl >= Loglvl::LogDebug; } let args: Vec<String> = env::args().collect(); diff --git a/src/01/src/main.rs b/src/01/src/main.rs @@ -1,5 +1,5 @@ -fn part1(info: &mut aoc::Info) { - let vals : Vec<u32> = info.input.lines() +fn part1(aoc: &mut aoc::Info) { + let vals : Vec<u32> = aoc.input.lines() .map(|x| x.parse().unwrap()) .collect(); @@ -12,12 +12,12 @@ fn part1(info: &mut aoc::Info) { prev = v; } - info.solution = Some("1692".to_string()); - info.answer = Some(format!("{}", count)); + aoc.answer = Some(format!("{}", count)); + aoc.solution = Some("1692"); } -fn part2(info: &mut aoc::Info) { - let vals : Vec<u32> = info.input.lines() +fn part2(aoc: &mut aoc::Info) { + let vals : Vec<u32> = aoc.input.lines() .map(|x| x.parse().unwrap()) .collect(); @@ -31,8 +31,8 @@ fn part2(info: &mut aoc::Info) { prev = Some(sum); } - info.solution = Some("1724".to_string()); - info.answer = Some(format!("{}", count)); + aoc.answer = Some(format!("{}", count)); + aoc.solution = Some("1724"); } fn main() { diff --git a/src/02/Cargo.toml b/src/02/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "aoc" +name = "day02" version = "0.1.0" edition = "2021" [dependencies] - +aoc = { path = "../../lib/aoc" } diff --git a/src/02/src/main.rs b/src/02/src/main.rs @@ -1,20 +1,5 @@ -use std::fs; -use std::env; - -fn main() { - let args: Vec<String> = env::args().collect(); - if args[1] == "1" { - part1(); - } else if args[1] == "2" { - part2(); - } else { - eprintln!("No such part\n"); - } -} - -fn part1() { - let content : String = fs::read_to_string("input").expect("no file"); - let lines : Vec<&str> = content.lines().collect(); +fn part1(aoc: &mut aoc::Info) { + let lines : Vec<&str> = aoc.input.lines().collect(); let mut dist : u32 = 0; let mut depth : u32 = 0; @@ -29,12 +14,13 @@ fn part1() { depth -= val; } } - println!("{}", depth * dist); + + aoc.answer = Some(format!("{}", depth * dist)); + aoc.solution = Some("2039912"); } -fn part2() { - let content : String = fs::read_to_string("input").expect("no file"); - let lines : Vec<&str> = content.lines().collect(); +fn part2(aoc: &mut aoc::Info) { + let lines : Vec<&str> = aoc.input.lines().collect(); let mut dist : u32 = 0; let mut aim : u32 = 0; @@ -51,6 +37,11 @@ fn part2() { aim -= val; } } - println!("{}", depth * dist); + + aoc.answer = Some(format!("{}", depth * dist)); + aoc.solution = Some("1942068080"); } +fn main() { + aoc::run(part1, part2); +} diff --git a/src/03/Cargo.toml b/src/03/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "aoc" +name = "day03" version = "0.1.0" edition = "2021" [dependencies] - +aoc = { path = "../../lib/aoc" } diff --git a/src/03/src/main.rs b/src/03/src/main.rs @@ -1,17 +1,3 @@ -use std::fs; -use std::env; - -fn main() { - let args: Vec<String> = env::args().collect(); - if args[1] == "1" { - part1(); - } else if args[1] == "2" { - part2(); - } else { - eprintln!("No such part\n"); - } -} - fn filter_lines<T>(lines: &Vec<&str>, char_sel : T) -> u32 where T: Fn(u32, u32) -> char { let mut cands : Vec<&str> = lines.clone(); let bits = cands[0].len(); @@ -37,14 +23,13 @@ fn filter_lines<T>(lines: &Vec<&str>, char_sel : T) -> u32 where T: Fn(u32, u32) return u32::from_str_radix(cands[0], 2).unwrap(); } -fn part1() { - let content = fs::read_to_string("input").expect("no file"); - let lines : Vec<&str> = content.lines().collect(); - +fn part1(aoc: &mut aoc::Info) { + let lines : Vec<&str> = aoc.input.lines().collect(); assert_ne!(lines.len(), 0); - let valcount : u32 = lines.len().try_into().unwrap(); + + let valcount : usize = lines.len(); let bits : usize = lines[0].len(); - let mut bitcounts : Vec<u32> = vec![0; bits]; + let mut bitcounts : Vec<usize> = vec![0; bits]; bitcounts.fill(0); for line in lines { @@ -67,16 +52,28 @@ fn part1() { } } - println!("{}", gamma * epsilon); + aoc.answer = Some(format!("{}", gamma * epsilon)); + aoc.solution = Some("3958484"); } -fn part2() { - let content = fs::read_to_string("input").expect("no file"); - let lines : Vec<&str> = content.lines().collect(); +fn part2(aoc: &mut aoc::Info) { + let lines : Vec<&str> = aoc.input.lines().collect(); assert_ne!(lines.len(), 0); - let oxygen = filter_lines(&lines, |count,valcount| if (count as f32) >= ((valcount as f32) / 2.0).ceil() { '1' } else { '0' }); - let co2 = filter_lines(&lines, |count,valcount| if (count as f32) < ((valcount as f32) / 2.0).floor() { '1' } else { '0' }); + let oxyfn = |count,valcount| + if (count as f32) >= ((valcount as f32) / 2.0).ceil() + { '1' } else { '0' }; + let oxygen = filter_lines(&lines, oxyfn); + + let co2fn = |count,valcount| + if (count as f32) < ((valcount as f32) / 2.0).floor() + { '1' } else { '0' }; + let co2 = filter_lines(&lines, co2fn); - println!("{}", oxygen * co2); + aoc.answer = Some(format!("{}", oxygen * co2)); + aoc.solution = Some("1613181"); +} + +fn main() { + aoc::run(part1, part2); } diff --git a/src/04/Cargo.toml b/src/04/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "aoc" +name = "day04" version = "0.1.0" edition = "2021" [dependencies] - +aoc = { path = "../../lib/aoc" } diff --git a/src/04/src/main.rs b/src/04/src/main.rs @@ -1,14 +1,10 @@ use std::io::BufRead; -use std::io::BufReader; - -use std::fs::File; -use std::env; struct Board { fields: Vec<Vec<u32>> } -fn read_board(reader: &mut BufReader<File>, boards: &mut Vec<Board>) -> bool { +fn read_board<'a>(reader: &mut &'a[u8], boards: &mut Vec<Board>) -> bool { let mut line = String::new(); let mut board = Board { fields: Vec::new() @@ -20,7 +16,8 @@ fn read_board(reader: &mut BufReader<File>, boards: &mut Vec<Board>) -> bool { let len = reader.read_line(&mut line).unwrap(); if len == 0 { return false; } line = line.trim_end().to_string(); - let vals: Vec<u32> = line.split_whitespace().map(|x| x.parse().unwrap()).collect(); + let vals: Vec<u32> = line.split_whitespace() + .map(|x| x.parse().unwrap()).collect(); board.fields.push(vals); } @@ -62,20 +59,8 @@ fn calc_score(board: &Board, nums: &[u32]) -> u32 { return sum * nums.last().unwrap(); } -fn main() { - let args: Vec<String> = env::args().collect(); - if args[1] == "1" { - part1(); - } else if args[1] == "2" { - part2(); - } else { - eprintln!("No such part\n"); - } -} - -fn part1() { - let file = File::open("input").expect(""); - let mut reader = BufReader::new(file); +fn part1(aoc: &mut aoc::Info) { + let mut reader = aoc.input.as_bytes(); let mut line = String::new(); let mut boards = Vec::new(); @@ -85,23 +70,27 @@ fn part1() { while read_board(&mut reader, &mut boards) {} + let mut score: u32 = 0; for i in 1..marked.len() { let curvals = &marked[..i]; for b in &boards { if board_win(&b, curvals) { - let score = calc_score(&b, curvals); - println!("{}", score); - return; + score = calc_score(&b, curvals); + break; } } + if score > 0 { + break; + } } + assert!(score > 0, "Didnt work!"); - println!("didnt work!"); + aoc.answer = Some(format!("{}", score)); + aoc.solution = Some("58838"); } -fn part2() { - let file = File::open("input").expect(""); - let mut reader = BufReader::new(file); +fn part2(aoc: &mut aoc::Info) { + let mut reader = aoc.input.as_bytes(); let mut line = String::new(); reader.read_line(&mut line).unwrap(); @@ -126,5 +115,10 @@ fn part2() { } let score = calc_score(lastboard.unwrap(), lastvals.unwrap()); - println!("{}", score); + aoc.answer = Some(format!("{}", score)); + aoc.solution = Some("6256"); +} + +fn main() { + aoc::run(part1, part2); } diff --git a/src/05/Cargo.toml b/src/05/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "aoc" +name = "day05" version = "0.1.0" edition = "2021" [dependencies] - +aoc = { path = "../../lib/aoc" } diff --git a/src/05/src/main.rs b/src/05/src/main.rs @@ -1,8 +1,6 @@ use std::collections::HashMap; use std::hash::Hash; use std::clone::Clone; -use std::env; -use std::fs; #[derive(PartialEq, Clone, Eq, Hash)] struct Pos { @@ -47,20 +45,9 @@ fn inc_count(map: &mut HashMap<Pos, i32>, pos: &Pos) { } } -fn main() { - let args: Vec<String> = env::args().collect(); - if args[1] == "1" { - part1(); - } else if args[1] == "2" { - part2(); - } else { - eprintln!("No such part\n"); - } -} - -fn part1() { - let lines: Vec<Line> = fs::read_to_string("input").unwrap() - .lines().map(|x| parse_line(x)).collect(); +fn part1(aoc: &mut aoc::Info) { + let lines: Vec<Line> = aoc.input.lines() + .map(|x| parse_line(x)).collect(); let mut points: HashMap<Pos, i32> = HashMap::new(); for line in lines { @@ -76,12 +63,13 @@ fn part1() { } let score = points.values().filter(|&v| *v >= 2).count(); - println!("{}", score); + aoc.answer = Some(format!("{}", score)); + aoc.solution = Some("7644"); } -fn part2() { - let lines: Vec<Line> = fs::read_to_string("input").unwrap() - .lines().map(|x| parse_line(x)).collect(); +fn part2(aoc: &mut aoc::Info) { + let lines: Vec<Line> = aoc.input.lines() + .map(|x| parse_line(x)).collect(); let mut points: HashMap<Pos, i32> = HashMap::new(); for line in lines { @@ -96,6 +84,10 @@ fn part2() { } let score = points.values().filter(|&v| *v >= 2).count(); - println!("{}", score); + aoc.answer = Some(format!("{}", score)); + aoc.solution = Some("18627"); +} +fn main() { + aoc::run(part1, part2); } diff --git a/src/06/Cargo.toml b/src/06/Cargo.toml @@ -1,8 +1,9 @@ [package] -name = "aoc" +name = "day06" version = "0.1.0" edition = "2021" [dependencies] +aoc = { path = "../../lib/aoc" } num-bigint = "0.4.3" num-traits = "*" diff --git a/src/06/src/main.rs b/src/06/src/main.rs @@ -1,19 +1,6 @@ -use std::fs; -use std::env; use num_bigint::BigUint; use num_traits::{FromPrimitive,ToPrimitive,Zero}; -fn main() { - let args: Vec<String> = env::args().collect(); - if args[1] == "1" { - part1(); - } else if args[1] == "2" { - part2(); - } else { - eprintln!("No such part\n"); - } -} - fn step_time_p1(les_fish: &mut Vec<u32>) { let mut new_count: u32 = 0; for fish in les_fish.iter_mut() { @@ -36,24 +23,21 @@ fn step_time_p2(cur_fish: &mut Vec<BigUint>) { cur_fish[6] = cur_fish[6].clone() + cur_fish[8].clone(); } -fn part1() { - let mut fish: Vec<u32> = fs::read_to_string("input").expect("no fish") - .strip_suffix("\n").unwrap() - .split(",") - .map(|x| x.parse().unwrap()).collect(); +fn part1(aoc: &mut aoc::Info) { + let mut fish: Vec<u32> = aoc.input.strip_suffix("\n").unwrap() + .split(",").map(|x| x.parse().unwrap()).collect(); for _i in 0..80 { step_time_p1(&mut fish); } - println!("{}", fish.len()); + aoc.answer = Some(format!("{}", fish.len())); + aoc.solution = Some("350605"); } -fn part2() { - let fish: Vec<BigUint> = fs::read_to_string("input").expect("no fish") - .strip_suffix("\n").unwrap() - .split(",") - .map(|x| x.parse().unwrap()).collect(); +fn part2(aoc: &mut aoc::Info) { + let fish: Vec<u32> = aoc.input.strip_suffix("\n").unwrap() + .split(",").map(|x| x.parse().unwrap()).collect(); let mut count: Vec<BigUint> = vec![Zero::zero(); 9]; for i in 0..9 { @@ -65,6 +49,10 @@ fn part2() { step_time_p2(&mut count); } - println!("{}", count.iter().sum::<BigUint>()); + aoc.answer = Some(format!("{}", count.iter().sum::<BigUint>())); + aoc.solution = Some("1592778185024"); } +fn main() { + aoc::run(part1, part2); +} diff --git a/src/07/Cargo.toml b/src/07/Cargo.toml @@ -1,7 +1,8 @@ [package] -name = "aoc" +name = "day07" version = "0.1.0" edition = "2021" [dependencies] +aoc = { path = "../../lib/aoc" } diff --git a/src/07/src/main.rs b/src/07/src/main.rs @@ -1,17 +1,3 @@ -use std::fs; -use std::env; - -fn main() { - let args: Vec<String> = env::args().collect(); - if args[1] == "1" { - part1(); - } else if args[1] == "2" { - part2(); - } else { - eprintln!("No such part\n"); - } -} - fn best_loc(crabs: &mut Vec<i32>) -> i32 { crabs.sort(); return crabs[crabs.len() / 2]; @@ -41,24 +27,21 @@ fn fuel_cost_p2_deriv(crabs: &Vec<i32>, loc: i32) -> i32 { return val2 - val1; } -fn part1() { - let mut crabs: Vec<i32> = fs::read_to_string("input").expect("no file") - .strip_suffix("\n").unwrap() - .split(",") - .map(|x| x.parse().expect("invalid crab")) +fn part1(aoc: &mut aoc::Info) { + let mut crabs: Vec<i32> = aoc.input.strip_suffix("\n").unwrap() + .split(",").map(|x| x.parse().expect("invalid crab")) .collect(); let loc = best_loc(&mut crabs); let answer = fuel_cost_p1(&crabs, loc); - println!("{}", answer); + aoc.answer = Some(format!("{}", answer)); + aoc.solution = Some("336721"); } -fn part2() { - let crabs: Vec<i32> = fs::read_to_string("input").expect("no file") - .strip_suffix("\n").unwrap() - .split(",") - .map(|x| x.parse().expect("invalid crab")) +fn part2(aoc: &mut aoc::Info) { + let crabs: Vec<i32> = aoc.input.strip_suffix("\n").unwrap() + .split(",").map(|x| x.parse().expect("invalid crab")) .collect(); let mut low: i32 = *crabs.iter().min().unwrap(); @@ -76,6 +59,10 @@ fn part2() { } }; - println!("{}", fuel_cost_p2(&crabs, low)); + aoc.answer = Some(format!("{}", fuel_cost_p2(&crabs, low))); + aoc.solution = Some("91638945"); } +fn main() { + aoc::run(part1, part2); +} diff --git a/src/08/Cargo.toml b/src/08/Cargo.toml @@ -1,7 +1,8 @@ [package] -name = "aoc" +name = "day08" version = "0.1.0" edition = "2021" [dependencies] +aoc = { path = "../../lib/aoc" } diff --git a/src/08/src/main.rs b/src/08/src/main.rs @@ -1,36 +1,5 @@ -use std::fs; -use std::env; use std::collections::HashMap; -fn main() { - let args: Vec<String> = env::args().collect(); - if args[1] == "1" { - part1(); - } else if args[1] == "2" { - part2(); - } else { - eprintln!("No such part\n"); - } -} - -fn part1() { - let content: String = fs::read_to_string("input").expect("no input"); - let display_digits: Vec<Vec<&str>> = content.lines() - .map(|x| x.split_once(" | ").unwrap().1.split(" ").collect()).collect(); - let accepted: Vec<usize> = vec![2, 3, 4, 7]; - let mut count: u32 = 0; - - for digits in display_digits { - for d in digits { - if accepted.contains(&d.len()) { - count += 1; - } - } - } - - println!("{}", count); -} - fn code2bin(code: &str) -> u32 { let alph = "abcdefg"; let mut val: u32 = 0; @@ -57,7 +26,8 @@ fn bits_set(bin: u32) -> u32 { return cnt; } -fn decode_value(codes: &Vec<&str>, out_codes: &Vec<&str>) -> u32 { +fn decode_value(aoc: &mut aoc::Info, + codes: &Vec<&str>, out_codes: &Vec<&str>) -> u32 { let len2code: HashMap<u32,u32> = HashMap::from([ (2, 1), (3, 7), @@ -106,25 +76,26 @@ fn decode_value(codes: &Vec<&str>, out_codes: &Vec<&str>) -> u32 { for digit in 0..10 { fit = true; for cmp in 0..10 { - // println!("-- {} {} --", digit, cmp); + aoc::debug!(aoc, "-- {} {} --\n", digit, cmp); let cmplen = overlaps[digit][cmp]; if digit == cmp && bits_set(code) != cmplen { - // println!("wrong length"); + aoc::debug!(aoc, "wrong length\n"); fit = false; break; } if mapping[cmp] == 0 { continue; } if bits_set(code & mapping[cmp]) != cmplen { - // println!("wrong # of same bits: {:08b} & {:08b} != {}", code, mapping[cmp], cmplen); + aoc::debug!(aoc, "wrong # of same bits: {:08b} & {:08b} != {}\n", + code, mapping[cmp], cmplen); fit = false; break; } - // println!("{}: {:08b} {:08b}", cmplen, code, mapping[cmp]); + aoc::debug!(aoc, "{}: {:08b} {:08b}\n", cmplen, code, mapping[cmp]); } if fit == true { - // println!("add {:08b} => {}", code, digit); + aoc::debug!(aoc, "add {:08b} => {}\n", code, digit); mapping[digit] = code; break; } @@ -144,16 +115,43 @@ fn decode_value(codes: &Vec<&str>, out_codes: &Vec<&str>) -> u32 { return output; } -fn part2() { - let content: String = fs::read_to_string("input").expect("no input"); +fn part1(aoc: &mut aoc::Info) { + let display_digits: Vec<Vec<&str>> = aoc.input.lines() + .map(|x| x.split_once(" | ").unwrap().1.split(" ").collect()) + .collect(); + + let accepted: Vec<usize> = vec![2, 3, 4, 7]; + let mut count: u32 = 0; + + for digits in display_digits { + for d in digits { + if accepted.contains(&d.len()) { + count += 1; + } + } + } + + aoc.answer = Some(format!("{}", count)); + aoc.solution = Some("237"); +} + +fn part2(aoc: &mut aoc::Info) { + let content = aoc.input.clone(); let lines: Vec<&str> = content.lines().collect(); let mut sum: u32 = 0; for line in lines { - let sig_codes: Vec<&str> = line.split_once(" | ").unwrap().0.split(" ").collect(); - let out_codes: Vec<&str> = line.split_once(" | ").unwrap().1.split(" ").collect(); - sum += decode_value(&sig_codes, &out_codes); + let sig_codes: Vec<&str> = line.split_once(" | ").unwrap().0 + .split(" ").collect(); + let out_codes: Vec<&str> = line.split_once(" | ").unwrap().1 + .split(" ").collect(); + sum += decode_value(aoc, &sig_codes, &out_codes); } - println!("{}", sum); + aoc.answer = Some(format!("{}", sum)); + aoc.solution = Some("1009098"); +} + +fn main() { + aoc::run(part1, part2); } diff --git a/src/09/Cargo.toml b/src/09/Cargo.toml @@ -1,7 +1,8 @@ [package] -name = "aoc" +name = "day09" version = "0.1.0" edition = "2021" [dependencies] +aoc = { path = "../../lib/aoc" } diff --git a/src/09/src/main.rs b/src/09/src/main.rs @@ -1,6 +1,3 @@ -use std::fs; -use std::env; - #[derive(PartialEq,Eq)] struct Pos { x: i32, @@ -14,21 +11,10 @@ const DIRS: [Pos; 4] = [ Pos { x: -1, y: 0 }, ]; -fn main() { - let args: Vec<String> = env::args().collect(); - if args[1] == "1" { - part1(); - } else if args[1] == "2" { - part2(); - } else { - eprintln!("No such part\n"); - } -} - -fn part1() { - let content = fs::read_to_string("input").expect("no file"); - let map: Vec<Vec<i32>> = content.lines() - .map(|x| x.chars().map(|c| c.to_digit(10).unwrap() as i32).collect()).collect(); +fn part1(aoc: &mut aoc::Info) { + let map: Vec<Vec<i32>> = aoc.input.lines() + .map(|x| x.chars().map(|c| c.to_digit(10).unwrap() as i32).collect()) + .collect(); assert_ne!(map.len(), 0); let width = map[0].len(); @@ -55,13 +41,14 @@ fn part1() { } } - println!("{}", sum); + aoc.answer = Some(format!("{}", sum)); + aoc.solution = Some("417"); } -fn part2() { - let content = fs::read_to_string("input").expect("no file"); - let map: Vec<Vec<i32>> = content.lines() - .map(|x| x.chars().map(|c| c.to_digit(10).unwrap() as i32).collect()).collect(); +fn part2(aoc: &mut aoc::Info) { + let map: Vec<Vec<i32>> = aoc.input.lines() + .map(|x| x.chars().map(|c| c.to_digit(10).unwrap() as i32).collect()) + .collect(); assert_ne!(map.len(), 0); let width = map[0].len(); @@ -77,7 +64,8 @@ fn part2() { let ny = (y as i32) + d.y; let inrange_x = nx >= 0 && nx < (width as i32); let inrange_y = ny >= 0 && ny < (height as i32); - if inrange_x && inrange_y && map[ny as usize][nx as usize] <= curh { + if inrange_x && inrange_y + && map[ny as usize][nx as usize] <= curh { is_lowest = false; break; } @@ -90,7 +78,10 @@ fn part2() { let mut basin_sizes: Vec<usize> = Vec::new(); for start in lowest { - // println!("S {} {}", start.x, start.y); + if aoc.debug { + println!("START {} {}", start.x, start.y); + } + let mut visited: Vec<Pos> = Vec::new(); let mut outer: Vec<Pos> = Vec::new(); @@ -99,11 +90,16 @@ fn part2() { let mut new_outer: Vec<Pos> = Vec::new(); for pos in &outer { for d in DIRS { - let npos = Pos { x: (pos.x as i32) + d.x, y: (pos.y as i32) + d.y }; + let npos = Pos { + x: (pos.x as i32) + d.x, + y: (pos.y as i32) + d.y + }; let inrange_x = npos.x >= 0 && npos.x < (width as i32); let inrange_y = npos.y >= 0 && npos.y < (height as i32); - if inrange_x && inrange_y && map[npos.y as usize][npos.x as usize] != 9 - && !visited.contains(&npos) && !new_outer.contains(&npos) { + if inrange_x && inrange_y + && map[npos.y as usize][npos.x as usize] != 9 + && !visited.contains(&npos) + && !new_outer.contains(&npos) { new_outer.push(Pos { x: npos.x, y: npos.y }); } } @@ -112,7 +108,10 @@ fn part2() { outer = new_outer; } - // println!("{}", visited.len()); + if aoc.debug { + println!("VISITED COUNT: {}", visited.len()); + } + basin_sizes.push(visited.len()); } @@ -120,5 +119,11 @@ fn part2() { basin_sizes.reverse(); assert!(basin_sizes.len() > 3); - println!("{}", basin_sizes[0] * basin_sizes[1] * basin_sizes[2]); + let product = basin_sizes[0] * basin_sizes[1] * basin_sizes[2]; + aoc.answer = Some(format!("{}", product)); + aoc.solution = Some("1148965"); +} + +fn main() { + aoc::run(part1, part2); } diff --git a/src/10/Cargo.toml b/src/10/Cargo.toml @@ -1,8 +1,9 @@ [package] -name = "aoc" +name = "day10" version = "0.1.0" edition = "2021" [dependencies] +aoc = { path = "../../lib/aoc" } lazy_static = "*" bimap = "*" diff --git a/src/10/src/main.rs b/src/10/src/main.rs @@ -1,6 +1,3 @@ -use std::fs; -use std::env; - #[macro_use] extern crate lazy_static; @@ -37,22 +34,9 @@ lazy_static! { const OPENING: [char; 4] = ['(', '[', '{', '<']; const CLOSING: [char; 4] = [')', ']', '}', '>']; -fn main() { - let args: Vec<String> = env::args().collect(); - if args[1] == "1" { - part1(); - } else if args[1] == "2" { - part2(); - } else { - eprintln!("No such part\n"); - } -} - -fn part1() { - let content = fs::read_to_string("input").expect("no file"); - +fn part1(aoc: &mut aoc::Info) { let mut score: usize = 0; - for line in content.lines() { + for line in aoc.input.lines() { let mut stack: Vec<char> = Vec::new(); for c in line.chars() { if OPENING.contains(&c) { @@ -69,14 +53,13 @@ fn part1() { /* ignore incomplete for now */ } - println!("{}", score); + aoc.answer = Some(format!("{}", score)); + aoc.solution = Some("167379"); } -fn part2() { - let content = fs::read_to_string("input").expect("no file"); - +fn part2(aoc: &mut aoc::Info) { let mut scores: Vec<usize> = Vec::new(); - for line in content.lines() { + for line in aoc.input.lines() { let mut stack: Vec<char> = Vec::new(); let mut corrupt = false; @@ -103,9 +86,14 @@ fn part2() { scores.push(score); } } + assert!(scores.len() % 2 == 1); scores.sort(); - assert!(scores.len() % 2 == 1); - println!("{}", scores[scores.len() / 2]); + aoc.answer = Some(format!("{}", scores[scores.len() / 2])); + aoc.solution = Some("2776842859"); +} + +fn main() { + aoc::run(part1, part2); } diff --git a/src/11/Cargo.toml b/src/11/Cargo.toml @@ -1,7 +1,8 @@ [package] -name = "aoc" +name = "day11" version = "0.1.0" edition = "2021" [dependencies] +aoc = { path = "../../lib/aoc" } diff --git a/src/11/src/main.rs b/src/11/src/main.rs @@ -1,6 +1,3 @@ -use std::fs; -use std::env; - #[derive(PartialEq,Eq)] struct Pos { x: i32, @@ -18,17 +15,6 @@ const SURROUNDING: [Pos; 8] = [ Pos { x: 1, y: 1 } ]; -fn main() { - let args: Vec<String> = env::args().collect(); - if args[1] == "1" { - part1(); - } else if args[1] == "2" { - part2(); - } else { - eprintln!("No such part\n"); - } -} - fn print_octos(octos: &Vec<Vec<u32>>) { for row in octos { for octo in row { @@ -76,10 +62,10 @@ fn sim_step(octos: &mut Vec<Vec<u32>>) -> usize { return flashed.len(); } -fn part1() { - let content = fs::read_to_string("input").expect("no file"); - let mut octos: Vec<Vec<u32>> = content.lines() - .map(|l| l.chars().map(|c| c.to_digit(10).unwrap()).collect()).collect(); +fn part1(aoc: &mut aoc::Info) { + let mut octos: Vec<Vec<u32>> = aoc.input.lines() + .map(|l| l.chars().map(|c| c.to_digit(10).unwrap()).collect()) + .collect(); let mut flashes: usize = 0; for _i in 0..100 { @@ -89,10 +75,10 @@ fn part1() { println!("{}", flashes); } -fn part2() { - let content = fs::read_to_string("input").expect("no file"); - let mut octos: Vec<Vec<u32>> = content.lines() - .map(|l| l.chars().map(|c| c.to_digit(10).unwrap()).collect()).collect(); +fn part2(aoc: &mut aoc::Info) { + let mut octos: Vec<Vec<u32>> = aoc.input.lines() + .map(|l| l.chars().map(|c| c.to_digit(10).unwrap()).collect()) + .collect(); let height = octos.len(); let width = octos[0].len(); @@ -104,5 +90,9 @@ fn part2() { step += 1; } - println!("{}", step); + aoc.answer = Some(format!("{}", step)); +} + +fn main() { + aoc::run(part1, part2); } diff --git a/src/12/Cargo.toml b/src/12/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "aoc" +name = "day12" version = "0.1.0" edition = "2021" [dependencies] - +aoc = { path = "../../lib/aoc" } diff --git a/src/12/src/main.rs b/src/12/src/main.rs @@ -1,6 +1,4 @@ use std::collections::HashMap; -use std::env; -use std::fs; /* assume no two big caves are next to each other * => otherwise infinite paths possible */ @@ -17,22 +15,10 @@ struct NodeState<'a> { index: usize } -fn main() { - let args: Vec<String> = env::args().collect(); - if args[1] == "1" { - part1(); - } else if args[1] == "2" { - part2(); - } else { - eprintln!("No such part\n"); - } -} - -fn parse_input() -> HashMap<String, Node> { +fn parse_input(input: &String) -> HashMap<String, Node> { let mut nodes: HashMap<String, Node> = HashMap::new(); - let content = fs::read_to_string("input").expect("no file"); - for line in content.lines() { + for line in input.lines() { let parts: Vec<String> = line.split("-").map(|x| x.to_string()).collect(); for key in &parts { if !nodes.contains_key(key) { @@ -53,8 +39,8 @@ fn parse_input() -> HashMap<String, Node> { return nodes; } -fn part1() { - let nodes = parse_input(); +fn part1(aoc: &mut aoc::Info) { + let nodes = parse_input(&aoc.input); let mut path: Vec<&Node> = Vec::new(); let mut adj_index = 0; @@ -91,8 +77,8 @@ fn part1() { println!("{}", paths); } -fn part2() { - let nodes = parse_input(); +fn part2(aoc: &mut aoc::Info) { + let nodes = parse_input(&aoc.input); let mut path: Vec<NodeState> = Vec::new(); @@ -106,9 +92,9 @@ fn part2() { current.index += 1; if adj.name == "end" { for p in &path { - print!("{} -> ", p.node.name); + aoc::debug!(aoc, "{} -> ", p.node.name); } - println!("end"); + aoc::debug!(aoc, "end\n"); paths += 1; } else if adj.name != "start" && path.iter().filter(|x| x.node == adj).count() <= 1 || !adj.small { @@ -122,3 +108,7 @@ fn part2() { println!("{}", paths); } + +fn main() { + aoc::run(part1, part2); +}