Skip to content

Instantly share code, notes, and snippets.

@qubyte qubyte/Cargo.toml
Last active Apr 22, 2019

Embed
What would you like to do?
My revised solution to Advent of code 2018 day 10 (both parts) in Rust, this time using recap.
[package]
name = "task-1"
version = "0.1.0"
authors = ["Mark S. Everitt <mark.s.everitt@gmail.com>"]
edition = "2018"
[dependencies]
recap = "0.1"
serde = "1.0.90"
use std::{
io::{stdin, BufRead},
cmp::{max, min}
};
use recap::Recap;
use serde::Deserialize;
const IMAX: isize = isize::max_value();
const IMIN: isize = isize::min_value();
#[derive(Debug, Clone, Deserialize, Recap)]
#[recap(regex = r"<\s*(?P<position_x>-?\d+),\s*(?P<position_y>-?\d+)>.*<\s*(?P<velocity_x>-?\d+),\s*(?P<velocity_y>-?\d)>")]
struct Particle {
position_x: isize,
position_y: isize,
velocity_x: isize,
velocity_y: isize
}
fn tick(particles: &Vec<Particle>) -> Vec<Particle> {
particles.iter().map(|particle| Particle {
position_x: particle.position_x + particle.velocity_x,
position_y: particle.position_y + particle.velocity_y,
velocity_x: particle.velocity_x,
velocity_y: particle.velocity_y
}).collect()
}
fn get_bounds(particles: &Vec<Particle>) -> (isize, isize, isize, isize) {
particles.iter().fold((IMAX, IMAX, IMIN, IMIN), |(least_x, least_y, most_x, most_y), particle| {
let px = particle.position_x;
let py = particle.position_y;
(min(least_x, px), min(least_y, py), max(most_x, px), max(most_y, py))
})
}
fn render(particles: &Vec<Particle>) -> String {
let (least_x, least_y, most_x, most_y) = get_bounds(particles);
let mut message = String::from("");
for j in least_y..=most_y {
for i in least_x..=most_x {
if particles.iter().any(|p| p.position_x == i && p.position_y == j) {
message.push_str("#");
} else {
message.push_str("-");
}
}
message.push_str("\n");
}
message
}
fn main() {
let mut particles: Vec<Particle> = stdin()
.lock()
.lines()
.filter_map(|line| line.ok())
.filter_map(|line| line.parse().ok())
.collect();
let mut seconds = 0;
// I assume the message is when the particles occupy the tightest bounding
// box (they have converged). This is not true for some known inputs. A
// better approach might be to look for lines in the grid of particles.
let message = loop {
let (least_x, least_y, most_x, most_y) = get_bounds(&particles);
let last_area = (most_y - least_y) * (most_x - least_x);
let last_particles = particles;
seconds += 1;
particles = tick(&last_particles);
let (least_x, least_y, most_x, most_y) = get_bounds(&particles);
let area = (most_y - least_y) * (most_x - least_x);
if last_area > 0 && last_area < area {
break render(&last_particles);
}
};
println!("Second {}", seconds - 1);
println!("{}", message);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.