|
|
|
@ -2,11 +2,16 @@ fn main() { |
|
|
|
println!("Hello, world!"); |
|
|
|
} |
|
|
|
|
|
|
|
pub const DEBUG : bool = true; |
|
|
|
pub const DEBUG : bool = false; |
|
|
|
|
|
|
|
pub struct Trail { |
|
|
|
waypoints: Vec<Point>, |
|
|
|
directions: Vec<Direction>, |
|
|
|
min: Point, |
|
|
|
max: Point, |
|
|
|
distance: i32, |
|
|
|
area: i32, |
|
|
|
size: i32, |
|
|
|
} |
|
|
|
|
|
|
|
impl Trail { |
|
|
|
@ -14,6 +19,11 @@ impl Trail { |
|
|
|
Trail { |
|
|
|
waypoints: Vec::new(), |
|
|
|
directions: Vec::new(), |
|
|
|
min: Point{x: 0, y: 0}, |
|
|
|
max: Point{x: 0, y: 0}, |
|
|
|
distance: 0, |
|
|
|
area: 0, |
|
|
|
size: 0, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -30,35 +40,22 @@ impl Trail { |
|
|
|
Ok(i) => i, |
|
|
|
}; |
|
|
|
|
|
|
|
self.directions.push(Direction::North); |
|
|
|
self.waypoints.push(Point{x: 0, y: 0}); |
|
|
|
self.distance = self.walk_rec(plan, steps, Direction::North, Point{x: 0, y: 0}); |
|
|
|
|
|
|
|
da.dist = self.walk(plan, steps); |
|
|
|
|
|
|
|
let mut min = Point{x: 0, y: 0}; |
|
|
|
let mut max = Point{x: 0, y: 0}; |
|
|
|
for i in &self.waypoints { |
|
|
|
if i.x < min.x { |
|
|
|
min.x = i.x; |
|
|
|
} |
|
|
|
if i.y < min.y { |
|
|
|
min.y = i.y; |
|
|
|
} |
|
|
|
if i.x > max.x { |
|
|
|
max.x = i.x; |
|
|
|
} |
|
|
|
if i.y > max.y { |
|
|
|
max.y = i.y; |
|
|
|
} |
|
|
|
} |
|
|
|
da.area = (max.x - min.x) * (max.y - min.y); |
|
|
|
self.calc_min(); |
|
|
|
self.calc_max(); |
|
|
|
self.calc_area(); |
|
|
|
self.calc_size(); |
|
|
|
da.dist = self.distance; |
|
|
|
da.area = self.area; |
|
|
|
da.size = self.size; |
|
|
|
da |
|
|
|
} else { |
|
|
|
DistArea{dist:0, area:0, size:0} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
fn walk(&mut self, mut plan: Vec<String>, steps: i32) -> i32 { |
|
|
|
fn walk_rec(&mut self, mut plan: Vec<String>, steps: i32, mut dir: Direction, mut pos: Point) -> i32 { |
|
|
|
if steps == 0 { |
|
|
|
0 |
|
|
|
} else { |
|
|
|
@ -68,8 +65,7 @@ impl Trail { |
|
|
|
Err(_) => 0, |
|
|
|
Ok(i) => i, |
|
|
|
}; |
|
|
|
let mut dir = self.directions.last().unwrap().clone(); |
|
|
|
let mut pos = self.waypoints.last().unwrap().clone(); |
|
|
|
|
|
|
|
for _i in 0 .. count { |
|
|
|
for c in part.chars() { |
|
|
|
match c { |
|
|
|
@ -78,32 +74,166 @@ impl Trail { |
|
|
|
if DEBUG { |
|
|
|
println!("F, pos: x={} y={}, dir: {:?}", pos.x, pos.y, dir); |
|
|
|
} |
|
|
|
self.directions.push(dir); |
|
|
|
self.waypoints.push(pos); |
|
|
|
stepcount += 1; |
|
|
|
}, |
|
|
|
'L' => { |
|
|
|
dir = Direction::turn_left(dir); |
|
|
|
if DEBUG { |
|
|
|
print!("L"); |
|
|
|
println!("L, pos: x={} y={}, dir: {:?}", pos.x, pos.y, dir); |
|
|
|
} |
|
|
|
}, |
|
|
|
'R' => { |
|
|
|
dir = Direction::turn_right(dir); |
|
|
|
if DEBUG { |
|
|
|
print!("R"); |
|
|
|
println!("R, pos: x={} y={}, dir: {:?}", pos.x, pos.y, dir); |
|
|
|
} |
|
|
|
}, |
|
|
|
_ => (), |
|
|
|
} |
|
|
|
self.directions.push(dir); |
|
|
|
self.waypoints.push(pos); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
stepcount += self.walk(plan, steps - 1); |
|
|
|
stepcount += self.walk_rec(plan, steps - 1, dir, pos); |
|
|
|
|
|
|
|
stepcount |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
fn calc_min(&mut self) { |
|
|
|
self.min = Point{x:0, y:0}; |
|
|
|
for i in &self.waypoints { |
|
|
|
if i.x < self.min.x { |
|
|
|
self.min.x = i.x; |
|
|
|
} |
|
|
|
if i.y < self.min.y { |
|
|
|
self.min.y = i.y; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
fn calc_max(&mut self) { |
|
|
|
self.max = Point{x:0, y:0}; |
|
|
|
for i in &self.waypoints { |
|
|
|
if i.x > self.max.x { |
|
|
|
self.max.x = i.x; |
|
|
|
} |
|
|
|
if i.y > self.max.y { |
|
|
|
self.max.y = i.y; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
fn calc_area(&mut self) { |
|
|
|
self.area = (self.max.x - self.min.x) * (self.max.y - self.min.y); |
|
|
|
} |
|
|
|
|
|
|
|
fn calc_size(&mut self) { |
|
|
|
for i in self.min.x .. self.max.x { |
|
|
|
for j in self.min.y .. self.max.y { |
|
|
|
if self.is_in_area(Point{x: i, y: j}) { |
|
|
|
self.size += 1; |
|
|
|
if DEBUG { |
|
|
|
println!("p: ({},{})", i, j); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
fn is_in_area(&self, point: Point) -> bool { |
|
|
|
let mut left = 0; |
|
|
|
let mut f = self.waypoints.clone().into_iter().enumerate().filter(|&(_,p)| p.y == point.y && p.x <= point.x); |
|
|
|
for (i, p) in f { |
|
|
|
if self.directions[i] == Direction::South { |
|
|
|
left += 1; |
|
|
|
if DEBUG { |
|
|
|
print!("{:?} {:?} ", p, self.directions[i]); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
let mut f = self.waypoints.clone().into_iter().enumerate().filter(|&(_,p)| p.y == point.y+1 && p.x <= point.x); |
|
|
|
for (i, p) in f { |
|
|
|
if self.directions[i] == Direction::North { |
|
|
|
left += 1; |
|
|
|
if DEBUG { |
|
|
|
print!("{:?} {:?} ", p, self.directions[i]); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if DEBUG { |
|
|
|
println!("- {} ", left); |
|
|
|
} |
|
|
|
left % 2 == 1 |
|
|
|
} |
|
|
|
|
|
|
|
fn calc_pocket(&mut self) { |
|
|
|
for i in self.min.x .. self.max.x { |
|
|
|
for j in self.min.y .. self.max.y { |
|
|
|
if self.is_in_pocket(Point{x: i, y: j}) { |
|
|
|
self.size += 1; |
|
|
|
if DEBUG { |
|
|
|
println!("p: ({},{})", i, j); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
fn is_in_pocket(&self, point: Point) -> bool { |
|
|
|
let mut left = 0; |
|
|
|
let mut right = 0; |
|
|
|
let mut top = 0; |
|
|
|
let mut down = 0; |
|
|
|
let mut f = self.waypoints.clone().into_iter().enumerate().filter(|&(_,p)| p.y == point.y && p.x <= point.x); |
|
|
|
for (i, p) in f { |
|
|
|
if self.directions[i] == Direction::South { |
|
|
|
left += 1; |
|
|
|
if DEBUG { |
|
|
|
print!("{:?} {:?} ", p, self.directions[i]); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
f = self.waypoints.clone().into_iter().enumerate().filter(|&(_,p)| p.y == point.y+1 && p.x <= point.x); |
|
|
|
for (i, p) in f { |
|
|
|
if self.directions[i] == Direction::North { |
|
|
|
left += 1; |
|
|
|
if DEBUG { |
|
|
|
print!("{:?} {:?} ", p, self.directions[i]); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if DEBUG { |
|
|
|
println!("- {} ", left); |
|
|
|
} |
|
|
|
|
|
|
|
if left % 2 != 0 || left == 0 { |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
f = self.waypoints.clone().into_iter().enumerate().filter(|&(_,p)| p.y == point.y && p.x > point.x); |
|
|
|
for (i, p) in f { |
|
|
|
if self.directions[i] == Direction::South { |
|
|
|
right += 1; |
|
|
|
if DEBUG { |
|
|
|
print!("{:?} {:?} ", p, self.directions[i]); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
f = self.waypoints.clone().into_iter().enumerate().filter(|&(_,p)| p.y == point.y+1 && p.x > point.x); |
|
|
|
for (i, p) in f { |
|
|
|
if self.directions[i] == Direction::North { |
|
|
|
right += 1; |
|
|
|
if DEBUG { |
|
|
|
print!("{:?} {:?} ", p, self.directions[i]); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if DEBUG { |
|
|
|
println!("- {} ", left); |
|
|
|
} |
|
|
|
right % 2 == 0 && right > 0 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
#[derive(Copy, Clone, Debug)] |
|
|
|
@ -133,6 +263,47 @@ impl Direction { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
impl PartialEq for Direction { |
|
|
|
fn eq(&self, other: &Direction) -> bool { |
|
|
|
match self { |
|
|
|
&Direction::North => { |
|
|
|
match other { |
|
|
|
&Direction::North => true, |
|
|
|
&Direction::East => false, |
|
|
|
&Direction::South => false, |
|
|
|
&Direction::West => false, |
|
|
|
} |
|
|
|
}, |
|
|
|
&Direction::East => { |
|
|
|
match other { |
|
|
|
&Direction::North => false, |
|
|
|
&Direction::East => true, |
|
|
|
&Direction::South => false, |
|
|
|
&Direction::West => false, |
|
|
|
} |
|
|
|
}, |
|
|
|
&Direction::South => { |
|
|
|
match other { |
|
|
|
&Direction::North => false, |
|
|
|
&Direction::East => false, |
|
|
|
&Direction::South => true, |
|
|
|
&Direction::West => false, |
|
|
|
} |
|
|
|
}, |
|
|
|
&Direction::West => { |
|
|
|
match other { |
|
|
|
&Direction::North => false, |
|
|
|
&Direction::East => false, |
|
|
|
&Direction::South => false, |
|
|
|
&Direction::West => true, |
|
|
|
} |
|
|
|
}, |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
impl Eq for Direction {} |
|
|
|
|
|
|
|
#[derive(Copy, Clone, Debug)] |
|
|
|
pub struct Point { |
|
|
|
x: i32, |
|
|
|
@ -268,7 +439,7 @@ mod tests { |
|
|
|
let mut trail = Trail::new(); |
|
|
|
let mut res = trail.start(input); |
|
|
|
|
|
|
|
assert_eq!(res.size, 12); |
|
|
|
assert_eq!(res.size, 9); |
|
|
|
} |
|
|
|
|
|
|
|
#[test] |
|
|
|
@ -277,7 +448,7 @@ mod tests { |
|
|
|
let mut trail = Trail::new(); |
|
|
|
let mut res = trail.start(input); |
|
|
|
|
|
|
|
assert_eq!(res.size, 12); |
|
|
|
assert_eq!(res.size, 22); |
|
|
|
} |
|
|
|
|
|
|
|
#[test] |
|
|
|
@ -286,7 +457,7 @@ mod tests { |
|
|
|
let mut trail = Trail::new(); |
|
|
|
let mut res = trail.start(input); |
|
|
|
|
|
|
|
assert_eq!(res.size, 12); |
|
|
|
assert_eq!(res.size, 115); |
|
|
|
} |
|
|
|
|
|
|
|
#[test] |
|
|
|
@ -295,7 +466,7 @@ mod tests { |
|
|
|
let mut trail = Trail::new(); |
|
|
|
let mut res = trail.start(input); |
|
|
|
|
|
|
|
assert_eq!(res.size, 12); |
|
|
|
assert_eq!(res.size, 2190); |
|
|
|
} |
|
|
|
|
|
|
|
#[test] |
|
|
|
@ -304,6 +475,6 @@ mod tests { |
|
|
|
let mut trail = Trail::new(); |
|
|
|
let mut res = trail.start(input); |
|
|
|
|
|
|
|
assert_eq!(res.size, 12); |
|
|
|
assert_eq!(res.size, 1156); |
|
|
|
} |
|
|
|
} |