use std::fmt; use std::fs::File; use std::io::{self, BufRead}; use std::path::Path; fn read_lines

(filename: P) -> io::Result>> where P: AsRef, { 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::().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::().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(); }