Restructure Rust solutions
This commit is contained in:
parent
da9884da75
commit
a8685c5145
331 changed files with 3081 additions and 11948 deletions
52
2021/01.rs
52
2021/01.rs
|
@ -1,52 +0,0 @@
|
|||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use std::fs;
|
||||
use test::Bencher;
|
||||
|
||||
type Input = Vec<i32>;
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = fs::read_to_string("2021/01.txt").unwrap();
|
||||
return puzzle.lines().map(|x| x.parse().unwrap()).collect();
|
||||
}
|
||||
|
||||
fn count(input: &Input, window: usize) -> i32 {
|
||||
let mut out = 0;
|
||||
for (a, b) in input.iter().zip(&input[window..]) {
|
||||
if b > a { out += 1; }
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
count(input, 1).to_string()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
count(input, 3).to_string()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (part1, part2) = run();
|
||||
println!("Part 1: {}", part1);
|
||||
println!("Part 2: {}", part2);
|
||||
}
|
||||
|
||||
pub fn run() -> (String, String) {
|
||||
let input = get_input();
|
||||
(part1(&input), part2(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part1(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| { part1(&input) })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part2(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| { part2(&input) })
|
||||
}
|
78
2021/02.rs
78
2021/02.rs
|
@ -1,78 +0,0 @@
|
|||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use std::fs;
|
||||
use test::Bencher;
|
||||
|
||||
enum Command { Forward(i32), Down(i32), Up(i32) }
|
||||
|
||||
type Input = Vec<Command>;
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = fs::read_to_string("2021/02.txt").unwrap();
|
||||
puzzle.lines().map(|line| {
|
||||
let mut x = line.split(" ");
|
||||
let cmd = x.next().unwrap();
|
||||
let n: i32 = x.next().unwrap().parse().unwrap();
|
||||
match cmd {
|
||||
"forward" => Command::Forward(n),
|
||||
"up" => Command::Up(n),
|
||||
"down" => Command::Down(n),
|
||||
_ => panic!(),
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
let mut d = 0;
|
||||
let mut h = 0;
|
||||
for cmd in input {
|
||||
match cmd {
|
||||
Command::Forward(n) => { h += n }
|
||||
Command::Down(n) => { d += n }
|
||||
Command::Up(n) => { d -= n }
|
||||
}
|
||||
}
|
||||
(d * h).to_string()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
let mut d = 0;
|
||||
let mut h = 0;
|
||||
let mut a = 0;
|
||||
for cmd in input {
|
||||
match cmd {
|
||||
Command::Forward(n) => {
|
||||
h += n;
|
||||
d += a * n;
|
||||
}
|
||||
Command::Down(n) => { a += n }
|
||||
Command::Up(n) => { a -= n }
|
||||
}
|
||||
}
|
||||
(d * h).to_string()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (part1, part2) = run();
|
||||
println!("Part 1: {}", part1);
|
||||
println!("Part 2: {}", part2);
|
||||
}
|
||||
|
||||
pub fn run() -> (String, String) {
|
||||
let input = get_input();
|
||||
(part1(&input), part2(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part1(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| { part1(&input) })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part2(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| { part2(&input) })
|
||||
}
|
71
2021/03.rs
71
2021/03.rs
|
@ -1,71 +0,0 @@
|
|||
#![feature(test)]
|
||||
#![feature(drain_filter)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use std::fs;
|
||||
use test::Bencher;
|
||||
|
||||
type Input = Vec<String>;
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = fs::read_to_string("2021/03.txt").unwrap();
|
||||
puzzle.lines().map(|s| s.to_string()).collect()
|
||||
}
|
||||
|
||||
fn count(input: &Input, i: usize, chr: &char) -> usize {
|
||||
input.iter().filter(|s| s.chars().nth(i).unwrap() == *chr).count()
|
||||
}
|
||||
|
||||
fn most_common(input: &Input, i: usize) -> char { "01".chars().max_by_key(|c| count(input, i, c)).unwrap() }
|
||||
|
||||
fn least_common(input: &Input, i: usize) -> char { "01".chars().min_by_key(|c| count(input, i, c)).unwrap() }
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
let mut most = 0;
|
||||
let mut least = 0;
|
||||
for i in 0..input[0].len() {
|
||||
most = most << 1 | most_common(input, i) as u32 - '0' as u32;
|
||||
least = least << 1 | least_common(input, i) as u32 - '0' as u32;
|
||||
}
|
||||
(most * least).to_string()
|
||||
}
|
||||
|
||||
fn find(input: &Input, x: bool) -> isize {
|
||||
let mut out = input.clone();
|
||||
for i in 0..input[0].len() {
|
||||
let mx = if x {least_common(&out, i) } else {most_common(&out, i)};
|
||||
out.drain_filter(|x|x.chars().nth(i).unwrap() != mx).count();
|
||||
if out.len() == 1 {
|
||||
return isize::from_str_radix(out[0].as_str(), 2).unwrap();
|
||||
}
|
||||
}
|
||||
panic!();
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
(find(input, true) * find(input, false)).to_string()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (part1, part2) = run();
|
||||
println!("Part 1: {}", part1);
|
||||
println!("Part 2: {}", part2);
|
||||
}
|
||||
|
||||
pub fn run() -> (String, String) {
|
||||
let input = get_input();
|
||||
(part1(&input), part2(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part1(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| { part1(&input) })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part2(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| { part2(&input) })
|
||||
}
|
105
2021/04.rs
105
2021/04.rs
|
@ -1,105 +0,0 @@
|
|||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use std::fs;
|
||||
use test::Bencher;
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
struct Input {
|
||||
nums: Vec<i32>,
|
||||
boards: Vec<Vec<Vec<i32>>>,
|
||||
}
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = fs::read_to_string("2021/04.txt").unwrap();
|
||||
let nums = puzzle.lines().next().unwrap().split(",").map(|n| n.parse().unwrap()).collect();
|
||||
let boards = puzzle.split("\n\n").skip(1).map(|board| {
|
||||
board.lines().map(|line| {
|
||||
line.split_whitespace().map(|n| n.parse().unwrap()).collect()
|
||||
}).collect()
|
||||
}).collect();
|
||||
return Input { nums, boards };
|
||||
}
|
||||
|
||||
struct State {
|
||||
boards: Vec<Vec<Vec<i32>>>,
|
||||
marked: FxHashSet<i32>,
|
||||
}
|
||||
|
||||
impl State {
|
||||
fn from_input(input: &Input) -> State {
|
||||
State {boards: input.boards.clone(), marked: FxHashSet::default()}
|
||||
}
|
||||
|
||||
fn mark(&mut self, num: i32) {
|
||||
self.marked.insert(num);
|
||||
}
|
||||
|
||||
fn check_board(&self, board: usize) -> bool {
|
||||
let board = &self.boards[board];
|
||||
for row in board {
|
||||
if row.iter().all(|n| self.marked.contains(n)) { return true; }
|
||||
}
|
||||
for i in 0..board[0].len() {
|
||||
if board.iter().all(|row| self.marked.contains(&row[i])) { return true; }
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn get_score(&self, board: usize) -> i32 {
|
||||
*&self.boards[board].iter().flatten().filter(|n| {
|
||||
!self.marked.contains(n)
|
||||
}).map(|n|*n).reduce(|a, b| a + b).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
let mut state = State::from_input(input);
|
||||
for num in &input.nums {
|
||||
state.mark(*num);
|
||||
for i in 0..state.boards.len() {
|
||||
if state.check_board(i) {
|
||||
return (num * state.get_score(i)).to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
panic!();
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
let mut state = State::from_input(input);
|
||||
for num in &input.nums {
|
||||
state.mark(*num);
|
||||
let mut i = 0;
|
||||
while i < state.boards.len() {
|
||||
if !state.check_board(i) { i += 1; continue }
|
||||
if state.boards.len() == 1 { return (num * state.get_score(i)).to_string()}
|
||||
state.boards.remove(i);
|
||||
}
|
||||
}
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (part1, part2) = run();
|
||||
println!("Part 1: {}", part1);
|
||||
println!("Part 2: {}", part2);
|
||||
}
|
||||
|
||||
pub fn run() -> (String, String) {
|
||||
let input = get_input();
|
||||
(part1(&input), part2(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part1(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| { part1(&input) })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part2(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| { part2(&input) })
|
||||
}
|
84
2021/05.rs
84
2021/05.rs
|
@ -1,84 +0,0 @@
|
|||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use std::fs;
|
||||
use test::Bencher;
|
||||
use regex::Regex;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
type Line = (i32, i32, i32, i32);
|
||||
type Input = Vec<Line>;
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = fs::read_to_string("2021/05.txt").unwrap();
|
||||
let regex = Regex::new(r"^(\d+),(\d+) -> (\d+),(\d+)$").unwrap();
|
||||
puzzle.lines().map(|line| {
|
||||
let capture = regex.captures(line).unwrap();
|
||||
(
|
||||
capture[1].parse().unwrap(),
|
||||
capture[2].parse().unwrap(),
|
||||
capture[3].parse().unwrap(),
|
||||
capture[4].parse().unwrap(),
|
||||
)
|
||||
}).collect()
|
||||
}
|
||||
|
||||
fn iter_line(line: &Line) -> Vec<(i32, i32)> {
|
||||
let (mut x, mut y, x2, y2) = line;
|
||||
let mut result = vec![(x, y)];
|
||||
while (x != *x2) || (y != *y2) {
|
||||
if x < *x2 { x += 1; }
|
||||
else if x > *x2 { x -= 1; }
|
||||
if y < *y2 { y += 1; }
|
||||
else if y > *y2 { y -= 1; }
|
||||
result.push((x, y));
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
let mut counter = FxHashMap::default();
|
||||
for line in input {
|
||||
if (line.0 != line.2) && (line.1 != line.3) { continue }
|
||||
for (x, y) in iter_line(line) {
|
||||
let cnt = *counter.entry((x, y)).or_insert(0) + 1;
|
||||
counter.insert((x, y), cnt);
|
||||
}
|
||||
}
|
||||
counter.iter().filter(|&(_, &cnt)| cnt > 1).count().to_string()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
let mut counter = FxHashMap::default();
|
||||
for line in input {
|
||||
for (x, y) in iter_line(line) {
|
||||
let cnt = *counter.entry((x, y)).or_insert(0) + 1;
|
||||
counter.insert((x, y), cnt);
|
||||
}
|
||||
}
|
||||
counter.iter().filter(|&(_, &cnt)| cnt > 1).count().to_string()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (part1, part2) = run();
|
||||
println!("Part 1: {}", part1);
|
||||
println!("Part 2: {}", part2);
|
||||
}
|
||||
|
||||
pub fn run() -> (String, String) {
|
||||
let input = get_input();
|
||||
(part1(&input), part2(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part1(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| { part1(&input) })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part2(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| { part2(&input) })
|
||||
}
|
57
2021/06.rs
57
2021/06.rs
|
@ -1,57 +0,0 @@
|
|||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use std::fs;
|
||||
use test::Bencher;
|
||||
|
||||
type Input = Vec<i32>;
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = fs::read_to_string("2021/06.txt").unwrap();
|
||||
puzzle.trim().split(",").map(|x| x.parse().unwrap()).collect()
|
||||
}
|
||||
|
||||
fn solve(input: &Input, n: u32) -> String {
|
||||
let mut counter = vec![0; 9];
|
||||
for num in input {
|
||||
counter[*num as usize] += 1;
|
||||
}
|
||||
for _ in 0..n {
|
||||
let x = counter.remove(0);
|
||||
counter.push(x);
|
||||
counter[6] += x;
|
||||
}
|
||||
counter.iter().sum::<u64>().to_string()
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
solve(input, 80)
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
solve(input, 256)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (part1, part2) = run();
|
||||
println!("Part 1: {}", part1);
|
||||
println!("Part 2: {}", part2);
|
||||
}
|
||||
|
||||
pub fn run() -> (String, String) {
|
||||
let input = get_input();
|
||||
(part1(&input), part2(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part1(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| { part1(&input) })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part2(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| { part2(&input) })
|
||||
}
|
51
2021/07.rs
51
2021/07.rs
|
@ -1,51 +0,0 @@
|
|||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use std::fs;
|
||||
use test::Bencher;
|
||||
|
||||
type Input = Vec<i32>;
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = fs::read_to_string("2021/07.txt").unwrap();
|
||||
puzzle.trim().split(",").map(|x| x.parse().unwrap()).collect()
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
(0..=input.len()).map(|pos| {
|
||||
input.iter().map(|n| (pos as i32 - *n).abs()).sum::<i32>()
|
||||
}).min().unwrap().to_string()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
(0..=input.len()).map(|pos| {
|
||||
input.iter().map(|n| {
|
||||
let x = (pos as i32 - *n).abs();
|
||||
x * (x + 1) >> 1
|
||||
}).sum::<i32>()
|
||||
}).min().unwrap().to_string()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (part1, part2) = run();
|
||||
println!("Part 1: {}", part1);
|
||||
println!("Part 2: {}", part2);
|
||||
}
|
||||
|
||||
pub fn run() -> (String, String) {
|
||||
let input = get_input();
|
||||
(part1(&input), part2(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part1(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| { part1(&input) })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part2(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| { part2(&input) })
|
||||
}
|
107
2021/08.rs
107
2021/08.rs
|
@ -1,107 +0,0 @@
|
|||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use std::fs;
|
||||
use test::Bencher;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
||||
struct Line {
|
||||
patterns: Vec<String>,
|
||||
output: Vec<String>,
|
||||
}
|
||||
|
||||
type Input = Vec<Line>;
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = fs::read_to_string("2021/08.txt").unwrap();
|
||||
puzzle.lines().map(|line| {
|
||||
let mut line = line.trim().split(" | ");
|
||||
let mut parse = || line.next().unwrap().split(" ").map(|x| x.to_string()).collect();
|
||||
Line {
|
||||
patterns: parse(),
|
||||
output: parse(),
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
input.iter().map(|line| {
|
||||
line.output.iter().filter(|x| [2, 3, 4, 7].contains(&x.len())).count()
|
||||
}).sum::<usize>().to_string()
|
||||
}
|
||||
|
||||
fn parse_num(num: &String) -> u16 {
|
||||
num.chars().map(|c| {
|
||||
1 << (c as u16) - ('a' as u16)
|
||||
}).sum::<u16>()
|
||||
}
|
||||
|
||||
fn is_subset(mut a: u16, mut b: u16) -> bool {
|
||||
while a > 0 {
|
||||
if 1 & a & !b == 1 { return false; }
|
||||
a >>= 1;
|
||||
b >>= 1;
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
let digits = FxHashMap::from_iter([((7, 2), 1), ((2, 5), 2), ((3, 5), 3), ((3, 4), 4), ((4, 5), 5), ((5, 3), 7), ((1, 7), 8)]);
|
||||
|
||||
input.iter().map(|line| {
|
||||
let patterns: Vec<u16> = line.patterns.iter().map(parse_num).collect();
|
||||
let output: Vec<u16> = line.output.iter().map(parse_num).collect();
|
||||
let mut mp: FxHashMap<u16, u8> = FxHashMap::default();
|
||||
let mut rp: FxHashMap<u8, u16> = FxHashMap::default();
|
||||
let mut u: FxHashSet<u16> = FxHashSet::from_iter(patterns.iter().cloned());
|
||||
for x in &patterns {
|
||||
let sc = patterns.iter().filter(|y| is_subset(*x, **y)).count();
|
||||
match digits.get(&(sc, x.count_ones())) {
|
||||
None => {}
|
||||
Some(digit) => {
|
||||
mp.insert(*x, *digit);
|
||||
rp.insert(*digit, *x);
|
||||
u.remove(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let x = *u.iter().filter(|x| !is_subset(*rp.get(&5).unwrap(), **x)).next().unwrap();
|
||||
mp.insert(x, 0);
|
||||
u.remove(&x);
|
||||
|
||||
let x = *u.iter().filter(|x| is_subset(*rp.get(&4).unwrap(), **x)).next().unwrap();
|
||||
mp.insert(x, 9);
|
||||
u.remove(&x);
|
||||
|
||||
let x = *u.iter().next().unwrap();
|
||||
mp.insert(x, 6);
|
||||
|
||||
output.iter().map(|x| *mp.get(x).unwrap() as u32).reduce(|a, b| a * 10 + b).unwrap()
|
||||
}).sum::<u32>().to_string()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (part1, part2) = run();
|
||||
println!("Part 1: {}", part1);
|
||||
println!("Part 2: {}", part2);
|
||||
}
|
||||
|
||||
pub fn run() -> (String, String) {
|
||||
let input = get_input();
|
||||
(part1(&input), part2(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part1(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| { part1(&input) })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part2(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| { part2(&input) })
|
||||
}
|
82
2021/10.rs
82
2021/10.rs
|
@ -1,82 +0,0 @@
|
|||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use std::fs;
|
||||
use test::Bencher;
|
||||
|
||||
type Input = Vec<String>;
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = fs::read_to_string("2021/10.txt").unwrap();
|
||||
puzzle.lines().map(|s| s.to_string()).collect()
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
input.iter().map(|line| {
|
||||
let mut stack = Vec::new();
|
||||
for c in line.chars() {
|
||||
if "([{<".contains(c) {
|
||||
stack.push(c);
|
||||
} else {
|
||||
let x = stack.pop().unwrap();
|
||||
if !["()", "[]", "{}", "<>"].contains(&format!("{}{}", x, c).as_str()) {
|
||||
return match c {
|
||||
')' => 3,
|
||||
']' => 57,
|
||||
'}' => 1197,
|
||||
'>' => 25137,
|
||||
_ => panic!()
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
0
|
||||
}).sum::<u32>().to_string()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
let mut scores: Vec<usize> = input.iter().filter_map(|line| {
|
||||
let mut stack = Vec::new();
|
||||
for c in line.chars() {
|
||||
if "([{<".contains(c) {
|
||||
stack.push(c);
|
||||
} else {
|
||||
let x = stack.pop().unwrap();
|
||||
if !["()", "[]", "{}", "<>"].contains(&format!("{}{}", x, c).as_str()) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut out = 0;
|
||||
for c in stack.iter().rev() {
|
||||
out = out * 5 + " ([{<".find(*c).unwrap();
|
||||
}
|
||||
Some(out)
|
||||
}).collect();
|
||||
scores.sort();
|
||||
scores[scores.len() / 2].to_string()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (part1, part2) = run();
|
||||
println!("Part 1: {}", part1);
|
||||
println!("Part 2: {}", part2);
|
||||
}
|
||||
|
||||
pub fn run() -> (String, String) {
|
||||
let input = get_input();
|
||||
(part1(&input), part2(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part1(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| part1(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part2(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| part2(&input))
|
||||
}
|
87
2021/12.rs
87
2021/12.rs
|
@ -1,87 +0,0 @@
|
|||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use std::fs;
|
||||
use test::Bencher;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
||||
type Input = FxHashMap<i32, Vec<i32>>;
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = fs::read_to_string("2021/12.txt").unwrap();
|
||||
let mut out = FxHashMap::default();
|
||||
let mut map = FxHashMap::default();
|
||||
map.insert("start", 0);
|
||||
map.insert("end", 1);
|
||||
for line in puzzle.trim().lines() {
|
||||
let mut split = line.split("-").map(|x| {
|
||||
if !map.contains_key(x) { map.insert(x, (map.len() as i32) * if x < "a" { 1 } else { -1 }); }
|
||||
*map.get(x).unwrap()
|
||||
});
|
||||
|
||||
let a = split.next().unwrap();
|
||||
let b = split.next().unwrap();
|
||||
|
||||
match out.get_mut(&a) {
|
||||
None => { out.insert(a, vec![b]); }
|
||||
Some(x) => { x.push(b); }
|
||||
}
|
||||
match out.get_mut(&b) {
|
||||
None => { out.insert(b, vec![a]); }
|
||||
Some(x) => { x.push(a); }
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
fn search(node: i32, graph: &Input, visited: &mut FxHashSet<i32>, small_twice: bool) -> u32 {
|
||||
if node == 1 { return 1; }
|
||||
let mut twice = false;
|
||||
if node <= 0 && visited.contains(&node) {
|
||||
if small_twice || node == 0 { return 0; }
|
||||
twice = true;
|
||||
}
|
||||
visited.insert(node);
|
||||
|
||||
let out = match graph.get(&node) {
|
||||
None => 0,
|
||||
Some(edges) => edges.iter().cloned().map(|next|
|
||||
search(next, graph, visited, twice || small_twice)
|
||||
).sum::<u32>()
|
||||
};
|
||||
|
||||
if !twice { visited.remove(&node); }
|
||||
out
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
search(0, input, &mut FxHashSet::default(), true).to_string()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
search(0, input, &mut FxHashSet::default(), false).to_string()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (part1, part2) = run();
|
||||
println!("Part 1: {}", part1);
|
||||
println!("Part 2: {}", part2);
|
||||
}
|
||||
|
||||
pub fn run() -> (String, String) {
|
||||
let input = get_input();
|
||||
(part1(&input), part2(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part1(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| part1(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part2(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| part2(&input))
|
||||
}
|
109
2021/13.rs
109
2021/13.rs
|
@ -1,109 +0,0 @@
|
|||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use std::borrow::Borrow;
|
||||
use std::fs;
|
||||
use test::Bencher;
|
||||
|
||||
use regex::Regex;
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
enum Instruction { X(u32), Y(u32) }
|
||||
|
||||
struct Input {
|
||||
dots: FxHashSet<(u32, u32)>,
|
||||
instructions: Vec<Instruction>,
|
||||
}
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = fs::read_to_string("2021/13.txt").unwrap();
|
||||
let mut blocks = puzzle.split("\n\n");
|
||||
let dots = blocks.next().unwrap().lines().map(|line| {
|
||||
let mut coords = line.split(",");
|
||||
(coords.next().unwrap().parse().unwrap(), coords.next().unwrap().parse().unwrap())
|
||||
}).collect();
|
||||
let regex = Regex::new(r"^fold along (.)=(\d+)$").unwrap();
|
||||
let instructions = blocks.next().unwrap().lines().map(|line| {
|
||||
let capture = regex.captures(line).unwrap();
|
||||
let n: u32 = capture.get(2).unwrap().as_str().parse().unwrap();
|
||||
match capture.get(1).unwrap().as_str() {
|
||||
"x" => Instruction::X(n),
|
||||
"y" => Instruction::Y(n),
|
||||
_ => panic!()
|
||||
}
|
||||
}).collect();
|
||||
Input { dots, instructions }
|
||||
}
|
||||
|
||||
fn fold(dots: &FxHashSet<(u32, u32)>, instruction: &Instruction) -> FxHashSet<(u32, u32)> {
|
||||
dots.iter().cloned().map(|(x, y)| {
|
||||
match instruction {
|
||||
Instruction::X(n) => (x.min(2 * n - x), y),
|
||||
Instruction::Y(n) => (x, y.min(2 * n - y)),
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
let mut dots = input.dots.clone();
|
||||
let instruction = input.instructions.first().unwrap();
|
||||
dots = fold(&dots, instruction);
|
||||
dots.len().to_string()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
let mut dots = input.dots.clone();
|
||||
for instruction in &input.instructions {
|
||||
dots = fold(&dots, instruction);
|
||||
}
|
||||
|
||||
(0..8).map(|n| {
|
||||
let k = (5 * n..5 * n+4).flat_map(|i| {
|
||||
let dots = &dots;
|
||||
(0..6).map(move |j| {
|
||||
dots.contains(&(i, j))
|
||||
})
|
||||
}).fold(0, |acc, x| { (acc << 1) | (x as i32) });
|
||||
match k {
|
||||
0b011111100100100100011111 => 'A',
|
||||
0b111111101001101001010110 => 'B',
|
||||
0b011110100001100001010010 => 'C',
|
||||
0b111111101001101001100001 => 'E',
|
||||
0b111111101000101000100000 => 'F',
|
||||
0b011110100001100101010111 => 'G',
|
||||
0b111111001000001000111111 => 'H',
|
||||
0b000010000001100001111111 => 'J',
|
||||
0b111111001000010110100001 => 'K',
|
||||
0b111111000001000001000001 => 'L',
|
||||
0b111111100100100100011000 => 'P',
|
||||
0b111111100100100110011001 => 'R',
|
||||
0b111110000001000001111110 => 'U',
|
||||
0b100011100101101001110001 => 'Z',
|
||||
_ => '?'
|
||||
}
|
||||
}).collect::<String>()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (part1, part2) = run();
|
||||
println!("Part 1: {}", part1);
|
||||
println!("Part 2: {}", part2);
|
||||
}
|
||||
|
||||
pub fn run() -> (String, String) {
|
||||
let input = get_input();
|
||||
(part1(&input), part2(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part1(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| part1(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part2(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| part2(&input))
|
||||
}
|
78
2021/15.rs
78
2021/15.rs
|
@ -1,78 +0,0 @@
|
|||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use std::cmp::Reverse;
|
||||
use std::collections::BinaryHeap;
|
||||
use std::fs;
|
||||
use test::Bencher;
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
type Input = Vec<Vec<u32>>;
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = fs::read_to_string("2021/15.txt").unwrap();
|
||||
puzzle.lines().map(|line| {
|
||||
line.chars().map(|c| (c as u32) - 0x30).collect()
|
||||
}).collect()
|
||||
}
|
||||
|
||||
fn dijkstra(grid: &Input, k: usize) -> u32 {
|
||||
let w = grid[0].len();
|
||||
let h = grid.len();
|
||||
let mut queue = BinaryHeap::new();
|
||||
queue.push(Reverse((0u32, 0usize, 0usize)));
|
||||
let mut visited = FxHashSet::default();
|
||||
while !queue.is_empty() {
|
||||
let (d, x, y) = queue.pop().unwrap().0;
|
||||
|
||||
if visited.contains(&(x, y)) { continue; }
|
||||
visited.insert((x, y));
|
||||
|
||||
if x == w * k - 1 && y == h * k - 1 { return d; }
|
||||
|
||||
for (dx, dy) in [(-1, 0), (1, 0), (0, -1), (0, 1)] {
|
||||
let p = (x as i32) + dx;
|
||||
let q = (y as i32) + dy;
|
||||
if p < 0 || q < 0 { continue; }
|
||||
let p = p as usize;
|
||||
let q = q as usize;
|
||||
if p >= k * w || q >= k * h { continue; }
|
||||
if visited.contains(&(p, q)) { continue; }
|
||||
let c = grid[q % h][p % w] + (q / h + p / w) as u32;
|
||||
queue.push(Reverse((d + (c - 1) % 9 + 1, p, q)));
|
||||
}
|
||||
}
|
||||
panic!();
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
dijkstra(input, 1).to_string()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
dijkstra(input, 5).to_string()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (part1, part2) = run();
|
||||
println!("Part 1: {}", part1);
|
||||
println!("Part 2: {}", part2);
|
||||
}
|
||||
|
||||
pub fn run() -> (String, String) {
|
||||
let input = get_input();
|
||||
(part1(&input), part2(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part1(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| part1(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part2(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| part2(&input))
|
||||
}
|
144
2021/18.rs
144
2021/18.rs
|
@ -1,144 +0,0 @@
|
|||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use std::fs;
|
||||
use test::Bencher;
|
||||
|
||||
type Number = [Option<u32>; 64];
|
||||
type Input = Vec<Number>;
|
||||
|
||||
fn parent(n: usize) -> usize { n >> 1 }
|
||||
|
||||
fn left(n: usize) -> usize { n << 1 }
|
||||
|
||||
fn right(n: usize) -> usize { n << 1 | 1 }
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = fs::read_to_string("2021/18.txt").unwrap();
|
||||
puzzle.trim().lines().map(|line| {
|
||||
let mut out = [Option::None; 64];
|
||||
let mut acc = Option::None;
|
||||
let mut n = 1;
|
||||
for c in line.trim().chars() {
|
||||
let digit = (c as i32) - 0x30;
|
||||
if digit >= 0 && digit <= 9 {
|
||||
acc = Option::Some(acc.unwrap_or(0) * 10 + (digit as u32));
|
||||
continue;
|
||||
}
|
||||
let mut write = |x| {
|
||||
if let Some(_) = acc { out[n] = acc; }
|
||||
acc = Option::None;
|
||||
x
|
||||
};
|
||||
n = match c {
|
||||
'[' => left(n),
|
||||
',' => write(n + 1),
|
||||
']' => write(parent(n)),
|
||||
_ => panic!()
|
||||
}
|
||||
}
|
||||
out
|
||||
}).collect()
|
||||
}
|
||||
|
||||
fn move_up(lst: &mut Number, i: usize, x: u32) {
|
||||
match lst[i] {
|
||||
None => { move_up(lst, parent(i), x); }
|
||||
Some(y) => { lst[i] = Some(x + y); }
|
||||
}
|
||||
}
|
||||
|
||||
fn explode(lst: &mut Number) -> bool {
|
||||
for n in (1 << 4)..(1 << 5) {
|
||||
if let Option::Some(_) = lst[n] { continue; }
|
||||
|
||||
let a = left(n);
|
||||
let b = right(n);
|
||||
if let (Option::Some(l), Option::Some(r)) = (lst[a], lst[b]) {
|
||||
lst[a] = Option::None;
|
||||
lst[b] = Option::None;
|
||||
lst[n] = Option::Some(0);
|
||||
if a - 1 >= 1 << 5 {
|
||||
move_up(lst, a - 1, l);
|
||||
}
|
||||
if b + 1 < 1 << 6 {
|
||||
move_up(lst, b + 1, r);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn split(lst: &mut Number, n: usize) -> bool {
|
||||
if let Option::Some(x) = lst[n] {
|
||||
if x < 10 { return false; }
|
||||
let k = x >> 1;
|
||||
lst[n] = Option::None;
|
||||
lst[left(n)] = Option::Some(k);
|
||||
lst[right(n)] = Option::Some(x - k);
|
||||
return true;
|
||||
}
|
||||
split(lst, left(n)) || split(lst, right(n))
|
||||
}
|
||||
|
||||
fn add(a: &Number, b: &Number) -> Number {
|
||||
let mut out = [Option::None; 64];
|
||||
let mut j = 2;
|
||||
for i in 0..=4 {
|
||||
for k in (1 << i)..(1 << i + 1) {
|
||||
out[j] = a[k];
|
||||
j += 1;
|
||||
}
|
||||
for k in (1 << i)..(1 << i + 1) {
|
||||
out[j] = b[k];
|
||||
j += 1;
|
||||
}
|
||||
}
|
||||
|
||||
while explode(&mut out) || split(&mut out, 1) {};
|
||||
|
||||
out
|
||||
}
|
||||
|
||||
fn magnitude(lst: &Number, n: usize) -> u32 {
|
||||
if let Some(x) = lst[n] { x }
|
||||
else { 3 * magnitude(lst, left(n)) + 2 * magnitude(lst, right(n)) }
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
magnitude(&input.iter().cloned().reduce(|a, b| { add(&a, &b) }).unwrap(), 1).to_string()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
input.iter().flat_map(|a| {
|
||||
input.iter().filter_map(move |b| {
|
||||
if a == b { Option::None } else { Option::Some(magnitude(&add(a, b), 1)) }
|
||||
})
|
||||
}).max().unwrap().to_string()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (part1, part2) = run();
|
||||
println!("Part 1: {}", part1);
|
||||
println!("Part 2: {}", part2);
|
||||
}
|
||||
|
||||
pub fn run() -> (String, String) {
|
||||
let input = get_input();
|
||||
(part1(&input), part2(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part1(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| part1(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part2(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| part2(&input))
|
||||
}
|
77
2021/20.rs
77
2021/20.rs
|
@ -1,77 +0,0 @@
|
|||
#![feature(test)]
|
||||
#![feature(destructuring_assignment)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use std::fs;
|
||||
use test::Bencher;
|
||||
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
|
||||
struct Input {
|
||||
algo: Vec<bool>,
|
||||
width: usize,
|
||||
height: usize,
|
||||
grid: FxHashSet<(i32, i32)>,
|
||||
}
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = fs::read_to_string("2021/20.txt").unwrap();
|
||||
let mut lines = puzzle.lines();
|
||||
let algo = lines.next().unwrap().chars().map(|c| c == '#').collect();
|
||||
let grid = lines.skip(1).enumerate().flat_map(|(i, line)| {
|
||||
line.chars().enumerate().filter_map(move |(j, c)| {
|
||||
if c == '#' { Option::Some((j as i32, i as i32)) } else { Option::None }
|
||||
})
|
||||
}).collect();
|
||||
Input { algo, grid, width: puzzle.lines().nth(2).unwrap().len(), height: puzzle.lines().count() - 2 }
|
||||
}
|
||||
|
||||
fn get_neighbors(x: i32, y: i32) -> Vec<(i32, i32)> {
|
||||
(-1..=1).flat_map(|dy| {
|
||||
(-1..=1).map(move |dx| {
|
||||
(x + dx, y + dy)
|
||||
})
|
||||
}).collect()
|
||||
}
|
||||
|
||||
fn solve(input: &Input) -> (usize, usize) {
|
||||
let mut grid = input.grid.clone();
|
||||
let mut inf = false;
|
||||
let mut part1 = 0;
|
||||
let mut part2 = 0;
|
||||
for i in 1..=50 {
|
||||
let new_inf = inf != input.algo[0];
|
||||
grid = (-i..=input.height as i32 + i).flat_map(|y| {
|
||||
(-i..=input.width as i32 + i).map(move |x| (x, y))
|
||||
}).filter(|(x, y)| {
|
||||
let idx = get_neighbors(*x, *y).iter().fold(0, |acc, (p, q)| {
|
||||
acc << 1 | (grid.contains(&(*p, *q)) != inf) as usize
|
||||
});
|
||||
input.algo[idx] != new_inf
|
||||
}).collect();
|
||||
inf = new_inf;
|
||||
if i == 2 {part1 = grid.len(); }
|
||||
if i == 50 {part2 = grid.len(); }
|
||||
}
|
||||
(part1, part2)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (part1, part2) = run();
|
||||
println!("Part 1: {}", part1);
|
||||
println!("Part 2: {}", part2);
|
||||
}
|
||||
|
||||
pub fn run() -> (String, String) {
|
||||
let input = get_input();
|
||||
let (part1, part2) = solve(&input);
|
||||
(part1.to_string(), part2.to_string())
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| solve(&input))
|
||||
}
|
176
2021/2021.rs
176
2021/2021.rs
|
@ -1,176 +0,0 @@
|
|||
#![allow(unused)]
|
||||
#![feature(test)]
|
||||
#![feature(drain_filter)]
|
||||
#![feature(int_abs_diff)]
|
||||
#![feature(binary_heap_into_iter_sorted)]
|
||||
|
||||
#![feature(div_duration)]
|
||||
|
||||
use std::ops::AddAssign;
|
||||
use std::path::Path;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
|
||||
#[path = "01.rs"]
|
||||
mod d01;
|
||||
|
||||
#[path = "02.rs"]
|
||||
mod d02;
|
||||
|
||||
#[path = "03.rs"]
|
||||
mod d03;
|
||||
|
||||
#[path = "04.rs"]
|
||||
mod d04;
|
||||
|
||||
#[path = "05.rs"]
|
||||
mod d05;
|
||||
|
||||
#[path = "06.rs"]
|
||||
mod d06;
|
||||
|
||||
#[path = "07.rs"]
|
||||
mod d07;
|
||||
|
||||
#[path = "08.rs"]
|
||||
mod d08;
|
||||
|
||||
#[path = "09.rs"]
|
||||
mod d09;
|
||||
|
||||
#[path = "10.rs"]
|
||||
mod d10;
|
||||
|
||||
#[path = "11.rs"]
|
||||
mod d11;
|
||||
|
||||
#[path = "12.rs"]
|
||||
mod d12;
|
||||
|
||||
#[path = "13.rs"]
|
||||
mod d13;
|
||||
|
||||
#[path = "14.rs"]
|
||||
mod d14;
|
||||
|
||||
#[path = "15.rs"]
|
||||
mod d15;
|
||||
|
||||
#[path = "16.rs"]
|
||||
mod d16;
|
||||
|
||||
#[path = "17.rs"]
|
||||
mod d17;
|
||||
|
||||
#[path = "18.rs"]
|
||||
mod d18;
|
||||
|
||||
#[path = "19.rs"]
|
||||
mod d19;
|
||||
|
||||
#[path = "20.rs"]
|
||||
mod d20;
|
||||
|
||||
#[path = "21.rs"]
|
||||
mod d21;
|
||||
|
||||
#[path = "22.rs"]
|
||||
mod d22;
|
||||
|
||||
#[path = "23.rs"]
|
||||
mod d23;
|
||||
|
||||
#[path = "24.rs"]
|
||||
mod d24;
|
||||
|
||||
#[path = "25.rs"]
|
||||
mod d25;
|
||||
|
||||
|
||||
struct Day {
|
||||
day: i32,
|
||||
func: fn() -> (String, String),
|
||||
part1: &'static str,
|
||||
part2: &'static str,
|
||||
}
|
||||
|
||||
struct DayResult<'a> {
|
||||
day: &'a Day,
|
||||
part1: String,
|
||||
part2: String,
|
||||
duration: Duration,
|
||||
}
|
||||
|
||||
fn print_result(part: u8, actual: &String, expected: &str, total: &mut usize, failed: &mut usize) {
|
||||
if expected.is_empty() {
|
||||
println!("\x1b[33m skipped\x1b[0m | Part {}: \x1b[33m{}\x1b[0m", part, actual);
|
||||
} else if actual == expected {
|
||||
total.add_assign(1);
|
||||
println!("\x1b[32m\x1b[1m✔ passed\x1b[0m | Part {}: \x1b[32m{}\x1b[0m", part, actual);
|
||||
} else {
|
||||
total.add_assign(1);
|
||||
failed.add_assign(1);
|
||||
println!("\x1b[31m\x1b[1m✘ failed\x1b[0m | Part {}: \x1b[31m{}\x1b[0m -> \x1b[32m{}\x1b[0m", part, actual, expected);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("##### Advent of Code 2021 #####");
|
||||
let mut results = vec![];
|
||||
let mut total = 0;
|
||||
let mut failed = 0;
|
||||
for day in &[
|
||||
Day { day: 01, func: d01::run, part1: "1266", part2: "1217" },
|
||||
Day { day: 02, func: d02::run, part1: "1648020", part2: "1759818555" },
|
||||
Day { day: 03, func: d03::run, part1: "3895776", part2: "7928162" },
|
||||
Day { day: 04, func: d04::run, part1: "49860", part2: "24628" },
|
||||
Day { day: 05, func: d05::run, part1: "5698", part2: "15463" },
|
||||
Day { day: 06, func: d06::run, part1: "345793", part2: "1572643095893" },
|
||||
Day { day: 07, func: d07::run, part1: "340052", part2: "92948968" },
|
||||
Day { day: 08, func: d08::run, part1: "392", part2: "1004688" },
|
||||
Day { day: 09, func: d09::run, part1: "425", part2: "1135260" },
|
||||
Day { day: 10, func: d10::run, part1: "278475", part2: "3015539998" },
|
||||
Day { day: 11, func: d11::run, part1: "1659", part2: "227" },
|
||||
Day { day: 12, func: d12::run, part1: "3679", part2: "107395" },
|
||||
Day { day: 13, func: d13::run, part1: "747", part2: "ARHZPCUH" },
|
||||
Day { day: 14, func: d14::run, part1: "3247", part2: "4110568157153" },
|
||||
Day { day: 15, func: d15::run, part1: "366", part2: "2829" },
|
||||
Day { day: 16, func: d16::run, part1: "906", part2: "819324480368" },
|
||||
Day { day: 17, func: d17::run, part1: "3916", part2: "2986" },
|
||||
Day { day: 18, func: d18::run, part1: "4469", part2: "4770" },
|
||||
Day { day: 19, func: d19::run, part1: "403", part2: "10569" },
|
||||
Day { day: 20, func: d20::run, part1: "5419", part2: "17325" },
|
||||
Day { day: 21, func: d21::run, part1: "1067724", part2: "630947104784464" },
|
||||
Day { day: 22, func: d22::run, part1: "623748", part2: "1227345351869476" },
|
||||
Day { day: 23, func: d23::run, part1: "13520", part2: "48708" },
|
||||
Day { day: 24, func: d24::run, part1: "96979989692495", part2: "51316214181141" },
|
||||
Day { day: 25, func: d25::run, part1: "380", part2: "" },
|
||||
|
||||
] {
|
||||
if !Path::new(format!("2021/{:02}.txt", day.day).as_str()).exists() {continue;}
|
||||
let s = Instant::now();
|
||||
let (part1, part2) = (day.func)() as (String, String);
|
||||
results.push(DayResult {day, part1, part2, duration: s.elapsed()});
|
||||
}
|
||||
|
||||
let total_duration = results.iter().map(|DayResult {duration, .. }| {
|
||||
duration
|
||||
}).sum::<Duration>();
|
||||
|
||||
for DayResult {day, part1, part2, duration} in results {
|
||||
println!();
|
||||
println!("=== Day {} ===", day.day);
|
||||
print_result(1, &part1, day.part1, &mut total, &mut failed);
|
||||
if day.day != 25 {
|
||||
print_result(2, &part2, day.part2, &mut total, &mut failed);
|
||||
}
|
||||
println!(" => {:.6} ms ({:.2}%)", duration.as_secs_f64() * 1000f64, duration.div_duration_f64(total_duration) * 100f64);
|
||||
}
|
||||
println!();
|
||||
if failed == 0 {
|
||||
println!("\x1b[32m\x1b[1m✔ {}/{} passed\x1b[0m", total, total);
|
||||
} else {
|
||||
println!("\x1b[31m\x1b[1m✘ {}/{} failed\x1b[0m", failed, total);
|
||||
}
|
||||
println!("=> {:.6} ms", total_duration.as_secs_f64() * 1000f64);
|
||||
}
|
122
2021/22.rs
122
2021/22.rs
|
@ -1,122 +0,0 @@
|
|||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use std::fs;
|
||||
use test::Bencher;
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
struct Cuboid {
|
||||
x1: i64,
|
||||
x2: i64,
|
||||
y1: i64,
|
||||
y2: i64,
|
||||
z1: i64,
|
||||
z2: i64,
|
||||
off: Vec<Cuboid>,
|
||||
}
|
||||
|
||||
fn line_intersection(a1: i64, a2: i64, b1: i64, b2: i64) -> Option<(i64, i64)> {
|
||||
if a2 < b1 || b2 < a1 { Option::None } else { Option::Some((a1.max(b1), a2.min(b2))) }
|
||||
}
|
||||
|
||||
impl Cuboid {
|
||||
fn copy(&self) -> Cuboid {
|
||||
Cuboid {
|
||||
x1: self.x1,
|
||||
x2: self.x2,
|
||||
y1: self.y1,
|
||||
y2: self.y2,
|
||||
z1: self.z1,
|
||||
z2: self.z2,
|
||||
off: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
fn get_intersection(&self, c: &Cuboid) -> Option<Cuboid> {
|
||||
let x = line_intersection(self.x1, self.x2, c.x1, c.x2);
|
||||
let y = line_intersection(self.y1, self.y2, c.y1, c.y2);
|
||||
let z = line_intersection(self.z1, self.z2, c.z1, c.z2);
|
||||
if let (Option::Some(x), Option::Some(y), Option::Some(z)) = (x, y, z) {
|
||||
Option::Some(Cuboid { x1: x.0, x2: x.1, y1: y.0, y2: y.1, z1: z.0, z2: z.1, off: vec![] })
|
||||
} else { Option::None }
|
||||
}
|
||||
|
||||
fn subtract(&mut self, c: &Cuboid) {
|
||||
if let Option::Some(intersection) = self.get_intersection(c) {
|
||||
for o in self.off.iter_mut() {
|
||||
o.subtract(c);
|
||||
}
|
||||
self.off.push(intersection);
|
||||
}
|
||||
}
|
||||
|
||||
fn volume(&self) -> i64 {
|
||||
(self.x2 - self.x1 + 1) * (self.y2 - self.y1 + 1) * (self.z2 - self.z1 + 1) - self.off.iter().map(|c| c.volume()).sum::<i64>()
|
||||
}
|
||||
}
|
||||
|
||||
struct Step {
|
||||
on: bool,
|
||||
cuboid: Cuboid,
|
||||
}
|
||||
|
||||
type Input = Vec<Step>;
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = fs::read_to_string("2021/22.txt").unwrap();
|
||||
let regex = Regex::new(r"^(on|off) x=(-?\d+)..(-?\d+),y=(-?\d+)..(-?\d+),z=(-?\d+)..(-?\d+)$").unwrap();
|
||||
puzzle.lines().map(|line| {
|
||||
let capture = regex.captures(line).unwrap();
|
||||
let get_num = |i| capture.get(i).unwrap().as_str().parse().unwrap();
|
||||
Step {
|
||||
on: capture.get(1).unwrap().as_str() == "on",
|
||||
cuboid: Cuboid { x1: get_num(2), x2: get_num(3), y1: get_num(4), y2: get_num(5), z1: get_num(6), z2: get_num(7), off: vec![] },
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
let mut cuboids: Vec<Cuboid> = vec![];
|
||||
for Step { on, cuboid } in input {
|
||||
if cuboid.x1 < -50 || cuboid.x2 > 50 || cuboid.y1 < -50 || cuboid.y2 > 50 || cuboid.z1 < -50 || cuboid.z2 > 50 {
|
||||
continue;
|
||||
}
|
||||
for c in cuboids.iter_mut() { c.subtract(cuboid); }
|
||||
if *on { cuboids.push(cuboid.copy()); }
|
||||
}
|
||||
cuboids.iter().map(|c| c.volume()).sum::<i64>().to_string()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
let mut cuboids: Vec<Cuboid> = vec![];
|
||||
for Step { on, cuboid } in input {
|
||||
for c in cuboids.iter_mut() { c.subtract(cuboid); }
|
||||
if *on { cuboids.push(cuboid.copy()); }
|
||||
}
|
||||
cuboids.iter().map(|c| c.volume()).sum::<i64>().to_string()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (part1, part2) = run();
|
||||
println!("Part 1: {}", part1);
|
||||
println!("Part 2: {}", part2);
|
||||
}
|
||||
|
||||
pub fn run() -> (String, String) {
|
||||
let input = get_input();
|
||||
(part1(&input), part2(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part1(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| part1(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part2(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| part2(&input))
|
||||
}
|
79
2021/25.rs
79
2021/25.rs
|
@ -1,79 +0,0 @@
|
|||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use std::fs;
|
||||
use test::Bencher;
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
enum Type { EMPTY, RIGHT, DOWN }
|
||||
|
||||
type Input = Vec<Vec<Type>>;
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = fs::read_to_string("2021/25.txt").unwrap();
|
||||
puzzle.lines().map(|line| {
|
||||
line.chars().map(|c| {
|
||||
match c {
|
||||
'v' => Type::DOWN,
|
||||
'>' => Type::RIGHT,
|
||||
_ => Type::EMPTY
|
||||
}
|
||||
}).collect()
|
||||
}).collect()
|
||||
}
|
||||
|
||||
fn solve(input: &Input) -> String {
|
||||
let mut grid = input.clone();
|
||||
let mut cnt = 0;
|
||||
loop {
|
||||
let mut moved = false;
|
||||
let mut new_grid = grid.clone();
|
||||
for (i, line) in grid.iter().enumerate() {
|
||||
for (j, &c) in line.iter().enumerate() {
|
||||
if c == Type::RIGHT {
|
||||
let k = (j + 1) % line.len();
|
||||
if grid[i][k] == Type::EMPTY {
|
||||
new_grid[i][k] = Type::RIGHT;
|
||||
new_grid[i][j] = Type::EMPTY;
|
||||
moved = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
grid = new_grid;
|
||||
let mut new_grid = grid.clone();
|
||||
for (i, line) in grid.iter().enumerate() {
|
||||
for (j, &c) in line.iter().enumerate() {
|
||||
if c == Type::DOWN {
|
||||
let k = (i + 1) % grid.len();
|
||||
if grid[k][j] == Type::EMPTY {
|
||||
new_grid[k][j] = Type::DOWN;
|
||||
new_grid[i][j] = Type::EMPTY;
|
||||
moved = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
grid = new_grid;
|
||||
cnt += 1;
|
||||
if !moved { break; }
|
||||
}
|
||||
cnt.to_string()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (part1, _) = run();
|
||||
println!("Part 1: {}", part1);
|
||||
}
|
||||
|
||||
pub fn run() -> (String, String) {
|
||||
let input = get_input();
|
||||
(solve(&input), "".to_string())
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| solve(&input))
|
||||
}
|
37
2022/01.rs
37
2022/01.rs
|
@ -1,37 +0,0 @@
|
|||
type Input = Vec<Vec<u32>>;
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
input
|
||||
.trim()
|
||||
.split("\n\n")
|
||||
.map(|elf| elf.split_whitespace().map(|x| x.parse().unwrap()).collect())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> u32 {
|
||||
input.iter().map(|elf| elf.iter().sum()).max().unwrap()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> u32 {
|
||||
let (a, b, c) = input
|
||||
.iter()
|
||||
.map(|elf| elf.iter().sum())
|
||||
.fold((0, 0, 0), |(a, b, c), x| {
|
||||
if x > b {
|
||||
if x > a {
|
||||
(x, a, b)
|
||||
} else {
|
||||
(a, x, b)
|
||||
}
|
||||
} else if x > c {
|
||||
(a, b, x)
|
||||
} else {
|
||||
(a, b, c)
|
||||
}
|
||||
});
|
||||
a + b + c
|
||||
}
|
||||
|
||||
aoc::main!(2022, 1);
|
||||
aoc::example!(ex01, "01.1.txt", 24000, 45000);
|
||||
aoc::test_input!("01.txt", 69912, 208180);
|
691
Cargo.lock
generated
691
Cargo.lock
generated
|
@ -1,691 +0,0 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "AdventOfCode"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"counter",
|
||||
"criterion",
|
||||
"itertools",
|
||||
"num",
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anes"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
|
||||
|
||||
[[package]]
|
||||
name = "cast"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "ciborium"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0c137568cc60b904a7724001b35ce2630fd00d5d84805fbb608ab89509d788f"
|
||||
dependencies = [
|
||||
"ciborium-io",
|
||||
"ciborium-ll",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ciborium-io"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "346de753af073cc87b52b2083a506b38ac176a44cfb05497b622e27be899b369"
|
||||
|
||||
[[package]]
|
||||
name = "ciborium-ll"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b"
|
||||
dependencies = [
|
||||
"ciborium-io",
|
||||
"half",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.2.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"clap_lex",
|
||||
"indexmap",
|
||||
"textwrap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
|
||||
dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "counter"
|
||||
version = "0.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d458e66999348f56fd3ffcfbb7f7951542075ca8359687c703de6500c1ddccd"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "criterion"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb"
|
||||
dependencies = [
|
||||
"anes",
|
||||
"atty",
|
||||
"cast",
|
||||
"ciborium",
|
||||
"clap",
|
||||
"criterion-plot",
|
||||
"itertools",
|
||||
"lazy_static",
|
||||
"num-traits",
|
||||
"oorandom",
|
||||
"plotters",
|
||||
"rayon",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"tinytemplate",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "criterion-plot"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
|
||||
dependencies = [
|
||||
"cast",
|
||||
"itertools",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"memoffset",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
|
||||
|
||||
[[package]]
|
||||
name = "half"
|
||||
version = "1.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.137"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-bigint",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
|
||||
|
||||
[[package]]
|
||||
name = "oorandom"
|
||||
version = "11.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "6.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
|
||||
|
||||
[[package]]
|
||||
name = "plotters"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"plotters-backend",
|
||||
"plotters-svg",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "plotters-backend"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142"
|
||||
|
||||
[[package]]
|
||||
name = "plotters-svg"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f"
|
||||
dependencies = [
|
||||
"plotters-backend",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
"num_cpus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.148"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e53f64bb4ba0191d6d0676e1b141ca55047d83b74f5607e6d8eb88126c52c2dc"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.148"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a55492425aa53521babf6137309e7d34c20bbfbbfcfe2c7f3a047fd1f6b92c0c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.105"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
|
||||
|
||||
[[package]]
|
||||
name = "tinytemplate"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
197
Cargo.toml
197
Cargo.toml
|
@ -1,197 +0,0 @@
|
|||
[package]
|
||||
name = "AdventOfCode"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[profile.dev]
|
||||
opt-level = 3
|
||||
|
||||
[profile.release]
|
||||
opt-level = 3
|
||||
debug = false
|
||||
strip = true
|
||||
debug-assertions = false
|
||||
overflow-checks = false
|
||||
lto = true
|
||||
panic = "abort"
|
||||
incremental = false
|
||||
codegen-units = 1
|
||||
rpath = false
|
||||
|
||||
[dependencies]
|
||||
regex = "*"
|
||||
counter = "*"
|
||||
rustc-hash = "*"
|
||||
criterion = "0.4.0"
|
||||
itertools = "0.10.5"
|
||||
num = "0.4.0"
|
||||
|
||||
[features]
|
||||
default = ["test_input"]
|
||||
test_input = []
|
||||
|
||||
[lib]
|
||||
name = "aoc"
|
||||
path = "lib/lib.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "2022_01"
|
||||
path = "2022/01.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "2022_01"
|
||||
path = "2022/01.rs"
|
||||
harness = false
|
||||
|
||||
[[bin]]
|
||||
name = "2022_02"
|
||||
path = "2022/02.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "2022_02"
|
||||
path = "2022/02.rs"
|
||||
harness = false
|
||||
|
||||
[[bin]]
|
||||
name = "2022_03"
|
||||
path = "2022/03.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "2022_03"
|
||||
path = "2022/03.rs"
|
||||
harness = false
|
||||
|
||||
[[bin]]
|
||||
name = "2022_04"
|
||||
path = "2022/04.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "2022_04"
|
||||
path = "2022/04.rs"
|
||||
harness = false
|
||||
|
||||
[[bin]]
|
||||
name = "2022_05"
|
||||
path = "2022/05.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "2022_05"
|
||||
path = "2022/05.rs"
|
||||
harness = false
|
||||
|
||||
[[bin]]
|
||||
name = "2022_06"
|
||||
path = "2022/06.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "2022_06"
|
||||
path = "2022/06.rs"
|
||||
harness = false
|
||||
|
||||
[[bin]]
|
||||
name = "2022_07"
|
||||
path = "2022/07.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "2022_07"
|
||||
path = "2022/07.rs"
|
||||
harness = false
|
||||
|
||||
[[bin]]
|
||||
name = "2022_08"
|
||||
path = "2022/08.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "2022_08"
|
||||
path = "2022/08.rs"
|
||||
harness = false
|
||||
|
||||
[[bin]]
|
||||
name = "2022_09"
|
||||
path = "2022/09.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "2022_09"
|
||||
path = "2022/09.rs"
|
||||
harness = false
|
||||
|
||||
[[bin]]
|
||||
name = "2022_10"
|
||||
path = "2022/10.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "2022_10"
|
||||
path = "2022/10.rs"
|
||||
harness = false
|
||||
|
||||
[[bin]]
|
||||
name = "2022_11"
|
||||
path = "2022/11.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "2022_11"
|
||||
path = "2022/11.rs"
|
||||
harness = false
|
||||
|
||||
[[bin]]
|
||||
name = "2022_12"
|
||||
path = "2022/12.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "2022_12"
|
||||
path = "2022/12.rs"
|
||||
harness = false
|
||||
|
||||
[[bin]]
|
||||
name = "2022_13"
|
||||
path = "2022/13.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "2022_13"
|
||||
path = "2022/13.rs"
|
||||
harness = false
|
||||
|
||||
[[bin]]
|
||||
name = "2022_14"
|
||||
path = "2022/14.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "2022_14"
|
||||
path = "2022/14.rs"
|
||||
harness = false
|
||||
|
||||
[[bin]]
|
||||
name = "2022_15"
|
||||
path = "2022/15.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "2022_15"
|
||||
path = "2022/15.rs"
|
||||
harness = false
|
||||
|
||||
[[bin]]
|
||||
name = "2022_16"
|
||||
path = "2022/16.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "2022_16"
|
||||
path = "2022/16.rs"
|
||||
harness = false
|
||||
|
||||
[[bin]]
|
||||
name = "2022_17"
|
||||
path = "2022/17.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "2022_17"
|
||||
path = "2022/17.rs"
|
||||
harness = false
|
||||
|
||||
[[bin]]
|
||||
name = "2022_18"
|
||||
path = "2022/18.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "2022_18"
|
||||
path = "2022/18.rs"
|
||||
harness = false
|
|
@ -1,11 +1,14 @@
|
|||
#![feature(test)]
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
fn get_input() -> Vec<i32> {
|
||||
let puzzle = include_str!("01.txt");
|
||||
puzzle.lines().map(|i| i.parse().unwrap()).collect()
|
||||
type Input = Vec<i32>;
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
input.lines().map(|i| i.parse().unwrap()).collect()
|
||||
}
|
||||
|
||||
fn part1(input: &Vec<i32>) -> i32 {
|
||||
fn part1(input: &Input) -> i32 {
|
||||
let mut seen: HashSet<i32> = HashSet::new();
|
||||
for &x in input {
|
||||
let y = 2020 - x;
|
||||
|
@ -17,10 +20,10 @@ fn part1(input: &Vec<i32>) -> i32 {
|
|||
panic!();
|
||||
}
|
||||
|
||||
fn part2(input: &Vec<i32>) -> i32 {
|
||||
fn part2(input: &Input) -> i32 {
|
||||
for (i, &x) in input.iter().enumerate() {
|
||||
let mut seen: HashSet<i32> = HashSet::new();
|
||||
for &y in &input[i+1..] {
|
||||
for &y in &input[i + 1..] {
|
||||
let z = 2020 - x - y;
|
||||
if seen.contains(&z) {
|
||||
return x * y * z;
|
||||
|
@ -31,8 +34,4 @@ fn part2(input: &Vec<i32>) -> i32 {
|
|||
panic!();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let input = get_input();
|
||||
println!("Part 1: {}", part1(&input));
|
||||
println!("Part 2: {}", part2(&input));
|
||||
}
|
||||
aoc::main!(2020, 1, ex: 1);
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(test)]
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
struct Policy {
|
||||
|
@ -8,11 +10,10 @@ struct Policy {
|
|||
|
||||
type Input = Vec<(Policy, String)>;
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = include_str!("02.txt");
|
||||
fn setup(input: &str) -> Input {
|
||||
let mut out: Input = Vec::new();
|
||||
let regex = Regex::new(r"^(\d+)-(\d+) (.): (\w+)$").unwrap();
|
||||
for line in puzzle.lines() {
|
||||
for line in input.lines() {
|
||||
let result = regex.captures(line).unwrap();
|
||||
let a = result[1].parse::<u32>().unwrap();
|
||||
let b = result[2].parse::<u32>().unwrap();
|
||||
|
@ -20,7 +21,7 @@ fn get_input() -> Input {
|
|||
let password = result[4].to_string();
|
||||
out.push((Policy { a, b, c }, password));
|
||||
}
|
||||
return out;
|
||||
out
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
|
@ -31,7 +32,7 @@ fn part1(input: &Input) -> String {
|
|||
out += 1;
|
||||
}
|
||||
}
|
||||
return out.to_string();
|
||||
out.to_string()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
|
@ -43,11 +44,7 @@ fn part2(input: &Input) -> String {
|
|||
out += 1;
|
||||
}
|
||||
}
|
||||
return out.to_string();
|
||||
out.to_string()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let input = get_input();
|
||||
println!("Part 1: {}", part1(&input));
|
||||
println!("Part 2: {}", part2(&input));
|
||||
}
|
||||
aoc::main!(2020, 2, ex: 1);
|
|
@ -1,8 +1,9 @@
|
|||
#![feature(test)]
|
||||
|
||||
type Input = Vec<String>;
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = include_str!("03.txt");
|
||||
return puzzle.lines().map(|s| s.to_string()).collect();
|
||||
fn setup(input: &str) -> Input {
|
||||
input.lines().map(|s| s.to_string()).collect()
|
||||
}
|
||||
|
||||
fn cnt_slope(input: &Input, dx: u64, dy: u64) -> u64 {
|
||||
|
@ -24,11 +25,11 @@ fn part1(input: &Input) -> String {
|
|||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
[(1, 1), (3, 1), (5, 1), (7, 1), (1, 2)].iter().map(|&(dx, dy)| cnt_slope(input, dx, dy)).product::<u64>().to_string()
|
||||
[(1, 1), (3, 1), (5, 1), (7, 1), (1, 2)]
|
||||
.iter()
|
||||
.map(|&(dx, dy)| cnt_slope(input, dx, dy))
|
||||
.product::<u64>()
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let input = get_input();
|
||||
println!("Part 1: {}", part1(&input));
|
||||
println!("Part 2: {}", part2(&input));
|
||||
}
|
||||
aoc::main!(2020, 3, ex: 1);
|
|
@ -1,17 +1,18 @@
|
|||
#![feature(test)]
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
type Input = Vec<HashMap<String, String>>;
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = include_str!("04.txt");
|
||||
fn setup(input: &str) -> Input {
|
||||
let mut out = Vec::new();
|
||||
for block in puzzle.split("\n\n") {
|
||||
for block in input.split("\n\n") {
|
||||
let mut cur = HashMap::new();
|
||||
for line in block.trim().lines() {
|
||||
for (key, value) in line.split(" ").map(|a| {
|
||||
let mut x = a.trim().split(":");
|
||||
for (key, value) in line.split(' ').map(|a| {
|
||||
let mut x = a.trim().split(':');
|
||||
(x.next().unwrap(), x.next().unwrap())
|
||||
}) {
|
||||
cur.insert(key.to_string(), value.to_string());
|
||||
|
@ -25,25 +26,30 @@ fn get_input() -> Input {
|
|||
fn part1(input: &Input) -> String {
|
||||
let mut out = 0;
|
||||
for passport in input {
|
||||
if ["byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid"].iter().all(|x| passport.contains_key(&x.to_string())) {
|
||||
if ["byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid"]
|
||||
.iter()
|
||||
.all(|x| passport.contains_key(&x.to_string()))
|
||||
{
|
||||
out += 1;
|
||||
}
|
||||
}
|
||||
out.to_string()
|
||||
}
|
||||
|
||||
const RULES: [(&str, fn(&String) -> bool); 7] = [
|
||||
type Rule = (&'static str, fn(&String) -> bool);
|
||||
|
||||
const RULES: [Rule; 7] = [
|
||||
("byr", |x: &String| {
|
||||
let num: i32 = x.parse().unwrap();
|
||||
num >= 1920 && num <= 2002
|
||||
(1920..=2002).contains(&num)
|
||||
}),
|
||||
("iyr", |x: &String| {
|
||||
let num: i32 = x.parse().unwrap();
|
||||
num >= 2010 && num <= 2020
|
||||
(2010..=2020).contains(&num)
|
||||
}),
|
||||
("eyr", |x: &String| {
|
||||
let num: i32 = x.parse().unwrap();
|
||||
num >= 2020 && num <= 2030
|
||||
(2020..=2030).contains(&num)
|
||||
}),
|
||||
("hgt", |x: &String| {
|
||||
let regex = Regex::new(r"^(\d+)(cm|in)$").unwrap();
|
||||
|
@ -52,9 +58,9 @@ const RULES: [(&str, fn(&String) -> bool); 7] = [
|
|||
Some(result) => {
|
||||
let num: i32 = result[1].parse().unwrap();
|
||||
match &result[2] {
|
||||
"cm" => num >= 150 && num <= 193,
|
||||
"in" => num >= 59 && num <= 76,
|
||||
_ => false
|
||||
"cm" => (150..=193).contains(&num),
|
||||
"in" => (59..=76).contains(&num),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,26 +75,23 @@ const RULES: [(&str, fn(&String) -> bool); 7] = [
|
|||
("pid", |x: &String| {
|
||||
let regex = Regex::new(r"^\d{9}$").unwrap();
|
||||
regex.captures(x).is_some()
|
||||
})
|
||||
}),
|
||||
];
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
let mut out = 0;
|
||||
for passport in input {
|
||||
if RULES.iter().all(|(key, validator)| {
|
||||
match passport.get(&key.to_string()) {
|
||||
if RULES
|
||||
.iter()
|
||||
.all(|(key, validator)| match passport.get(&key.to_string()) {
|
||||
None => false,
|
||||
Some(value) => validator(value)
|
||||
}
|
||||
}) {
|
||||
Some(value) => validator(value),
|
||||
})
|
||||
{
|
||||
out += 1;
|
||||
}
|
||||
}
|
||||
out.to_string()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let input = get_input();
|
||||
println!("Part 1: {}", part1(&input));
|
||||
println!("Part 2: {}", part2(&input));
|
||||
}
|
||||
aoc::main!(2020, 4, ex: 1[a]);
|
27
Rust/2021/01.rs
Normal file
27
Rust/2021/01.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
#![feature(test)]
|
||||
|
||||
type Input = Vec<i32>;
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
input.lines().map(|x| x.parse().unwrap()).collect()
|
||||
}
|
||||
|
||||
fn count(input: &Input, window: usize) -> i32 {
|
||||
let mut out = 0;
|
||||
for (a, b) in input.iter().zip(&input[window..]) {
|
||||
if b > a {
|
||||
out += 1;
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
count(input, 1).to_string()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
count(input, 3).to_string()
|
||||
}
|
||||
|
||||
aoc::main!(2021, 1, ex: 1);
|
58
Rust/2021/02.rs
Normal file
58
Rust/2021/02.rs
Normal file
|
@ -0,0 +1,58 @@
|
|||
#![feature(test)]
|
||||
|
||||
enum Command {
|
||||
Forward(i32),
|
||||
Down(i32),
|
||||
Up(i32),
|
||||
}
|
||||
|
||||
type Input = Vec<Command>;
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
input
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let mut x = line.split(' ');
|
||||
let cmd = x.next().unwrap();
|
||||
let n: i32 = x.next().unwrap().parse().unwrap();
|
||||
match cmd {
|
||||
"forward" => Command::Forward(n),
|
||||
"up" => Command::Up(n),
|
||||
"down" => Command::Down(n),
|
||||
_ => panic!(),
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
let mut d = 0;
|
||||
let mut h = 0;
|
||||
for cmd in input {
|
||||
match cmd {
|
||||
Command::Forward(n) => h += n,
|
||||
Command::Down(n) => d += n,
|
||||
Command::Up(n) => d -= n,
|
||||
}
|
||||
}
|
||||
(d * h).to_string()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
let mut d = 0;
|
||||
let mut h = 0;
|
||||
let mut a = 0;
|
||||
for cmd in input {
|
||||
match cmd {
|
||||
Command::Forward(n) => {
|
||||
h += n;
|
||||
d += a * n;
|
||||
}
|
||||
Command::Down(n) => a += n,
|
||||
Command::Up(n) => a -= n,
|
||||
}
|
||||
}
|
||||
(d * h).to_string()
|
||||
}
|
||||
|
||||
aoc::main!(2021, 2, ex: 1);
|
54
Rust/2021/03.rs
Normal file
54
Rust/2021/03.rs
Normal file
|
@ -0,0 +1,54 @@
|
|||
#![feature(test, extract_if)]
|
||||
|
||||
type Input = Vec<String>;
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
input.lines().map(|s| s.to_string()).collect()
|
||||
}
|
||||
|
||||
fn count(input: &Input, i: usize, chr: &char) -> usize {
|
||||
input
|
||||
.iter()
|
||||
.filter(|s| s.chars().nth(i).unwrap() == *chr)
|
||||
.count()
|
||||
}
|
||||
|
||||
fn most_common(input: &Input, i: usize) -> char {
|
||||
"01".chars().max_by_key(|c| count(input, i, c)).unwrap()
|
||||
}
|
||||
|
||||
fn least_common(input: &Input, i: usize) -> char {
|
||||
"01".chars().min_by_key(|c| count(input, i, c)).unwrap()
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
let mut most = 0;
|
||||
let mut least = 0;
|
||||
for i in 0..input[0].len() {
|
||||
most = most << 1 | (most_common(input, i) as u32 - '0' as u32);
|
||||
least = least << 1 | (least_common(input, i) as u32 - '0' as u32);
|
||||
}
|
||||
(most * least).to_string()
|
||||
}
|
||||
|
||||
fn find(input: &Input, x: bool) -> isize {
|
||||
let mut out = input.clone();
|
||||
for i in 0..input[0].len() {
|
||||
let mx = if x {
|
||||
least_common(&out, i)
|
||||
} else {
|
||||
most_common(&out, i)
|
||||
};
|
||||
out.extract_if(|x| x.chars().nth(i).unwrap() != mx).count();
|
||||
if out.len() == 1 {
|
||||
return isize::from_str_radix(out[0].as_str(), 2).unwrap();
|
||||
}
|
||||
}
|
||||
panic!();
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
(find(input, true) * find(input, false)).to_string()
|
||||
}
|
||||
|
||||
aoc::main!(2021, 3, ex: 1);
|
110
Rust/2021/04.rs
Normal file
110
Rust/2021/04.rs
Normal file
|
@ -0,0 +1,110 @@
|
|||
#![feature(test)]
|
||||
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
struct Input {
|
||||
nums: Vec<i32>,
|
||||
boards: Vec<Vec<Vec<i32>>>,
|
||||
}
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
let nums = input
|
||||
.lines()
|
||||
.next()
|
||||
.unwrap()
|
||||
.split(',')
|
||||
.map(|n| n.parse().unwrap())
|
||||
.collect();
|
||||
let boards = input
|
||||
.split("\n\n")
|
||||
.skip(1)
|
||||
.map(|board| {
|
||||
board
|
||||
.lines()
|
||||
.map(|line| {
|
||||
line.split_whitespace()
|
||||
.map(|n| n.parse().unwrap())
|
||||
.collect()
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.collect();
|
||||
Input { nums, boards }
|
||||
}
|
||||
|
||||
struct State {
|
||||
boards: Vec<Vec<Vec<i32>>>,
|
||||
marked: FxHashSet<i32>,
|
||||
}
|
||||
|
||||
impl State {
|
||||
fn from_input(input: &Input) -> State {
|
||||
State {
|
||||
boards: input.boards.clone(),
|
||||
marked: FxHashSet::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn mark(&mut self, num: i32) {
|
||||
self.marked.insert(num);
|
||||
}
|
||||
|
||||
fn check_board(&self, board: usize) -> bool {
|
||||
let board = &self.boards[board];
|
||||
for row in board {
|
||||
if row.iter().all(|n| self.marked.contains(n)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for i in 0..board[0].len() {
|
||||
if board.iter().all(|row| self.marked.contains(&row[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn get_score(&self, board: usize) -> i32 {
|
||||
self.boards[board]
|
||||
.iter()
|
||||
.flatten()
|
||||
.filter(|n| !self.marked.contains(n))
|
||||
.copied()
|
||||
.reduce(|a, b| a + b)
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
let mut state = State::from_input(input);
|
||||
for num in &input.nums {
|
||||
state.mark(*num);
|
||||
for i in 0..state.boards.len() {
|
||||
if state.check_board(i) {
|
||||
return (num * state.get_score(i)).to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
panic!();
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
let mut state = State::from_input(input);
|
||||
for num in &input.nums {
|
||||
state.mark(*num);
|
||||
let mut i = 0;
|
||||
while i < state.boards.len() {
|
||||
if !state.check_board(i) {
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
if state.boards.len() == 1 {
|
||||
return (num * state.get_score(i)).to_string();
|
||||
}
|
||||
state.boards.remove(i);
|
||||
}
|
||||
}
|
||||
panic!()
|
||||
}
|
||||
|
||||
aoc::main!(2021, 4, ex: 1);
|
79
Rust/2021/05.rs
Normal file
79
Rust/2021/05.rs
Normal file
|
@ -0,0 +1,79 @@
|
|||
#![feature(test)]
|
||||
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use regex::Regex;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
type Line = (i32, i32, i32, i32);
|
||||
type Input = Vec<Line>;
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
let regex = Regex::new(r"^(\d+),(\d+) -> (\d+),(\d+)$").unwrap();
|
||||
input
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let capture = regex.captures(line).unwrap();
|
||||
(
|
||||
capture[1].parse().unwrap(),
|
||||
capture[2].parse().unwrap(),
|
||||
capture[3].parse().unwrap(),
|
||||
capture[4].parse().unwrap(),
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn iter_line(line: &Line) -> Vec<(i32, i32)> {
|
||||
let (mut x, mut y, x2, y2) = line;
|
||||
let mut result = vec![(x, y)];
|
||||
while (x != *x2) || (y != *y2) {
|
||||
match x.cmp(x2) {
|
||||
Ordering::Less => x += 1,
|
||||
Ordering::Greater => x -= 1,
|
||||
_ => {}
|
||||
}
|
||||
match y.cmp(y2) {
|
||||
Ordering::Less => y += 1,
|
||||
Ordering::Greater => y -= 1,
|
||||
_ => {}
|
||||
}
|
||||
result.push((x, y));
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
let mut counter = FxHashMap::default();
|
||||
for line in input {
|
||||
if (line.0 != line.2) && (line.1 != line.3) {
|
||||
continue;
|
||||
}
|
||||
for (x, y) in iter_line(line) {
|
||||
let cnt = *counter.entry((x, y)).or_insert(0) + 1;
|
||||
counter.insert((x, y), cnt);
|
||||
}
|
||||
}
|
||||
counter
|
||||
.iter()
|
||||
.filter(|&(_, &cnt)| cnt > 1)
|
||||
.count()
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
let mut counter = FxHashMap::default();
|
||||
for line in input {
|
||||
for (x, y) in iter_line(line) {
|
||||
let cnt = *counter.entry((x, y)).or_insert(0) + 1;
|
||||
counter.insert((x, y), cnt);
|
||||
}
|
||||
}
|
||||
counter
|
||||
.iter()
|
||||
.filter(|&(_, &cnt)| cnt > 1)
|
||||
.count()
|
||||
.to_string()
|
||||
}
|
||||
|
||||
aoc::main!(2021, 5, ex: 1);
|
34
Rust/2021/06.rs
Normal file
34
Rust/2021/06.rs
Normal file
|
@ -0,0 +1,34 @@
|
|||
#![feature(test)]
|
||||
|
||||
type Input = Vec<i32>;
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
input
|
||||
.trim()
|
||||
.split(',')
|
||||
.map(|x| x.parse().unwrap())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn solve(input: &Input, n: u32) -> String {
|
||||
let mut counter = vec![0; 9];
|
||||
for num in input {
|
||||
counter[*num as usize] += 1;
|
||||
}
|
||||
for _ in 0..n {
|
||||
let x = counter.remove(0);
|
||||
counter.push(x);
|
||||
counter[6] += x;
|
||||
}
|
||||
counter.iter().sum::<u64>().to_string()
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
solve(input, 80)
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
solve(input, 256)
|
||||
}
|
||||
|
||||
aoc::main!(2021, 6, ex: 1);
|
37
Rust/2021/07.rs
Normal file
37
Rust/2021/07.rs
Normal file
|
@ -0,0 +1,37 @@
|
|||
#![feature(test)]
|
||||
|
||||
type Input = Vec<i32>;
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
input
|
||||
.trim()
|
||||
.split(',')
|
||||
.map(|x| x.parse().unwrap())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
(0..=input.len())
|
||||
.map(|pos| input.iter().map(|n| (pos as i32 - *n).abs()).sum::<i32>())
|
||||
.min()
|
||||
.unwrap()
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
(0..=input.len())
|
||||
.map(|pos| {
|
||||
input
|
||||
.iter()
|
||||
.map(|n| {
|
||||
let x = (pos as i32 - *n).abs();
|
||||
(x * (x + 1)) >> 1
|
||||
})
|
||||
.sum::<i32>()
|
||||
})
|
||||
.min()
|
||||
.unwrap()
|
||||
.to_string()
|
||||
}
|
||||
|
||||
aoc::main!(2021, 7, ex: 1);
|
120
Rust/2021/08.rs
Normal file
120
Rust/2021/08.rs
Normal file
|
@ -0,0 +1,120 @@
|
|||
#![feature(test)]
|
||||
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
||||
struct Line {
|
||||
patterns: Vec<String>,
|
||||
output: Vec<String>,
|
||||
}
|
||||
|
||||
type Input = Vec<Line>;
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
input
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let mut line = line.trim().split(" | ");
|
||||
let mut parse = || {
|
||||
line.next()
|
||||
.unwrap()
|
||||
.split(' ')
|
||||
.map(|x| x.to_string())
|
||||
.collect()
|
||||
};
|
||||
Line {
|
||||
patterns: parse(),
|
||||
output: parse(),
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
input
|
||||
.iter()
|
||||
.map(|line| {
|
||||
line.output
|
||||
.iter()
|
||||
.filter(|x| [2, 3, 4, 7].contains(&x.len()))
|
||||
.count()
|
||||
})
|
||||
.sum::<usize>()
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn parse_num(num: &str) -> u16 {
|
||||
num.chars()
|
||||
.map(|c| 1 << ((c as u16) - ('a' as u16)))
|
||||
.sum::<u16>()
|
||||
}
|
||||
|
||||
fn is_subset(mut a: u16, mut b: u16) -> bool {
|
||||
while a > 0 {
|
||||
if 1 & a & !b == 1 {
|
||||
return false;
|
||||
}
|
||||
a >>= 1;
|
||||
b >>= 1;
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
let digits = FxHashMap::from_iter([
|
||||
((7, 2), 1),
|
||||
((2, 5), 2),
|
||||
((3, 5), 3),
|
||||
((3, 4), 4),
|
||||
((4, 5), 5),
|
||||
((5, 3), 7),
|
||||
((1, 7), 8),
|
||||
]);
|
||||
|
||||
input
|
||||
.iter()
|
||||
.map(|line| {
|
||||
let patterns: Vec<u16> = line.patterns.iter().map(|s| parse_num(s)).collect();
|
||||
let output: Vec<u16> = line.output.iter().map(|s| parse_num(s)).collect();
|
||||
let mut mp: FxHashMap<u16, u8> = FxHashMap::default();
|
||||
let mut rp: FxHashMap<u8, u16> = FxHashMap::default();
|
||||
let mut u: FxHashSet<u16> = FxHashSet::from_iter(patterns.iter().cloned());
|
||||
for x in &patterns {
|
||||
let sc = patterns.iter().filter(|y| is_subset(*x, **y)).count();
|
||||
match digits.get(&(sc, x.count_ones())) {
|
||||
None => {}
|
||||
Some(digit) => {
|
||||
mp.insert(*x, *digit);
|
||||
rp.insert(*digit, *x);
|
||||
u.remove(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let x = *u
|
||||
.iter()
|
||||
.find(|x| !is_subset(*rp.get(&5).unwrap(), **x))
|
||||
.unwrap();
|
||||
mp.insert(x, 0);
|
||||
u.remove(&x);
|
||||
|
||||
let x = *u
|
||||
.iter()
|
||||
.find(|x| is_subset(*rp.get(&4).unwrap(), **x))
|
||||
.unwrap();
|
||||
mp.insert(x, 9);
|
||||
u.remove(&x);
|
||||
|
||||
let x = *u.iter().next().unwrap();
|
||||
mp.insert(x, 6);
|
||||
|
||||
output
|
||||
.iter()
|
||||
.map(|x| *mp.get(x).unwrap() as u32)
|
||||
.reduce(|a, b| a * 10 + b)
|
||||
.unwrap()
|
||||
})
|
||||
.sum::<u32>()
|
||||
.to_string()
|
||||
}
|
||||
|
||||
aoc::main!(2021, 8, ex: 1[b], 2);
|
|
@ -4,29 +4,32 @@
|
|||
extern crate test;
|
||||
|
||||
use std::collections::{BinaryHeap, VecDeque};
|
||||
use std::fs;
|
||||
use test::Bencher;
|
||||
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
type Input = Vec<Vec<u32>>;
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = fs::read_to_string("2021/09.txt").unwrap();
|
||||
puzzle.trim().lines().map(|line| {
|
||||
line.trim().chars().map(|c| (c as u32) - 48).collect()
|
||||
}).collect()
|
||||
fn setup(input: &str) -> Input {
|
||||
input
|
||||
.trim()
|
||||
.lines()
|
||||
.map(|line| line.trim().chars().map(|c| (c as u32) - 48).collect())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn get_neighbors(i: i32, j: i32, w: i32, h: i32) -> impl Iterator<Item=(i32, i32)> {
|
||||
[(-1, 0), (1, 0), (0, -1), (0, 1)].iter().cloned().filter_map(move |(dx, dy)| {
|
||||
let x = j + dx;
|
||||
let y = i + dy;
|
||||
if x >= 0 && y >= 0 && x < w && y < h {
|
||||
Option::Some((x, y))
|
||||
} else {
|
||||
Option::None
|
||||
}
|
||||
})
|
||||
fn get_neighbors(i: i32, j: i32, w: i32, h: i32) -> impl Iterator<Item = (i32, i32)> {
|
||||
[(-1, 0), (1, 0), (0, -1), (0, 1)]
|
||||
.iter()
|
||||
.cloned()
|
||||
.filter_map(move |(dx, dy)| {
|
||||
let x = j + dx;
|
||||
let y = i + dy;
|
||||
if x >= 0 && y >= 0 && x < w && y < h {
|
||||
Option::Some((x, y))
|
||||
} else {
|
||||
Option::None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
|
@ -34,7 +37,8 @@ fn part1(input: &Input) -> String {
|
|||
for (i, line) in input.iter().enumerate() {
|
||||
for (j, c) in line.iter().enumerate() {
|
||||
if get_neighbors(i as i32, j as i32, line.len() as i32, input.len() as i32)
|
||||
.all(|(p, q)| c < &input[q as usize][p as usize].clone()) {
|
||||
.all(|(p, q)| c < &input[q as usize][p as usize].clone())
|
||||
{
|
||||
out += c + 1;
|
||||
}
|
||||
}
|
||||
|
@ -47,18 +51,25 @@ fn part2(input: &Input) -> String {
|
|||
for (i, line) in input.iter().enumerate() {
|
||||
for (j, c) in line.iter().enumerate() {
|
||||
if get_neighbors(i as i32, j as i32, line.len() as i32, input.len() as i32)
|
||||
.all(|(p, q)| c < &input[q as usize][p as usize].clone()) {
|
||||
.all(|(p, q)| c < &input[q as usize][p as usize].clone())
|
||||
{
|
||||
let mut queue = VecDeque::from([(i, j)]);
|
||||
let mut visited = FxHashSet::default();
|
||||
while !queue.is_empty() {
|
||||
let (y, x) = queue.pop_front().unwrap();
|
||||
|
||||
if input[y][x] == 9 { continue; }
|
||||
if input[y][x] == 9 {
|
||||
continue;
|
||||
}
|
||||
|
||||
if visited.contains(&(y, x)) { continue; }
|
||||
if visited.contains(&(y, x)) {
|
||||
continue;
|
||||
}
|
||||
visited.insert((y, x));
|
||||
|
||||
for (p, q) in get_neighbors(y as i32, x as i32, line.len() as i32, input.len() as i32) {
|
||||
for (p, q) in
|
||||
get_neighbors(y as i32, x as i32, line.len() as i32, input.len() as i32)
|
||||
{
|
||||
queue.push_back((q as usize, p as usize));
|
||||
}
|
||||
}
|
||||
|
@ -66,28 +77,11 @@ fn part2(input: &Input) -> String {
|
|||
}
|
||||
}
|
||||
}
|
||||
sizes.into_iter_sorted().take(3).product::<usize>().to_string()
|
||||
sizes
|
||||
.into_iter_sorted()
|
||||
.take(3)
|
||||
.product::<usize>()
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (part1, part2) = run();
|
||||
println!("Part 1: {}", part1);
|
||||
println!("Part 2: {}", part2);
|
||||
}
|
||||
|
||||
pub fn run() -> (String, String) {
|
||||
let input = get_input();
|
||||
(part1(&input), part2(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part1(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| { part1(&input) })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part2(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| { part2(&input) })
|
||||
}
|
||||
aoc::main!(2021, 9, ex: 1);
|
62
Rust/2021/10.rs
Normal file
62
Rust/2021/10.rs
Normal file
|
@ -0,0 +1,62 @@
|
|||
#![feature(test)]
|
||||
|
||||
type Input = Vec<String>;
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
input.lines().map(|s| s.to_string()).collect()
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
input
|
||||
.iter()
|
||||
.map(|line| {
|
||||
let mut stack = Vec::new();
|
||||
for c in line.chars() {
|
||||
if "([{<".contains(c) {
|
||||
stack.push(c);
|
||||
} else {
|
||||
let x = stack.pop().unwrap();
|
||||
if !["()", "[]", "{}", "<>"].contains(&format!("{}{}", x, c).as_str()) {
|
||||
return match c {
|
||||
')' => 3,
|
||||
']' => 57,
|
||||
'}' => 1197,
|
||||
'>' => 25137,
|
||||
_ => panic!(),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
0
|
||||
})
|
||||
.sum::<u32>()
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
let mut scores: Vec<usize> = input
|
||||
.iter()
|
||||
.filter_map(|line| {
|
||||
let mut stack = Vec::new();
|
||||
for c in line.chars() {
|
||||
if "([{<".contains(c) {
|
||||
stack.push(c);
|
||||
} else {
|
||||
let x = stack.pop().unwrap();
|
||||
if !["()", "[]", "{}", "<>"].contains(&format!("{}{}", x, c).as_str()) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut out = 0;
|
||||
for c in stack.iter().rev() {
|
||||
out = out * 5 + " ([{<".find(*c).unwrap();
|
||||
}
|
||||
Some(out)
|
||||
})
|
||||
.collect();
|
||||
scores.sort();
|
||||
scores[scores.len() / 2].to_string()
|
||||
}
|
||||
|
||||
aoc::main!(2021, 10, ex: 1);
|
|
@ -1,16 +1,14 @@
|
|||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use std::fs;
|
||||
use test::Bencher;
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
type Input = Vec<Vec<u8>>;
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = fs::read_to_string("2021/11.txt").unwrap();
|
||||
puzzle.lines().map(|line| line.chars().map(|c| (c as u8) - 48).collect()).collect()
|
||||
fn setup(input: &str) -> Input {
|
||||
input
|
||||
.lines()
|
||||
.map(|line| line.chars().map(|c| (c as u8) - 48).collect())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn flash(grid: &mut Input) -> usize {
|
||||
|
@ -26,21 +24,27 @@ fn flash(grid: &mut Input) -> usize {
|
|||
}
|
||||
|
||||
let mut visited: FxHashSet<(usize, usize)> = FxHashSet::default();
|
||||
while !flashes.is_empty() {
|
||||
let (i, j) = flashes.pop().unwrap();
|
||||
|
||||
if visited.contains(&(i, j)) { continue }
|
||||
while let Some((i, j)) = flashes.pop() {
|
||||
if visited.contains(&(i, j)) {
|
||||
continue;
|
||||
}
|
||||
visited.insert((i, j));
|
||||
|
||||
grid[i][j] = 0;
|
||||
|
||||
for k in 0..9 {
|
||||
if k == 4 {continue;}
|
||||
if k == 4 {
|
||||
continue;
|
||||
}
|
||||
let p = (i as i32) + k / 3 - 1;
|
||||
let q = (j as i32) + k % 3 - 1;
|
||||
if p < 0 || q < 0 {continue;}
|
||||
if p < 0 || q < 0 {
|
||||
continue;
|
||||
}
|
||||
let (p, q) = (p as usize, q as usize);
|
||||
if p >= grid.len() || q >= grid[0].len() {continue;}
|
||||
if p >= grid.len() || q >= grid[0].len() {
|
||||
continue;
|
||||
}
|
||||
if grid[p][q] >= 9 {
|
||||
flashes.push((p, q));
|
||||
} else if !visited.contains(&(p, q)) {
|
||||
|
@ -53,34 +57,19 @@ fn flash(grid: &mut Input) -> usize {
|
|||
|
||||
fn part1(input: &Input) -> String {
|
||||
let mut grid = input.clone();
|
||||
(0..100).map(|_| flash(&mut grid)).sum::<usize>().to_string()
|
||||
(0..100)
|
||||
.map(|_| flash(&mut grid))
|
||||
.sum::<usize>()
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
let mut grid = input.clone();
|
||||
let size = grid.len() * grid[0].len();
|
||||
(1..).filter(|_| flash(&mut grid) == size).next().unwrap().to_string()
|
||||
(1..)
|
||||
.find(|_| flash(&mut grid) == size)
|
||||
.unwrap()
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (part1, part2) = run();
|
||||
println!("Part 1: {}", part1);
|
||||
println!("Part 2: {}", part2);
|
||||
}
|
||||
|
||||
pub fn run() -> (String, String) {
|
||||
let input = get_input();
|
||||
(part1(&input), part2(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part1(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| part1(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part2(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| part2(&input))
|
||||
}
|
||||
aoc::main!(2021, 11, ex: 1);
|
79
Rust/2021/12.rs
Normal file
79
Rust/2021/12.rs
Normal file
|
@ -0,0 +1,79 @@
|
|||
#![feature(test)]
|
||||
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
||||
type Input = FxHashMap<i32, Vec<i32>>;
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
let mut out = FxHashMap::default();
|
||||
let mut map = FxHashMap::default();
|
||||
map.insert("start", 0);
|
||||
map.insert("end", 1);
|
||||
for line in input.trim().lines() {
|
||||
let mut split = line.split('-').map(|x| {
|
||||
if !map.contains_key(x) {
|
||||
map.insert(x, (map.len() as i32) * if x < "a" { 1 } else { -1 });
|
||||
}
|
||||
*map.get(x).unwrap()
|
||||
});
|
||||
|
||||
let a = split.next().unwrap();
|
||||
let b = split.next().unwrap();
|
||||
|
||||
match out.get_mut(&a) {
|
||||
None => {
|
||||
out.insert(a, vec![b]);
|
||||
}
|
||||
Some(x) => {
|
||||
x.push(b);
|
||||
}
|
||||
}
|
||||
match out.get_mut(&b) {
|
||||
None => {
|
||||
out.insert(b, vec![a]);
|
||||
}
|
||||
Some(x) => {
|
||||
x.push(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
fn search(node: i32, graph: &Input, visited: &mut FxHashSet<i32>, small_twice: bool) -> u32 {
|
||||
if node == 1 {
|
||||
return 1;
|
||||
}
|
||||
let mut twice = false;
|
||||
if node <= 0 && visited.contains(&node) {
|
||||
if small_twice || node == 0 {
|
||||
return 0;
|
||||
}
|
||||
twice = true;
|
||||
}
|
||||
visited.insert(node);
|
||||
|
||||
let out = match graph.get(&node) {
|
||||
None => 0,
|
||||
Some(edges) => edges
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|next| search(next, graph, visited, twice || small_twice))
|
||||
.sum::<u32>(),
|
||||
};
|
||||
|
||||
if !twice {
|
||||
visited.remove(&node);
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
search(0, input, &mut FxHashSet::default(), true).to_string()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
search(0, input, &mut FxHashSet::default(), false).to_string()
|
||||
}
|
||||
|
||||
aoc::main!(2021, 12, ex: 1, 2, 3);
|
100
Rust/2021/13.rs
Normal file
100
Rust/2021/13.rs
Normal file
|
@ -0,0 +1,100 @@
|
|||
#![feature(test)]
|
||||
|
||||
use regex::Regex;
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
enum Instruction {
|
||||
X(u32),
|
||||
Y(u32),
|
||||
}
|
||||
|
||||
struct Input {
|
||||
dots: FxHashSet<(u32, u32)>,
|
||||
instructions: Vec<Instruction>,
|
||||
}
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
let mut blocks = input.split("\n\n");
|
||||
let dots = blocks
|
||||
.next()
|
||||
.unwrap()
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let mut coords = line.split(',');
|
||||
(
|
||||
coords.next().unwrap().parse().unwrap(),
|
||||
coords.next().unwrap().parse().unwrap(),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let regex = Regex::new(r"^fold along (.)=(\d+)$").unwrap();
|
||||
let instructions = blocks
|
||||
.next()
|
||||
.unwrap()
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let capture = regex.captures(line).unwrap();
|
||||
let n: u32 = capture.get(2).unwrap().as_str().parse().unwrap();
|
||||
match capture.get(1).unwrap().as_str() {
|
||||
"x" => Instruction::X(n),
|
||||
"y" => Instruction::Y(n),
|
||||
_ => panic!(),
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
Input { dots, instructions }
|
||||
}
|
||||
|
||||
fn fold(dots: &FxHashSet<(u32, u32)>, instruction: &Instruction) -> FxHashSet<(u32, u32)> {
|
||||
dots.iter()
|
||||
.cloned()
|
||||
.map(|(x, y)| match instruction {
|
||||
Instruction::X(n) => (x.min(2 * n - x), y),
|
||||
Instruction::Y(n) => (x, y.min(2 * n - y)),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
let mut dots = input.dots.clone();
|
||||
let instruction = input.instructions.first().unwrap();
|
||||
dots = fold(&dots, instruction);
|
||||
dots.len().to_string()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
let mut dots = input.dots.clone();
|
||||
for instruction in &input.instructions {
|
||||
dots = fold(&dots, instruction);
|
||||
}
|
||||
|
||||
(0..8)
|
||||
.map(|n| {
|
||||
let k = (5 * n..5 * n + 4)
|
||||
.flat_map(|i| {
|
||||
let dots = &dots;
|
||||
(0..6).map(move |j| dots.contains(&(i, j)))
|
||||
})
|
||||
.fold(0, |acc, x| (acc << 1) | (x as i32));
|
||||
match k {
|
||||
0b011111100100100100011111 => 'A',
|
||||
0b111111101001101001010110 => 'B',
|
||||
0b011110100001100001010010 => 'C',
|
||||
0b111111101001101001100001 => 'E',
|
||||
0b111111101000101000100000 => 'F',
|
||||
0b011110100001100101010111 => 'G',
|
||||
0b111111001000001000111111 => 'H',
|
||||
0b000010000001100001111111 => 'J',
|
||||
0b111111001000010110100001 => 'K',
|
||||
0b111111000001000001000001 => 'L',
|
||||
0b111111100100100100011000 => 'P',
|
||||
0b111111100100100110011001 => 'R',
|
||||
0b111110000001000001111110 => 'U',
|
||||
0b100011100101101001110001 => 'Z',
|
||||
_ => '?',
|
||||
}
|
||||
})
|
||||
.collect::<String>()
|
||||
}
|
||||
|
||||
aoc::main!(2021, 13, ex: 1[a]);
|
|
@ -1,10 +1,5 @@
|
|||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use std::fs;
|
||||
use test::Bencher;
|
||||
|
||||
use counter::Counter;
|
||||
use regex::Regex;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
@ -14,23 +9,28 @@ struct Input {
|
|||
rules: FxHashMap<(char, char), char>,
|
||||
}
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = fs::read_to_string("2021/14.txt").unwrap();
|
||||
let mut lines = puzzle.lines();
|
||||
fn setup(input: &str) -> Input {
|
||||
let mut lines = input.lines();
|
||||
let template = lines.next().unwrap().to_string();
|
||||
lines.next();
|
||||
let regex = Regex::new(r"^([A-Z])([A-Z]) -> ([A-Z])$").unwrap();
|
||||
let rules = lines.map(|line| {
|
||||
let capture = regex.captures(line).unwrap();
|
||||
let get = |i| capture.get(i).unwrap().as_str().chars().next().unwrap();
|
||||
((get(1), get(2)), get(3))
|
||||
}).collect();
|
||||
let rules = lines
|
||||
.map(|line| {
|
||||
let capture = regex.captures(line).unwrap();
|
||||
let get = |i| capture.get(i).unwrap().as_str().chars().next().unwrap();
|
||||
((get(1), get(2)), get(3))
|
||||
})
|
||||
.collect();
|
||||
|
||||
Input { template, rules }
|
||||
}
|
||||
|
||||
fn solve(input: &Input, n: usize) -> usize {
|
||||
let mut adj: Counter<(char, char)> = input.template.chars().zip(input.template[1..].chars()).collect();
|
||||
let mut adj: Counter<(char, char)> = input
|
||||
.template
|
||||
.chars()
|
||||
.zip(input.template[1..].chars())
|
||||
.collect();
|
||||
for _ in 0..n {
|
||||
let mut new: Counter<(char, char)> = Counter::new();
|
||||
for ((a, b), c) in adj.iter().map(|((a, b), c)| ((*a, *b), *c)) {
|
||||
|
@ -62,25 +62,4 @@ fn part2(input: &Input) -> String {
|
|||
solve(input, 40).to_string()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (part1, part2) = run();
|
||||
println!("Part 1: {}", part1);
|
||||
println!("Part 2: {}", part2);
|
||||
}
|
||||
|
||||
pub fn run() -> (String, String) {
|
||||
let input = get_input();
|
||||
(part1(&input), part2(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part1(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| part1(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part2(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| part2(&input))
|
||||
}
|
||||
aoc::main!(2021, 14, ex: 1);
|
63
Rust/2021/15.rs
Normal file
63
Rust/2021/15.rs
Normal file
|
@ -0,0 +1,63 @@
|
|||
#![feature(test)]
|
||||
|
||||
use std::{cmp::Reverse, collections::BinaryHeap};
|
||||
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
type Input = Vec<Vec<u32>>;
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
input
|
||||
.lines()
|
||||
.map(|line| line.chars().map(|c| (c as u32) - 0x30).collect())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn dijkstra(grid: &Input, k: usize) -> u32 {
|
||||
let w = grid[0].len();
|
||||
let h = grid.len();
|
||||
let mut queue = BinaryHeap::new();
|
||||
queue.push(Reverse((0u32, 0usize, 0usize)));
|
||||
let mut visited = FxHashSet::default();
|
||||
while !queue.is_empty() {
|
||||
let (d, x, y) = queue.pop().unwrap().0;
|
||||
|
||||
if visited.contains(&(x, y)) {
|
||||
continue;
|
||||
}
|
||||
visited.insert((x, y));
|
||||
|
||||
if x == w * k - 1 && y == h * k - 1 {
|
||||
return d;
|
||||
}
|
||||
|
||||
for (dx, dy) in [(-1, 0), (1, 0), (0, -1), (0, 1)] {
|
||||
let p = (x as i32) + dx;
|
||||
let q = (y as i32) + dy;
|
||||
if p < 0 || q < 0 {
|
||||
continue;
|
||||
}
|
||||
let p = p as usize;
|
||||
let q = q as usize;
|
||||
if p >= k * w || q >= k * h {
|
||||
continue;
|
||||
}
|
||||
if visited.contains(&(p, q)) {
|
||||
continue;
|
||||
}
|
||||
let c = grid[q % h][p % w] + (q / h + p / w) as u32;
|
||||
queue.push(Reverse((d + (c - 1) % 9 + 1, p, q)));
|
||||
}
|
||||
}
|
||||
panic!();
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
dijkstra(input, 1).to_string()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
dijkstra(input, 5).to_string()
|
||||
}
|
||||
|
||||
aoc::main!(2021, 15, ex: 1);
|
|
@ -1,36 +1,38 @@
|
|||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use std::fs;
|
||||
use test::Bencher;
|
||||
|
||||
type Input = Vec<bool>;
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = fs::read_to_string("2021/16.txt").unwrap();
|
||||
puzzle.trim().chars().flat_map(|c| {
|
||||
let n = "0123456789ABCDEF".find(c).unwrap();
|
||||
(0..4).rev().map(move |i| n & (1 << i) > 0)
|
||||
}).collect()
|
||||
fn setup(input: &str) -> Input {
|
||||
input
|
||||
.trim()
|
||||
.chars()
|
||||
.flat_map(|c| {
|
||||
let n = "0123456789ABCDEF".find(c).unwrap();
|
||||
(0..4).rev().map(move |i| n & (1 << i) > 0)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
struct Reader {
|
||||
data: Vec<bool>,
|
||||
struct Reader<'a> {
|
||||
data: &'a [bool],
|
||||
pos: usize,
|
||||
}
|
||||
|
||||
impl Reader {
|
||||
fn new(data: Vec<bool>) -> Reader {
|
||||
impl<'a> Reader<'a> {
|
||||
fn new(data: &'a [bool]) -> Self {
|
||||
Reader { data, pos: 0 }
|
||||
}
|
||||
|
||||
fn read(&mut self, n: usize) -> u64 {
|
||||
let mut out = 0;
|
||||
for _ in 0..n {
|
||||
if self.pos >= self.data.len() { break; }
|
||||
if self.pos >= self.data.len() {
|
||||
break;
|
||||
}
|
||||
out <<= 1;
|
||||
if self.data[self.pos] { out |= 1; }
|
||||
if self.data[self.pos] {
|
||||
out |= 1;
|
||||
}
|
||||
self.pos += 1;
|
||||
}
|
||||
out
|
||||
|
@ -51,9 +53,14 @@ fn solve(io: &mut Reader) -> Result {
|
|||
let c = io.read(1);
|
||||
lit <<= 4;
|
||||
lit |= io.read(4);
|
||||
if c == 0 { break; }
|
||||
if c == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Result { version_sum: version, value: lit };
|
||||
return Result {
|
||||
version_sum: version,
|
||||
value: lit,
|
||||
};
|
||||
}
|
||||
|
||||
let mut values = vec![];
|
||||
|
@ -82,25 +89,19 @@ fn solve(io: &mut Reader) -> Result {
|
|||
5 => (values[0] > values[1]) as u64,
|
||||
6 => (values[0] < values[1]) as u64,
|
||||
7 => (values[0] == values[1]) as u64,
|
||||
_ => panic!()
|
||||
_ => panic!(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (part1, part2) = run();
|
||||
println!("Part 1: {}", part1);
|
||||
println!("Part 2: {}", part2);
|
||||
fn part1(input: &Input) -> u64 {
|
||||
let mut reader = Reader::new(input);
|
||||
solve(&mut reader).version_sum
|
||||
}
|
||||
|
||||
pub fn run() -> (String, String) {
|
||||
let input = get_input();
|
||||
let result = solve(&mut Reader::new(input.clone()));
|
||||
(result.version_sum.to_string(), result.value.to_string())
|
||||
fn part2(input: &Input) -> u64 {
|
||||
let mut reader = Reader::new(input);
|
||||
solve(&mut reader).value
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_solution(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| solve(&mut Reader::new(input.clone())))
|
||||
}
|
||||
aoc::main!(2021, 16, ex: "1a"[a], "2a"[a], "3a"[a], "4a"[a], "1b"[b], "2b"[b], "3b"[b], "4b"[b], "5b"[b], "6b"[b], "7b"[b], "8b"[b]);
|
|
@ -1,9 +1,5 @@
|
|||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use std::fs;
|
||||
use test::Bencher;
|
||||
use regex::Regex;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
||||
|
@ -14,10 +10,9 @@ struct Input {
|
|||
y2: i32,
|
||||
}
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = fs::read_to_string("2021/17.txt").unwrap();
|
||||
fn setup(input: &str) -> Input {
|
||||
let regex = Regex::new(r"^target area: x=(-?\d+)..(-?\d+), y=(-?\d+)..(-?\d+)$").unwrap();
|
||||
let capture = regex.captures(puzzle.trim()).unwrap();
|
||||
let capture = regex.captures(input.trim()).unwrap();
|
||||
let get = |i| capture.get(i).unwrap().as_str().parse().unwrap();
|
||||
Input {
|
||||
x1: get(1),
|
||||
|
@ -38,7 +33,7 @@ fn solve(input: &Input) -> (i32, usize) {
|
|||
|
||||
while y >= input.y1 {
|
||||
if y <= input.y2 {
|
||||
if !ok.contains_key(&t) {ok.insert(t, (0, FxHashSet::default()));}
|
||||
ok.entry(t).or_insert_with(|| (0, FxHashSet::default()));
|
||||
let (my, vys) = ok.get_mut(&t).unwrap();
|
||||
*my = maxy.max(*my);
|
||||
vys.insert(ovy);
|
||||
|
@ -77,20 +72,12 @@ fn solve(input: &Input) -> (i32, usize) {
|
|||
(outa, outb)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (part1, part2) = run();
|
||||
println!("Part 1: {}", part1);
|
||||
println!("Part 2: {}", part2);
|
||||
fn part1(input: &Input) -> i32 {
|
||||
solve(input).0
|
||||
}
|
||||
|
||||
pub fn run() -> (String, String) {
|
||||
let input = get_input();
|
||||
let (part1, part2) = solve(&input);
|
||||
(part1.to_string(), part2.to_string())
|
||||
fn part2(input: &Input) -> usize {
|
||||
solve(input).1
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| solve(&input))
|
||||
}
|
||||
aoc::main!(2021, 17, ex: 1);
|
153
Rust/2021/18.rs
Normal file
153
Rust/2021/18.rs
Normal file
|
@ -0,0 +1,153 @@
|
|||
#![feature(test)]
|
||||
|
||||
type Number = [Option<u32>; 64];
|
||||
type Input = Vec<Number>;
|
||||
|
||||
fn parent(n: usize) -> usize {
|
||||
n >> 1
|
||||
}
|
||||
|
||||
fn left(n: usize) -> usize {
|
||||
n << 1
|
||||
}
|
||||
|
||||
fn right(n: usize) -> usize {
|
||||
n << 1 | 1
|
||||
}
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
input
|
||||
.trim()
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let mut out = [Option::None; 64];
|
||||
let mut acc = Option::None;
|
||||
let mut n = 1;
|
||||
for c in line.trim().chars() {
|
||||
let digit = (c as i32) - 0x30;
|
||||
if (0..=9).contains(&digit) {
|
||||
acc = Option::Some(acc.unwrap_or(0) * 10 + (digit as u32));
|
||||
continue;
|
||||
}
|
||||
let mut write = |x| {
|
||||
if acc.is_some() {
|
||||
out[n] = acc;
|
||||
}
|
||||
acc = Option::None;
|
||||
x
|
||||
};
|
||||
n = match c {
|
||||
'[' => left(n),
|
||||
',' => write(n + 1),
|
||||
']' => write(parent(n)),
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
out
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn move_up(lst: &mut Number, i: usize, x: u32) {
|
||||
match lst[i] {
|
||||
None => {
|
||||
move_up(lst, parent(i), x);
|
||||
}
|
||||
Some(y) => {
|
||||
lst[i] = Some(x + y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn explode(lst: &mut Number) -> bool {
|
||||
for n in (1 << 4)..(1 << 5) {
|
||||
if lst[n].is_some() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let a = left(n);
|
||||
let b = right(n);
|
||||
if let (Option::Some(l), Option::Some(r)) = (lst[a], lst[b]) {
|
||||
lst[a] = Option::None;
|
||||
lst[b] = Option::None;
|
||||
lst[n] = Option::Some(0);
|
||||
if a > 1 << 5 {
|
||||
move_up(lst, a - 1, l);
|
||||
}
|
||||
if b + 1 < 1 << 6 {
|
||||
move_up(lst, b + 1, r);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn split(lst: &mut Number, n: usize) -> bool {
|
||||
if let Option::Some(x) = lst[n] {
|
||||
if x < 10 {
|
||||
return false;
|
||||
}
|
||||
let k = x >> 1;
|
||||
lst[n] = Option::None;
|
||||
lst[left(n)] = Option::Some(k);
|
||||
lst[right(n)] = Option::Some(x - k);
|
||||
return true;
|
||||
}
|
||||
split(lst, left(n)) || split(lst, right(n))
|
||||
}
|
||||
|
||||
fn add(a: &Number, b: &Number) -> Number {
|
||||
let mut out = [Option::None; 64];
|
||||
let mut j = 2;
|
||||
for i in 0..=4 {
|
||||
((1 << i)..(1 << (i + 1))).for_each(|k| {
|
||||
out[j] = a[k];
|
||||
j += 1;
|
||||
});
|
||||
((1 << i)..(1 << (i + 1))).for_each(|k| {
|
||||
out[j] = b[k];
|
||||
j += 1;
|
||||
});
|
||||
}
|
||||
|
||||
while explode(&mut out) || split(&mut out, 1) {}
|
||||
|
||||
out
|
||||
}
|
||||
|
||||
fn magnitude(lst: &Number, n: usize) -> u32 {
|
||||
if let Some(x) = lst[n] {
|
||||
x
|
||||
} else {
|
||||
3 * magnitude(lst, left(n)) + 2 * magnitude(lst, right(n))
|
||||
}
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
magnitude(
|
||||
&input.iter().cloned().reduce(|a, b| add(&a, &b)).unwrap(),
|
||||
1,
|
||||
)
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
input
|
||||
.iter()
|
||||
.flat_map(|a| {
|
||||
input.iter().filter_map(move |b| {
|
||||
if a == b {
|
||||
Option::None
|
||||
} else {
|
||||
Option::Some(magnitude(&add(a, b), 1))
|
||||
}
|
||||
})
|
||||
})
|
||||
.max()
|
||||
.unwrap()
|
||||
.to_string()
|
||||
}
|
||||
|
||||
aoc::main!(2021, 18, ex: 1);
|
|
@ -1,11 +1,10 @@
|
|||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
use std::{
|
||||
hash::Hash,
|
||||
ops::{Add, Sub},
|
||||
};
|
||||
|
||||
use std::fs;
|
||||
use std::hash::Hash;
|
||||
use std::ops::{Add, Sub};
|
||||
use test::Bencher;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
||||
#[derive(Copy, Clone, Hash, Eq, PartialEq)]
|
||||
|
@ -24,7 +23,11 @@ impl Pos {
|
|||
2 => Pos { x, y: -y, z: -z },
|
||||
3 => Pos { x, y: z, z: -y },
|
||||
4 => Pos { x: -x, y: -y, z },
|
||||
5 => Pos { x: -x, y: -z, z: -y },
|
||||
5 => Pos {
|
||||
x: -x,
|
||||
y: -z,
|
||||
z: -y,
|
||||
},
|
||||
6 => Pos { x: -x, y, z: -z },
|
||||
7 => Pos { x: -x, y: z, z: y },
|
||||
8 => Pos { x: y, y: -x, z },
|
||||
|
@ -33,7 +36,11 @@ impl Pos {
|
|||
11 => Pos { x: y, y: z, z: x },
|
||||
12 => Pos { x: -y, y: x, z },
|
||||
13 => Pos { x: -y, y: -z, z: x },
|
||||
14 => Pos { x: -y, y: -x, z: -z },
|
||||
14 => Pos {
|
||||
x: -y,
|
||||
y: -x,
|
||||
z: -z,
|
||||
},
|
||||
15 => Pos { x: -y, y: z, z: -x },
|
||||
16 => Pos { x: z, y: -y, z: x },
|
||||
17 => Pos { x: z, y: -x, z: -y },
|
||||
|
@ -41,9 +48,13 @@ impl Pos {
|
|||
19 => Pos { x: z, y: x, z: y },
|
||||
20 => Pos { x: -z, y, z: x },
|
||||
21 => Pos { x: -z, y: -x, z: y },
|
||||
22 => Pos { x: -z, y: -y, z: -x },
|
||||
22 => Pos {
|
||||
x: -z,
|
||||
y: -y,
|
||||
z: -x,
|
||||
},
|
||||
23 => Pos { x: -z, y: x, z: -y },
|
||||
_ => panic!()
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,7 +73,11 @@ impl Add for Pos {
|
|||
type Output = Pos;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Pos { x: self.x + rhs.x, y: self.y + rhs.y, z: self.z + rhs.z }
|
||||
Pos {
|
||||
x: self.x + rhs.x,
|
||||
y: self.y + rhs.y,
|
||||
z: self.z + rhs.z,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,28 +85,47 @@ impl Sub for Pos {
|
|||
type Output = Pos;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
Pos { x: self.x - rhs.x, y: self.y - rhs.y, z: self.z - rhs.z }
|
||||
Pos {
|
||||
x: self.x - rhs.x,
|
||||
y: self.y - rhs.y,
|
||||
z: self.z - rhs.z,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Scanner = (Vec<Pos>, FxHashSet<i32>);
|
||||
type Input = Vec<Scanner>;
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = fs::read_to_string("2021/19.txt").unwrap();
|
||||
puzzle.split("\n\n").map(|scanner| {
|
||||
let poss: Vec<Pos> = scanner.lines().skip(1).map(|line| {
|
||||
let mut res = line.split(",").map(|x| x.parse().unwrap());
|
||||
Pos { x: res.next().unwrap(), y: res.next().unwrap(), z: res.next().unwrap() }
|
||||
}).collect();
|
||||
let distances: FxHashSet<i32> = poss.iter().flat_map(|a| {
|
||||
poss.iter().map(|b| a.distance(*b))
|
||||
}).collect();
|
||||
(poss, distances)
|
||||
}).collect()
|
||||
fn setup(input: &str) -> Input {
|
||||
input
|
||||
.split("\n\n")
|
||||
.map(|scanner| {
|
||||
let poss: Vec<Pos> = scanner
|
||||
.lines()
|
||||
.skip(1)
|
||||
.map(|line| {
|
||||
let mut res = line.split(',').map(|x| x.parse().unwrap());
|
||||
Pos {
|
||||
x: res.next().unwrap(),
|
||||
y: res.next().unwrap(),
|
||||
z: res.next().unwrap(),
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let distances: FxHashSet<i32> = poss
|
||||
.iter()
|
||||
.flat_map(|a| poss.iter().map(|b| a.distance(*b)))
|
||||
.collect();
|
||||
(poss, distances)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn match_scanner(beacons: &mut FxHashSet<Pos>, scanner_positions: &mut Vec<Pos>, scanner: &Scanner) {
|
||||
fn match_scanner(
|
||||
beacons: &mut FxHashSet<Pos>,
|
||||
scanner_positions: &mut Vec<Pos>,
|
||||
scanner: &Scanner,
|
||||
) {
|
||||
for i in 0..24 {
|
||||
let mut counter: FxHashMap<Pos, usize> = FxHashMap::default();
|
||||
for rel in &scanner.0 {
|
||||
|
@ -114,15 +148,15 @@ fn match_scanner(beacons: &mut FxHashSet<Pos>, scanner_positions: &mut Vec<Pos>,
|
|||
}
|
||||
|
||||
fn solve(input: &Input) -> (usize, i32) {
|
||||
let mut remaining: Vec<Scanner> = input.iter().cloned().collect();
|
||||
let mut remaining: Vec<Scanner> = input.to_vec();
|
||||
let first = remaining.remove(0);
|
||||
let mut beacons: FxHashSet<Pos> = FxHashSet::from_iter(first.0);
|
||||
let mut distances: FxHashSet<i32> = FxHashSet::from_iter(first.1);
|
||||
let mut scanners: Vec<Pos> = vec![];
|
||||
while !remaining.is_empty() {
|
||||
let i = (0..remaining.len()).max_by_key(|&i| {
|
||||
remaining[i].1.intersection(&distances).count()
|
||||
}).unwrap();
|
||||
let i = (0..remaining.len())
|
||||
.max_by_key(|&i| remaining[i].1.intersection(&distances).count())
|
||||
.unwrap();
|
||||
|
||||
let s = remaining.remove(i);
|
||||
match_scanner(&mut beacons, &mut scanners, &s);
|
||||
|
@ -130,25 +164,22 @@ fn solve(input: &Input) -> (usize, i32) {
|
|||
distances.insert(*x);
|
||||
}
|
||||
}
|
||||
(beacons.len(), scanners.iter().flat_map(|x| {
|
||||
scanners.iter().map(|&y| { x.manhatten_distance(y) })
|
||||
}).max().unwrap())
|
||||
(
|
||||
beacons.len(),
|
||||
scanners
|
||||
.iter()
|
||||
.flat_map(|x| scanners.iter().map(|&y| x.manhatten_distance(y)))
|
||||
.max()
|
||||
.unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (part1, part2) = run();
|
||||
println!("Part 1: {}", part1);
|
||||
println!("Part 2: {}", part2);
|
||||
fn part1(input: &Input) -> usize {
|
||||
solve(input).0
|
||||
}
|
||||
|
||||
pub fn run() -> (String, String) {
|
||||
let input = get_input();
|
||||
let (part1, part2) = solve(&input);
|
||||
(part1.to_string(), part2.to_string())
|
||||
fn part2(input: &Input) -> i32 {
|
||||
solve(input).1
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| solve(&input))
|
||||
}
|
||||
aoc::main!(2021, 19, ex: 1);
|
77
Rust/2021/20.rs
Normal file
77
Rust/2021/20.rs
Normal file
|
@ -0,0 +1,77 @@
|
|||
#![feature(test)]
|
||||
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
struct Input {
|
||||
algo: Vec<bool>,
|
||||
width: usize,
|
||||
height: usize,
|
||||
grid: FxHashSet<(i32, i32)>,
|
||||
}
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
let mut lines = input.lines();
|
||||
let algo = lines.next().unwrap().chars().map(|c| c == '#').collect();
|
||||
let grid = lines
|
||||
.skip(1)
|
||||
.enumerate()
|
||||
.flat_map(|(i, line)| {
|
||||
line.chars().enumerate().filter_map(move |(j, c)| {
|
||||
if c == '#' {
|
||||
Option::Some((j as i32, i as i32))
|
||||
} else {
|
||||
Option::None
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
Input {
|
||||
algo,
|
||||
grid,
|
||||
width: input.lines().nth(2).unwrap().len(),
|
||||
height: input.lines().count() - 2,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_neighbors(x: i32, y: i32) -> Vec<(i32, i32)> {
|
||||
(-1..=1)
|
||||
.flat_map(|dy| (-1..=1).map(move |dx| (x + dx, y + dy)))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn solve(input: &Input) -> (usize, usize) {
|
||||
let mut grid = input.grid.clone();
|
||||
let mut inf = false;
|
||||
let mut part1 = 0;
|
||||
let mut part2 = 0;
|
||||
for i in 1..=50 {
|
||||
let new_inf = inf != input.algo[0];
|
||||
grid = (-i..=input.height as i32 + i)
|
||||
.flat_map(|y| (-i..=input.width as i32 + i).map(move |x| (x, y)))
|
||||
.filter(|(x, y)| {
|
||||
let idx = get_neighbors(*x, *y).iter().fold(0, |acc, (p, q)| {
|
||||
acc << 1 | (grid.contains(&(*p, *q)) != inf) as usize
|
||||
});
|
||||
input.algo[idx] != new_inf
|
||||
})
|
||||
.collect();
|
||||
inf = new_inf;
|
||||
if i == 2 {
|
||||
part1 = grid.len();
|
||||
}
|
||||
if i == 50 {
|
||||
part2 = grid.len();
|
||||
}
|
||||
}
|
||||
(part1, part2)
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> usize {
|
||||
solve(input).0
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> usize {
|
||||
solve(input).1
|
||||
}
|
||||
|
||||
aoc::main!(2021, 20, ex: 1);
|
|
@ -1,18 +1,21 @@
|
|||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use std::fs;
|
||||
use test::Bencher;
|
||||
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
type Input = (u32, u32);
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = fs::read_to_string("2021/21.txt").unwrap();
|
||||
let mut lines = puzzle.lines();
|
||||
let mut next = || lines.next().unwrap().split(" ").last().unwrap().parse().unwrap();
|
||||
fn setup(input: &str) -> Input {
|
||||
let mut lines = input.lines();
|
||||
let mut next = || {
|
||||
lines
|
||||
.next()
|
||||
.unwrap()
|
||||
.split(' ')
|
||||
.last()
|
||||
.unwrap()
|
||||
.parse()
|
||||
.unwrap()
|
||||
};
|
||||
(next(), next())
|
||||
}
|
||||
|
||||
|
@ -40,7 +43,9 @@ struct State {
|
|||
}
|
||||
|
||||
fn dirac(state: State, mem: &mut FxHashMap<State, (u64, u64)>) -> (u64, u64) {
|
||||
if state.s2 >= 21 { return (0, 1); }
|
||||
if state.s2 >= 21 {
|
||||
return (0, 1);
|
||||
}
|
||||
|
||||
match mem.get(&state) {
|
||||
Some(&result) => result,
|
||||
|
@ -48,7 +53,15 @@ fn dirac(state: State, mem: &mut FxHashMap<State, (u64, u64)>) -> (u64, u64) {
|
|||
let result = (0u32..27).fold((0, 0), |acc, i| {
|
||||
let x = i / 9 % 3 + i / 3 % 3 + i % 3 + 3;
|
||||
let q = (state.p1 - 1 + x) % 10 + 1;
|
||||
let res = dirac(State { p1: state.p2, p2: q, s1: state.s2, s2: state.s1 + q }, mem);
|
||||
let res = dirac(
|
||||
State {
|
||||
p1: state.p2,
|
||||
p2: q,
|
||||
s1: state.s2,
|
||||
s2: state.s1 + q,
|
||||
},
|
||||
mem,
|
||||
);
|
||||
(acc.0 + res.1, acc.1 + res.0)
|
||||
});
|
||||
|
||||
|
@ -59,34 +72,16 @@ fn dirac(state: State, mem: &mut FxHashMap<State, (u64, u64)>) -> (u64, u64) {
|
|||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
let (a, b) = dirac(State {
|
||||
p1: input.0,
|
||||
p2: input.1,
|
||||
s1: 0,
|
||||
s2: 0,
|
||||
}, &mut FxHashMap::default());
|
||||
let (a, b) = dirac(
|
||||
State {
|
||||
p1: input.0,
|
||||
p2: input.1,
|
||||
s1: 0,
|
||||
s2: 0,
|
||||
},
|
||||
&mut FxHashMap::default(),
|
||||
);
|
||||
a.max(b).to_string()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (part1, part2) = run();
|
||||
println!("Part 1: {}", part1);
|
||||
println!("Part 2: {}", part2);
|
||||
}
|
||||
|
||||
pub fn run() -> (String, String) {
|
||||
let input = get_input();
|
||||
(part1(&input), part2(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part1(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| part1(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part2(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| part2(&input))
|
||||
}
|
||||
aoc::main!(2021, 21, ex: 1);
|
136
Rust/2021/22.rs
Normal file
136
Rust/2021/22.rs
Normal file
|
@ -0,0 +1,136 @@
|
|||
#![feature(test)]
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
struct Cuboid {
|
||||
x1: i64,
|
||||
x2: i64,
|
||||
y1: i64,
|
||||
y2: i64,
|
||||
z1: i64,
|
||||
z2: i64,
|
||||
off: Vec<Cuboid>,
|
||||
}
|
||||
|
||||
fn line_intersection(a1: i64, a2: i64, b1: i64, b2: i64) -> Option<(i64, i64)> {
|
||||
if a2 < b1 || b2 < a1 {
|
||||
Option::None
|
||||
} else {
|
||||
Option::Some((a1.max(b1), a2.min(b2)))
|
||||
}
|
||||
}
|
||||
|
||||
impl Cuboid {
|
||||
fn copy(&self) -> Cuboid {
|
||||
Cuboid {
|
||||
x1: self.x1,
|
||||
x2: self.x2,
|
||||
y1: self.y1,
|
||||
y2: self.y2,
|
||||
z1: self.z1,
|
||||
z2: self.z2,
|
||||
off: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
fn get_intersection(&self, c: &Cuboid) -> Option<Cuboid> {
|
||||
let x = line_intersection(self.x1, self.x2, c.x1, c.x2);
|
||||
let y = line_intersection(self.y1, self.y2, c.y1, c.y2);
|
||||
let z = line_intersection(self.z1, self.z2, c.z1, c.z2);
|
||||
if let (Option::Some(x), Option::Some(y), Option::Some(z)) = (x, y, z) {
|
||||
Option::Some(Cuboid {
|
||||
x1: x.0,
|
||||
x2: x.1,
|
||||
y1: y.0,
|
||||
y2: y.1,
|
||||
z1: z.0,
|
||||
z2: z.1,
|
||||
off: vec![],
|
||||
})
|
||||
} else {
|
||||
Option::None
|
||||
}
|
||||
}
|
||||
|
||||
fn subtract(&mut self, c: &Cuboid) {
|
||||
if let Option::Some(intersection) = self.get_intersection(c) {
|
||||
for o in self.off.iter_mut() {
|
||||
o.subtract(c);
|
||||
}
|
||||
self.off.push(intersection);
|
||||
}
|
||||
}
|
||||
|
||||
fn volume(&self) -> i64 {
|
||||
(self.x2 - self.x1 + 1) * (self.y2 - self.y1 + 1) * (self.z2 - self.z1 + 1)
|
||||
- self.off.iter().map(|c| c.volume()).sum::<i64>()
|
||||
}
|
||||
}
|
||||
|
||||
struct Step {
|
||||
on: bool,
|
||||
cuboid: Cuboid,
|
||||
}
|
||||
|
||||
type Input = Vec<Step>;
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
let regex =
|
||||
Regex::new(r"^(on|off) x=(-?\d+)..(-?\d+),y=(-?\d+)..(-?\d+),z=(-?\d+)..(-?\d+)$").unwrap();
|
||||
input
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let capture = regex.captures(line).unwrap();
|
||||
let get_num = |i| capture.get(i).unwrap().as_str().parse().unwrap();
|
||||
Step {
|
||||
on: capture.get(1).unwrap().as_str() == "on",
|
||||
cuboid: Cuboid {
|
||||
x1: get_num(2),
|
||||
x2: get_num(3),
|
||||
y1: get_num(4),
|
||||
y2: get_num(5),
|
||||
z1: get_num(6),
|
||||
z2: get_num(7),
|
||||
off: vec![],
|
||||
},
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
let mut cuboids: Vec<Cuboid> = vec![];
|
||||
for Step { on, cuboid } in input {
|
||||
if cuboid.x1 < -50
|
||||
|| cuboid.x2 > 50
|
||||
|| cuboid.y1 < -50
|
||||
|| cuboid.y2 > 50
|
||||
|| cuboid.z1 < -50
|
||||
|| cuboid.z2 > 50
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for c in cuboids.iter_mut() {
|
||||
c.subtract(cuboid);
|
||||
}
|
||||
if *on {
|
||||
cuboids.push(cuboid.copy());
|
||||
}
|
||||
}
|
||||
cuboids.iter().map(|c| c.volume()).sum::<i64>().to_string()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> String {
|
||||
let mut cuboids: Vec<Cuboid> = vec![];
|
||||
for Step { on, cuboid } in input {
|
||||
for c in cuboids.iter_mut() {
|
||||
c.subtract(cuboid);
|
||||
}
|
||||
if *on {
|
||||
cuboids.push(cuboid.copy());
|
||||
}
|
||||
}
|
||||
cuboids.iter().map(|c| c.volume()).sum::<i64>().to_string()
|
||||
}
|
||||
|
||||
aoc::main!(2021, 22, ex: "1a"[a], "2a"[a], "1b"[b]);
|
|
@ -1,24 +1,22 @@
|
|||
#![feature(test)]
|
||||
#![feature(int_abs_diff)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use std::cmp::Reverse;
|
||||
use std::collections::BinaryHeap;
|
||||
use std::fs;
|
||||
use test::Bencher;
|
||||
use std::{cmp::Reverse, collections::BinaryHeap};
|
||||
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
type Input = [Vec<char>; 4];
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = fs::read_to_string("2021/23.txt").unwrap();
|
||||
fn setup(input: &str) -> Input {
|
||||
let mut out = [vec![], vec![], vec![], vec![]];
|
||||
let lines: Vec<(char, char, char, char)> = puzzle.lines().skip(2).take(2).map(|line| {
|
||||
let get = |i| line.chars().nth(3 + 2 * i as usize).unwrap();
|
||||
(get(0), get(1), get(2), get(3))
|
||||
}).collect();
|
||||
let lines: Vec<(char, char, char, char)> = input
|
||||
.lines()
|
||||
.skip(2)
|
||||
.take(2)
|
||||
.map(|line| {
|
||||
let get = |i| line.chars().nth(3 + 2 * i as usize).unwrap();
|
||||
(get(0), get(1), get(2), get(3))
|
||||
})
|
||||
.collect();
|
||||
for line in lines.iter().rev() {
|
||||
out[0].push(line.0);
|
||||
out[1].push(line.1);
|
||||
|
@ -37,7 +35,7 @@ struct State {
|
|||
|
||||
impl State {
|
||||
fn make_key(&self) -> ([Vec<char>; 4], [char; 11]) {
|
||||
(self.rooms.clone(), self.hallway.clone())
|
||||
(self.rooms.clone(), self.hallway)
|
||||
}
|
||||
|
||||
fn check_room(&self, idx: usize) -> bool {
|
||||
|
@ -46,11 +44,11 @@ impl State {
|
|||
}
|
||||
|
||||
fn done(&self) -> bool {
|
||||
self.hallway.iter().all(|&x| x == '.') && (0..4).all(|i| { self.check_room(i) })
|
||||
self.hallway.iter().all(|&x| x == '.') && (0..4).all(|i| self.check_room(i))
|
||||
}
|
||||
|
||||
fn check_hallway(&self, start: usize, end: usize) -> bool {
|
||||
(start.min(end)..=end.max(start)).all(|i| { self.hallway[i] == '.' || i == start })
|
||||
(start.min(end)..=end.max(start)).all(|i| self.hallway[i] == '.' || i == start)
|
||||
}
|
||||
|
||||
fn add_cost(mut self, cost: u32) -> Self {
|
||||
|
@ -75,14 +73,21 @@ impl State {
|
|||
|
||||
fn generate_moves(&self, n: usize) -> Vec<State> {
|
||||
for (i, &c) in self.hallway.iter().enumerate() {
|
||||
if c == '.' { continue; }
|
||||
if c == '.' {
|
||||
continue;
|
||||
}
|
||||
|
||||
let dst = "ABCD".find(c).unwrap();
|
||||
if self.rooms[dst].iter().any(|&x| x != c) { continue; }
|
||||
if !self.check_hallway(i, 2 + 2 * dst) { continue; }
|
||||
if self.rooms[dst].iter().any(|&x| x != c) {
|
||||
continue;
|
||||
}
|
||||
if !self.check_hallway(i, 2 + 2 * dst) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let dist = i.abs_diff(2 + 2 * dst) + n - self.rooms[dst].len();
|
||||
return vec![self.clone()
|
||||
return vec![self
|
||||
.clone()
|
||||
.add_cost(dist as u32 * 10u32.pow(dst as u32))
|
||||
.push_room(dst, c)
|
||||
.set_hallway(i, '.')];
|
||||
|
@ -90,18 +95,24 @@ impl State {
|
|||
|
||||
let mut out = vec![];
|
||||
for i in 0..4 {
|
||||
if self.check_room(i) { continue; }
|
||||
if self.check_room(i) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let c = *self.rooms[i].last().unwrap();
|
||||
let src = 2 + 2 * i;
|
||||
let dst = "ABCD".find(c).unwrap();
|
||||
for j in [0, 1, 3, 5, 7, 9, 10] {
|
||||
if !self.check_hallway(src, j) {continue;}
|
||||
if !self.check_hallway(src, j) {
|
||||
continue;
|
||||
}
|
||||
let dist = (1 + n - self.rooms[i].len()) + src.abs_diff(j);
|
||||
out.push(self.clone()
|
||||
.add_cost(dist as u32 * 10u32.pow(dst as u32))
|
||||
.pop_room(i)
|
||||
.set_hallway(j, c))
|
||||
out.push(
|
||||
self.clone()
|
||||
.add_cost(dist as u32 * 10u32.pow(dst as u32))
|
||||
.pop_room(i)
|
||||
.set_hallway(j, c),
|
||||
)
|
||||
}
|
||||
}
|
||||
out
|
||||
|
@ -111,10 +122,10 @@ impl State {
|
|||
fn solve(input: &Input, part2: bool) -> u32 {
|
||||
let mut input = input.clone();
|
||||
if part2 {
|
||||
for i in 0..4 {
|
||||
(0..4).for_each(|i| {
|
||||
input[i].insert(1, "DBAC".chars().nth(i).unwrap());
|
||||
input[i].insert(2, "DCBA".chars().nth(i).unwrap());
|
||||
}
|
||||
});
|
||||
}
|
||||
let n = input[0].len();
|
||||
let mut queue = BinaryHeap::new();
|
||||
|
@ -128,10 +139,14 @@ fn solve(input: &Input, part2: bool) -> u32 {
|
|||
let state = queue.pop().unwrap().0;
|
||||
|
||||
let key = state.make_key();
|
||||
if visited.contains(&key) { continue; }
|
||||
if visited.contains(&key) {
|
||||
continue;
|
||||
}
|
||||
visited.insert(key);
|
||||
|
||||
if state.done() { return state.energy; }
|
||||
if state.done() {
|
||||
return state.energy;
|
||||
}
|
||||
|
||||
for next in state.generate_moves(n) {
|
||||
queue.push(Reverse(next));
|
||||
|
@ -148,25 +163,4 @@ fn part2(input: &Input) -> String {
|
|||
solve(input, true).to_string()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (part1, part2) = run();
|
||||
println!("Part 1: {}", part1);
|
||||
println!("Part 2: {}", part2);
|
||||
}
|
||||
|
||||
pub fn run() -> (String, String) {
|
||||
let input = get_input();
|
||||
(part1(&input), part2(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part1(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| part1(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part2(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| part2(&input))
|
||||
}
|
||||
aoc::main!(2021, 23, ex: 1);
|
|
@ -1,19 +1,22 @@
|
|||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use std::fs;
|
||||
use test::Bencher;
|
||||
|
||||
type Input = Vec<(i8, i8)>;
|
||||
|
||||
fn get_input() -> Input {
|
||||
let puzzle = fs::read_to_string("2021/24.txt").unwrap();
|
||||
let lines: Vec<String> = puzzle.lines().map(|line| line.to_string()).collect();
|
||||
(0..14).map(|i| {
|
||||
let get = |j: usize| lines[i * 18 + j].split(" ").nth(2).unwrap().parse().unwrap();
|
||||
(get(5), get(15))
|
||||
}).collect()
|
||||
fn setup(input: &str) -> Input {
|
||||
let lines: Vec<String> = input.lines().map(|line| line.to_string()).collect();
|
||||
(0..14)
|
||||
.map(|i| {
|
||||
let get = |j: usize| {
|
||||
lines[i * 18 + j]
|
||||
.split(' ')
|
||||
.nth(2)
|
||||
.unwrap()
|
||||
.parse()
|
||||
.unwrap()
|
||||
};
|
||||
(get(5), get(15))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
|
@ -54,25 +57,4 @@ fn part2(input: &Input) -> String {
|
|||
out.iter().map(|&x| (x + 0x30) as char).collect()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (part1, part2) = run();
|
||||
println!("Part 1: {}", part1);
|
||||
println!("Part 2: {}", part2);
|
||||
}
|
||||
|
||||
pub fn run() -> (String, String) {
|
||||
let input = get_input();
|
||||
(part1(&input), part2(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part1(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| part1(&input))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_part2(b: &mut Bencher) {
|
||||
let input = get_input();
|
||||
b.iter(|| part2(&input))
|
||||
}
|
||||
aoc::main!(2021, 24);
|
68
Rust/2021/25.rs
Normal file
68
Rust/2021/25.rs
Normal file
|
@ -0,0 +1,68 @@
|
|||
#![feature(test)]
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
enum Type {
|
||||
Empty,
|
||||
Right,
|
||||
Down,
|
||||
}
|
||||
|
||||
type Input = Vec<Vec<Type>>;
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
input
|
||||
.lines()
|
||||
.map(|line| {
|
||||
line.chars()
|
||||
.map(|c| match c {
|
||||
'v' => Type::Down,
|
||||
'>' => Type::Right,
|
||||
_ => Type::Empty,
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> String {
|
||||
let mut grid = input.clone();
|
||||
let mut cnt = 0;
|
||||
loop {
|
||||
let mut moved = false;
|
||||
let mut new_grid = grid.clone();
|
||||
for (i, line) in grid.iter().enumerate() {
|
||||
for (j, &c) in line.iter().enumerate() {
|
||||
if c == Type::Right {
|
||||
let k = (j + 1) % line.len();
|
||||
if grid[i][k] == Type::Empty {
|
||||
new_grid[i][k] = Type::Right;
|
||||
new_grid[i][j] = Type::Empty;
|
||||
moved = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
grid = new_grid;
|
||||
let mut new_grid = grid.clone();
|
||||
for (i, line) in grid.iter().enumerate() {
|
||||
for (j, &c) in line.iter().enumerate() {
|
||||
if c == Type::Down {
|
||||
let k = (i + 1) % grid.len();
|
||||
if grid[k][j] == Type::Empty {
|
||||
new_grid[k][j] = Type::Down;
|
||||
new_grid[i][j] = Type::Empty;
|
||||
moved = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
grid = new_grid;
|
||||
cnt += 1;
|
||||
if !moved {
|
||||
break;
|
||||
}
|
||||
}
|
||||
cnt.to_string()
|
||||
}
|
||||
|
||||
aoc::main!(2021, 25, ex: 1);
|
31
Rust/2022/01.rs
Normal file
31
Rust/2022/01.rs
Normal file
|
@ -0,0 +1,31 @@
|
|||
#![feature(test)]
|
||||
|
||||
use itertools::Itertools;
|
||||
|
||||
type Input = Vec<Vec<u32>>;
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
input
|
||||
.split("\n\n")
|
||||
.map(|block| {
|
||||
block
|
||||
.split_whitespace()
|
||||
.map(|num| num.parse().unwrap())
|
||||
.collect()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> u32 {
|
||||
input.iter().map(|block| block.iter().sum()).max().unwrap()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> u32 {
|
||||
-input
|
||||
.iter()
|
||||
.map(|block| -(block.iter().sum::<u32>() as i32))
|
||||
.k_smallest(3)
|
||||
.sum::<i32>() as u32
|
||||
}
|
||||
|
||||
aoc::main!(2022, 1, ex: 1);
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(test)]
|
||||
|
||||
type Input = Vec<(u32, u32)>;
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
|
@ -21,6 +23,4 @@ fn part2(input: &Input) -> u32 {
|
|||
input.iter().map(|(a, b)| (2 + a + b) % 3 + 1 + b * 3).sum()
|
||||
}
|
||||
|
||||
aoc::main!(2022, 2);
|
||||
aoc::example!(ex01, "02.1.txt", 15, 12);
|
||||
aoc::test_input!("02.txt", 10816, 11657);
|
||||
aoc::main!(2022, 2, ex: 1);
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(test)]
|
||||
|
||||
type Input<'a> = Vec<&'a [u8]>;
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
|
@ -36,6 +38,4 @@ fn part2(input: &Input) -> u32 {
|
|||
.sum()
|
||||
}
|
||||
|
||||
aoc::main!(2022, 3);
|
||||
aoc::example!(ex01, "03.1.txt", 157, 70);
|
||||
aoc::test_input!("03.txt", 7903, 2548);
|
||||
aoc::main!(2022, 3, ex: 1);
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(test)]
|
||||
|
||||
type Input = Vec<(u8, u8, u8, u8)>;
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
|
@ -21,6 +23,4 @@ fn part2(input: &Input) -> usize {
|
|||
input.iter().filter(|(a, b, c, d)| d >= a && c <= b).count()
|
||||
}
|
||||
|
||||
aoc::main!(2022, 4);
|
||||
aoc::example!(ex01, "04.1.txt", 2, 4);
|
||||
aoc::test_input!("04.txt", 453, 919);
|
||||
aoc::main!(2022, 4, ex: 1);
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(test)]
|
||||
|
||||
type Input = (Vec<String>, Vec<(usize, usize, usize)>);
|
||||
|
||||
pub fn solve((stacks, instructions): &Input, get_next: fn(usize, usize) -> usize) -> String {
|
||||
|
@ -63,6 +65,4 @@ fn part2(input: &Input) -> String {
|
|||
solve(input, |_, h| h)
|
||||
}
|
||||
|
||||
aoc::main!(2022, 5);
|
||||
aoc::example!(ex01, "05.1.txt", "CMZ", "MCD");
|
||||
aoc::test_input!("05.txt", "QMBMJDFTD", "NBTVTJNFJ");
|
||||
aoc::main!(2022, 5, ex: 1);
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(test)]
|
||||
|
||||
type Input = Vec<usize>;
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
|
@ -51,10 +53,4 @@ fn part2(input: &Input) -> usize {
|
|||
solve(input, 14)
|
||||
}
|
||||
|
||||
aoc::main!(2022, 6);
|
||||
aoc::example!(ex01, "06.1.txt", 7, 19);
|
||||
aoc::example!(ex02, "06.2.txt", 5, 23);
|
||||
aoc::example!(ex03, "06.3.txt", 6, 23);
|
||||
aoc::example!(ex04, "06.4.txt", 10, 29);
|
||||
aoc::example!(ex05, "06.5.txt", 11, 26);
|
||||
aoc::test_input!("06.txt", 1802, 3551);
|
||||
aoc::main!(2022, 6, ex: 1, 2, 3, 4, 5);
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(test)]
|
||||
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
type Input<'a> = Vec<Node<'a>>;
|
||||
|
@ -92,6 +94,4 @@ fn part2(nodes: &Input) -> u64 {
|
|||
.unwrap()
|
||||
}
|
||||
|
||||
aoc::main!(2022, 7);
|
||||
aoc::example!(ex01, "07.1.txt", 95437, 24933642);
|
||||
aoc::test_input!("07.txt", 1206825, 9608311);
|
||||
aoc::main!(2022, 7, ex: 1);
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(test)]
|
||||
|
||||
use aoc::{grid::Direction, iter_ext::IterExt};
|
||||
|
||||
type Input = Vec<Vec<u8>>;
|
||||
|
@ -75,6 +77,4 @@ fn part2(grid: &Input) -> usize {
|
|||
.unwrap()
|
||||
}
|
||||
|
||||
aoc::main!(2022, 8);
|
||||
aoc::example!(ex01, "08.1.txt", 21, 8);
|
||||
aoc::test_input!("08.txt", 1825, 235200);
|
||||
aoc::main!(2022, 8, ex: 1);
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(test)]
|
||||
|
||||
use aoc::grid::Direction;
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
|
@ -66,7 +68,4 @@ fn part2(input: &Input) -> usize {
|
|||
Solver::new(input, 10).solve()
|
||||
}
|
||||
|
||||
aoc::main!(2022, 9);
|
||||
aoc::example!(ex01, "09.1.txt", 13, 1);
|
||||
aoc::example!(ex02, "09.2.txt", 88, 36);
|
||||
aoc::test_input!("09.txt", 6030, 2545);
|
||||
aoc::main!(2022, 9, ex: 1, 2);
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(test)]
|
||||
|
||||
use aoc::parsing::parse_ascii;
|
||||
|
||||
type Input = Vec<Instruction>;
|
||||
|
@ -91,10 +93,6 @@ fn part2(input: &Input) -> String {
|
|||
parse_ascii(&dots.iter().map(|l| &l[..]).collect::<Vec<_>>())
|
||||
}
|
||||
|
||||
aoc::main!(2022, 10);
|
||||
aoc::example!(ex01, "10.1.txt", p1: 13140);
|
||||
aoc::test_input!("10.txt", 14820, "RZEKEFHA");
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_cpu {
|
||||
#[allow(unused_imports)]
|
||||
|
@ -125,3 +123,5 @@ mod test_cpu {
|
|||
[1, 1, 1, 3, 3, 6]
|
||||
);
|
||||
}
|
||||
|
||||
aoc::main!(2022, 10, ex: 1[a]);
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(test)]
|
||||
|
||||
use std::collections::hash_map::Entry;
|
||||
|
||||
use itertools::Itertools;
|
||||
|
@ -182,6 +184,4 @@ fn part2(input: &Input) -> u64 {
|
|||
Solver::new(input, 10000, false).solve()
|
||||
}
|
||||
|
||||
aoc::main!(2022, 11);
|
||||
aoc::example!(ex01, "11.1.txt", 10605, 2713310158);
|
||||
aoc::test_input!("11.txt", 54054, 14314925001);
|
||||
aoc::main!(2022, 11, ex: 1);
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(test)]
|
||||
|
||||
use std::collections::VecDeque;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
|
@ -100,6 +102,4 @@ fn part2(Input { end, grid, .. }: &Input) -> u32 {
|
|||
)
|
||||
}
|
||||
|
||||
aoc::main!(2022, 12);
|
||||
aoc::example!(ex01, "12.1.txt", 31, 29);
|
||||
aoc::test_input!("12.txt", 380, 375);
|
||||
aoc::main!(2022, 12, ex: 1);
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(test)]
|
||||
|
||||
use std::cmp::Ordering;
|
||||
|
||||
type Input = Vec<(Value, Value)>;
|
||||
|
@ -95,6 +97,4 @@ fn part2(input: &Input) -> usize {
|
|||
idx(&fst) * idx(&snd)
|
||||
}
|
||||
|
||||
aoc::main!(2022, 13);
|
||||
aoc::example!(ex01, "13.1.txt", 13, 140);
|
||||
aoc::test_input!("13.txt", 6046, 21423);
|
||||
aoc::main!(2022, 13, ex: 1);
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(test)]
|
||||
|
||||
use std::cmp::Ordering;
|
||||
|
||||
struct Input {
|
||||
|
@ -105,6 +107,4 @@ fn part2(input: &Input) -> usize {
|
|||
out
|
||||
}
|
||||
|
||||
aoc::main!(2022, 14);
|
||||
aoc::example!(ex01, "14.1.txt", 24, 93);
|
||||
aoc::test_input!("14.txt", 885, 28691);
|
||||
aoc::main!(2022, 14, ex: 1);
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(test)]
|
||||
|
||||
use std::ops::RangeInclusive;
|
||||
|
||||
use itertools::Itertools;
|
||||
|
@ -48,7 +50,9 @@ fn merge_ranges(ranges: &mut Vec<RangeInclusive<i64>>) {
|
|||
ranges.sort_unstable_by(|a, b| a.start().cmp(b.start()));
|
||||
let mut out = Vec::with_capacity(ranges.len());
|
||||
let mut it = ranges.iter();
|
||||
let Some(mut current) = it.next().cloned() else {return;};
|
||||
let Some(mut current) = it.next().cloned() else {
|
||||
return;
|
||||
};
|
||||
for range in it {
|
||||
if *range.start() > current.end() + 1 {
|
||||
out.push(current);
|
||||
|
@ -157,6 +161,4 @@ fn part2(input: &Input) -> i64 {
|
|||
x * 4000000 + y
|
||||
}
|
||||
|
||||
aoc::main!(2022, 15);
|
||||
aoc::example!(ex01, "15.1.txt", 26, 56000011);
|
||||
aoc::test_input!("15.txt", 5716881, 10852583132904);
|
||||
aoc::main!(2022, 15, ex: 1);
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(test)]
|
||||
|
||||
use regex::Regex;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
|
@ -141,6 +143,4 @@ fn part2(input: &Input) -> u32 {
|
|||
.unwrap()
|
||||
}
|
||||
|
||||
aoc::main!(2022, 16);
|
||||
aoc::example!(ex01, "16.1.txt", 1651, 1707);
|
||||
aoc::test_input!("16.txt", 1991, 2705);
|
||||
aoc::main!(2022, 16, ex: 1);
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(test)]
|
||||
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
||||
const SHAPES: &[Shape] = &[
|
||||
|
@ -189,6 +191,4 @@ fn part2(input: &Input) -> u64 {
|
|||
.unwrap()
|
||||
}
|
||||
|
||||
aoc::main!(2022, 17);
|
||||
aoc::example!(ex01, "17.1.txt", 3068, 1514285714288);
|
||||
aoc::test_input!("17.txt", 3168, 1554117647070);
|
||||
aoc::main!(2022, 17, ex: 1);
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(test)]
|
||||
|
||||
use std::collections::VecDeque;
|
||||
|
||||
use itertools::Itertools;
|
||||
|
@ -106,6 +108,4 @@ fn part2(input: &Input) -> usize {
|
|||
out
|
||||
}
|
||||
|
||||
aoc::main!(2022, 18);
|
||||
aoc::example!(ex01, "18.1.txt", 64, 58);
|
||||
aoc::test_input!("18.txt", 4244, 2460);
|
||||
aoc::main!(2022, 18, ex: 1);
|
177
Rust/Cargo.lock
generated
Normal file
177
Rust/Cargo.lock
generated
Normal file
|
@ -0,0 +1,177 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aoc"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"counter",
|
||||
"itertools",
|
||||
"num",
|
||||
"paste",
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "counter"
|
||||
version = "0.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d458e66999348f56fd3ffcfbb7f7951542075ca8359687c703de6500c1ddccd"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-bigint",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
178
Rust/Cargo.toml
Normal file
178
Rust/Cargo.toml
Normal file
|
@ -0,0 +1,178 @@
|
|||
[package]
|
||||
name = "aoc"
|
||||
version = "0.0.0"
|
||||
edition = "2021"
|
||||
|
||||
[profile.dev]
|
||||
opt-level = 3
|
||||
|
||||
[profile.release]
|
||||
opt-level = 3
|
||||
debug = false
|
||||
strip = true
|
||||
debug-assertions = false
|
||||
overflow-checks = false
|
||||
lto = true
|
||||
panic = "abort"
|
||||
incremental = false
|
||||
codegen-units = 1
|
||||
rpath = false
|
||||
|
||||
[dependencies]
|
||||
counter = "0.5.7"
|
||||
itertools = "0.11.0"
|
||||
num = "0.4.1"
|
||||
paste = "1.0.14"
|
||||
regex = "1.10.2"
|
||||
rustc-hash = "1.1.0"
|
||||
|
||||
[lib]
|
||||
name = "aoc"
|
||||
path = "lib/lib.rs"
|
||||
|
||||
# 2020
|
||||
[[bin]]
|
||||
name = "2020_01"
|
||||
path = "2020/01.rs"
|
||||
[[bin]]
|
||||
name = "2020_02"
|
||||
path = "2020/02.rs"
|
||||
[[bin]]
|
||||
name = "2020_03"
|
||||
path = "2020/03.rs"
|
||||
[[bin]]
|
||||
name = "2020_04"
|
||||
path = "2020/04.rs"
|
||||
|
||||
# 2021
|
||||
[[bin]]
|
||||
name = "2021_01"
|
||||
path = "2021/01.rs"
|
||||
[[bin]]
|
||||
name = "2021_02"
|
||||
path = "2021/02.rs"
|
||||
[[bin]]
|
||||
name = "2021_03"
|
||||
path = "2021/03.rs"
|
||||
[[bin]]
|
||||
name = "2021_04"
|
||||
path = "2021/04.rs"
|
||||
[[bin]]
|
||||
name = "2021_05"
|
||||
path = "2021/05.rs"
|
||||
[[bin]]
|
||||
name = "2021_06"
|
||||
path = "2021/06.rs"
|
||||
[[bin]]
|
||||
name = "2021_07"
|
||||
path = "2021/07.rs"
|
||||
[[bin]]
|
||||
name = "2021_08"
|
||||
path = "2021/08.rs"
|
||||
[[bin]]
|
||||
name = "2021_09"
|
||||
path = "2021/09.rs"
|
||||
[[bin]]
|
||||
name = "2021_10"
|
||||
path = "2021/10.rs"
|
||||
[[bin]]
|
||||
name = "2021_11"
|
||||
path = "2021/11.rs"
|
||||
[[bin]]
|
||||
name = "2021_12"
|
||||
path = "2021/12.rs"
|
||||
[[bin]]
|
||||
name = "2021_13"
|
||||
path = "2021/13.rs"
|
||||
[[bin]]
|
||||
name = "2021_14"
|
||||
path = "2021/14.rs"
|
||||
[[bin]]
|
||||
name = "2021_15"
|
||||
path = "2021/15.rs"
|
||||
[[bin]]
|
||||
name = "2021_16"
|
||||
path = "2021/16.rs"
|
||||
[[bin]]
|
||||
name = "2021_17"
|
||||
path = "2021/17.rs"
|
||||
[[bin]]
|
||||
name = "2021_18"
|
||||
path = "2021/18.rs"
|
||||
[[bin]]
|
||||
name = "2021_19"
|
||||
path = "2021/19.rs"
|
||||
[[bin]]
|
||||
name = "2021_20"
|
||||
path = "2021/20.rs"
|
||||
[[bin]]
|
||||
name = "2021_21"
|
||||
path = "2021/21.rs"
|
||||
[[bin]]
|
||||
name = "2021_22"
|
||||
path = "2021/22.rs"
|
||||
[[bin]]
|
||||
name = "2021_23"
|
||||
path = "2021/23.rs"
|
||||
[[bin]]
|
||||
name = "2021_24"
|
||||
path = "2021/24.rs"
|
||||
[[bin]]
|
||||
name = "2021_25"
|
||||
path = "2021/25.rs"
|
||||
|
||||
# 2022
|
||||
[[bin]]
|
||||
name = "2022_01"
|
||||
path = "2022/01.rs"
|
||||
[[bin]]
|
||||
name = "2022_02"
|
||||
path = "2022/02.rs"
|
||||
[[bin]]
|
||||
name = "2022_03"
|
||||
path = "2022/03.rs"
|
||||
[[bin]]
|
||||
name = "2022_04"
|
||||
path = "2022/04.rs"
|
||||
[[bin]]
|
||||
name = "2022_05"
|
||||
path = "2022/05.rs"
|
||||
[[bin]]
|
||||
name = "2022_06"
|
||||
path = "2022/06.rs"
|
||||
[[bin]]
|
||||
name = "2022_07"
|
||||
path = "2022/07.rs"
|
||||
[[bin]]
|
||||
name = "2022_08"
|
||||
path = "2022/08.rs"
|
||||
[[bin]]
|
||||
name = "2022_09"
|
||||
path = "2022/09.rs"
|
||||
[[bin]]
|
||||
name = "2022_10"
|
||||
path = "2022/10.rs"
|
||||
[[bin]]
|
||||
name = "2022_11"
|
||||
path = "2022/11.rs"
|
||||
[[bin]]
|
||||
name = "2022_12"
|
||||
path = "2022/12.rs"
|
||||
[[bin]]
|
||||
name = "2022_13"
|
||||
path = "2022/13.rs"
|
||||
[[bin]]
|
||||
name = "2022_14"
|
||||
path = "2022/14.rs"
|
||||
[[bin]]
|
||||
name = "2022_15"
|
||||
path = "2022/15.rs"
|
||||
[[bin]]
|
||||
name = "2022_16"
|
||||
path = "2022/16.rs"
|
||||
[[bin]]
|
||||
name = "2022_17"
|
||||
path = "2022/17.rs"
|
||||
[[bin]]
|
||||
name = "2022_18"
|
||||
path = "2022/18.rs"
|
|
@ -75,7 +75,7 @@ mod tests_take_while_inclusive {
|
|||
};
|
||||
}
|
||||
|
||||
test!(split, vec![1, 2, 3, 4], |x| x < 3, vec![1, 2, 3]);
|
||||
test!(always_true, vec![1, 2, 3, 4], |_| true, vec![1, 2, 3, 4]);
|
||||
test!(always_false, vec![1, 2, 3, 4], |_| false, vec![1]);
|
||||
test!(split, [1, 2, 3, 4], |x| x < 3, vec![1, 2, 3]);
|
||||
test!(always_true, [1, 2, 3, 4], |_| true, vec![1, 2, 3, 4]);
|
||||
test!(always_false, [1, 2, 3, 4], |_| false, vec![1]);
|
||||
}
|
108
Rust/lib/lib.rs
Normal file
108
Rust/lib/lib.rs
Normal file
|
@ -0,0 +1,108 @@
|
|||
#![feature(test)]
|
||||
|
||||
#[doc(hidden)]
|
||||
pub use test::Bencher;
|
||||
|
||||
pub mod grid;
|
||||
pub mod iter_ext;
|
||||
pub mod parsing;
|
||||
|
||||
extern crate test;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! main {
|
||||
($year:literal, $day:tt $(, ex: $($example:literal $([$expart:ident])?),*)?) => {
|
||||
::aoc::__main!($year, $day);
|
||||
::aoc::__setup!(_input, ::std::concat!("../../.cache/", $year, "/", $day));
|
||||
::aoc::__inp!($day, _input, ::std::concat!("../../.cache/", $year, "/", $day));
|
||||
$($(
|
||||
::paste::paste! {
|
||||
::aoc::__setup!([< _ex $example >], ::std::concat!("../../examples/", $year, "/", $day, "/", $example));
|
||||
::aoc::__inp!($day, [< _ex $example >], ::std::concat!("../../examples/", $year, "/", $day, "/", $example) $(, $expart)?);
|
||||
}
|
||||
)*)?
|
||||
};
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! __ifnot25 {
|
||||
(25, $($tt:tt)*) => {};
|
||||
($x:tt, $($tt:tt)*) => {
|
||||
$($tt)*
|
||||
};
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! __main {
|
||||
($year:literal, $day:tt) => {
|
||||
fn main() {
|
||||
let path = ::std::concat!("../.cache/", $year, "/", $day);
|
||||
let input = ::std::fs::read_to_string(path).unwrap();
|
||||
let input = setup(&input);
|
||||
::std::println!("{}", part1(&input));
|
||||
::aoc::__ifnot25! { $day,
|
||||
::std::println!("{}", part2(&input));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! __setup {
|
||||
($ident:expr, $in:expr) => {
|
||||
::paste::paste! {
|
||||
#[cfg(test)]
|
||||
#[bench]
|
||||
fn [< bench $ident _setup >](b: &mut ::aoc::Bencher) {
|
||||
let input = ::std::include_str!($in);
|
||||
b.iter(|| setup(input));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! __inp {
|
||||
($day:tt, $ident:expr, $in:expr) => {
|
||||
::aoc::__inp!($day, $ident, $in, 1);
|
||||
::aoc::__ifnot25! { $day,
|
||||
::aoc::__inp!($day, $ident, $in, 2);
|
||||
}
|
||||
};
|
||||
($day:tt, $ident:expr, $in:expr) => {
|
||||
::aoc::__inp!($day, $ident, $in, 1);
|
||||
::aoc::__inp!($day, $ident, $in, 2);
|
||||
};
|
||||
($day:tt, $ident:expr, $in:expr, a) => {
|
||||
::aoc::__inp!($day, $ident, $in, 1);
|
||||
};
|
||||
($day:tt, $ident:expr, $in:expr, b) => {
|
||||
::aoc::__inp!($day, $ident, $in, 2);
|
||||
};
|
||||
($day:tt, $ident:expr, $in:expr, $part:expr) => {
|
||||
::paste::paste! {
|
||||
#[cfg(test)]
|
||||
#[test]
|
||||
fn [< test $ident _part $part >]() {
|
||||
let input = setup(::std::include_str!($in));
|
||||
let out = [< part $part >](&input);
|
||||
assert_eq!(
|
||||
out.to_string().trim(),
|
||||
include_str!(::std::concat!($in, ".", $part)).trim()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
#[bench]
|
||||
fn [< bench $ident _part $part >](b: &mut ::aoc::Bencher) {
|
||||
let input = setup(::std::include_str!($in));
|
||||
b.iter(|| [< part $part >](&input));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
6
examples/2020/1/1
Normal file
6
examples/2020/1/1
Normal file
|
@ -0,0 +1,6 @@
|
|||
1721
|
||||
979
|
||||
366
|
||||
299
|
||||
675
|
||||
1456
|
1
examples/2020/1/1.1
Normal file
1
examples/2020/1/1.1
Normal file
|
@ -0,0 +1 @@
|
|||
514579
|
1
examples/2020/1/1.2
Normal file
1
examples/2020/1/1.2
Normal file
|
@ -0,0 +1 @@
|
|||
241861950
|
3
examples/2020/2/1
Normal file
3
examples/2020/2/1
Normal file
|
@ -0,0 +1,3 @@
|
|||
1-3 a: abcde
|
||||
1-3 b: cdefg
|
||||
2-9 c: ccccccccc
|
1
examples/2020/2/1.1
Normal file
1
examples/2020/2/1.1
Normal file
|
@ -0,0 +1 @@
|
|||
2
|
1
examples/2020/2/1.2
Normal file
1
examples/2020/2/1.2
Normal file
|
@ -0,0 +1 @@
|
|||
1
|
11
examples/2020/3/1
Normal file
11
examples/2020/3/1
Normal file
|
@ -0,0 +1,11 @@
|
|||
..##.......
|
||||
#...#...#..
|
||||
.#....#..#.
|
||||
..#.#...#.#
|
||||
.#...##..#.
|
||||
..#.##.....
|
||||
.#.#.#....#
|
||||
.#........#
|
||||
#.##...#...
|
||||
#...##....#
|
||||
.#..#...#.#
|
1
examples/2020/3/1.1
Normal file
1
examples/2020/3/1.1
Normal file
|
@ -0,0 +1 @@
|
|||
7
|
1
examples/2020/3/1.2
Normal file
1
examples/2020/3/1.2
Normal file
|
@ -0,0 +1 @@
|
|||
336
|
13
examples/2020/4/1
Normal file
13
examples/2020/4/1
Normal file
|
@ -0,0 +1,13 @@
|
|||
ecl:gry pid:860033327 eyr:2020 hcl:#fffffd
|
||||
byr:1937 iyr:2017 cid:147 hgt:183cm
|
||||
|
||||
iyr:2013 ecl:amb cid:350 eyr:2023 pid:028048884
|
||||
hcl:#cfa07d byr:1929
|
||||
|
||||
hcl:#ae17e1 iyr:2013
|
||||
eyr:2024
|
||||
ecl:brn pid:760753108 byr:1931
|
||||
hgt:179cm
|
||||
|
||||
hcl:#cfa07d eyr:2025 pid:166559648
|
||||
iyr:2011 ecl:brn hgt:59in
|
1
examples/2020/4/1.1
Normal file
1
examples/2020/4/1.1
Normal file
|
@ -0,0 +1 @@
|
|||
2
|
10
examples/2021/1/1
Normal file
10
examples/2021/1/1
Normal file
|
@ -0,0 +1,10 @@
|
|||
199
|
||||
200
|
||||
208
|
||||
210
|
||||
200
|
||||
207
|
||||
240
|
||||
269
|
||||
260
|
||||
263
|
1
examples/2021/1/1.1
Normal file
1
examples/2021/1/1.1
Normal file
|
@ -0,0 +1 @@
|
|||
7
|
1
examples/2021/1/1.2
Normal file
1
examples/2021/1/1.2
Normal file
|
@ -0,0 +1 @@
|
|||
5
|
10
examples/2021/10/1
Normal file
10
examples/2021/10/1
Normal file
|
@ -0,0 +1,10 @@
|
|||
[({(<(())[]>[[{[]{<()<>>
|
||||
[(()[<>])]({[<{<<[]>>(
|
||||
{([(<{}[<>[]}>{[]{[(<()>
|
||||
(((({<>}<{<{<>}{[]{[]{}
|
||||
[[<[([]))<([[{}[[()]]]
|
||||
[{[{({}]{}}([{[{{{}}([]
|
||||
{<[[]]>}<{[{[{[]{()[[[]
|
||||
[<(<(<(<{}))><([]([]()
|
||||
<{([([[(<>()){}]>(<<{{
|
||||
<{([{{}}[<[[[<>{}]]]>[]]
|
1
examples/2021/10/1.1
Normal file
1
examples/2021/10/1.1
Normal file
|
@ -0,0 +1 @@
|
|||
26397
|
1
examples/2021/10/1.2
Normal file
1
examples/2021/10/1.2
Normal file
|
@ -0,0 +1 @@
|
|||
288957
|
10
examples/2021/11/1
Normal file
10
examples/2021/11/1
Normal file
|
@ -0,0 +1,10 @@
|
|||
5483143223
|
||||
2745854711
|
||||
5264556173
|
||||
6141336146
|
||||
6357385478
|
||||
4167524645
|
||||
2176841721
|
||||
6882881134
|
||||
4846848554
|
||||
5283751526
|
1
examples/2021/11/1.1
Normal file
1
examples/2021/11/1.1
Normal file
|
@ -0,0 +1 @@
|
|||
1656
|
1
examples/2021/11/1.2
Normal file
1
examples/2021/11/1.2
Normal file
|
@ -0,0 +1 @@
|
|||
195
|
7
examples/2021/12/1
Normal file
7
examples/2021/12/1
Normal file
|
@ -0,0 +1,7 @@
|
|||
start-A
|
||||
start-b
|
||||
A-c
|
||||
A-b
|
||||
b-d
|
||||
A-end
|
||||
b-end
|
1
examples/2021/12/1.1
Normal file
1
examples/2021/12/1.1
Normal file
|
@ -0,0 +1 @@
|
|||
10
|
1
examples/2021/12/1.2
Normal file
1
examples/2021/12/1.2
Normal file
|
@ -0,0 +1 @@
|
|||
36
|
10
examples/2021/12/2
Normal file
10
examples/2021/12/2
Normal file
|
@ -0,0 +1,10 @@
|
|||
dc-end
|
||||
HN-start
|
||||
start-kj
|
||||
dc-start
|
||||
dc-HN
|
||||
LN-dc
|
||||
HN-end
|
||||
kj-sa
|
||||
kj-HN
|
||||
kj-dc
|
1
examples/2021/12/2.1
Normal file
1
examples/2021/12/2.1
Normal file
|
@ -0,0 +1 @@
|
|||
19
|
1
examples/2021/12/2.2
Normal file
1
examples/2021/12/2.2
Normal file
|
@ -0,0 +1 @@
|
|||
103
|
18
examples/2021/12/3
Normal file
18
examples/2021/12/3
Normal file
|
@ -0,0 +1,18 @@
|
|||
fs-end
|
||||
he-DX
|
||||
fs-he
|
||||
start-DX
|
||||
pj-DX
|
||||
end-zg
|
||||
zg-sl
|
||||
zg-pj
|
||||
pj-he
|
||||
RW-he
|
||||
fs-DX
|
||||
pj-RW
|
||||
zg-RW
|
||||
start-pj
|
||||
he-WI
|
||||
zg-he
|
||||
pj-fs
|
||||
start-RW
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue