initial commit and solutions
This commit is contained in:
commit
81dbdcb25a
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
/target
|
||||||
|
/Cargo.lock
|
||||||
|
/data
|
8
Cargo.toml
Normal file
8
Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "aoc-rust"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
58
src/lib.rs
Normal file
58
src/lib.rs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#![allow(unused)]
|
||||||
|
mod year2022;
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! solve1 {
|
||||||
|
($test:expr) => {
|
||||||
|
#[test]
|
||||||
|
fn sample_part1() {
|
||||||
|
let result = solve1(SAMPLE_INPUT);
|
||||||
|
println!("{result}");
|
||||||
|
assert_eq!(result, $test);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
($test:expr, $solution:expr) => {
|
||||||
|
#[test]
|
||||||
|
fn sample_part1() {
|
||||||
|
let result = solve1(SAMPLE_INPUT);
|
||||||
|
println!("{result}");
|
||||||
|
assert_eq!(result, $test);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn real_part1() {
|
||||||
|
let now = std::time::SystemTime::now();
|
||||||
|
let result = solve1(INPUT);
|
||||||
|
println!("{:?}", now.elapsed().unwrap());
|
||||||
|
println!("{result}");
|
||||||
|
assert_eq!(result, $solution);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! solve2 {
|
||||||
|
($test:expr) => {
|
||||||
|
#[test]
|
||||||
|
fn sample_part2() {
|
||||||
|
let result = solve2(SAMPLE_INPUT);
|
||||||
|
println!("{result}");
|
||||||
|
assert_eq!(result, $test);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
($test:expr, $solution:expr) => {
|
||||||
|
#[test]
|
||||||
|
fn sample_part2() {
|
||||||
|
let result = solve2(SAMPLE_INPUT);
|
||||||
|
println!("{result}");
|
||||||
|
assert_eq!(result, $test);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn real_part2() {
|
||||||
|
let now = std::time::SystemTime::now();
|
||||||
|
let result = solve2(INPUT);
|
||||||
|
println!("{:?}", now.elapsed().unwrap());
|
||||||
|
println!("{result}");
|
||||||
|
assert_eq!(result, $solution);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
25
src/year2022/day01.rs
Normal file
25
src/year2022/day01.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
use crate::{solve1, solve2};
|
||||||
|
static INPUT: &str = include_str!("../../data/year2022/day01.txt");
|
||||||
|
static SAMPLE_INPUT: &str = include_str!("../../data/year2022/day01_test.txt");
|
||||||
|
|
||||||
|
fn calories_per_elf(input: &str) -> impl Iterator<Item = i64> + '_ {
|
||||||
|
input.split("\r\n\r\n").map(|group| {
|
||||||
|
group
|
||||||
|
.split("\r\n")
|
||||||
|
.map(|num| num.parse::<i64>().unwrap())
|
||||||
|
.sum::<i64>()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve1(input: &str) -> i64 {
|
||||||
|
calories_per_elf(input).max().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve2(input: &str) -> i64 {
|
||||||
|
let mut cals: Vec<i64> = calories_per_elf(input).collect();
|
||||||
|
cals.sort();
|
||||||
|
cals.iter().rev().take(3).sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
solve1!(24000, 71506);
|
||||||
|
solve2!(45000, 209603);
|
65
src/year2022/day02.rs
Normal file
65
src/year2022/day02.rs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
use crate::{solve1, solve2};
|
||||||
|
static INPUT: &str = include_str!("../../data/year2022/day02.txt");
|
||||||
|
static SAMPLE_INPUT: &str = include_str!("../../data/year2022/day02_test.txt");
|
||||||
|
|
||||||
|
fn win(input: &str) -> i64 {
|
||||||
|
match input {
|
||||||
|
"A X" => 3,
|
||||||
|
"A Y" => 6,
|
||||||
|
"A Z" => 0,
|
||||||
|
"B X" => 0,
|
||||||
|
"B Y" => 3,
|
||||||
|
"B Z" => 6,
|
||||||
|
"C X" => 6,
|
||||||
|
"C Y" => 0,
|
||||||
|
"C Z" => 3,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn play(input: &str) -> char {
|
||||||
|
match input {
|
||||||
|
"A X" => 'Z',
|
||||||
|
"A Y" => 'X',
|
||||||
|
"A Z" => 'Y',
|
||||||
|
"B X" => 'X',
|
||||||
|
"B Y" => 'Y',
|
||||||
|
"B Z" => 'Z',
|
||||||
|
"C X" => 'Y',
|
||||||
|
"C Y" => 'Z',
|
||||||
|
"C Z" => 'X',
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn score(input: char) -> i64 {
|
||||||
|
match input {
|
||||||
|
'X' => 1,
|
||||||
|
'Y' => 2,
|
||||||
|
'Z' => 3,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve1(input: &str) -> i64 {
|
||||||
|
input
|
||||||
|
.lines()
|
||||||
|
.map(|line| win(line) + score(line.chars().last().unwrap()))
|
||||||
|
.sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve2(input: &str) -> i64 {
|
||||||
|
input
|
||||||
|
.lines()
|
||||||
|
.map(|line| {
|
||||||
|
let mut out = String::with_capacity(3);
|
||||||
|
out.push_str(&line[0..2]);
|
||||||
|
out.push(play(line));
|
||||||
|
out
|
||||||
|
})
|
||||||
|
.map(|line| win(&line) + score(line.chars().last().unwrap()))
|
||||||
|
.sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
solve1!(15, 11475);
|
||||||
|
solve2!(12, 16862);
|
48
src/year2022/day03.rs
Normal file
48
src/year2022/day03.rs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
use crate::{solve1, solve2};
|
||||||
|
static INPUT: &str = include_str!("../../data/year2022/day03.txt");
|
||||||
|
static SAMPLE_INPUT: &str = include_str!("../../data/year2022/day03_test.txt");
|
||||||
|
|
||||||
|
const fn prio(c: char) -> i64 {
|
||||||
|
match c {
|
||||||
|
'a'..='z' => c as i64 - 96,
|
||||||
|
'A'..='Z' => c as i64 - 64 + 26,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve1(input: &str) -> i64 {
|
||||||
|
input
|
||||||
|
.lines()
|
||||||
|
.map(|line| {
|
||||||
|
let (left, right) = line.split_at(line.len() / 2);
|
||||||
|
let set: Vec<char> = left.chars().collect();
|
||||||
|
let dup = right
|
||||||
|
.chars()
|
||||||
|
.find(|c| set.contains(c))
|
||||||
|
.expect("char has no duplicate");
|
||||||
|
prio(dup)
|
||||||
|
})
|
||||||
|
.sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve2(input: &str) -> i64 {
|
||||||
|
let mut lines = input.lines();
|
||||||
|
let mut sum = 0;
|
||||||
|
while let Some(first) = lines.next() {
|
||||||
|
let second = lines.next().expect("No second rucksack");
|
||||||
|
let third = lines.next().expect("No third rucksack");
|
||||||
|
let set1: Vec<char> = first.chars().collect();
|
||||||
|
let set2: Vec<char> = second.chars().collect();
|
||||||
|
let dup = third
|
||||||
|
.chars()
|
||||||
|
.find(|c| set1.contains(c) && set2.contains(c))
|
||||||
|
.expect("No dupes");
|
||||||
|
sum += prio(dup)
|
||||||
|
}
|
||||||
|
sum
|
||||||
|
}
|
||||||
|
|
||||||
|
solve1!(157, 8298);
|
||||||
|
solve2!(70, 2708);
|
74
src/year2022/day04.rs
Normal file
74
src/year2022/day04.rs
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
use crate::{solve1, solve2};
|
||||||
|
static INPUT: &str = include_str!("../../data/year2022/day04.txt");
|
||||||
|
static SAMPLE_INPUT: &str = include_str!("../../data/year2022/day04_test.txt");
|
||||||
|
|
||||||
|
struct AssignmentPair {
|
||||||
|
l1: i64,
|
||||||
|
l2: i64,
|
||||||
|
r1: i64,
|
||||||
|
r2: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AssignmentPair {
|
||||||
|
fn fully_contained(self) -> Option<()> {
|
||||||
|
if (self.l1 <= self.r1 && self.l2 >= self.r2) || (self.r1 <= self.l1 && self.r2 >= self.l2)
|
||||||
|
{
|
||||||
|
return Some(());
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn overlap(self) -> Option<()> {
|
||||||
|
if self.l1 >= self.r1 && self.l1 <= self.r2
|
||||||
|
|| self.l2 >= self.r1 && self.l2 <= self.r2
|
||||||
|
|| self.r1 >= self.l1 && self.r1 <= self.l2
|
||||||
|
|| self.r2 >= self.l1 && self.r2 <= self.l2
|
||||||
|
{
|
||||||
|
return Some(());
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_input(line: &str) -> AssignmentPair {
|
||||||
|
let mut split = line.split(',');
|
||||||
|
let (left, right) = (
|
||||||
|
split.next().expect("No left side"),
|
||||||
|
split.next().expect("No right side"),
|
||||||
|
);
|
||||||
|
let mut left_split = left.split('-');
|
||||||
|
let mut right_split = right.split('-');
|
||||||
|
let (l1, l2) = (
|
||||||
|
left_split.next().expect("No left side"),
|
||||||
|
left_split.next().expect("No right side"),
|
||||||
|
);
|
||||||
|
let (r1, r2) = (
|
||||||
|
right_split.next().expect("No left side"),
|
||||||
|
right_split.next().expect("No right side"),
|
||||||
|
);
|
||||||
|
AssignmentPair {
|
||||||
|
l1: l1.parse().expect("Not a number"),
|
||||||
|
l2: l2.parse().expect("Not a number"),
|
||||||
|
r1: r1.parse().expect("Not a number"),
|
||||||
|
r2: r2.parse().expect("Not a number"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve1(input: &str) -> i64 {
|
||||||
|
input
|
||||||
|
.lines()
|
||||||
|
.map(parse_input)
|
||||||
|
.filter_map(AssignmentPair::fully_contained)
|
||||||
|
.count() as i64
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve2(input: &str) -> i64 {
|
||||||
|
input
|
||||||
|
.lines()
|
||||||
|
.map(parse_input)
|
||||||
|
.filter_map(AssignmentPair::overlap)
|
||||||
|
.count() as i64
|
||||||
|
}
|
||||||
|
|
||||||
|
solve1!(2, 547);
|
||||||
|
solve2!(4, 843);
|
4
src/year2022/mod.rs
Normal file
4
src/year2022/mod.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
mod day01;
|
||||||
|
mod day02;
|
||||||
|
mod day03;
|
||||||
|
mod day04;
|
Loading…
x
Reference in New Issue
Block a user