use crate::util::iter::*;
use crate::util::parse::*;
use crate::util::point::*;
type Move = (Point, i32);
type Input = (Vec<Move>, Vec<Move>);
pub fn parse(input: &str) -> Input {
let mut first = Vec::with_capacity(1000);
let mut second = Vec::with_capacity(1000);
for [a, b, c] in input.split_ascii_whitespace().chunk::<3>() {
let direction = Point::from(a.as_bytes()[0]);
let amount = b.signed();
first.push((direction, amount));
let direction = match c.as_bytes()[7] {
b'0' => RIGHT,
b'1' => DOWN,
b'2' => LEFT,
b'3' => UP,
_ => unreachable!(),
};
let hex = &c[2..c.len() - 2];
let amount = i32::from_str_radix(hex, 16).unwrap();
second.push((direction, amount));
}
(first, second)
}
pub fn part1(input: &Input) -> i64 {
lava(&input.0)
}
pub fn part2(input: &Input) -> i64 {
lava(&input.1)
}
fn lava(moves: &[Move]) -> i64 {
let mut previous;
let mut position = ORIGIN;
let mut area = 0;
let mut perimeter = 0;
for &(direction, amount) in moves {
previous = position;
position += direction * amount;
area += determinant(previous, position);
perimeter += amount as i64;
}
area / 2 + perimeter / 2 + 1
}
fn determinant(a: Point, b: Point) -> i64 {
(a.x as i64) * (b.y as i64) - (a.y as i64) * (b.x as i64)
}