diff options
-rw-r--r-- | 2021/rust/Cargo.toml | 2 | ||||
-rw-r--r-- | 2021/rust/day02/Cargo.toml | 10 | ||||
-rw-r--r-- | 2021/rust/day02/src/main.rs | 140 |
3 files changed, 151 insertions, 1 deletions
diff --git a/2021/rust/Cargo.toml b/2021/rust/Cargo.toml index 9674b94..8609abe 100644 --- a/2021/rust/Cargo.toml +++ b/2021/rust/Cargo.toml @@ -1,7 +1,7 @@ [workspace] members = [ "day01", -# "day02", + "day02", # "day03", # "day04", # "day05", diff --git a/2021/rust/day02/Cargo.toml b/2021/rust/day02/Cargo.toml new file mode 100644 index 0000000..232d0dc --- /dev/null +++ b/2021/rust/day02/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "day02" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +aoc = { path = "../../../common/rust/aoc" } +anyhow = "1.0" diff --git a/2021/rust/day02/src/main.rs b/2021/rust/day02/src/main.rs new file mode 100644 index 0000000..4178ecc --- /dev/null +++ b/2021/rust/day02/src/main.rs @@ -0,0 +1,140 @@ +use { + anyhow::{ + anyhow, + Context, + Result, + }, + std::{ + env::args, + fmt::{ + Debug, + Display, + }, + fs::File, + io::{ + BufRead, + BufReader, + }, + path::Path, + str::FromStr, + }, +}; + +struct Position { + x: isize, + y: isize, +} + +impl Display for Position { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "(x: {}, y: {})", self.x, self.y) + } +} + +#[derive(PartialEq)] +enum Command { + Down(usize), + Forward(usize), + Up(usize), +} + +struct CommandError { + s: String, +} + +impl CommandError { + fn new(s: &str) -> Self { + Self { + s: String::from(s), + } + } +} + +type CommandResult<T> = std::result::Result<T, CommandError>; + +impl Display for CommandError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "invalid command string: {}", self.s) + } +} + +impl Debug for CommandError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "invalid command string: {}", self.s) + } +} + +impl FromStr for Command { + type Err = CommandError; + + fn from_str(s: &str) -> CommandResult<Self> { + let (direction, steps) = s.split_once(' ').ok_or_else(|| CommandError::new(s))?; + let count = steps.parse().map_err(|_| CommandError::new(s))?; + if direction == "up" { + Ok(Command::Up(count)) + } else if direction == "down" { + Ok(Command::Down(count)) + } else if direction == "forward" { + Ok(Command::Forward(count)) + } else { + Err(CommandError::new(s)) + } + + } +} + +fn read_input<T: AsRef<Path>>(filename: T) -> Result<Vec<Command>> { + let reader = BufReader::new(File::open(filename)?); + + reader.lines().map( + |v| v?.parse().map_err(|err| anyhow!("Could not parse input: {}", err)) + ).collect() +} + +fn part1(input: &[Command]) -> Result<Position> { + let mut position = Position { x: 0, y:0 }; + for command in input { + match command { + Command::Up(steps) => position.y -= *steps as isize, + Command::Down(steps) => position.y += *steps as isize, + Command::Forward(steps) => position.x += *steps as isize, + } + } + + Ok(position) +} + +fn part2(input: &[Command]) -> Result<Position> { + let mut position = Position { x: 0, y:0 }; + let mut aim = 0; + for command in input { + match command { + Command::Up(steps) => aim -= *steps as isize, + Command::Down(steps) => aim += *steps as isize, + Command::Forward(steps) => { + position.x += *steps as isize; + position.y += aim * *steps as isize; + }, + } + } + + Ok(position) +} + +fn main() -> Result<()> { + let ( do_part_1, do_part_2 ) = aoc::do_parts(); + + let filename = args().nth(1).ok_or(anyhow!("Missing input filename"))?; + let input = read_input(filename).context("Could not read input")?; + if do_part_1 { + let position = part1(&input).context("No solution for part 1")?; + let solution = position.x * position.y; + println!("Part1, resulting position: {}. Door answer: {}", position, solution); + } + if do_part_2 { + let position = part2(&input).context("No solution for part 1")?; + let solution = position.x * position.y; + println!("Part2, resulting position: {}. Door answer: {}", position, solution); + } + Ok(()) +} |