Last active
January 14, 2021 05:24
-
-
Save YoshiTheChinchilla/fec3e7d3f77b2cfb8641bf2f86c91d0c to your computer and use it in GitHub Desktop.
A Kiyoshi Hikawa's Zundoko Bushi script written in Rust
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "zundoko" | |
version = "0.1.0" | |
authors = ["Takashi Yoshimura"] | |
edition = "2018" | |
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | |
[lib] | |
name = "zundoko" | |
path = "lib.rs" | |
[dependencies] | |
rand = "0.8.2" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(test)] | |
#![feature(variant_count)] | |
extern crate test; | |
// cargo add zundoko --git https://gist.github.com/YoshiTheChinchilla/fec3e7d3f77b2cfb8641bf2f86c91d0c | |
// Or use this text of a dependency: `zundoko = { git = "https://gist.github.com/YoshiTheChinchilla/fec3e7d3f77b2cfb8641bf2f86c91d0c" }` | |
// Rust Playground URL: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=dc83ac03bf9502bf4c5e26018d46420d | |
use std::fmt::{self, Display, Formatter}; | |
use std::borrow::Borrow; | |
use std::mem::variant_count; | |
// cargo add rand | |
use rand::{Rng, distributions::{Distribution, Standard}}; | |
use Lyric::*; | |
/// enum Dun or Doko of Kiyoshi Hikawa's Zundoko Bushi | |
#[derive(Debug, Clone, Copy, PartialEq, Eq)] | |
pub enum Lyric { | |
Zun, | |
Doko, | |
} | |
/// implements [`Borrow<str>`](https://doc.rust-lang.org/std/borrow/trait.Borrow.html) to use [`[T]::join`](https://doc.rust-lang.org/std/slice/trait.Join.html) method | |
impl Borrow<str> for Lyric { | |
#[inline] | |
fn borrow(&self) -> &str { | |
match self { | |
Zun => "ズン", | |
Doko => "ドコ", | |
} | |
} | |
} | |
impl Display for Lyric { | |
#[inline] | |
fn fmt(&self, f: &mut Formatter) -> fmt::Result { | |
write!(f, "{}", self.borrow() as &str) | |
} | |
} | |
impl Distribution<Lyric> for Standard { | |
#[inline] | |
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Lyric { | |
if rng.gen() { | |
Zun | |
} else { | |
Doko | |
} | |
} | |
} | |
/// New type of Vec<Lyric> | |
#[derive(Debug, Clone, PartialEq, Eq)] | |
pub struct Zundoko(Vec<Lyric>); | |
impl Zundoko { | |
/// returns Zundoko struct | |
#[inline] | |
pub fn new() -> Self { | |
Self(Vec::new()) | |
} | |
/// returns Zundoko struct with perfect lyrics of Zundoko Bushi | |
#[inline] | |
pub fn perfect() -> Self { | |
Self(vec![Zun, Zun, Zun, Zun, Doko]) | |
} | |
/// returns Zundoko struct that ends with `&[Lyric]` | |
#[inline] | |
pub fn new_until_complete(complete: &[Lyric]) -> Self { | |
let mut rng = rand::thread_rng(); | |
let mut v = Vec::with_capacity(variant_count::<Lyric>().pow(complete.len() as u32)); | |
while !v.ends_with(complete) { | |
v.push(rng.gen()); | |
} | |
v.shrink_to_fit(); | |
Zundoko(v) | |
} | |
/// formats the lyrics with the tail (キ・ヨ・シ!) and returns the formatted String | |
#[inline] | |
pub fn format(&self) -> String { | |
format!("{} キ・ヨ・シ!", self.0.join(" ")) | |
} | |
/// prints all lyrics of Zundoko Bushi | |
#[inline] | |
pub fn sing(&self) { | |
println!("{}", self.format()); | |
} | |
} | |
#[cfg(test)] | |
mod tests { | |
use super::*; | |
use test::Bencher; | |
#[test] | |
fn test_zundoko() { | |
let complete = Zundoko::perfect(); | |
let zundoko = Zundoko::new_until_complete(&complete.0); | |
let zundoko_str = zundoko.format(); | |
let tail = "ズン ズン ズン ズン ドコ キ・ヨ・シ!"; | |
let tail_count = tail.chars().count(); | |
let count = zundoko.0.len(); | |
assert!(zundoko_str.chars().count() >= tail_count); | |
assert!(zundoko_str.ends_with(tail)); | |
assert_eq!(zundoko_str.chars().count(), count * 2 + count + "キ・ヨ・シ!".chars().count()); | |
} | |
#[bench] | |
fn bench_zundoko(b: &mut Bencher) { | |
b.iter(|| test_zundoko()); | |
// use std::time::Instant; | |
// use std::sync::Arc; | |
// let now = Instant::now(); | |
// let num_threads = num_cpus::get(); | |
// println!("Using {} CPU threads.", num_threads); | |
// let complete = Arc::new([Zun, Zun, Zun, Zun, Doko]); | |
// (0..num_threads) | |
// .map(|_| { | |
// let complete = complete.clone(); | |
// std::thread::spawn(move || ZunDoko::new_until_complete(complete.as_ref())) | |
// }) | |
// .for_each(|h| {h.join().map(|zundoko| zundoko.sing());}); | |
// println!("{}", now.elapsed().as_millis()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment