~cdv/aoc-2018-rs

bb809c17c5516457cb838dddf91f07388e8ec9bd — Christopher Vittal 2 years ago 34e9731
Rewrite day 13 for SPEED!!!
1 files changed, 75 insertions(+), 66 deletions(-)

M src/bin/day13.rs
M src/bin/day13.rs => src/bin/day13.rs +75 -66
@@ 1,6 1,6 @@
use std::ops::AddAssign;

use rustc_hash::FxHashSet;
// NOTE, in this solution, x and y are reversed from the problem

static INPUT: &str = "data/day13";



@@ 21,17 21,25 @@ enum Dir {

#[derive(Clone, Copy, PartialEq, Eq)]
struct Cart {
    x: usize,
    y: usize,
    dir: Dir,
    next: Turn,
}

impl Cart {
    fn new(dir: Dir) -> Self {
    fn new(dir: Dir, x: usize, y: usize) -> Self {
        Cart {
            x,
            y,
            dir,
            next: Turn::Lf,
        }
    }

    fn xy(&self) -> (usize, usize) {
        (self.x, self.y)
    }
}

#[derive(Clone, Copy, PartialEq, Eq)]


@@ 75,81 83,82 @@ impl AddAssign<Turn> for Dir {
}

fn main() {
    let mut input: Vec<Vec<(Point, Option<Cart>)>> = aoc::file::to_lines(INPUT)
        .map(|l| l.unwrap().bytes().map(|b| {
    let (board, mut carts): (Vec<Vec<Point>>, Vec<Cart>) = aoc::file::to_lines(INPUT)
        .enumerate()
        .map(|(i, l)| l.unwrap().bytes().enumerate().map(|(j, b)| {
            match b {
                b'|' => (Point::Vert, None),
                b'-' => (Point::Horiz, None),
                b'\\' => (Point::TurnSl, None),
                b'/' => (Point::TurnFw, None),
                b'+' => (Point::Inter, None),
                b'^' => (Point::Vert, Some(Cart::new(Dir::Up))),
                b'v' => (Point::Vert, Some(Cart::new(Dir::Dn))),
                b'>' => (Point::Horiz, Some(Cart::new(Dir::Rt))),
                b'<' => (Point::Horiz, Some(Cart::new(Dir::Lf))),
                b'^' => (Point::Vert, Some(Cart::new(Dir::Up, i, j))),
                b'v' => (Point::Vert, Some(Cart::new(Dir::Dn, i, j))),
                b'>' => (Point::Horiz, Some(Cart::new(Dir::Rt, i, j))),
                b'<' => (Point::Horiz, Some(Cart::new(Dir::Lf, i, j))),
                _ => (Point::None, None),
            }
        }).collect()).collect();
    let mut ncarts: usize = input.iter().map(|i| i.iter().filter(|(_, p)| p.is_some()).count()).sum();
    let mut moved: FxHashSet<(usize, usize)> = FxHashSet::default();
        }).unzip())
        .fold((vec![], vec![]), |mut a, (pts, cts): (Vec<Point>, Vec<Option<Cart>>)| {
            a.0.push(pts);
            a.1.extend(cts.into_iter().filter_map(|c| c));
            a
        });
    let mut p1 = true;
    let (x, y) = 'outer: loop {
        moved.clear();
        for x in 0..input.len() {
            for y in 0..input[x].len() {
                if moved.contains(&(x, y)) { continue; }
                match input[x][y] {
                    (_, None) => {},
                    (_, Some(_)) => {
                        let mut cart = input[x][y].1.take().unwrap();
                        let (a, b) = match cart.dir {
                            Dir::Up => (x - 1, y),
                            Dir::Rt => (x, y + 1),
                            Dir::Dn => (x + 1, y),
                            Dir::Lf => (x, y - 1),
                        };
                        if input[a][b].1.is_some() {
                            if p1 {
                                println!("  1: {},{}", b, a);
                                p1 = false;
                            }
                            input[a][b].1 = None;
                            ncarts -= 2;
                            continue;
                        }
                        match input[a][b].0 {
                            Point::Vert | Point::Horiz => {},
                            Point::TurnSl => cart.dir = match cart.dir {
                                Dir::Up => Dir::Lf,
                                Dir::Rt => Dir::Dn,
                                Dir::Lf => Dir::Up,
                                Dir::Dn => Dir::Rt,
                            },
                            Point::TurnFw => cart.dir = match cart.dir {
                                Dir::Up => Dir::Rt,
                                Dir::Rt => Dir::Up,
                                Dir::Lf => Dir::Dn,
                                Dir::Dn => Dir::Lf,
                            },
                            Point::Inter => {
                                cart.dir += cart.next;
                                cart.next = match cart.next {
                                    Turn::Lf => Turn::St,
                                    Turn::St => Turn::Ri,
                                    Turn::Ri => Turn::Lf,
                                };
                            }
                            _ => unreachable!("{}, {}", x, y),
                        }
                        if ncarts == 1 {
                            break 'outer (a, b);
                        }
                        input[a][b].1 = Some(cart);
                        moved.insert((a, b));
    while carts.len() > 1 {
        carts.sort_by(|c1, c2| c2.xy().cmp(&c1.xy()));
        let mut i = carts.len() - 1;
        loop {
            let mut cart = carts.remove(i);
            match cart.dir {
                Dir::Up => cart.x -= 1,
                Dir::Rt => cart.y += 1,
                Dir::Dn => cart.x += 1,
                Dir::Lf => cart.y -= 1,
            }
            if let Some(j) = carts.iter().rposition(|c| c.xy() == cart.xy()) {
                if p1 {
                    println!("  1: {},{}", cart.xy().1, cart.xy().0);
                    p1 = false;
                }
                carts.remove(j);
                if j < i {
                    i -= 1;
                }
            } else {
                let (x, y) = cart.xy();
                match board[x][y] {
                    Point::Vert | Point::Horiz => {},
                    Point::TurnSl => cart.dir = match cart.dir {
                        Dir::Up => Dir::Lf,
                        Dir::Rt => Dir::Dn,
                        Dir::Lf => Dir::Up,
                        Dir::Dn => Dir::Rt,
                    },
                    Point::TurnFw => cart.dir = match cart.dir {
                        Dir::Up => Dir::Rt,
                        Dir::Rt => Dir::Up,
                        Dir::Lf => Dir::Dn,
                        Dir::Dn => Dir::Lf,
                    },
                    Point::Inter => {
                        cart.dir += cart.next;
                        cart.next = match cart.next {
                            Turn::Lf => Turn::St,
                            Turn::St => Turn::Ri,
                            Turn::Ri => Turn::Lf,
                        };
                    }
                    _ => unreachable!("{}, {}", x, y),
                }
                carts.push(cart);
            }
            if i == 0 {
                break;
            } else {
                i -= 1;
            }
        }
    };
    println!("  2: {},{}", y, x);
    }
    println!("  2: {},{}", carts[0].y, carts[0].x);
}