Last active
August 18, 2022 12:10
-
-
Save qubyte/d259676b4927a6fbe8fd5f99e61d2e62 to your computer and use it in GitHub Desktop.
My revised solution to Advent of code 2018 day 10 (both parts) in Rust, this time using recap.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "task-1" | |
version = "0.1.0" | |
authors = ["Mark S. Everitt <[email protected]>"] | |
edition = "2018" | |
[dependencies] | |
recap = "0.1" | |
serde = "1.0.90" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
Thank you, I really like the approach to use regex for more robust struct parsing.
Now parsing a config-file-format (looks similar to nginx but isn't) with this.
https://github.com/AiyionPrime/gluon-mesh-vpn-key-translate/blob/f3538a359f74788ed96a4241a3ddd62f75098fd9/src/fastd_key.rs#L5-L10