132 lines
4.0 KiB
Rust
132 lines
4.0 KiB
Rust
use std::fmt;
|
|
use std::fs::File;
|
|
use std::io::{self, BufRead};
|
|
use std::path::Path;
|
|
|
|
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
|
|
where
|
|
P: AsRef<Path>,
|
|
{
|
|
let file = File::open(filename)?;
|
|
Ok(io::BufReader::new(file).lines())
|
|
}
|
|
|
|
struct Coord(i32, i32);
|
|
|
|
impl fmt::Display for Coord {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
write!(f, "(x={}, y={})", self.0, self.1)
|
|
}
|
|
}
|
|
|
|
fn part1() {
|
|
let result = read_lines("input.txt")
|
|
.expect("Expected a file to read")
|
|
.map(|line| line.expect("Could not read line"))
|
|
.map(|line| {
|
|
let mut parts = line.split_whitespace();
|
|
let direction = parts
|
|
.next()
|
|
.expect(format!("Missing direction on line: {}", line).as_str());
|
|
let distance = parts
|
|
.next()
|
|
.map(|value| {
|
|
value.parse::<i32>().expect(
|
|
format!("Expect distance to be a value instead got: {}", value).as_str(),
|
|
)
|
|
})
|
|
.expect(format!("Missing distance on line: {}", line).as_str());
|
|
if parts.next().is_some() {
|
|
panic!("More than 2 parts in line: {}", line);
|
|
}
|
|
match direction {
|
|
"forward" => Coord(distance, 0),
|
|
"down" => Coord(0, -1 * distance),
|
|
"up" => Coord(0, distance),
|
|
&_ => panic!("Unknown direction {}", direction),
|
|
}
|
|
})
|
|
.reduce(|location, delta| Coord(location.0 + delta.0, location.1 + delta.1))
|
|
.expect("No value reduced");
|
|
|
|
println!(
|
|
"Part 1 location: {}, result: {}",
|
|
result,
|
|
result.0 * result.1 * -1
|
|
)
|
|
}
|
|
|
|
struct Position {
|
|
location: Coord,
|
|
aim: i32,
|
|
}
|
|
|
|
fn part2() {
|
|
let result = read_lines("input.txt")
|
|
.expect("Expected a file to read")
|
|
.map(|line| line.expect("Could not read line"))
|
|
.map(|line| {
|
|
let mut parts = line.split_whitespace();
|
|
let direction = parts
|
|
.next()
|
|
.expect(format!("Missing direction on line: {}", line).as_str());
|
|
let value = parts
|
|
.next()
|
|
.map(|value| {
|
|
value.parse::<i32>().expect(
|
|
format!("Expect distance to be a value instead got: {}", value).as_str(),
|
|
)
|
|
})
|
|
.expect(format!("Missing distance on line: {}", line).as_str());
|
|
if parts.next().is_some() {
|
|
panic!("More than 2 parts in line: {}", line);
|
|
}
|
|
match direction {
|
|
// Increase aim
|
|
"down" => Position {
|
|
location: Coord(0, 0),
|
|
aim: value,
|
|
},
|
|
// Decrease aim
|
|
"up" => Position {
|
|
location: Coord(0, 0),
|
|
aim: -1 * value,
|
|
},
|
|
// Increase horiziontal and depty by aim
|
|
"forward" => Position {
|
|
location: Coord(value, value),
|
|
aim: 0,
|
|
},
|
|
&_ => panic!("Unknown direction {}", direction),
|
|
}
|
|
})
|
|
.fold(
|
|
Position {
|
|
location: Coord(0, 0),
|
|
aim: 0,
|
|
},
|
|
|position, delta| {
|
|
let aim = position.aim + delta.aim;
|
|
let x = position.location.0 + delta.location.0;
|
|
let y = position.location.1 - (aim * delta.location.1);
|
|
let coord = Coord(x, y);
|
|
println!("Coord: {}, aim: {}", coord, aim);
|
|
Position {
|
|
location: coord,
|
|
aim: aim,
|
|
}
|
|
},
|
|
);
|
|
|
|
println!(
|
|
"Part 2 location: {}, result: {}",
|
|
result.location,
|
|
result.location.0 * result.location.1 * -1
|
|
)
|
|
}
|
|
|
|
fn main() {
|
|
part1();
|
|
part2();
|
|
}
|