Switch bitint lib. Should get the answer if run long enough...but that's a nightmare so far

This commit is contained in:
Timothy Warren 2022-12-15 16:52:16 -05:00
parent 44a837741d
commit 9f68b6fbe3
3 changed files with 373 additions and 84 deletions

281
day11/Cargo.lock generated
View File

@ -3,44 +3,287 @@
version = 3 version = 3
[[package]] [[package]]
name = "autocfg" name = "base64"
version = "1.1.0" version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]]
name = "block-buffer"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
dependencies = [
"block-padding",
"generic-array",
]
[[package]]
name = "block-padding"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cpufeatures"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "day11" name = "day11"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"num-bigint", "malachite",
] ]
[[package]] [[package]]
name = "num-bigint" name = "digest"
version = "0.4.3" version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
dependencies = [ dependencies = [
"autocfg", "generic-array",
"num-integer",
"num-traits",
] ]
[[package]] [[package]]
name = "num-integer" name = "either"
version = "0.1.45" version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
[[package]]
name = "embed-doc-image"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af36f591236d9d822425cb6896595658fa558fcebf5ee8accac1d4b92c47166e"
dependencies = [ dependencies = [
"autocfg", "base64",
"num-traits", "proc-macro2",
"quote",
"syn",
] ]
[[package]] [[package]]
name = "num-traits" name = "generic-array"
version = "0.2.15" version = "0.14.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
dependencies = [ dependencies = [
"autocfg", "typenum",
"version_check",
] ]
[[package]]
name = "getrandom"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "itertools"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
dependencies = [
"either",
]
[[package]]
name = "keccak"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768"
dependencies = [
"cpufeatures",
]
[[package]]
name = "libc"
version = "0.2.138"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
[[package]]
name = "malachite"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80f6be3354f81a8566e001afe15cb774ce4c7f09ecc19f395f111943c3fba343"
dependencies = [
"malachite-base",
"malachite-nz",
"malachite-q",
]
[[package]]
name = "malachite-base"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30e363f2fe3ec28952bd742c49e81183d00140bf45894a26d3dc2d8dfc126fda"
dependencies = [
"itertools",
"rand",
"rand_chacha",
"ryu",
"sha3",
]
[[package]]
name = "malachite-nz"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6b0e6908a9ab7394526b00f2ec44816adfd47a72acbafdb0b3d0b16ec0ac6af"
dependencies = [
"embed-doc-image",
"itertools",
"malachite-base",
]
[[package]]
name = "malachite-q"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9850d5c4e7b95324d9e9c344f220e189af7cc78eb21c67ac47822757097bd9ce"
dependencies = [
"itertools",
"malachite-base",
"malachite-nz",
]
[[package]]
name = "opaque-debug"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "ppv-lite86"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro2"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
dependencies = [
"getrandom",
"libc",
"rand_chacha",
"rand_core",
"rand_hc",
]
[[package]]
name = "rand_chacha"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_hc"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
dependencies = [
"rand_core",
]
[[package]]
name = "ryu"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
[[package]]
name = "sha3"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809"
dependencies = [
"block-buffer",
"digest",
"keccak",
"opaque-debug",
]
[[package]]
name = "syn"
version = "1.0.105"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "typenum"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
[[package]]
name = "unicode-ident"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasi"
version = "0.9.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"

View File

@ -6,4 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
num-bigint = "^0.4.3" malachite = "0.3.0"
[profile.dev]
debug = 1

View File

