mirror of
https://github.com/Smaug123/advent-of-code-2021
synced 2025-10-07 04:58:40 +00:00
Day 2
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
[workspace]
|
||||
members = [
|
||||
"day_1",
|
||||
"day_2",
|
||||
]
|
||||
|
15
day_2/Cargo.toml
Normal file
15
day_2/Cargo.toml
Normal 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
19
day_2/benches/day_2.rs
Normal 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
5
day_2/day_1.m
Normal 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
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
180
day_2/src/lib.rs
Normal 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
7
day_2/src/main.rs
Normal 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));
|
||||
}
|
Reference in New Issue
Block a user