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:
2024-12-14 23:08:31 +01:00
parent fa842890ce
commit f56780d1cf
4 changed files with 860 additions and 0 deletions

27
y2024/src/bin/d14.rs Normal file
View 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
View 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);
}
}

View File

@@ -15,3 +15,5 @@ pub mod d11;
pub mod d12;
pub mod d13;
pub mod d14;