@@ 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);
}