@ -1,12 +1,13 @@
use num_bigint::BigUint; use malachite::integer::Integer;
use malachite::num::arithmetic::traits::DivisibleBy;
use malachite::num::arithmetic::traits::Square;
use malachite::num::basic::traits::Zero;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::ops::*;
use std::str::FromStr; use std::str::FromStr;
/// Just to cut down on boilerplate for operations /// Just to cut down on boilerplate for operations
/// with primitive types /// with primitive types
#[inline(always)] fn big(n: usize) -> Integer {
fn big(n: usize) -> BigUint {
n.into() n.into()
} }
@ -16,24 +17,46 @@ pub enum WorryType {
Extra, Extra,
} }
#[derive(Debug, PartialEq, Clone)]
enum Operand {
Old,
Literal(Integer)
}
#[derive(Debug)] #[derive(Debug)]
pub struct Operation { struct Operation {
pub operator: char, operator: char,
pub operand: String, operand: Operand,
} }
impl Operation { impl Operation {
fn new(operator: char, operand: &str) -> Self {
let operand = match operand {
"old" => Operand::Old,
_ => Operand::Literal(Integer::from_str(operand).unwrap()),
};
Operation {
operator,
operand,
}
}
#[inline(always)] #[inline(always)]
pub fn run(&self, old: BigUint) -> BigUint { fn run(&self, old: Integer) -> Integer {
let other = match self.operand.as_str() { let operand = self.operand.clone();
"old" => old.clone(), if operand == Operand::Old && self.operator == '*' {
_ => BigUint::from_str(&self.operand).unwrap(), return old.square();
}
let other = match operand {
Operand::Old => old.clone(),
Operand::Literal(other) => other,
}; };
match self.operator { match self.operator {
'+' => old.add(other), '+' => old + other,
'-' => old.sub(other), '*' => old * other,
'*' => old.mul(other),
_ => panic!("Invalid operator"), _ => panic!("Invalid operator"),
} }
} }
@ -41,13 +64,13 @@ impl Operation {
#[derive(Debug)] #[derive(Debug)]
pub struct Monkey { pub struct Monkey {
pub items: VecDeque<BigUint>, items: VecDeque<Integer>,
pub operation: Operation, operation: Operation,
pub test: usize, test: Integer,
pub pass_monkey: usize, pass_monkey: usize,
pub fail_monkey: usize, fail_monkey: usize,
pub inspection_count: BigUint, inspection_count: Integer,
pub inspection_worry: WorryType, inspection_worry: WorryType,
} }
impl Monkey { impl Monkey {
@ -55,9 +78,9 @@ impl Monkey {
let lines: Vec<&str> = raw.lines().collect(); let lines: Vec<&str> = raw.lines().collect();
let item_parts: Vec<&str> = lines[1].split(": ").collect(); let item_parts: Vec<&str> = lines[1].split(": ").collect();
let items: VecDeque<BigUint> = item_parts[1] let items: VecDeque<Integer> = item_parts[1]
.split(", ") .split(", ")
.map(|i| i.parse::<BigUint>().unwrap()) .map(|i| i.parse::<Integer>().unwrap())
.collect(); .collect();
let op_parts: Vec<&str> = lines[2].split(" = ").collect(); let op_parts: Vec<&str> = lines[2].split(" = ").collect();
@ -78,20 +101,21 @@ impl Monkey {
Monkey { Monkey {
items, items,
operation: Operation { operation: Operation::new(
operator: operator.chars().next().unwrap(), operator.chars().next().unwrap(),
operand: operand.to_string(), operand
}, ),
test, test: big(test),
pass_monkey, pass_monkey,
fail_monkey, fail_monkey,
inspection_count: big(0), inspection_count: Integer::ZERO,
inspection_worry, inspection_worry,
} }
} }
pub fn run_test(&self, item: BigUint) -> usize { #[inline(always)]
if item % big(self.test) == big(0) { fn run_test(&self, item: &Integer) -> usize {
if item.divisible_by(&self.test) {
self.pass_monkey self.pass_monkey
} else { } else {
self.fail_monkey self.fail_monkey
@ -99,7 +123,7 @@ impl Monkey {
} }
#[inline(always)] #[inline(always)]
pub fn inspect(&mut self, item: BigUint) -> (usize, BigUint) { pub fn inspect(&mut self, item: Integer) -> (usize, Integer) {
self.inspection_count += big(1); self.inspection_count += big(1);
let worry = if self.inspection_worry == WorryType::Normal { let worry = if self.inspection_worry == WorryType::Normal {
@ -108,19 +132,20 @@ impl Monkey {
self.operation.run(item) self.operation.run(item)
}; };
let new_monkey = self.run_test(worry.clone()); let new_monkey = self.run_test(&worry);
(new_monkey, worry) (new_monkey, worry)
} }
pub fn catch(&mut self, item: BigUint) { #[inline(always)]
pub fn catch(&mut self, item: Integer) {
self.items.push_back(item); self.items.push_back(item);
} }
} }
#[derive(Debug)] #[derive(Debug)]
pub struct MonkeyGame { pub struct MonkeyGame {
pub monkeys: Vec<Monkey>, monkeys: Vec<Monkey>,
} }
impl MonkeyGame { impl MonkeyGame {
@ -134,33 +159,30 @@ impl MonkeyGame {
} }
} }
pub fn throw(&mut self, item: BigUint, to: usize) { fn throw(&mut self, item: Integer, to: usize) {
self.monkeys[to].catch(item); self.monkeys[to].catch(item);
} }
pub fn do_round(&mut self) { #[inline(always)]
for m in 0..self.monkeys.len() {
while let Some(worry) = self.monkeys[m].items.pop_front() {
let (monkey_idx, worry) = self.monkeys[m].inspect(worry);
self.throw(worry, monkey_idx);
}
}
}
pub fn do_rounds(&mut self, rounds: usize) -> &Self { pub fn do_rounds(&mut self, rounds: usize) -> &Self {
for r in 0..rounds { for r in 0..rounds {
if r % 100 == 0 { if r % 100 == 0 {
println!("Running round {}", r); println!("Running round {}", r);
} }
self.do_round(); for m in 0..self.monkeys.len() {
while let Some(worry) = self.monkeys[m].items.pop_front() {
let (monkey_idx, worry) = self.monkeys[m].inspect(worry);
self.throw(worry, monkey_idx);
}
}
} }
self self
} }
pub fn get_inspection_counts(&self) -> Vec<BigUint> { pub fn get_inspection_counts(&self) -> Vec<Integer> {
let mut counts: Vec<BigUint> = self let mut counts: Vec<Integer> = self
.monkeys .monkeys
.iter() .iter()
.map(|m| m.inspection_count.clone()) .map(|m| m.inspection_count.clone())
@ -171,7 +193,7 @@ impl MonkeyGame {
counts.into_iter().rev().collect() counts.into_iter().rev().collect()
} }
pub fn get_monkey_business(&self) -> BigUint { pub fn get_monkey_business(&self) -> Integer {
let inspections = self.get_inspection_counts(); let inspections = self.get_inspection_counts();
inspections.get(0).unwrap() * inspections.get(1).unwrap() inspections.get(0).unwrap() * inspections.get(1).unwrap()
@ -183,20 +205,12 @@ fn main() {
let monkey_business1 = MonkeyGame::from_file_str(file_str, WorryType::Normal) let monkey_business1 = MonkeyGame::from_file_str(file_str, WorryType::Normal)
.do_rounds(20) .do_rounds(20)
.get_monkey_business(); .get_monkey_business();
println!("Part 1 monkey business: {}", monkey_business1); println!("Part 1 monkey business: {}", monkey_business1);
let monkey_business1 = MonkeyGame::from_file_str(file_str, WorryType::Extra) let monkey_business2 = MonkeyGame::from_file_str(file_str, WorryType::Extra)
.do_rounds(500) .do_rounds(10_000)
.get_monkey_business(); .get_monkey_business();
println!("Part 2 monkey business: {}", monkey_business2);
println!("monkey business 400 rounds: {}", monkey_business1);
// let monkey_business2 = MonkeyGame::from_file_str(file_str, WorryType::Extra)
// .do_rounds(10_000)
// .get_monkey_business();
//
// println!("Part 2 monkey business: {}", monkey_business2);
} }
#[cfg(test)] #[cfg(test)]
@ -208,9 +222,9 @@ mod tests {
} }
#[test] #[test]
fn test_monkey_round() { fn monkey_round() {
let mut game = MonkeyGame::from_file_str(get_test_data(), WorryType::Normal); let mut game = MonkeyGame::from_file_str(get_test_data(), WorryType::Normal);
game.do_round(); game.do_rounds(1);
assert_eq!( assert_eq!(
game.monkeys[0].items, game.monkeys[0].items,
@ -232,15 +246,44 @@ mod tests {
} }
#[test] #[test]
fn test_monkey_20_rounds() { fn monkey_20_rounds() {
let mut game = MonkeyGame::from_file_str(get_test_data(), WorryType::Normal); let mut game = MonkeyGame::from_file_str(get_test_data(), WorryType::Normal);
game.do_rounds(20); game.do_rounds(20);
assert_eq!(game.monkeys[0].inspection_count, big(101)); assert_eq!(game.monkeys[0].inspection_count, big(101));
assert_eq!(game.monkeys[3].inspection_count, big(105)); assert_eq!(game.monkeys[3].inspection_count, big(105));
assert_eq!(game.get_monkey_business(), big(10605));
} }
fn test_monkey_10000_rounds() { fn monkey_10_000_rounds() {
let mut game = MonkeyGame::from_file_str(get_test_data(), WorryType::Normal);
game.do_rounds(10_000);
assert_eq!(game.monkeys[0].inspection_count, big(52166));
assert_eq!(game.monkeys[3].inspection_count, big(52013));
}
#[test]
fn monkey_20_rounds_extra_worry() {
let mut game = MonkeyGame::from_file_str(get_test_data(), WorryType::Extra);
game.do_rounds(20);
assert_eq!(game.monkeys[0].inspection_count, big(99));
assert_eq!(game.monkeys[3].inspection_count, big(103));
assert_eq!(game.get_monkey_business(), big(10197));
}
fn monkey_1000_rounds_extra_worry() {
let mut game = MonkeyGame::from_file_str(get_test_data(), WorryType::Extra);
game.do_rounds(1000);
assert_eq!(game.monkeys[0].inspection_count, big(5204));
assert_eq!(game.monkeys[3].inspection_count, big(5192));
}
fn monkey_10_000_rounds_extra_worry() {
let mut game = MonkeyGame::from_file_str(get_test_data(), WorryType::Extra); let mut game = MonkeyGame::from_file_str(get_test_data(), WorryType::Extra);
game.do_rounds(10_000); game.do_rounds(10_000);