day 1
This commit is contained in:
commit
078fb7b1b0
4 changed files with 4965 additions and 0 deletions
7
aoc-2025-1/Cargo.lock
generated
Normal file
7
aoc-2025-1/Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "aoc-2025-1"
|
||||
version = "0.1.0"
|
||||
6
aoc-2025-1/Cargo.toml
Normal file
6
aoc-2025-1/Cargo.toml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
[package]
|
||||
name = "aoc-2025-1"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
4780
aoc-2025-1/input.txt
Normal file
4780
aoc-2025-1/input.txt
Normal file
File diff suppressed because it is too large
Load diff
172
aoc-2025-1/src/main.rs
Normal file
172
aoc-2025-1/src/main.rs
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
use std::fs;
|
||||
|
||||
fn main() {
|
||||
let input_contents = fs::read_to_string("input.txt").expect("read file");
|
||||
println!("Password: {:?}", calculate_password(&input_contents));
|
||||
}
|
||||
|
||||
fn calculate_password(input: &str) -> PasswordSafe {
|
||||
input
|
||||
.split("\n")
|
||||
.into_iter()
|
||||
.filter(|s| s.len() > 0)
|
||||
.fold(PasswordSafe::default(), |psafe, raw_spin| {
|
||||
psafe.spin_dial(raw_spin.into())
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct PasswordSafe {
|
||||
position: i32,
|
||||
zero_landings: u64,
|
||||
zero_crossings: u64,
|
||||
}
|
||||
struct Spin {
|
||||
ticks: i32,
|
||||
}
|
||||
|
||||
impl Default for PasswordSafe {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
position: 50,
|
||||
zero_landings: 0,
|
||||
zero_crossings: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PasswordSafe {
|
||||
fn spin_dial(self, spin: Spin) -> Self {
|
||||
// Zero Crossings
|
||||
let zero_crossing_delta: u64 = match spin.ticks {
|
||||
t if t > 0 => {
|
||||
let res = (self.position + t) as u64 / 100;
|
||||
// println!("{} -> {} => {}", self.position, t, res);
|
||||
res
|
||||
},
|
||||
t if t < 0 => {
|
||||
let res = (self.position - 100 + t).abs() as u64 / 100;
|
||||
// println!("hm {}, {}, {}", self.position, t, (self.position - 100 + t).abs());
|
||||
// println!("{} <- {} => {}", self.position, t, res);
|
||||
res - (match self.position {
|
||||
0 => 1,
|
||||
_ => 0
|
||||
})
|
||||
},
|
||||
_ => panic!("0 is an invalid spin"),
|
||||
};
|
||||
let zero_crossings: u64 = self.zero_crossings + zero_crossing_delta;
|
||||
|
||||
// Zero Landings
|
||||
let new_position = (self.position + spin.ticks) % 100;
|
||||
let position = match new_position {
|
||||
p if p < 0 => p + 100,
|
||||
p => p,
|
||||
};
|
||||
let zero_landings = match position {
|
||||
0 => self.zero_landings + 1,
|
||||
_ => self.zero_landings,
|
||||
};
|
||||
|
||||
// println!("Spun to `{}`", position);
|
||||
Self {
|
||||
position,
|
||||
zero_landings,
|
||||
zero_crossings,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Spin {
|
||||
fn from(s: &str) -> Spin {
|
||||
let (direction, raw_num) = s.split_at(1);
|
||||
let num: i32 = raw_num
|
||||
.parse()
|
||||
.expect(&format!("Couldn't parse num `{}`", raw_num));
|
||||
let ticks = match direction {
|
||||
"L" => -num,
|
||||
"R" => num,
|
||||
_ => panic!("invalid input spin: `{}`", s),
|
||||
};
|
||||
Spin { ticks }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::calculate_password;
|
||||
use std::fs;
|
||||
|
||||
const TEST_INPUT: &str = "L68
|
||||
L30
|
||||
R48
|
||||
L5
|
||||
R60
|
||||
L55
|
||||
L1
|
||||
L99
|
||||
R14
|
||||
L82
|
||||
";
|
||||
|
||||
#[test]
|
||||
fn test_zero_landings() {
|
||||
let calculated = calculate_password(TEST_INPUT);
|
||||
assert_eq!(calculated.zero_landings, 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zero_crossings_guess_1() {
|
||||
let input_contents = fs::read_to_string("input.txt").expect("read file");
|
||||
let calculated = calculate_password(&input_contents);
|
||||
assert!(calculated.zero_crossings > 5598);
|
||||
assert!(calculated.zero_crossings < 7509);
|
||||
assert_eq!(calculated.zero_crossings, 6907);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn negative_unit_zero_crossing() {
|
||||
let calculated = calculate_password("L50
|
||||
");
|
||||
println!("{:?}", calculated);
|
||||
assert_eq!(calculated.zero_crossings, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn negative_unit_zero_crossing_5() {
|
||||
let calculated = calculate_password("L550
|
||||
L1
|
||||
L1
|
||||
L1
|
||||
L1
|
||||
");
|
||||
println!("{:?}", calculated);
|
||||
assert_eq!(calculated.zero_crossings, 6);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn positive_unit_zero_crossing_5() {
|
||||
let calculated = calculate_password("R550
|
||||
R1
|
||||
R1
|
||||
R1
|
||||
R1
|
||||
");
|
||||
println!("{:?}", calculated);
|
||||
assert_eq!(calculated.zero_crossings, 6);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zig_zag() {
|
||||
let calculated = calculate_password("L51
|
||||
R2
|
||||
L2
|
||||
R2
|
||||
L2
|
||||
R2
|
||||
L2
|
||||
");
|
||||
println!("{:?}", calculated);
|
||||
assert_eq!(calculated.zero_crossings, 7);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue