add day 11, part 1
This commit is contained in:
parent
88e56549d7
commit
d0c057572a
|
@ -0,0 +1,197 @@
|
||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
enum Operation {
|
||||||
|
Add { arg: u64 },
|
||||||
|
Multiply { arg: u64 },
|
||||||
|
Square,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Monkey {
|
||||||
|
items: Vec<u64>,
|
||||||
|
operation: Operation,
|
||||||
|
modulus: u64,
|
||||||
|
target_devisible: usize,
|
||||||
|
target_indevisible: usize,
|
||||||
|
item_count: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Game {
|
||||||
|
monkeys: Vec<Monkey>,
|
||||||
|
divisor: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Round {
|
||||||
|
monkeys: Vec<Monkey>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Monkey {
|
||||||
|
fn from_stdin() -> Result<Option<Self>, &'static str> {
|
||||||
|
const ERROR: &str = "cannot parse monkey";
|
||||||
|
let mut line = String::new();
|
||||||
|
let _ = io::stdin().read_line(&mut line).map_err(|_| ERROR)?;
|
||||||
|
if line.len() == 0 {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
if !line.starts_with("Monkey ") {
|
||||||
|
return Err(ERROR);
|
||||||
|
}
|
||||||
|
line.clear();
|
||||||
|
|
||||||
|
// parse starting items
|
||||||
|
let _ = io::stdin().read_line(&mut line).map_err(|_| ERROR)?;
|
||||||
|
if !line.starts_with(" Starting items: ") {
|
||||||
|
return Err(ERROR);
|
||||||
|
}
|
||||||
|
let mut items = vec![];
|
||||||
|
for part in line[18..].split(',') {
|
||||||
|
items.push(part.trim().parse::<u64>().map_err(|_| ERROR)?);
|
||||||
|
}
|
||||||
|
line.clear();
|
||||||
|
|
||||||
|
// parse operation
|
||||||
|
let _ = io::stdin().read_line(&mut line).map_err(|_| ERROR)?;
|
||||||
|
if !line.starts_with(" Operation: new = old ") {
|
||||||
|
return Err(ERROR);
|
||||||
|
}
|
||||||
|
let operation = match line[23..].trim() {
|
||||||
|
"* old" => Operation::Square,
|
||||||
|
arg if { arg.starts_with("+ ") } => Operation::Add {
|
||||||
|
arg: arg[2..].parse().map_err(|_| ERROR)?,
|
||||||
|
},
|
||||||
|
arg if { arg.starts_with("* ") } => Operation::Multiply {
|
||||||
|
arg: arg[2..].parse().map_err(|_| ERROR)?,
|
||||||
|
},
|
||||||
|
_ => return Err(ERROR),
|
||||||
|
};
|
||||||
|
line.clear();
|
||||||
|
|
||||||
|
// parse modulus
|
||||||
|
let _ = io::stdin().read_line(&mut line).map_err(|_| ERROR)?;
|
||||||
|
if !line.starts_with(" Test: divisible by ") {
|
||||||
|
return Err(ERROR);
|
||||||
|
}
|
||||||
|
let modulus = line[21..].trim().parse().map_err(|_| ERROR)?;
|
||||||
|
line.clear();
|
||||||
|
|
||||||
|
// parse action if devisible
|
||||||
|
let _ = io::stdin().read_line(&mut line).map_err(|_| ERROR)?;
|
||||||
|
if !line.starts_with(" If true: throw to monkey ") {
|
||||||
|
return Err(ERROR);
|
||||||
|
}
|
||||||
|
let target_devisible = line[29..].trim().parse().map_err(|_| ERROR)?;
|
||||||
|
line.clear();
|
||||||
|
|
||||||
|
// parse action if indevisible
|
||||||
|
let _ = io::stdin().read_line(&mut line).map_err(|_| ERROR)?;
|
||||||
|
if !line.starts_with(" If false: throw to monkey ") {
|
||||||
|
return Err(ERROR);
|
||||||
|
}
|
||||||
|
let target_indevisible = line[30..].trim().parse().map_err(|_| ERROR)?;
|
||||||
|
line.clear();
|
||||||
|
let _ = io::stdin().read_line(&mut line).map_err(|_| ERROR)?;
|
||||||
|
if line.trim().len() > 0 {
|
||||||
|
return Err(ERROR);
|
||||||
|
}
|
||||||
|
Ok(Some(Self {
|
||||||
|
items: items,
|
||||||
|
operation: operation,
|
||||||
|
modulus: modulus,
|
||||||
|
target_devisible: target_devisible,
|
||||||
|
target_indevisible: target_indevisible,
|
||||||
|
item_count: 0,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn throw_item(&mut self, divisor: u64) -> Result<Option<(u64, usize)>, &'static str> {
|
||||||
|
const ERROR: &str = "integer overflow";
|
||||||
|
if self.items.len() == 0 {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
let mut item = self.items.remove(0);
|
||||||
|
match self.operation {
|
||||||
|
Operation::Add { arg } => item = item.checked_add(arg).ok_or(ERROR)?,
|
||||||
|
Operation::Multiply { arg } => item = item.checked_mul(arg).ok_or(ERROR)?,
|
||||||
|
Operation::Square => item = item.checked_mul(item).ok_or(ERROR)?,
|
||||||
|
};
|
||||||
|
item /= divisor;
|
||||||
|
let target = match item % self.modulus {
|
||||||
|
0 => self.target_devisible,
|
||||||
|
_ => self.target_indevisible,
|
||||||
|
};
|
||||||
|
self.item_count += 1;
|
||||||
|
Ok(Some((item, target)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_item(&mut self, item: u64) {
|
||||||
|
self.items.push(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn items(&self) -> &[u64] {
|
||||||
|
&self.items[..]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn item_count(&self) -> usize {
|
||||||
|
self.item_count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Game {
|
||||||
|
pub fn from_stdin(divisor: u64) -> Result<Self, &'static str> {
|
||||||
|
let mut monkeys = vec![];
|
||||||
|
while let Some(monkey) = Monkey::from_stdin()? {
|
||||||
|
monkeys.push(monkey);
|
||||||
|
}
|
||||||
|
Ok(Self {
|
||||||
|
monkeys: monkeys,
|
||||||
|
divisor: divisor,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn monkeys(&self) -> &[Monkey] {
|
||||||
|
&self.monkeys[..]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for Game {
|
||||||
|
type Item = Result<Round, &'static str>;
|
||||||
|
|
||||||
|
fn next<'a>(&'a mut self) -> Option<Self::Item> {
|
||||||
|
for i in 0..self.monkeys.len() {
|
||||||
|
loop {
|
||||||
|
match self.monkeys[i].throw_item(self.divisor) {
|
||||||
|
Ok(None) => break,
|
||||||
|
Ok(Some((item, target))) => {
|
||||||
|
self.monkeys[target].add_item(item);
|
||||||
|
}
|
||||||
|
Err(e) => return Some(Err(e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(Ok(Round {
|
||||||
|
monkeys: self.monkeys.clone(),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Round {
|
||||||
|
pub fn monkeys(&self) -> &[Monkey] {
|
||||||
|
&self.monkeys[..]
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
Monkey 0:
|
||||||
|
Starting items: 98, 70, 75, 80, 84, 89, 55, 98
|
||||||
|
Operation: new = old * 2
|
||||||
|
Test: divisible by 11
|
||||||
|
If true: throw to monkey 1
|
||||||
|
If false: throw to monkey 4
|
||||||
|
|
||||||
|
Monkey 1:
|
||||||
|
Starting items: 59
|
||||||
|
Operation: new = old * old
|
||||||
|
Test: divisible by 19
|
||||||
|
If true: throw to monkey 7
|
||||||
|
If false: throw to monkey 3
|
||||||
|
|
||||||
|
Monkey 2:
|
||||||
|
Starting items: 77, 95, 54, 65, 89
|
||||||
|
Operation: new = old + 6
|
||||||
|
Test: divisible by 7
|
||||||
|
If true: throw to monkey 0
|
||||||
|
If false: throw to monkey 5
|
||||||
|
|
||||||
|
Monkey 3:
|
||||||
|
Starting items: 71, 64, 75
|
||||||
|
Operation: new = old + 2
|
||||||
|
Test: divisible by 17
|
||||||
|
If true: throw to monkey 6
|
||||||
|
If false: throw to monkey 2
|
||||||
|
|
||||||
|
Monkey 4:
|
||||||
|
Starting items: 74, 55, 87, 98
|
||||||
|
Operation: new = old * 11
|
||||||
|
Test: divisible by 3
|
||||||
|
If true: throw to monkey 1
|
||||||
|
If false: throw to monkey 7
|
||||||
|
|
||||||
|
Monkey 5:
|
||||||
|
Starting items: 90, 98, 85, 52, 91, 60
|
||||||
|
Operation: new = old + 7
|
||||||
|
Test: divisible by 5
|
||||||
|
If true: throw to monkey 0
|
||||||
|
If false: throw to monkey 4
|
||||||
|
|
||||||
|
Monkey 6:
|
||||||
|
Starting items: 99, 51
|
||||||
|
Operation: new = old + 1
|
||||||
|
Test: divisible by 13
|
||||||
|
If true: throw to monkey 5
|
||||||
|
If false: throw to monkey 2
|
||||||
|
|
||||||
|
Monkey 7:
|
||||||
|
Starting items: 98, 94, 59, 76, 51, 65, 75
|
||||||
|
Operation: new = old + 5
|
||||||
|
Test: divisible by 2
|
||||||
|
If true: throw to monkey 3
|
||||||
|
If false: throw to monkey 6
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
// usage: ./part1 < input
|
||||||
|
|
||||||
|
pub mod common;
|
||||||
|
|
||||||
|
use common::{Game, Monkey};
|
||||||
|
|
||||||
|
fn main() -> Result<(), &'static str> {
|
||||||
|
let game = Game::from_stdin(3)?;
|
||||||
|
let last_round = game.take(20).last().unwrap();
|
||||||
|
let mut item_counts: Vec<_> = last_round?
|
||||||
|
.monkeys()
|
||||||
|
.iter()
|
||||||
|
.map(Monkey::item_count)
|
||||||
|
.collect();
|
||||||
|
item_counts.sort();
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
item_counts[item_counts.len() - 1] * item_counts[item_counts.len() - 2]
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
Monkey 0:
|
||||||
|
Starting items: 79, 98
|
||||||
|
Operation: new = old * 19
|
||||||
|
Test: divisible by 23
|
||||||
|
If true: throw to monkey 2
|
||||||
|
If false: throw to monkey 3
|
||||||
|
|
||||||
|
Monkey 1:
|
||||||
|
Starting items: 54, 65, 75, 74
|
||||||
|
Operation: new = old + 6
|
||||||
|
Test: divisible by 19
|
||||||
|
If true: throw to monkey 2
|
||||||
|
If false: throw to monkey 0
|
||||||
|
|
||||||
|
Monkey 2:
|
||||||
|
Starting items: 79, 60, 97
|
||||||
|
Operation: new = old * old
|
||||||
|
Test: divisible by 13
|
||||||
|
If true: throw to monkey 1
|
||||||
|
If false: throw to monkey 3
|
||||||
|
|
||||||
|
Monkey 3:
|
||||||
|
Starting items: 74
|
||||||
|
Operation: new = old + 3
|
||||||
|
Test: divisible by 17
|
||||||
|
If true: throw to monkey 0
|
||||||
|
If false: throw to monkey 1
|
||||||
|
|
Loading…
Reference in New Issue