add 54 benchmarks, small performance improvement

This commit is contained in:
Dr. Matthias Ratajczak
2022-08-18 18:01:42 +02:00
parent a4a5e0b49c
commit 06f722ba7f
8 changed files with 132 additions and 54 deletions
+18
View File
@@ -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
+29
View File
@@ -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
View File
@@ -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");
+10 -9
View File
@@ -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 -1
View File
@@ -1,4 +1,4 @@
use crate::{card::CardTrait, hand::Hand};
use crate::hand::Hand;
#[derive(Debug, PartialEq)]
pub enum Player {
+2 -3
View File
@@ -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 }
}
+6
View File
@@ -0,0 +1,6 @@
pub mod card;
pub mod evaluation;
pub mod game;
pub mod hand;
pub mod suit;
pub mod value;
+1 -8
View File
@@ -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;