add 54 benchmarks, small performance improvement
This commit is contained in:
@@ -3,7 +3,25 @@ name = "euler54"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
name = "poker"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "euler54"
|
||||
path = "src/main.rs"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
rstest = "*"
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = "*"
|
||||
|
||||
[profile.release]
|
||||
debug = true
|
||||
|
||||
[[bench]]
|
||||
name = "benchmark"
|
||||
harness = false
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
use std::io::BufRead;
|
||||
use std::io::BufReader;
|
||||
|
||||
use criterion::{criterion_group, criterion_main, Criterion};
|
||||
|
||||
use poker::game::Game;
|
||||
|
||||
fn bench_game(c: &mut Criterion) {
|
||||
c.bench_function("example game", |b| {
|
||||
b.iter(|| Game::from("5H 5C 6S 7S KD 2C 3S 8S 8D TD"))
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_all(c: &mut Criterion) {
|
||||
c.bench_function("all games", |b| {
|
||||
let content: Vec<_> = BufReader::new(std::fs::File::open("poker.txt").unwrap())
|
||||
.lines()
|
||||
.map(|l| l.unwrap())
|
||||
.collect();
|
||||
b.iter(|| {
|
||||
for line in &content {
|
||||
let _ = Game::from(line.as_ref());
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(benches, bench_game, bench_all);
|
||||
criterion_main!(benches);
|
||||
+65
-33
@@ -3,7 +3,13 @@ use crate::value::{Value, Values};
|
||||
use std::cmp::max;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
pub type Cards = [Card; 5];
|
||||
pub struct Cards {
|
||||
pub array: CardsArray,
|
||||
pub suit_hashset: HashSet<Suit>,
|
||||
pub value_hashmap: HashMap<Value, usize>,
|
||||
}
|
||||
|
||||
type CardsArray = [Card; 5];
|
||||
|
||||
#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Copy, Hash)]
|
||||
pub struct Card {
|
||||
@@ -21,48 +27,49 @@ impl From<&str> for Card {
|
||||
}
|
||||
}
|
||||
|
||||
trait Contains<T> {
|
||||
fn contains_value(&self, x: &T) -> bool;
|
||||
}
|
||||
|
||||
impl Contains<Value> for &Cards {
|
||||
fn contains_value(&self, x: &Value) -> bool {
|
||||
for card in self.iter() {
|
||||
if card.value == *x {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
impl From<&str> for Cards {
|
||||
fn from(s: &str) -> Self {
|
||||
let cards_array: CardsArray = s
|
||||
.split_whitespace()
|
||||
.map(Card::from)
|
||||
.collect::<Vec<_>>()
|
||||
.try_into()
|
||||
.unwrap_or_else(|_| panic!());
|
||||
Cards::new(cards_array)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait CardTrait {
|
||||
fn have_matching_suits(&self) -> bool;
|
||||
fn contain_all_values_of(&self, values: &Values) -> bool;
|
||||
fn get_highest_card(&self) -> Card;
|
||||
fn have_consecutive_values(&self) -> bool;
|
||||
fn to_value_hashset(&self) -> HashSet<Value>;
|
||||
fn to_value_hashmap(&self) -> HashMap<Value, usize>;
|
||||
fn to_suit_hashset(&self) -> HashSet<Suit>;
|
||||
}
|
||||
impl Cards {
|
||||
fn new(cards: CardsArray) -> Self {
|
||||
let suit_hashset = cards.to_suit_hashset();
|
||||
let value_hashmap = cards.to_value_hashmap();
|
||||
Self {
|
||||
array: cards,
|
||||
suit_hashset,
|
||||
value_hashmap,
|
||||
}
|
||||
}
|
||||
|
||||
impl CardTrait for Cards {
|
||||
fn have_matching_suits(&self) -> bool {
|
||||
self[1..]
|
||||
pub fn have_matching_suits(&self) -> bool {
|
||||
self.array[1..]
|
||||
.iter()
|
||||
.zip(self[..4].iter())
|
||||
.zip(self.array[..4].iter())
|
||||
.all(|(c1, c2)| c1.suit == c2.suit)
|
||||
}
|
||||
|
||||
fn contain_all_values_of(&self, values: &Values) -> bool {
|
||||
values.iter().all(|v| self.contains_value(v))
|
||||
pub fn contain_all_values_of(&self, values: &Values) -> bool {
|
||||
values.iter().all(|v| self.value_hashmap.contains_key(v))
|
||||
}
|
||||
|
||||
fn get_highest_card(&self) -> Card {
|
||||
*self.iter().reduce(|accum, item| max(accum, item)).unwrap()
|
||||
pub fn get_highest_card(&self) -> Card {
|
||||
*self
|
||||
.array
|
||||
.iter()
|
||||
.reduce(|accum, item| max(accum, item))
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn have_consecutive_values(&self) -> bool {
|
||||
pub fn have_consecutive_values(&self) -> bool {
|
||||
let mut count = 0;
|
||||
for value in Value::iterator() {
|
||||
if self.contains_value(value) {
|
||||
@@ -77,6 +84,33 @@ impl CardTrait for Cards {
|
||||
true
|
||||
}
|
||||
|
||||
fn contains_value(&self, value: &Value) -> bool {
|
||||
self.value_hashmap.contains_key(value)
|
||||
}
|
||||
}
|
||||
|
||||
trait Contains<T> {
|
||||
fn contains_value(&self, x: &T) -> bool;
|
||||
}
|
||||
|
||||
impl Contains<Value> for &CardsArray {
|
||||
fn contains_value(&self, x: &Value) -> bool {
|
||||
for card in self.iter() {
|
||||
if card.value == *x {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub trait CardTrait {
|
||||
fn to_value_hashmap(&self) -> HashMap<Value, usize>;
|
||||
fn to_suit_hashset(&self) -> HashSet<Suit>;
|
||||
fn to_value_hashset(&self) -> HashSet<Value>;
|
||||
}
|
||||
|
||||
impl CardTrait for CardsArray {
|
||||
fn to_suit_hashset(&self) -> HashSet<Suit> {
|
||||
self.iter().map(|c| c.suit).collect()
|
||||
}
|
||||
@@ -102,8 +136,6 @@ mod test {
|
||||
// use super::Card;
|
||||
use crate::hand::Hand;
|
||||
|
||||
use super::CardTrait;
|
||||
|
||||
#[test]
|
||||
fn test_consecutive_values() {
|
||||
let hand = Hand::from("2H 3C 4D 5D 6S");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::card::{CardTrait, Cards};
|
||||
use crate::card::Cards;
|
||||
use crate::value::Value;
|
||||
|
||||
impl From<&Cards> for Evaluation {
|
||||
@@ -46,7 +46,7 @@ impl Evaluation {
|
||||
|
||||
fn is_four_of_a_kind(cards: &Cards) -> Option<Value> {
|
||||
cards
|
||||
.to_value_hashmap()
|
||||
.value_hashmap
|
||||
.iter()
|
||||
.filter(|(_, count)| **count == 4)
|
||||
.map(|(value, _)| *value)
|
||||
@@ -55,7 +55,7 @@ impl Evaluation {
|
||||
|
||||
fn is_full_house(cards: &Cards) -> Option<Value> {
|
||||
if cards
|
||||
.to_value_hashmap()
|
||||
.value_hashmap
|
||||
.values()
|
||||
.filter(|v| [2, 3].contains(v))
|
||||
.count()
|
||||
@@ -85,7 +85,7 @@ impl Evaluation {
|
||||
|
||||
fn is_three_of_a_kind(cards: &Cards) -> Option<Value> {
|
||||
cards
|
||||
.to_value_hashmap()
|
||||
.value_hashmap
|
||||
.iter()
|
||||
.filter(|(_, count)| **count == 3)
|
||||
.map(|(value, _)| *value)
|
||||
@@ -93,8 +93,8 @@ impl Evaluation {
|
||||
}
|
||||
|
||||
fn is_two_pairs(cards: &Cards) -> Option<Value> {
|
||||
let hm = cards.to_value_hashmap();
|
||||
let values: Vec<_> = hm
|
||||
let values: Vec<_> = cards
|
||||
.value_hashmap
|
||||
.iter()
|
||||
.filter(|(_, count)| **count == 2)
|
||||
.map(|(value, _)| value)
|
||||
@@ -106,9 +106,10 @@ impl Evaluation {
|
||||
}
|
||||
|
||||
fn is_one_pair(cards: &Cards) -> Option<Value> {
|
||||
let hm = cards.to_value_hashmap();
|
||||
if hm.len() == 4 {
|
||||
hm.iter()
|
||||
if cards.value_hashmap.len() == 4 {
|
||||
cards
|
||||
.value_hashmap
|
||||
.iter()
|
||||
.filter(|(_, count)| **count == 2)
|
||||
.map(|(value, _)| *value)
|
||||
.next()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::{card::CardTrait, hand::Hand};
|
||||
use crate::hand::Hand;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Player {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::card::{Card, Cards};
|
||||
use crate::card::Cards;
|
||||
use crate::evaluation::Evaluation;
|
||||
|
||||
pub struct Hand {
|
||||
@@ -9,8 +9,7 @@ pub struct Hand {
|
||||
impl From<&str> for Hand {
|
||||
fn from(line: &str) -> Self {
|
||||
assert_eq!(line.len(), 14);
|
||||
let vec: Vec<_> = line.split_whitespace().map(Card::from).collect();
|
||||
let cards: [Card; 5] = vec.try_into().unwrap_or_else(|_| panic!());
|
||||
let cards = Cards::from(line);
|
||||
let evaluation = Evaluation::from(&cards);
|
||||
Self { cards, evaluation }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
pub mod card;
|
||||
pub mod evaluation;
|
||||
pub mod game;
|
||||
pub mod hand;
|
||||
pub mod suit;
|
||||
pub mod value;
|
||||
@@ -1,13 +1,6 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::io::{BufRead, BufReader};
|
||||
|
||||
mod card;
|
||||
mod evaluation;
|
||||
mod game;
|
||||
mod hand;
|
||||
mod suit;
|
||||
mod value;
|
||||
use poker::game;
|
||||
|
||||
fn main() {
|
||||
let mut p1_wins = 0;
|
||||
|
||||
Reference in New Issue
Block a user