Skip to content

Commit

Permalink
better parsing for day 22
Browse files Browse the repository at this point in the history
  • Loading branch information
kcaffrey committed Dec 22, 2023
1 parent 7639294 commit 89c48c6
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 40 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www.
| [Day 19](./src/bin/19.rs) | `83.9µs` | `90.9µs` |
| [Day 20](./src/bin/20.rs) | `323.9µs` | `1.2ms` |
| [Day 21](./src/bin/21.rs) | `64.1µs` | `494.7µs` |
| [Day 22](./src/bin/22.rs) | `223.3µs` | `387.2µs` |
| [Day 22](./src/bin/22.rs) | `147.5µs` | `317.1µs` |

**Total: 16.95ms**
**Total: 16.80ms**
<!--- benchmarking table --->

---
Expand Down
104 changes: 66 additions & 38 deletions src/bin/22.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ use rayon::iter::{IntoParallelIterator, ParallelIterator};
advent_of_code::solution!(22);

pub fn part_one(input: &str) -> Option<u32> {
let mut bricks = input.lines().map(Brick::from).collect::<Vec<_>>();
bricks.sort_unstable();
let tower = Tower::from_bricks(bricks);
let tower = build_tower(input);
Some(
(0..tower.bricks.len())
.filter(|&brick| {
Expand All @@ -19,9 +17,7 @@ pub fn part_one(input: &str) -> Option<u32> {
}

pub fn part_two(input: &str) -> Option<u32> {
let mut bricks = input.lines().map(Brick::from).collect::<Vec<_>>();
bricks.sort_unstable();
let tower = Tower::from_bricks(bricks);
let tower = build_tower(input);
Some(
(0..tower.bricks.len())
.into_par_iter()
Expand Down Expand Up @@ -51,6 +47,69 @@ pub fn part_two(input: &str) -> Option<u32> {
)
}

fn build_tower(input: &str) -> Tower {
let (mut bricks, (max_x, max_y)) = parse_input(input);
bricks.sort_unstable();
Tower::from_bricks(bricks, max_x, max_y)
}

fn parse_input(input: &str) -> (Vec<Brick>, (u16, u16)) {
let mut input = input.as_bytes();
let mut ret = Vec::with_capacity(input.len() / 16); // guess at total length
let mut max_x = 0;
let mut max_y = 0;

while input.len() > 1 {
let (rest, brick) = parse_brick(input);
input = rest;
if brick.ends[1].x > max_x {
max_x = brick.ends[1].x
}
if brick.ends[1].y > max_y {
max_y = brick.ends[1].y;
}
ret.push(brick);
}

(ret, (max_x, max_y))
}

fn parse_number(input: &[u8]) -> (&[u8], u16) {
let mut ret = 0;
for i in 0..input.len() {
let ch = input[i];
match ch {
b'0'..=b'9' => {
ret *= 10;
ret += (ch - b'0') as u16;
}
_ => {
return (&input[i..], ret);
}
}
}
(&input[input.len()..], ret)
}

fn parse_point3(input: &[u8]) -> (&[u8], Point3) {
let (input, x) = parse_number(input);
let (input, y) = parse_number(&input[1..]);
let (input, z) = parse_number(&input[1..]);
(input, Point3::new(x, y, z))
}

fn parse_brick(input: &[u8]) -> (&[u8], Brick) {
let (input, mut left) = parse_point3(input);
let (input, mut right) = parse_point3(&input[1..]);
if right < left {
std::mem::swap(&mut left, &mut right);
}
let brick = Brick {
ends: [left, right],
};
(&input[1..], brick)
}

#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
struct Point3 {
x: u16,
Expand Down Expand Up @@ -84,13 +143,7 @@ struct Tower {
}

impl Tower {
pub fn from_bricks(bricks: Vec<Brick>) -> Self {
let (max_x, max_y) = bricks
.iter()
.copied()
.map(|b| (b.ends[1].x, b.ends[1].y))
.reduce(|(max_x, max_y), (x, y)| (max_x.max(x), max_y.max(y)))
.unwrap();
pub fn from_bricks(bricks: Vec<Brick>, max_x: u16, max_y: u16) -> Self {
let mut ret = Self {
top_view: Grid2::new(max_x, max_y),
supports: vec![Default::default(); bricks.len()],
Expand Down Expand Up @@ -123,7 +176,6 @@ impl Tower {
}

impl Point3 {
#[allow(unused)]
pub const fn new(x: u16, y: u16, z: u16) -> Self {
Self { x, y, z }
}
Expand Down Expand Up @@ -198,30 +250,6 @@ impl PartialOrd for Point3 {
}
}

impl From<&str> for Brick {
fn from(value: &str) -> Self {
let (left, right) = value.split_once('~').unwrap();
let (mut left, mut right) = (Point3::from(left), Point3::from(right));
if right < left {
std::mem::swap(&mut left, &mut right);
}
Self {
ends: [left, right],
}
}
}

impl From<&str> for Point3 {
fn from(value: &str) -> Self {
let mut parts = value.split(',').map(|s| s.parse().unwrap());
Self {
x: parts.next().unwrap(),
y: parts.next().unwrap(),
z: parts.next().unwrap(),
}
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down

0 comments on commit 89c48c6

Please sign in to comment.