diff --git a/projecteuler/084/Cargo.lock b/projecteuler/084/Cargo.lock new file mode 100644 index 0000000..1f09d9e --- /dev/null +++ b/projecteuler/084/Cargo.lock @@ -0,0 +1,75 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "getrandom" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "libc" +version = "0.2.139" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" + +[[package]] +name = "main" +version = "0.1.0" +dependencies = [ + "rand", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/projecteuler/084/Cargo.toml b/projecteuler/084/Cargo.toml new file mode 100644 index 0000000..a6db181 --- /dev/null +++ b/projecteuler/084/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "main" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +rand = "0.8.5" diff --git a/projecteuler/084/src/main.rs b/projecteuler/084/src/main.rs new file mode 100644 index 0000000..e34f0c9 --- /dev/null +++ b/projecteuler/084/src/main.rs @@ -0,0 +1,283 @@ +use rand::prelude::*; + +#[derive(Debug, Clone, Copy)] +enum CommunityChest { + ToGo, + ToJail, + Empty, +} +struct CommunityChestDeck { + deck: Vec, + current_index: usize, +} + +impl CommunityChestDeck { + fn next(&mut self) -> CommunityChest { + self.current_index = (self.current_index + 1) % self.deck.len(); + self.deck[self.current_index] + } +} + +#[derive(Debug, Clone, Copy)] +enum Chance { + ToGo, + ToJail, + ToC1, + ToE3, + ToH2, + ToR1, + ToNextRailway, + ToNextUtility, + GoBack3, + Empty, +} +struct ChanceDeck { + deck: Vec, + current_index: usize, +} + +impl ChanceDeck { + fn next(&mut self) -> Chance { + self.current_index = (self.current_index + 1) % self.deck.len(); + self.deck[self.current_index] + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum TileType { + Go, + Jail, + GoToJail, + C1, + E3, + H2, + R1, + Railway, + Utility, + Empty, + CommunityChest, + Chance, +} +use TileType::*; + +struct Board { + board: Vec, + current_index: usize, +} + +impl Board { + fn next(&mut self) -> TileType { + self.current_index = (self.current_index + 1) % self.board.len(); + self.board[self.current_index] + } + + fn prev(&mut self) -> TileType { + self.current_index = ((self.current_index as i32 - 1) % self.board.len() as i32) as usize; + self.board[self.current_index] + } +} + +struct DoubleDice { + sides: u32, + rng: ThreadRng, +} + +impl DoubleDice { + // Need to know each specific throw because we need to keep track of the doubles + fn throw(&mut self) -> (u32, u32) { + let dice1 = self.rng.gen_range(1..=self.sides); + let dice2 = self.rng.gen_range(1..=self.sides); + + (dice1, dice2) + } +} + +enum ThrowResult { + ToJail, + Moves(u32), +} + +fn handle_dice(dice: &mut DoubleDice, past_throws: &mut [(u32, u32)]) -> ThrowResult { + let dice_throw = dice.throw(); + if past_throws[0] == past_throws[1] && past_throws[1] == dice_throw { + past_throws[0] = (0, 0); + past_throws[1] = (0, 0); + ThrowResult::ToJail + } else { + past_throws[0] = past_throws[1]; + past_throws[1] = dice_throw; + ThrowResult::Moves(dice_throw.0 + dice_throw.1) + } +} + +fn main() { + println!("Hello, this is Patrick!"); + let mut rng = thread_rng(); + + // First create card decks, board and dice + let mut community_chest_cards = vec![ + CommunityChest::Empty, + CommunityChest::Empty, + CommunityChest::Empty, + CommunityChest::Empty, + CommunityChest::Empty, + CommunityChest::Empty, + CommunityChest::Empty, + CommunityChest::Empty, + CommunityChest::Empty, + CommunityChest::Empty, + CommunityChest::Empty, + CommunityChest::Empty, + CommunityChest::Empty, + CommunityChest::Empty, + CommunityChest::ToGo, + CommunityChest::ToJail, + ]; + community_chest_cards.shuffle(&mut rng); + + let mut chance_cards = vec![ + Chance::Empty, + Chance::Empty, + Chance::Empty, + Chance::Empty, + Chance::Empty, + Chance::Empty, + Chance::ToGo, + Chance::ToJail, + Chance::ToC1, + Chance::ToE3, + Chance::ToH2, + Chance::ToR1, + Chance::ToNextRailway, + Chance::ToNextRailway, + Chance::ToNextUtility, + Chance::GoBack3, + ]; + chance_cards.shuffle(&mut rng); + + let board_tiles = vec![ + Go, + Empty, + CommunityChest, + Empty, + Empty, + R1, + Empty, + Chance, + Empty, + Empty, + Jail, + C1, + Utility, + Empty, + Empty, + Railway, + Empty, + CommunityChest, + Empty, + Empty, + Empty, + Empty, + Chance, + Empty, + E3, + Railway, + Empty, + Empty, + Utility, + Empty, + GoToJail, + Empty, + Empty, + CommunityChest, + Empty, + Railway, + Chance, + Empty, + Empty, + H2, + ]; + + let mut cc_deck = CommunityChestDeck { + deck: community_chest_cards, + current_index: 0, + }; + let mut chance_deck = ChanceDeck { + deck: chance_cards, + current_index: 0, + }; + let mut board = Board { + board: board_tiles, + current_index: 0, + }; + + let mut dice = DoubleDice { sides: 4, rng }; + let mut square_popularity = vec![0; board.board.len()]; + let mut dice_throws = [(0, 0), (0, 0)]; + + for _ in 0..2000000 { + match handle_dice(&mut dice, &mut dice_throws) { + ThrowResult::ToJail => { + board.current_index = 10; + } + ThrowResult::Moves(n) => { + let mut next_tile = Empty; + for _ in 0..n { + next_tile = board.next(); + } + match next_tile { + GoToJail => { + board.current_index = 10; + } + CommunityChest => { + let card_drawn = cc_deck.next(); + match card_drawn { + CommunityChest::ToGo => { + board.current_index = 0; + } + CommunityChest::ToJail => { + board.current_index = 10; + } + _ => {} + } + } + Chance => { + let card_drawn = chance_deck.next(); + match card_drawn { + Chance::ToJail => { + board.current_index = 10; + } + Chance::ToGo => { + board.current_index = 0; + } + Chance::Empty => {} + Chance::GoBack3 => { + for _ in 0..3 { + _ = board.prev() + } + } + Chance::ToC1 => while board.next() != TileType::C1 {}, + Chance::ToE3 => while board.next() != TileType::E3 {}, + Chance::ToH2 => while board.next() != TileType::H2 {}, + Chance::ToNextUtility => while board.next() != TileType::Utility {}, + Chance::ToR1 => while board.next() != TileType::R1 {}, + Chance::ToNextRailway => { + let mut next_tile = board.next(); + while next_tile != TileType::R1 && next_tile != TileType::Railway { + next_tile = board.next(); + } + } + } + } + _ => {} + } + } + } + + square_popularity[board.current_index] += 1; + } + let mut squares_sorted: Vec<(usize, u32)> = square_popularity.into_iter().enumerate().collect(); + squares_sorted.sort_by(|(_, a), (_, b)| a.cmp(b)); + + println!("Square popularity: {:?}", squares_sorted); +}