diff --git a/day05/common.rs b/day05/common.rs new file mode 100644 index 0000000..facbef5 --- /dev/null +++ b/day05/common.rs @@ -0,0 +1,154 @@ +// Copyright 2022 Christian Ulrich +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use std::io; + +#[derive(Debug)] +pub struct Stacks { + inner: Vec>, +} + +pub struct Moves {} + +#[derive(Debug)] +pub struct Move { + count: usize, + from: usize, + to: usize, +} + +impl Stacks { + pub fn from_stdin() -> Result { + let mut stacks = vec![]; + for line in io::stdin().lines() { + match Self::parse_line(&line.unwrap())? { + None => break, + Some(items) => { + if items.len() != stacks.len() { + if !stacks.is_empty() { + return Err("input file contains invalid line"); + } + stacks = vec![vec![]; items.len()]; + } + for i in 0..items.len() { + if let Some(item) = items[i] { + stacks[i].push(item); + } + } + } + } + } + for stack in stacks.iter_mut() { + stack.reverse(); + } + Ok(Self { inner: stacks }) + } + + fn parse_line(input: &str) -> Result>>, &'static str> { + if input.starts_with(" 1 ") { + return Ok(None); + } + let mut result = vec![]; + for chunk in input.chars().collect::>().chunks(4) { + match chunk.iter().collect::().as_str() { + "" => break, + item => result.push(Self::parse_item(item)?), + } + } + Ok(Some(result)) + } + + fn parse_item(input: &str) -> Result, &'static str> { + match input.trim() { + "" => return Ok(None), + item => { + if item.len() == 3 + && item.chars().nth(0).unwrap() == '[' + && item.chars().nth(2).unwrap() == ']' + { + return Ok(item.chars().nth(1)); + } + } + } + Err("cannot parse item") + } + + pub fn move_items(&mut self, spec: Move) -> Result<(), &'static str> { + if spec.from >= self.inner.len() + || spec.to >= self.inner.len() + || spec.count > self.inner[spec.from].len() + { + return Err("invalid move"); + } + for _ in 0..spec.count { + let item = self.inner[spec.from].pop().unwrap(); + self.inner[spec.to].push(item); + } + Ok(()) + } +} + +impl Iterator for Stacks { + type Item = Vec; + + fn next(&mut self) -> Option { + match self.inner.len() { + 0 => None, + _ => Some(self.inner.remove(0)), + } + } +} + +impl Move { + pub fn from_str(input: &str) -> Result { + let parts = input.split(' ').collect::>(); + if parts.len() != 6 || parts[0] != "move" || parts[2] != "from" || parts[4] != "to" { + return Err("cannot parse move"); + } + let from = match parts[3].parse::().map_err(|_| "cannot parse move")? { + value if { value > 0 } => Ok(value - 1), + _ => Err("integer out of range"), + }; + let to = match parts[5].parse::().map_err(|_| "cannot parse move")? { + value if { value > 0 } => Ok(value - 1), + _ => Err("integer out of range"), + }; + Ok(Self { + count: parts[1].parse().map_err(|_| "cannot parse integer")?, + from: from?, + to: to?, + }) + } +} + +impl Moves { + pub fn from_stdin() -> Self { + Self {} + } +} + +impl Iterator for Moves { + type Item = Result; + + fn next(&mut self) -> Option { + for line in io::stdin().lines() { + let line = line.unwrap(); + if line.len() > 0 { + return Some(Move::from_str(&line)); + } + } + None + } +} diff --git a/day05/input b/day05/input new file mode 100644 index 0000000..924a9a2 --- /dev/null +++ b/day05/input @@ -0,0 +1,516 @@ + [G] [W] [Q] +[Z] [Q] [M] [J] [F] +[V] [V] [S] [F] [N] [R] +[T] [F] [C] [H] [F] [W] [P] +[B] [L] [L] [J] [C] [V] [D] [V] +[J] [V] [F] [N] [T] [T] [C] [Z] [W] +[G] [R] [Q] [H] [Q] [W] [Z] [G] [B] +[R] [J] [S] [Z] [R] [S] [D] [L] [J] + 1 2 3 4 5 6 7 8 9 + +move 6 from 5 to 7 +move 2 from 9 to 1 +move 4 from 8 to 6 +move 1 from 8 to 1 +move 2 from 9 to 1 +move 1 from 6 to 1 +move 13 from 7 to 8 +move 1 from 2 to 8 +move 9 from 1 to 5 +move 1 from 3 to 8 +move 3 from 6 to 7 +move 4 from 4 to 1 +move 11 from 5 to 6 +move 6 from 6 to 9 +move 3 from 4 to 2 +move 7 from 8 to 6 +move 1 from 7 to 5 +move 1 from 4 to 3 +move 7 from 1 to 5 +move 2 from 2 to 7 +move 4 from 9 to 6 +move 1 from 3 to 6 +move 1 from 1 to 9 +move 1 from 3 to 6 +move 1 from 5 to 8 +move 4 from 6 to 7 +move 3 from 8 to 7 +move 7 from 5 to 7 +move 1 from 3 to 1 +move 1 from 2 to 6 +move 14 from 6 to 5 +move 2 from 5 to 2 +move 3 from 9 to 2 +move 6 from 2 to 9 +move 7 from 8 to 6 +move 7 from 7 to 3 +move 2 from 8 to 7 +move 6 from 3 to 7 +move 17 from 7 to 1 +move 1 from 3 to 1 +move 1 from 2 to 5 +move 4 from 5 to 6 +move 17 from 6 to 9 +move 7 from 9 to 4 +move 1 from 2 to 7 +move 2 from 5 to 4 +move 3 from 7 to 8 +move 7 from 5 to 2 +move 6 from 2 to 8 +move 8 from 9 to 6 +move 1 from 2 to 3 +move 8 from 4 to 9 +move 7 from 6 to 9 +move 18 from 1 to 7 +move 1 from 1 to 8 +move 2 from 6 to 9 +move 1 from 3 to 9 +move 1 from 4 to 6 +move 1 from 8 to 3 +move 1 from 3 to 1 +move 10 from 7 to 2 +move 9 from 8 to 4 +move 1 from 6 to 4 +move 2 from 7 to 8 +move 5 from 4 to 9 +move 17 from 9 to 5 +move 2 from 7 to 6 +move 5 from 9 to 7 +move 5 from 4 to 2 +move 8 from 2 to 4 +move 8 from 4 to 3 +move 2 from 6 to 5 +move 2 from 8 to 5 +move 3 from 9 to 3 +move 4 from 7 to 3 +move 6 from 9 to 6 +move 4 from 6 to 9 +move 5 from 9 to 3 +move 8 from 5 to 2 +move 1 from 1 to 9 +move 1 from 6 to 3 +move 1 from 9 to 4 +move 5 from 7 to 4 +move 19 from 3 to 1 +move 4 from 2 to 8 +move 13 from 5 to 1 +move 1 from 6 to 3 +move 3 from 3 to 6 +move 2 from 8 to 9 +move 4 from 2 to 9 +move 2 from 2 to 6 +move 1 from 1 to 6 +move 5 from 1 to 9 +move 10 from 9 to 3 +move 15 from 1 to 6 +move 21 from 6 to 2 +move 20 from 2 to 1 +move 2 from 8 to 9 +move 28 from 1 to 2 +move 6 from 4 to 6 +move 2 from 1 to 5 +move 3 from 3 to 4 +move 2 from 5 to 4 +move 1 from 4 to 3 +move 3 from 4 to 5 +move 2 from 5 to 4 +move 1 from 1 to 8 +move 25 from 2 to 9 +move 1 from 4 to 6 +move 1 from 3 to 8 +move 4 from 3 to 6 +move 1 from 4 to 9 +move 2 from 6 to 3 +move 1 from 5 to 9 +move 5 from 2 to 8 +move 7 from 9 to 6 +move 2 from 9 to 4 +move 3 from 2 to 1 +move 3 from 3 to 4 +move 1 from 3 to 5 +move 16 from 6 to 3 +move 7 from 8 to 3 +move 5 from 4 to 3 +move 1 from 1 to 3 +move 1 from 2 to 6 +move 1 from 5 to 6 +move 21 from 3 to 5 +move 2 from 1 to 2 +move 1 from 6 to 7 +move 10 from 9 to 8 +move 1 from 6 to 5 +move 5 from 8 to 7 +move 12 from 5 to 3 +move 20 from 3 to 6 +move 4 from 7 to 9 +move 1 from 7 to 3 +move 1 from 2 to 5 +move 1 from 3 to 8 +move 2 from 8 to 4 +move 4 from 8 to 7 +move 3 from 6 to 1 +move 1 from 1 to 5 +move 2 from 9 to 2 +move 2 from 1 to 5 +move 2 from 5 to 6 +move 3 from 7 to 1 +move 2 from 1 to 4 +move 4 from 6 to 8 +move 3 from 4 to 7 +move 3 from 2 to 5 +move 2 from 7 to 9 +move 9 from 9 to 8 +move 1 from 4 to 1 +move 7 from 5 to 7 +move 1 from 7 to 8 +move 1 from 3 to 1 +move 4 from 7 to 5 +move 2 from 1 to 9 +move 1 from 1 to 2 +move 5 from 5 to 4 +move 1 from 2 to 6 +move 5 from 7 to 9 +move 5 from 4 to 7 +move 11 from 9 to 6 +move 14 from 8 to 9 +move 23 from 6 to 5 +move 6 from 9 to 5 +move 1 from 6 to 2 +move 10 from 5 to 3 +move 1 from 4 to 9 +move 1 from 2 to 1 +move 2 from 7 to 3 +move 10 from 5 to 7 +move 8 from 5 to 2 +move 5 from 3 to 5 +move 7 from 5 to 8 +move 1 from 2 to 7 +move 9 from 7 to 9 +move 3 from 2 to 3 +move 2 from 6 to 2 +move 2 from 3 to 6 +move 4 from 7 to 5 +move 1 from 1 to 5 +move 4 from 3 to 1 +move 2 from 5 to 2 +move 1 from 3 to 2 +move 2 from 6 to 8 +move 7 from 5 to 3 +move 9 from 2 to 4 +move 2 from 1 to 2 +move 2 from 5 to 3 +move 1 from 4 to 9 +move 1 from 6 to 9 +move 1 from 4 to 2 +move 2 from 1 to 7 +move 3 from 2 to 6 +move 4 from 8 to 7 +move 2 from 8 to 3 +move 2 from 3 to 7 +move 1 from 6 to 5 +move 2 from 8 to 2 +move 5 from 4 to 1 +move 8 from 9 to 8 +move 1 from 5 to 7 +move 10 from 9 to 2 +move 8 from 8 to 2 +move 1 from 1 to 6 +move 12 from 3 to 9 +move 7 from 7 to 4 +move 13 from 2 to 4 +move 7 from 2 to 7 +move 1 from 6 to 7 +move 3 from 9 to 8 +move 2 from 6 to 3 +move 1 from 3 to 2 +move 1 from 3 to 9 +move 3 from 1 to 5 +move 1 from 1 to 6 +move 4 from 7 to 6 +move 5 from 7 to 1 +move 1 from 2 to 1 +move 6 from 9 to 4 +move 5 from 9 to 7 +move 3 from 8 to 3 +move 22 from 4 to 9 +move 24 from 9 to 8 +move 1 from 9 to 2 +move 2 from 4 to 3 +move 10 from 8 to 3 +move 1 from 2 to 1 +move 1 from 3 to 8 +move 1 from 6 to 3 +move 1 from 1 to 4 +move 4 from 3 to 4 +move 4 from 6 to 1 +move 2 from 4 to 5 +move 4 from 7 to 2 +move 7 from 4 to 6 +move 4 from 6 to 1 +move 2 from 6 to 3 +move 1 from 6 to 2 +move 5 from 5 to 2 +move 12 from 3 to 5 +move 3 from 7 to 8 +move 6 from 2 to 3 +move 11 from 1 to 9 +move 1 from 1 to 7 +move 1 from 7 to 5 +move 2 from 3 to 9 +move 2 from 9 to 7 +move 4 from 2 to 5 +move 2 from 7 to 1 +move 17 from 8 to 1 +move 1 from 3 to 2 +move 16 from 1 to 3 +move 8 from 3 to 4 +move 2 from 8 to 3 +move 2 from 1 to 5 +move 1 from 2 to 6 +move 12 from 5 to 8 +move 1 from 6 to 3 +move 9 from 3 to 9 +move 8 from 4 to 6 +move 2 from 1 to 6 +move 6 from 8 to 4 +move 3 from 4 to 6 +move 1 from 1 to 9 +move 11 from 6 to 8 +move 3 from 4 to 3 +move 17 from 9 to 5 +move 2 from 6 to 7 +move 1 from 9 to 1 +move 2 from 8 to 6 +move 1 from 7 to 5 +move 1 from 8 to 9 +move 1 from 1 to 7 +move 3 from 9 to 6 +move 2 from 7 to 8 +move 1 from 9 to 6 +move 15 from 5 to 2 +move 9 from 3 to 9 +move 11 from 8 to 3 +move 6 from 9 to 8 +move 4 from 6 to 7 +move 3 from 3 to 7 +move 5 from 5 to 6 +move 7 from 7 to 5 +move 3 from 6 to 1 +move 2 from 1 to 4 +move 1 from 9 to 2 +move 2 from 9 to 3 +move 2 from 6 to 3 +move 1 from 1 to 8 +move 6 from 5 to 9 +move 8 from 2 to 5 +move 10 from 8 to 5 +move 1 from 2 to 9 +move 21 from 5 to 9 +move 2 from 8 to 4 +move 5 from 9 to 1 +move 2 from 5 to 2 +move 15 from 9 to 2 +move 1 from 5 to 9 +move 9 from 9 to 3 +move 1 from 1 to 6 +move 3 from 4 to 1 +move 20 from 3 to 5 +move 20 from 5 to 4 +move 7 from 4 to 3 +move 1 from 1 to 7 +move 11 from 4 to 5 +move 4 from 3 to 2 +move 11 from 5 to 4 +move 2 from 6 to 7 +move 4 from 3 to 9 +move 2 from 2 to 8 +move 2 from 9 to 4 +move 6 from 4 to 6 +move 2 from 7 to 9 +move 1 from 7 to 6 +move 1 from 4 to 9 +move 4 from 4 to 6 +move 2 from 8 to 6 +move 1 from 4 to 3 +move 1 from 4 to 6 +move 1 from 3 to 1 +move 3 from 4 to 3 +move 9 from 2 to 8 +move 2 from 3 to 7 +move 5 from 6 to 2 +move 2 from 7 to 5 +move 1 from 5 to 2 +move 1 from 9 to 3 +move 1 from 5 to 1 +move 13 from 2 to 5 +move 4 from 9 to 5 +move 1 from 3 to 4 +move 9 from 2 to 3 +move 7 from 3 to 2 +move 11 from 5 to 6 +move 5 from 8 to 7 +move 1 from 3 to 1 +move 2 from 8 to 5 +move 2 from 8 to 1 +move 1 from 4 to 1 +move 6 from 2 to 7 +move 3 from 5 to 3 +move 1 from 2 to 5 +move 7 from 7 to 9 +move 3 from 3 to 5 +move 1 from 2 to 5 +move 2 from 3 to 2 +move 6 from 1 to 7 +move 10 from 7 to 3 +move 1 from 2 to 3 +move 6 from 9 to 8 +move 1 from 2 to 4 +move 2 from 6 to 1 +move 5 from 1 to 9 +move 8 from 5 to 8 +move 2 from 1 to 6 +move 6 from 3 to 4 +move 1 from 5 to 3 +move 4 from 9 to 6 +move 1 from 1 to 4 +move 2 from 9 to 2 +move 5 from 6 to 1 +move 11 from 6 to 7 +move 1 from 2 to 8 +move 6 from 7 to 5 +move 10 from 8 to 4 +move 2 from 3 to 9 +move 3 from 3 to 5 +move 4 from 7 to 9 +move 2 from 1 to 3 +move 10 from 5 to 8 +move 6 from 6 to 1 +move 2 from 6 to 8 +move 2 from 9 to 5 +move 4 from 9 to 6 +move 7 from 4 to 8 +move 5 from 6 to 1 +move 4 from 8 to 2 +move 2 from 5 to 6 +move 5 from 4 to 5 +move 1 from 7 to 5 +move 2 from 3 to 6 +move 1 from 3 to 8 +move 4 from 6 to 1 +move 4 from 2 to 3 +move 5 from 5 to 1 +move 2 from 3 to 2 +move 2 from 3 to 2 +move 20 from 8 to 2 +move 5 from 4 to 8 +move 1 from 4 to 3 +move 8 from 2 to 1 +move 1 from 5 to 6 +move 5 from 2 to 3 +move 1 from 6 to 5 +move 5 from 3 to 2 +move 1 from 3 to 7 +move 6 from 8 to 5 +move 13 from 2 to 9 +move 7 from 9 to 8 +move 1 from 7 to 8 +move 5 from 8 to 3 +move 2 from 2 to 5 +move 2 from 8 to 4 +move 27 from 1 to 5 +move 1 from 2 to 3 +move 5 from 3 to 1 +move 22 from 5 to 7 +move 1 from 8 to 5 +move 1 from 3 to 2 +move 7 from 1 to 3 +move 2 from 3 to 7 +move 2 from 2 to 4 +move 5 from 9 to 1 +move 5 from 3 to 9 +move 3 from 1 to 5 +move 3 from 1 to 6 +move 3 from 6 to 3 +move 4 from 4 to 2 +move 8 from 5 to 3 +move 8 from 7 to 4 +move 14 from 7 to 4 +move 1 from 1 to 7 +move 6 from 9 to 6 +move 7 from 5 to 3 +move 14 from 3 to 6 +move 2 from 2 to 1 +move 4 from 3 to 7 +move 6 from 7 to 6 +move 1 from 7 to 6 +move 1 from 5 to 1 +move 2 from 1 to 5 +move 3 from 5 to 7 +move 8 from 6 to 5 +move 5 from 5 to 1 +move 1 from 7 to 3 +move 1 from 3 to 8 +move 22 from 4 to 7 +move 7 from 6 to 3 +move 4 from 3 to 2 +move 3 from 1 to 3 +move 17 from 7 to 6 +move 1 from 8 to 1 +move 2 from 2 to 4 +move 3 from 7 to 2 +move 2 from 2 to 9 +move 1 from 1 to 8 +move 2 from 3 to 1 +move 6 from 6 to 8 +move 2 from 9 to 2 +move 4 from 5 to 1 +move 5 from 8 to 9 +move 1 from 7 to 3 +move 4 from 3 to 4 +move 1 from 7 to 4 +move 4 from 9 to 7 +move 5 from 7 to 9 +move 1 from 7 to 3 +move 2 from 2 to 8 +move 5 from 4 to 2 +move 21 from 6 to 8 +move 2 from 3 to 8 +move 23 from 8 to 6 +move 1 from 2 to 6 +move 2 from 9 to 8 +move 22 from 6 to 7 +move 2 from 9 to 3 +move 2 from 3 to 7 +move 2 from 1 to 6 +move 1 from 2 to 5 +move 3 from 1 to 3 +move 6 from 7 to 4 +move 5 from 8 to 5 +move 1 from 3 to 8 +move 1 from 9 to 3 +move 6 from 4 to 8 +move 1 from 5 to 3 +move 6 from 2 to 8 +move 15 from 7 to 5 +move 1 from 7 to 1 +move 14 from 5 to 8 +move 1 from 4 to 9 +move 5 from 1 to 7 +move 3 from 6 to 2 +move 4 from 5 to 6 +move 1 from 4 to 8 +move 4 from 3 to 1 +move 2 from 9 to 2 +move 7 from 7 to 1 +move 7 from 2 to 7 +move 9 from 8 to 6 +move 7 from 7 to 1 +move 12 from 6 to 8 +move 25 from 8 to 6 +move 3 from 8 to 1 +move 28 from 6 to 2 +move 15 from 2 to 3 +move 1 from 5 to 4 +move 3 from 2 to 7 +move 6 from 2 to 9 + diff --git a/day05/part1.rs b/day05/part1.rs new file mode 100644 index 0000000..c23971a --- /dev/null +++ b/day05/part1.rs @@ -0,0 +1,32 @@ +// Copyright 2022 Christian Ulrich +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// usage: ./part1 < input + +pub mod common; + +use common::{Moves, Stacks}; + +fn main() -> Result<(), &'static str> { + let mut stacks = Stacks::from_stdin()?; + for op in Moves::from_stdin() { + stacks.move_items(op?)?; + } + let result: Result = stacks + .map(|s| s.last().cloned().ok_or("at least one stack is empty")) + .collect(); + println!("{}", result?); + Ok(()) +} diff --git a/day05/testinput b/day05/testinput new file mode 100644 index 0000000..84933bb --- /dev/null +++ b/day05/testinput @@ -0,0 +1,9 @@ + [D] +[N] [C] +[Z] [M] [P] + 1 2 3 + +move 1 from 2 to 1 +move 3 from 1 to 3 +move 2 from 2 to 1 +move 1 from 1 to 2