-fn input() -> &'static str {
- include_str!("../input/day00.txt")
-}
-
fn parse(input: &str) -> () {
todo!()
}
-pub fn part1() {
- let n = 0;
- println!("Day 0 Part 1: {}", n);
+pub fn part1(input: &str) -> u64 {
+ 0
}
-pub fn part2() {
- let n = 0;
- println!("Day 0 Part 2: {}", n);
+pub fn part2(input: &str) -> u64 {
+ 0
}
#[cfg(test)]
fn test_parse() {
assert_eq!(parse(INPUT_STR), parse(INPUT_STR))
}
+
+ #[test]
+ #[ignore]
+ fn test_part1() {
+ assert_eq!(part1(&crate::input(0).unwrap()), 0)
+ }
+
+ #[test]
+ #[ignore]
+ fn test_part2() {
+ assert_eq!(part2(&crate::input(0).unwrap()), 0)
+ }
}
use std::collections::HashMap;
-fn input() -> &'static str {
- include_str!("../input/day01.txt")
-}
-
fn parse(input: &str) -> (Vec<u32>, Vec<u32>) {
let mut left = vec![];
let mut right = vec![];
left.iter().map(|n| n * counts.get(n).unwrap_or(&0)).sum()
}
-pub fn part1() {
- let (mut left, mut right) = parse(input());
- let d = distance(&mut left, &mut right);
- println!("Day 1 Part 1: {}", d);
+pub fn part1(input: &str) -> u64 {
+ let (mut left, mut right) = parse(input);
+ distance(&mut left, &mut right).into()
}
-pub fn part2() {
- let (mut left, mut right) = parse(input());
- let d = similarity(&mut left, &mut right);
- println!("Day 1 Part 2: {}", d);
+pub fn part2(input: &str) -> u64 {
+ let (mut left, mut right) = parse(input);
+ similarity(&mut left, &mut right).into()
}
#[cfg(test)]
let (mut left, mut right) = parse(INPUT_STR);
assert_eq!(similarity(&mut left, &mut right), 31)
}
+
+ #[test]
+ fn test_part1() {
+ assert_eq!(part1(&crate::input(1).unwrap()), 1151792)
+ }
+
+ #[test]
+ fn test_part2() {
+ assert_eq!(part2(&crate::input(1).unwrap()), 21790168)
+ }
}
-fn input() -> &'static str {
- include_str!("../input/day02.txt")
-}
-
fn parse(input: &str) -> Vec<Vec<i32>> {
input
.split_terminator('\n')
.any(|x| x)
}
-pub fn part1() {
- let vecs = parse(input());
- let n = vecs.iter().map(|v| is_safe(v)).filter(|&x| x).count();
- println!("Day 2 Part 1: {}", n);
+pub fn part1(input: &str) -> u64 {
+ parse(input)
+ .iter()
+ .map(|v| is_safe(v))
+ .filter(|&x| x)
+ .count()
+ .try_into()
+ .unwrap()
}
-pub fn part2() {
- let vecs = parse(input());
- let n = vecs
+pub fn part2(input: &str) -> u64 {
+ parse(input)
.iter()
.map(|v| is_safe_dampened(v))
.filter(|&x| x)
- .count();
- println!("Day 2 Part 2: {}", n);
+ .count()
+ .try_into()
+ .unwrap()
}
#[cfg(test)]
vec![true, false, false, true, true, true]
)
}
+
+ #[test]
+ fn test_part1() {
+ assert_eq!(part1(&crate::input(2).unwrap()), 202)
+ }
+
+ #[test]
+ fn test_part2() {
+ assert_eq!(part2(&crate::input(2).unwrap()), 271)
+ }
}
use regex::Regex;
-fn input() -> &'static str {
- include_str!("../input/day03.txt")
-}
-
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
enum Op {
Do,
.1
}
-pub fn part1() {
- let ops = parse(input());
- let n: u32 = ops.iter().map(|o| eval(true, o).1).sum();
- println!("Day 3 Part 1: {}", n);
+pub fn part1(input: &str) -> u64 {
+ let ops = parse(input);
+ ops.iter().map(|o| eval(true, o).1).sum::<u32>().into()
}
-pub fn part2() {
- let ops = parse(input());
- let n: u32 = exec(&ops);
- println!("Day 3 Part 2: {}", n);
+pub fn part2(input: &str) -> u64 {
+ let ops = parse(input);
+ exec(&ops).into()
}
#[cfg(test)]
fn test_exec() {
assert_eq!(exec(&parse(INPUT_STR2)), 48);
}
+
+ #[test]
+ fn test_part1() {
+ assert_eq!(part1(&crate::input(3).unwrap()), 184122457)
+ }
+
+ #[test]
+ fn test_part2() {
+ assert_eq!(part2(&crate::input(3).unwrap()), 107862689)
+ }
}
-fn input() -> &'static str {
- include_str!("../input/day04.txt")
-}
-
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
enum Char {
X,
.sum()
}
-pub fn part1() {
- let n = check_xs_for_xmas(&parse(input()));
- println!("Day 4 Part 1: {}", n);
+pub fn part1(input: &str) -> u64 {
+ check_xs_for_xmas(&parse(input)).try_into().unwrap()
}
-pub fn part2() {
- let n = check_as_for_xmas(&parse(input()));
- println!("Day 4 Part 2: {}", n);
+pub fn part2(input: &str) -> u64 {
+ check_as_for_xmas(&parse(input)).try_into().unwrap()
}
#[cfg(test)]
fn test_check_as() {
assert_eq!(check_as_for_xmas(&parse(INPUT_STR)), 9)
}
+
+ #[test]
+ fn test_part1() {
+ assert_eq!(part1(&crate::input(4).unwrap()), 2406)
+ }
+
+ #[test]
+ fn test_part2() {
+ assert_eq!(part2(&crate::input(4).unwrap()), 1807)
+ }
}
use std::collections::{HashMap, HashSet};
use std::rc::Rc;
-fn input() -> &'static str {
- include_str!("../input/day05.txt")
-}
-
type PageSet = HashSet<u8>;
type PageRel = HashMap<u8, PageSet>;
run[(run.len() + 1) / 2].num
}
-pub fn part1() {
- let pages = parse(input());
- let n: u32 = pages
+pub fn part1(input: &str) -> u64 {
+ let pages = parse(input);
+ pages
.iter()
.filter(|p| p.is_sorted())
.map(|p| -> u32 { get_middle(p).into() })
- .sum();
- println!("Day 5 Part 1: {}", n);
+ .sum::<u32>()
+ .into()
}
-pub fn part2() {
- let mut pages = parse(input());
- let n: u32 = pages
+pub fn part2(input: &str) -> u64 {
+ let mut pages = parse(input);
+ pages
.iter_mut()
.filter(|p| !p.is_sorted())
.map(|p| -> u32 {
p.sort();
get_middle(p).into()
})
- .sum();
- println!("Day 5 Part 2: {}", n);
+ .sum::<u32>()
+ .into()
}
#[cfg(test)]
assert!(!&pages[4].is_sorted());
assert!(!&pages[5].is_sorted());
}
+
+ #[test]
+ fn test_part1() {
+ assert_eq!(part1(&crate::input(5).unwrap()), 6251)
+ }
+
+ #[test]
+ fn test_part2() {
+ assert_eq!(part2(&crate::input(5).unwrap()), 7314)
+ }
}
use std::collections::HashSet;
-fn input() -> &'static str {
- include_str!("../input/day06.txt")
-}
-
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
enum Dir {
N,
}
}
-pub fn part1() {
- let n = GuardWalk::new(&parse(input()))
+pub fn part1(input: &str) -> u64 {
+ GuardWalk::new(&parse(input))
.collect::<HashSet<_>>()
- .len();
- println!("Day 6 Part 1: {}", n);
+ .len()
+ .try_into()
+ .unwrap()
}
-pub fn part2() {
- let map = parse(input());
+pub fn part2(input: &str) -> u64 {
+ let map = parse(input);
let walk = GuardWalk::new(&map);
let guard_pos = walk.find_guard();
- let n = walk
- .collect::<HashSet<_>>()
+ walk.collect::<HashSet<_>>()
.iter()
.filter(|&&p| GuardWalk::new_blocked(&map, p, guard_pos).has_cycle())
- .count();
- println!("Day 6 Part 2: {}", n);
+ .count()
+ .try_into()
+ .unwrap()
}
#[cfg(test)]
6
)
}
+
+ #[test]
+ fn test_part1() {
+ assert_eq!(part1(&crate::input(6).unwrap()), 5516)
+ }
+
+ #[test]
+ fn test_part2() {
+ assert_eq!(part2(&crate::input(6).unwrap()), 2008)
+ }
}
-fn input() -> &'static str {
- include_str!("../input/day07.txt")
-}
-
fn parse(input: &str) -> Vec<(u64, Vec<u64>)> {
input
.lines()
OpString::new_with_cat(rhs.len()).any(|ops| *lhs == op_eval(rhs, &ops))
}
-pub fn part1() {
- let n: u64 = parse(input())
+pub fn part1(input: &str) -> u64 {
+ parse(input)
.iter()
.filter(check_ops)
.map(|&(lhs, _)| lhs)
- .sum();
- println!("Day 7 Part 1: {}", n);
+ .sum()
}
-pub fn part2() {
- let n: u64 = parse(input())
+pub fn part2(input: &str) -> u64 {
+ parse(input)
.iter()
.filter(check_ops_with_cat)
.map(|&(lhs, _)| lhs)
- .sum();
- println!("Day 7 Part 2: {}", n);
+ .sum()
}
#[cfg(test)]
[190, 3267, 156, 7290, 192, 292]
)
}
+
+ #[test]
+ fn test_part1() {
+ assert_eq!(part1(&crate::input(7).unwrap()), 7885693428401)
+ }
+
+ #[test]
+ fn test_part2() {
+ assert_eq!(part2(&crate::input(7).unwrap()), 8398052607990)
+ }
}
use std::collections::{HashMap, HashSet};
use std::ops::{Add, Sub};
-fn input() -> &'static str {
- include_str!("../input/day08.txt")
-}
-
#[derive(Debug, Hash, Eq, PartialEq, Copy, Clone)]
struct Point(i32, i32);
.flat_map(move |(a, b)| get_colinear_points(bound, *a, *b))
}
-pub fn part1() {
- let size: i32 = input().lines().count().try_into().unwrap();
- let n = parse(input())
+pub fn part1(input: &str) -> u64 {
+ let size: i32 = input.lines().count().try_into().unwrap();
+ parse(input)
.iter()
.flat_map(|(_, pos)| find_nearby_antinodes(size, pos))
.collect::<HashSet<_>>()
- .len();
- println!("Day 8 Part 1: {}", n);
+ .len()
+ .try_into()
+ .unwrap()
}
-pub fn part2() {
- let size: i32 = input().lines().count().try_into().unwrap();
- let n = parse(input())
+pub fn part2(input: &str) -> u64 {
+ let size: i32 = input.lines().count().try_into().unwrap();
+ parse(input)
.iter()
.flat_map(|(_, pos)| find_antinodes(size, pos))
.collect::<HashSet<_>>()
- .len();
- println!("Day 8 Part 2: {}", n);
+ .len()
+ .try_into()
+ .unwrap()
}
#[cfg(test)]
34
);
}
+
+ #[test]
+ fn test_part1() {
+ assert_eq!(part1(&crate::input(8).unwrap()), 336)
+ }
+
+ #[test]
+ fn test_part2() {
+ assert_eq!(part2(&crate::input(8).unwrap()), 1131)
+ }
}
-fn input() -> &'static str {
- include_str!("../input/day09.txt")
-}
-
type DiskMap = Option<u64>;
fn parse(input: &str) -> Vec<DiskMap> {
.sum()
}
-pub fn part1() {
- let mut map = parse(input());
+pub fn part1(input: &str) -> u64 {
+ let mut map = parse(input);
fragment(&mut map);
- let n = checksum(&map);
- println!("Day 9 Part 1: {}", n);
+ checksum(&map)
}
-pub fn part2() {
- let mut disk = parse(input());
+pub fn part2(input: &str) -> u64 {
+ let mut disk = parse(input);
compact(&mut disk);
- let n = checksum(&disk);
- println!("Day 9 Part 2: {}", n);
+ checksum(&disk)
}
#[cfg(test)]
compact(&mut disk);
assert_eq!(checksum(&disk), 2858);
}
+
+ #[test]
+ fn test_part1() {
+ assert_eq!(part1(&crate::input(9).unwrap()), 6225730762521)
+ }
+
+ #[test]
+ fn test_part2() {
+ assert_eq!(part2(&crate::input(9).unwrap()), 6250605700557)
+ }
}
use std::collections::HashSet;
use std::ops::{Add, Index, Sub};
-fn input() -> &'static str {
- include_str!("../input/day10.txt")
-}
-
#[derive(Debug, Hash, Eq, PartialEq, Copy, Clone)]
struct Point(i32, i32);
.collect())
}
-pub fn part1() {
- let map = parse(input());
- let n: u64 = map
- .find_height(0)
+pub fn part1(input: &str) -> u64 {
+ let map = parse(input);
+ map.find_height(0)
.map(|p| map.count_reachable_heights(&p))
- .sum();
- println!("Day 10 Part 1: {}", n);
+ .sum()
}
-pub fn part2() {
- let map = parse(input());
- let n: u64 = map
- .find_height(0)
+pub fn part2(input: &str) -> u64 {
+ let map = parse(input);
+ map.find_height(0)
.map(|p| map.count_unique_trails(&p))
- .sum();
- println!("Day 10 Part 2: {}", n);
+ .sum()
}
#[cfg(test)]
assert_eq!(map.count_unique_trails(&Point(6, 6)), 8);
assert_eq!(map.count_unique_trails(&Point(7, 1)), 5);
}
+
+ #[test]
+ fn test_part1() {
+ assert_eq!(part1(&crate::input(10).unwrap()), 617)
+ }
+
+ #[test]
+ fn test_part2() {
+ assert_eq!(part2(&crate::input(10).unwrap()), 1477)
+ }
}
-fn input() -> &'static str {
- include_str!("../input/day11.txt")
-}
-
fn parse(input: &str) -> Vec<u64> {
input
.split_whitespace()
.collect()
}
-pub fn part1() {
- let n = std::iter::successors(Some(parse(input())), |v| Some(iterate(v)))
+pub fn part1(input: &str) -> u64 {
+ std::iter::successors(Some(parse(input)), |v| Some(iterate(v)))
.take(26)
.last()
.unwrap()
- .len();
- println!("Day 11 Part 1: {}", n);
+ .len()
+ .try_into()
+ .unwrap()
}
-pub fn part2() {
+pub fn part2(input: &str) -> u64 {
// lol no
- let n = std::iter::successors(Some(parse(input())), |v| Some(iterate(v)))
+ std::iter::successors(Some(parse(input)), |v| Some(iterate(v)))
.take(76)
.last()
.unwrap()
- .len();
- println!("Day 11 Part 2: {}", n);
+ .len()
+ .try_into()
+ .unwrap()
}
#[cfg(test)]
]
)
}
+
+ #[test]
+ fn test_part1() {
+ assert_eq!(part1(&crate::input(11).unwrap()), 212655)
+ }
+
+ #[test]
+ #[ignore]
+ fn test_part2() {
+ assert_eq!(part2(&crate::input(11).unwrap()), 0)
+ }
}
// pub mod day24;
// pub mod day25;
-type Part = fn();
+type Part = fn(&str) -> u64;
const DAYS: &[(Part, Part)] = &[
- (day01::part1 as fn(), day01::part2 as fn()),
- (day02::part1 as fn(), day02::part2 as fn()),
- (day03::part1 as fn(), day03::part2 as fn()),
- (day04::part1 as fn(), day04::part2 as fn()),
- (day05::part1 as fn(), day05::part2 as fn()),
- (day06::part1 as fn(), day06::part2 as fn()),
- (day07::part1 as fn(), day07::part2 as fn()),
- (day08::part1 as fn(), day08::part2 as fn()),
- (day09::part1 as fn(), day09::part2 as fn()),
- (day10::part1 as fn(), day10::part2 as fn()),
- (day11::part1 as fn(), day11::part2 as fn()),
- // (day12::part1 as fn(), day12::part2 as fn()),
- // (day13::part1 as fn(), day13::part2 as fn()),
- // (day14::part1 as fn(), day14::part2 as fn()),
- // (day15::part1 as fn(), day15::part2 as fn()),
- // (day16::part1 as fn(), day16::part2 as fn()),
- // (day17::part1 as fn(), day17::part2 as fn()),
- // (day18::part1 as fn(), day18::part2 as fn()),
- // (day19::part1 as fn(), day19::part2 as fn()),
- // (day20::part1 as fn(), day20::part2 as fn()),
- // (day21::part1 as fn(), day21::part2 as fn()),
- // (day22::part1 as fn(), day22::part2 as fn()),
- // (day23::part1 as fn(), day23::part2 as fn()),
- // (day24::part1 as fn(), day24::part2 as fn()),
- // (day25::part1 as fn(), day25::part2 as fn()),
+ (day01::part1, day01::part2),
+ (day02::part1, day02::part2),
+ (day03::part1, day03::part2),
+ (day04::part1, day04::part2),
+ (day05::part1, day05::part2),
+ (day06::part1, day06::part2),
+ (day07::part1, day07::part2),
+ (day08::part1, day08::part2),
+ (day09::part1, day09::part2),
+ (day10::part1, day10::part2),
+ (day11::part1, day11::part2),
+ // (day12::part1, day12::part2),
+ // (day13::part1, day13::part2),
+ // (day14::part1, day14::part2),
+ // (day15::part1, day15::part2),
+ // (day16::part1, day16::part2),
+ // (day17::part1, day17::part2),
+ // (day18::part1, day18::part2),
+ // (day19::part1, day19::part2),
+ // (day20::part1, day20::part2),
+ // (day21::part1, day21::part2),
+ // (day22::part1, day22::part2),
+ // (day23::part1, day23::part2),
+ // (day24::part1, day24::part2),
+ // (day25::part1, day25::part2),
];
+fn input(day: usize) -> std::io::Result<String> {
+ let file = std::fs::File::open(format!("input/day{:02}.txt", day))?;
+ std::io::read_to_string(file)
+}
+
fn main() {
let args: Vec<String> = std::env::args().collect();
let arg = args.get(1).expect("Please provide a day.");
if arg == "all" {
- for day in DAYS {
- day.0();
- day.1();
+ for (day, i) in DAYS.iter().zip(1..) {
+ let input = input(i).unwrap().to_string();
+ let p1 = day.0(&input);
+ println!("Day {} Part 1: {}", i, p1);
+ let p2 = day.1(&input);
+ println!("Day {} Part 2: {}", i, p2);
}
} else {
let day: usize = arg.parse().expect("The day should be a number.");
if day < 1 || day > DAYS.len() {
panic!("That day hasn't been implemented yet!");
}
- DAYS[day - 1].0();
- DAYS[day - 1].1();
+ let input = input(day).unwrap().to_string();
+ let p1 = DAYS[day - 1].0(&input);
+ println!("Day {} Part 1: {}", day, p1);
+ let p2 = DAYS[day - 1].1(&input);
+ println!("Day {} Part 2: {}", day, p2);
}
}