Slightly cleaned up by using structs.

This commit is contained in:
2018-12-13 11:44:18 +01:00
parent e6c8c6b100
commit 91f0ec55f1

View File

@@ -1,3 +1,4 @@
use std::cmp::Ordering;
use std::io::BufRead; use std::io::BufRead;
use std::io::BufReader; use std::io::BufReader;
use std::io::Read; use std::io::Read;
@@ -48,10 +49,45 @@ impl Direction {
} }
} }
#[derive(Default, Debug)] #[derive(Copy, Clone, Eq, PartialEq)]
struct Cart {
coordinate: Coordinate,
direction: Direction,
turns: u8,
alive: bool,
}
impl Cart {
pub fn new(coordinate: Coordinate, direction: Direction) -> Self {
Cart {
coordinate,
direction,
turns: 0,
alive: true,
}
}
}
impl Ord for Cart {
fn cmp(&self, other: &Self) -> Ordering {
let (sx, sy) = self.coordinate;
let (ox, oy) = other.coordinate;
(sy, sx).cmp(&(oy, ox))
}
}
impl PartialOrd for Cart {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
#[derive(Default)]
pub struct Day13 { pub struct Day13 {
grid: Vec<Vec<char>>, grid: Vec<Vec<char>>,
carts: Vec<(Coordinate, Direction, usize, bool)>, carts: Vec<Cart>,
} }
impl Day13 { impl Day13 {
@@ -60,7 +96,7 @@ impl Day13 {
} }
fn alive(&self) -> usize { fn alive(&self) -> usize {
self.carts.iter().filter(|(_, _, _, x)| *x).count() self.carts.iter().filter(|x| x.alive).count()
} }
fn read_input(&mut self, input: &mut Read) { fn read_input(&mut self, input: &mut Read) {
@@ -73,12 +109,12 @@ impl Day13 {
'^' | 'v' => { '^' | 'v' => {
current.push('|'); current.push('|');
let direction = Direction::from_char(c); let direction = Direction::from_char(c);
self.carts.push(((x, y), direction, 0, true)); self.carts.push(Cart::new((x, y), direction));
} }
'>' | '<' => { '>' | '<' => {
current.push('-'); current.push('-');
let direction = Direction::from_char(c); let direction = Direction::from_char(c);
self.carts.push(((x, y), direction, 0, true)); self.carts.push(Cart::new((x, y), direction));
} }
other => current.push(other), other => current.push(other),
} }
@@ -89,54 +125,56 @@ impl Day13 {
fn simulate(&mut self) -> Option<Coordinate> { fn simulate(&mut self) -> Option<Coordinate> {
let mut collision = None; let mut collision = None;
self.carts.sort_unstable_by_key(|&((x, y), _, _ , _)| (y, x)); self.carts.sort_unstable();
for i in 0..self.carts.len() { for i in 0..self.carts.len() {
{ if !self.carts[i].alive {
let (coordinate, direction, turns, alive) = self.carts.get_mut(i).unwrap(); continue;
if !*alive {
continue;
}
*coordinate = direction.run(*coordinate);
let &mut (x, y) = coordinate;
*direction = match self.grid[y][x] {
'|' | '-' => *direction,
'+' => {
let new_dir = match turns {
0 => direction.counter_clockwise(),
1 => *direction,
2 => direction.clockwise(),
_ => unreachable!(),
};
*turns = (*turns + 1) % 3;
new_dir
},
'/' => match *direction {
Direction::North | Direction::South => direction.clockwise(),
Direction::West | Direction::East => direction.counter_clockwise(),
},
'\\' => match *direction {
Direction::North | Direction::South => direction.counter_clockwise(),
Direction::West | Direction::East => direction.clockwise(),
},
val => panic!("Invalid tile to be on: {}", val),
};
} }
let current_direction = self.carts[i].direction;
self.carts[i].coordinate = current_direction.run(self.carts[i].coordinate);
let (x, y) = self.carts[i].coordinate;
let current_direction = self.carts[i].direction;
self.carts[i].direction = match self.grid[y][x] {
'|' | '-' => current_direction,
'+' => {
let turns = self.carts[i].turns;
let new_dir = match turns {
0 => current_direction.counter_clockwise(),
1 => current_direction,
2 => current_direction.clockwise(),
_ => unreachable!(),
};
self.carts[i].turns = (turns + 1) % 3;
new_dir
}
'/' => match current_direction {
Direction::North | Direction::South => current_direction.clockwise(),
Direction::West | Direction::East => current_direction.counter_clockwise(),
},
'\\' => match current_direction {
Direction::North | Direction::South => current_direction.counter_clockwise(),
Direction::West | Direction::East => current_direction.clockwise(),
},
val => panic!("Invalid tile to be on: {}", val),
};
for j in 0..self.carts.len() { for j in 0..self.carts.len() {
if i == j { if i == j {
continue; continue;
} }
if !self.carts[i].3 { if !self.carts[i].alive {
break; break;
} }
if !self.carts[j].3 { if !self.carts[j].alive {
continue; continue;
} }
if self.carts[i].0 == self.carts[j].0 { if self.carts[i].coordinate == self.carts[j].coordinate {
self.carts[i].3 = false; self.carts[i].alive = false;
self.carts[j].3 = false; self.carts[j].alive = false;
collision = Some(self.carts[i].0); collision = Some(self.carts[i].coordinate);
} }
} }
} }
@@ -162,9 +200,10 @@ impl Solution for Day13 {
self.simulate(); self.simulate();
} }
for &((x, y), _, _, alive) in &self.carts { for cart in &self.carts {
if alive { if cart.alive {
return format!("{},{}", x, y) let (x, y) = cart.coordinate;
return format!("{},{}", x, y);
} }
} }
unreachable!() unreachable!()