This commit is contained in:
Smaug123
2021-12-02 08:46:46 +00:00
parent 4c5150940e
commit 46a193631d
7 changed files with 1227 additions and 0 deletions

View File

@@ -1,4 +1,5 @@
[workspace]
members = [
"day_1",
"day_2",
]

15
day_2/Cargo.toml Normal file
View File

@@ -0,0 +1,15 @@
[package]
name = "day_2"
version = "0.1.0"
authors = ["Smaug123 <patrick+github@patrickstevens.co.uk>"]
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
[dev-dependencies]
criterion = "0.3"
[[bench]]
name = "day_2"
harness = false

19
day_2/benches/day_2.rs Normal file
View File

@@ -0,0 +1,19 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use day_2::day_2::{input, part_1, part_2};
fn criterion_benchmark(c: &mut Criterion) {
let input = input();
c.bench_function("day 2 part 1", |b| {
b.iter(|| {
black_box(part_1(&input));
})
});
c.bench_function("day 2 part 2", |b| {
b.iter(|| {
black_box(part_2(&input));
})
});
}
criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);

5
day_2/day_1.m Normal file
View File

@@ -0,0 +1,5 @@
ints = ReadList[StringJoin[NotebookDirectory[], "/input.txt"], "Number"];
part1 = Tr@Clip[Differences@#, {0, 1}] &;
part2 = Tr@Boole[Less @@@ Partition[#, 4, 1][[All, {1, 4}]]] &;

1000
day_2/input.txt Normal file

File diff suppressed because it is too large Load Diff

180
day_2/src/lib.rs Normal file
View File

@@ -0,0 +1,180 @@
pub mod day_2 {
pub enum Direction {
Forward,
Down,
Up,
}
pub struct Movement {
direction: Direction,
distance: u32,
}
fn chomp<I>(input: &mut I, s: &str)
where
I: Iterator<Item = char>,
{
for expected in s.chars() {
if input.next() != Some(expected) {
panic!("Unexpected character");
}
}
}
fn parse_int<I>(input: &mut I) -> u32
where
I: Iterator<Item = char>,
{
let mut answer = 0;
for c in input {
answer = answer * 10 + char::to_digit(c, 10).unwrap();
}
answer
}
pub fn parse_movement(s: &str) -> Movement {
let mut iter = s.chars();
let direction = match iter.next() {
None => {
panic!("Expected a nonempty string");
}
Some('f') => {
chomp(&mut iter, "orward ");
Direction::Forward
}
Some('u') => {
chomp(&mut iter, "p ");
Direction::Up
}
Some('d') => {
chomp(&mut iter, "own ");
Direction::Down
}
Some(c) => {
panic!("Unknown character: {}", c);
}
};
Movement {
direction,
distance: parse_int(&mut iter),
}
}
pub fn input() -> Vec<Movement> {
let input = include_str!("../input.txt");
input
.trim()
.split('\n')
.map(parse_movement)
.collect::<Vec<Movement>>()
}
pub struct Position {
x: u32,
y: u32,
}
fn step(position: Position, movement: &Movement) -> Position {
match movement.direction {
Direction::Forward => Position {
x: position.x + movement.distance,
y: position.y,
},
Direction::Up => Position {
x: position.x,
y: position.y - movement.distance,
},
Direction::Down => Position {
x: position.x,
y: position.y + movement.distance,
},
}
}
pub fn part_1(movements: &[Movement]) -> u32 {
let start_pos = Position { x: 0, y: 0 };
let final_pos = movements.iter().fold(start_pos, |pos, dir| step(pos, dir));
final_pos.x * final_pos.y
}
pub struct Position2 {
x: u32,
depth: u32,
aim: u32,
}
fn step_2(position: Position2, movement: &Movement) -> Position2 {
match movement.direction {
Direction::Forward => Position2 {
aim: position.aim,
x: position.x + movement.distance,
depth: position.depth + movement.distance * position.aim,
},
Direction::Up => Position2 {
x: position.x,
depth: position.depth,
aim: position.aim - movement.distance,
},
Direction::Down => Position2 {
x: position.x,
depth: position.depth,
aim: position.aim + movement.distance,
},
}
}
pub fn part_2(movements: &[Movement]) -> u32 {
let start_pos = Position2 {
x: 0,
depth: 0,
aim: 0,
};
let final_pos = movements
.iter()
.fold(start_pos, |pos, dir| step_2(pos, dir));
final_pos.x * final_pos.depth
}
}
#[cfg(test)]
mod tests {
use super::day_2::*;
#[test]
fn part1_known() {
let input = [
"forward 5",
"down 5",
"forward 8",
"up 3",
"down 8",
"forward 2",
]
.map(parse_movement);
assert_eq!(part_1(&input), 150);
}
#[test]
fn part2_known() {
let input = [
"forward 5",
"down 5",
"forward 8",
"up 3",
"down 8",
"forward 2",
]
.map(parse_movement);
println!("{}", part_2(&input));
assert_eq!(part_2(&input), 900);
}
#[test]
fn test_day_2() {
let input = input();
assert_eq!(part_1(&input), 1451208);
assert_eq!(part_2(&input), 1620141160);
}
}

7
day_2/src/main.rs Normal file
View File

@@ -0,0 +1,7 @@
use day_2::day_2;
fn main() {
let input = day_2::input();
println!("part 1 => {}", day_2::part_1(&input));
println!("part 2 => {}", day_2::part_2(&input));
}