y2024d14 tipp from reddit, most robots form the tree aka not evenly spread aka use quadrants and check all frames where they are not even
This commit is contained in:
27
y2024/src/bin/d14.rs
Normal file
27
y2024/src/bin/d14.rs
Normal file
@@ -0,0 +1,27 @@
|
||||
use std::{fs, time::Instant};
|
||||
|
||||
use utils::time::get_elapsed_string;
|
||||
use y2024::days::d14;
|
||||
|
||||
fn main() {
|
||||
let now = Instant::now();
|
||||
println!("Part 1:");
|
||||
part1();
|
||||
println!("Ran in {}", get_elapsed_string(now.elapsed()));
|
||||
let now = Instant::now();
|
||||
println!("Part 2:");
|
||||
part2();
|
||||
println!("Ran in {}", get_elapsed_string(now.elapsed()));
|
||||
}
|
||||
|
||||
fn part1() {
|
||||
let root = env!("CARGO_MANIFEST_DIR");
|
||||
let content = fs::read_to_string(format!("{root}/resources/14_input.txt")).unwrap();
|
||||
println!("{}", d14::process_part1(&content));
|
||||
}
|
||||
|
||||
fn part2() {
|
||||
let root = env!("CARGO_MANIFEST_DIR");
|
||||
let content = fs::read_to_string(format!("{root}/resources/14_input.txt")).unwrap();
|
||||
d14::process_part2(&content);
|
||||
}
|
||||
331
y2024/src/days/d14.rs
Normal file
331
y2024/src/days/d14.rs
Normal file
@@ -0,0 +1,331 @@
|
||||
use std::{collections::HashMap, thread, time::Duration};
|
||||
|
||||
use itertools::Itertools;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
struct Robot {
|
||||
position: (i32, i32),
|
||||
velocity: (i32, i32),
|
||||
}
|
||||
|
||||
impl Robot {
|
||||
fn parse(s: &str) -> Self {
|
||||
let (p, v) = s.split_once(" ").unwrap();
|
||||
let (_, p_x_y) = p.split_once("=").unwrap();
|
||||
let (px, py) = p_x_y.split_once(",").unwrap();
|
||||
let position: (i32, i32) = (px.parse().unwrap(), py.parse().unwrap());
|
||||
let (_, v_x_y) = v.split_once("=").unwrap();
|
||||
let (vx, vy) = v_x_y.split_once(",").unwrap();
|
||||
let velocity: (i32, i32) = (vx.parse().unwrap(), vy.parse().unwrap());
|
||||
Robot { position, velocity }
|
||||
}
|
||||
|
||||
fn walk(&mut self, seconds: i32, grid_size: (i32, i32)) {
|
||||
let movement = (
|
||||
self.velocity.0 * seconds + self.position.0,
|
||||
self.velocity.1 * seconds + self.position.1,
|
||||
);
|
||||
let mut position = (movement.0 % (grid_size.0), movement.1 % (grid_size.1));
|
||||
if position.0 < 0 {
|
||||
position.0 += grid_size.0;
|
||||
}
|
||||
if position.1 < 0 {
|
||||
position.1 += grid_size.1;
|
||||
}
|
||||
self.position = position;
|
||||
}
|
||||
|
||||
fn get_quadrant(&self, grid_size: (i32, i32)) -> i32 {
|
||||
if self.position.0 == (grid_size.0 / 2) || self.position.1 == (grid_size.1 / 2) {
|
||||
return 0;
|
||||
}
|
||||
let top = self.position.1 < grid_size.1 / 2;
|
||||
let left = self.position.0 < grid_size.0 / 2;
|
||||
match (top, left) {
|
||||
(true, true) => 1,
|
||||
(true, false) => 2,
|
||||
(false, true) => 3,
|
||||
(false, false) => 4,
|
||||
}
|
||||
}
|
||||
|
||||
fn print_robots(robots: &Vec<Self>, grid_size: (i32, i32)) {
|
||||
let mut grid = vec![vec![0; grid_size.0 as usize]; grid_size.1 as usize];
|
||||
for robot in robots {
|
||||
let value = grid[robot.position.1 as usize][robot.position.0 as usize];
|
||||
grid[robot.position.1 as usize][robot.position.0 as usize] = value + 1;
|
||||
}
|
||||
for row in grid {
|
||||
for tile in row {
|
||||
if tile == 0 {
|
||||
print!(".");
|
||||
} else {
|
||||
print!("{tile}");
|
||||
}
|
||||
}
|
||||
println!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn process_part1(input: &str) -> i32 {
|
||||
let robots = input
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let mut robot = Robot::parse(line);
|
||||
robot.walk(100, (101, 103));
|
||||
robot
|
||||
})
|
||||
.collect_vec();
|
||||
Robot::print_robots(&robots, (101, 103));
|
||||
let mut quadrants = HashMap::new();
|
||||
for robot in robots {
|
||||
let quadrant = robot.get_quadrant((101, 103));
|
||||
quadrants
|
||||
.entry(quadrant)
|
||||
.and_modify(|count| *count += 1)
|
||||
.or_insert(1);
|
||||
}
|
||||
quadrants
|
||||
.iter()
|
||||
.filter(|(quadrant, _)| **quadrant != 0)
|
||||
.map(|(_, count)| count)
|
||||
.product()
|
||||
}
|
||||
|
||||
pub fn process_part2(input: &str) {
|
||||
let mut robots = input.lines().map(Robot::parse).collect_vec();
|
||||
for seconds in 1..=10000 {
|
||||
for robot in robots.iter_mut() {
|
||||
robot.walk(1, (101, 103));
|
||||
}
|
||||
let mut quadrants = HashMap::new();
|
||||
for robot in robots.iter() {
|
||||
let quadrant = robot.get_quadrant((101, 103));
|
||||
quadrants
|
||||
.entry(quadrant)
|
||||
.and_modify(|count| *count += 1)
|
||||
.or_insert(1);
|
||||
}
|
||||
if quadrants.iter().any(|(_, count)| *count > robots.len() / 3) {
|
||||
Robot::print_robots(&robots, (101, 103));
|
||||
println!("{seconds} secs");
|
||||
let half_sec = Duration::from_millis(1000);
|
||||
thread::sleep(half_sec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
const INPUT: &str = "p=0,4 v=3,-3
|
||||
p=6,3 v=-1,-3
|
||||
p=10,3 v=-1,2
|
||||
p=2,0 v=2,-1
|
||||
p=0,0 v=1,3
|
||||
p=3,0 v=-2,-2
|
||||
p=7,6 v=-1,-3
|
||||
p=3,0 v=-1,-2
|
||||
p=9,3 v=2,3
|
||||
p=7,3 v=-1,2
|
||||
p=2,4 v=2,-3
|
||||
p=9,5 v=-3,-3";
|
||||
|
||||
#[test]
|
||||
fn part1_1() {
|
||||
let mut robot = Robot {
|
||||
position: (0, 4),
|
||||
velocity: (3, -3),
|
||||
};
|
||||
robot.walk(100, (11, 7));
|
||||
let result = Robot {
|
||||
position: (3, 5),
|
||||
velocity: (3, -3),
|
||||
};
|
||||
assert_eq!(robot, result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part1_2() {
|
||||
let mut robot = Robot {
|
||||
position: (6, 3),
|
||||
velocity: (-1, -3),
|
||||
};
|
||||
robot.walk(100, (11, 7));
|
||||
let result = Robot {
|
||||
position: (5, 4),
|
||||
velocity: (-1, -3),
|
||||
};
|
||||
assert_eq!(robot, result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part1_3() {
|
||||
let mut robot = Robot {
|
||||
position: (10, 3),
|
||||
velocity: (-1, 2),
|
||||
};
|
||||
robot.walk(100, (11, 7));
|
||||
let result = Robot {
|
||||
position: (9, 0),
|
||||
velocity: (-1, 2),
|
||||
};
|
||||
assert_eq!(robot, result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part1_4() {
|
||||
let mut robot = Robot {
|
||||
position: (2, 0),
|
||||
velocity: (2, -1),
|
||||
};
|
||||
robot.walk(100, (11, 7));
|
||||
let result = Robot {
|
||||
position: (4, 5),
|
||||
velocity: (2, -1),
|
||||
};
|
||||
assert_eq!(robot, result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part1_5() {
|
||||
let mut robot = Robot {
|
||||
position: (0, 0),
|
||||
velocity: (1, 3),
|
||||
};
|
||||
robot.walk(100, (11, 7));
|
||||
let result = Robot {
|
||||
position: (1, 6),
|
||||
velocity: (1, 3),
|
||||
};
|
||||
assert_eq!(robot, result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part1_6() {
|
||||
let mut robot = Robot {
|
||||
position: (3, 0),
|
||||
velocity: (-2, -2),
|
||||
};
|
||||
robot.walk(100, (11, 7));
|
||||
let result = Robot {
|
||||
position: (1, 3),
|
||||
velocity: (-2, -2),
|
||||
};
|
||||
assert_eq!(robot, result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part1_7() {
|
||||
let mut robot = Robot {
|
||||
position: (7, 6),
|
||||
velocity: (-1, -3),
|
||||
};
|
||||
robot.walk(100, (11, 7));
|
||||
let result = Robot {
|
||||
position: (6, 0),
|
||||
velocity: (-1, -3),
|
||||
};
|
||||
assert_eq!(robot, result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part1_8() {
|
||||
let mut robot = Robot {
|
||||
position: (3, 0),
|
||||
velocity: (-1, -2),
|
||||
};
|
||||
robot.walk(100, (11, 7));
|
||||
let result = Robot {
|
||||
position: (2, 3),
|
||||
velocity: (-1, -2),
|
||||
};
|
||||
assert_eq!(robot, result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part1_9() {
|
||||
let mut robot = Robot {
|
||||
position: (9, 3),
|
||||
velocity: (2, 3),
|
||||
};
|
||||
robot.walk(100, (11, 7));
|
||||
let result = Robot {
|
||||
position: (0, 2),
|
||||
velocity: (2, 3),
|
||||
};
|
||||
assert_eq!(robot, result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part1_10() {
|
||||
let mut robot = Robot {
|
||||
position: (7, 3),
|
||||
velocity: (-1, 2),
|
||||
};
|
||||
robot.walk(100, (11, 7));
|
||||
let result = Robot {
|
||||
position: (6, 0),
|
||||
velocity: (-1, 2),
|
||||
};
|
||||
assert_eq!(robot, result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part1_11() {
|
||||
let mut robot = Robot {
|
||||
position: (2, 4),
|
||||
velocity: (2, -3),
|
||||
};
|
||||
robot.walk(100, (11, 7));
|
||||
let result = Robot {
|
||||
position: (4, 5),
|
||||
velocity: (2, -3),
|
||||
};
|
||||
assert_eq!(robot, result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part1_12() {
|
||||
let mut robot = Robot {
|
||||
position: (9, 5),
|
||||
velocity: (-3, -3),
|
||||
};
|
||||
robot.walk(100, (11, 7));
|
||||
let result = Robot {
|
||||
position: (6, 6),
|
||||
velocity: (-3, -3),
|
||||
};
|
||||
assert_eq!(robot, result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part1() {
|
||||
let robots = INPUT
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let mut robot = Robot::parse(line);
|
||||
robot.walk(100, (11, 7));
|
||||
robot
|
||||
})
|
||||
.collect_vec();
|
||||
Robot::print_robots(&robots, (11, 7));
|
||||
let mut quadrants = HashMap::new();
|
||||
for robot in robots {
|
||||
let quadrant = robot.get_quadrant((11, 7));
|
||||
quadrants
|
||||
.entry(quadrant)
|
||||
.and_modify(|count| *count += 1)
|
||||
.or_insert(1);
|
||||
}
|
||||
println!("{quadrants:?}");
|
||||
let result: i32 = quadrants
|
||||
.iter()
|
||||
.filter(|(quadrant, _)| **quadrant != 0)
|
||||
.map(|(_, count)| count)
|
||||
.product();
|
||||
assert_eq!(result, 12);
|
||||
}
|
||||
}
|
||||
@@ -15,3 +15,5 @@ pub mod d11;
|
||||
pub mod d12;
|
||||
|
||||
pub mod d13;
|
||||
|
||||
pub mod d14;
|
||||
|
||||
Reference in New Issue
Block a user