fizzbuzz
This commit is contained in:
parent
d727e41a07
commit
02c8347634
|
@ -0,0 +1,284 @@
|
|||
#![recursion_limit = "1024"]
|
||||
#![feature(specialization)]
|
||||
use std::marker::PhantomData;
|
||||
|
||||
trait Num { fn render() -> u64; }
|
||||
struct Zero;
|
||||
impl Num for Zero { fn render() -> u64 { 0 } }
|
||||
struct Succ<I: Num>(PhantomData<I>);
|
||||
impl<I: Num> Num for Succ<I> { fn render() -> u64 { <I>::render() + 1 } }
|
||||
|
||||
|
||||
trait Char { fn render() -> char; }
|
||||
struct S0 {} impl Char for S0 { fn render() -> char { '0' } }
|
||||
struct S1 {} impl Char for S1 { fn render() -> char { '1' } }
|
||||
struct S2 {} impl Char for S2 { fn render() -> char { '2' } }
|
||||
struct S3 {} impl Char for S3 { fn render() -> char { '3' } }
|
||||
struct S4 {} impl Char for S4 { fn render() -> char { '4' } }
|
||||
struct S5 {} impl Char for S5 { fn render() -> char { '5' } }
|
||||
struct S6 {} impl Char for S6 { fn render() -> char { '6' } }
|
||||
struct S7 {} impl Char for S7 { fn render() -> char { '7' } }
|
||||
struct S8 {} impl Char for S8 { fn render() -> char { '8' } }
|
||||
struct S9 {} impl Char for S9 { fn render() -> char { '9' } }
|
||||
|
||||
struct SF {} impl Char for SF { fn render() -> char { 'F' } }
|
||||
struct Si {} impl Char for Si { fn render() -> char { 'i' } }
|
||||
struct Sz {} impl Char for Sz { fn render() -> char { 'z' } }
|
||||
struct SB {} impl Char for SB { fn render() -> char { 'B' } }
|
||||
struct Su {} impl Char for Su { fn render() -> char { 'u' } }
|
||||
struct Snl {} impl Char for Snl { fn render() -> char { '\n' } }
|
||||
|
||||
|
||||
trait String { fn render(); }
|
||||
struct SEmpty {} impl String for SEmpty { fn render() {} }
|
||||
struct SCons<F: Char, R: String>(PhantomData<F>, PhantomData<R>);
|
||||
impl<F: Char, R: String> String for SCons<F, R> {
|
||||
fn render() {
|
||||
print!("{}", <F>::render());
|
||||
<R>::render();
|
||||
}
|
||||
}
|
||||
struct SBadEval {}
|
||||
impl String for SBadEval { fn render() { print!("BAD EVAL"); } }
|
||||
|
||||
trait StringifiedImpl: Num {
|
||||
type Result: String;
|
||||
}
|
||||
|
||||
impl<N: Num> StringifiedImpl for N {
|
||||
default type Result = SBadEval;
|
||||
}
|
||||
|
||||
impl StringifiedImpl for Zero {
|
||||
type Result = SCons<S0, SEmpty>;
|
||||
}
|
||||
|
||||
impl<N: Num> StringifiedImpl for Succ<N> {
|
||||
type Result = <<N as StringifiedImpl>::Result as StringIncrement>::Result;
|
||||
}
|
||||
|
||||
trait Stringified: Num {
|
||||
type Result: String;
|
||||
}
|
||||
|
||||
impl<N: Num> Stringified for N {
|
||||
type Result = <<N as StringifiedImpl>::Result as Rev>::Result;
|
||||
}
|
||||
|
||||
trait StringIncrement: String {
|
||||
type Result: String;
|
||||
}
|
||||
|
||||
impl StringIncrement for SEmpty {
|
||||
type Result = SCons<S1, SEmpty>;
|
||||
}
|
||||
|
||||
impl<S: String> StringIncrement for S {
|
||||
default type Result = SBadEval;
|
||||
}
|
||||
|
||||
impl<S: String> StringIncrement for SCons<S0, S> {
|
||||
type Result = SCons<S1, S>;
|
||||
}
|
||||
impl<S: String> StringIncrement for SCons<S1, S> {
|
||||
type Result = SCons<S2, S>;
|
||||
}
|
||||
impl<S: String> StringIncrement for SCons<S2, S> {
|
||||
type Result = SCons<S3, S>;
|
||||
}
|
||||
impl<S: String> StringIncrement for SCons<S3, S> {
|
||||
type Result = SCons<S4, S>;
|
||||
}
|
||||
impl<S: String> StringIncrement for SCons<S4, S> {
|
||||
type Result = SCons<S5, S>;
|
||||
}
|
||||
impl<S: String> StringIncrement for SCons<S5, S> {
|
||||
type Result = SCons<S6, S>;
|
||||
}
|
||||
impl<S: String> StringIncrement for SCons<S6, S> {
|
||||
type Result = SCons<S7, S>;
|
||||
}
|
||||
impl<S: String> StringIncrement for SCons<S7, S> {
|
||||
type Result = SCons<S8, S>;
|
||||
}
|
||||
impl<S: String> StringIncrement for SCons<S8, S> {
|
||||
type Result = SCons<S9, S>;
|
||||
}
|
||||
impl<S: String + StringIncrement> StringIncrement for SCons<S9, S> {
|
||||
type Result = SCons<S0, <S as StringIncrement>::Result>;
|
||||
}
|
||||
|
||||
trait App<S: String>: String {
|
||||
type Result: String;
|
||||
}
|
||||
|
||||
impl<S: String, T: String> App<S> for T {
|
||||
default type Result = SBadEval;
|
||||
}
|
||||
|
||||
impl<S: String> App<S> for SEmpty {
|
||||
type Result = S;
|
||||
}
|
||||
|
||||
impl<S: String, F: Char, R: String> App<S> for SCons<F, R> {
|
||||
type Result = SCons<F, <R as App<S>>::Result>;
|
||||
}
|
||||
|
||||
trait Rev: String {
|
||||
type Result: String;
|
||||
}
|
||||
|
||||
impl<S: String> Rev for S {
|
||||
default type Result = SBadEval;
|
||||
}
|
||||
|
||||
impl Rev for SEmpty {
|
||||
type Result = SEmpty;
|
||||
}
|
||||
|
||||
impl<F: Char, R: String> Rev for SCons<F, R> {
|
||||
type Result = <R as App<SCons<F, SEmpty>>>::Result;
|
||||
}
|
||||
|
||||
trait ModResult { fn render(); }
|
||||
struct ModBadEval {} impl ModResult for ModBadEval { fn render() { println!("mod bad eval"); } }
|
||||
struct Mod {} impl ModResult for Mod { fn render() { println!("mod"); } }
|
||||
struct Modnt {} impl ModResult for Modnt { fn render() { println!("not mod"); } }
|
||||
|
||||
trait NumMod3: Num {
|
||||
type Result: ModResult;
|
||||
}
|
||||
|
||||
impl<T: Num> NumMod3 for T {
|
||||
default type Result = ModBadEval;
|
||||
}
|
||||
|
||||
impl NumMod3 for Zero {
|
||||
type Result = Mod;
|
||||
}
|
||||
|
||||
impl NumMod3 for Succ<Zero> {
|
||||
type Result = Modnt;
|
||||
}
|
||||
|
||||
impl NumMod3 for Succ<Succ<Zero>> {
|
||||
type Result = Modnt;
|
||||
}
|
||||
|
||||
impl<T: Num> NumMod3 for Succ<Succ<Succ<T>>> {
|
||||
type Result = <T as NumMod3>::Result;
|
||||
}
|
||||
|
||||
trait NumMod5: Num {
|
||||
type Result: ModResult;
|
||||
}
|
||||
|
||||
impl<T: Num> NumMod5 for T {
|
||||
default type Result = ModBadEval;
|
||||
}
|
||||
|
||||
impl NumMod5 for Zero {
|
||||
type Result = Mod;
|
||||
}
|
||||
|
||||
impl NumMod5 for Succ<Zero> {
|
||||
type Result = Modnt;
|
||||
}
|
||||
|
||||
impl NumMod5 for Succ<Succ<Zero>> {
|
||||
type Result = Modnt;
|
||||
}
|
||||
|
||||
impl NumMod5 for Succ<Succ<Succ<Zero>>> {
|
||||
type Result = Modnt;
|
||||
}
|
||||
|
||||
impl NumMod5 for Succ<Succ<Succ<Succ<Zero>>>> {
|
||||
type Result = Modnt;
|
||||
}
|
||||
|
||||
impl<T: Num> NumMod5 for Succ<Succ<Succ<Succ<Succ<T>>>>> {
|
||||
type Result = <T as NumMod5>::Result;
|
||||
}
|
||||
|
||||
|
||||
trait FizzbuzzStringified: Num {
|
||||
type Result: String;
|
||||
}
|
||||
|
||||
trait FbstrHelper<Mod3: ModResult, Mod5: ModResult>: Num {
|
||||
type Result: String;
|
||||
}
|
||||
|
||||
impl<T: Num, Mod3: ModResult, Mod5: ModResult> FbstrHelper<Mod3, Mod5> for T {
|
||||
default type Result = SBadEval;
|
||||
}
|
||||
|
||||
impl<T: Num> FbstrHelper<Modnt, Modnt> for T {
|
||||
type Result = <T as Stringified>::Result;
|
||||
}
|
||||
|
||||
impl<T: Num> FbstrHelper<Mod, Modnt> for T {
|
||||
type Result = SCons<SF, SCons<Si, SCons<Sz, SCons<Sz, SEmpty>>>>;
|
||||
}
|
||||
|
||||
impl<T: Num> FbstrHelper<Modnt, Mod> for T {
|
||||
type Result = SCons<SB, SCons<Su, SCons<Sz, SCons<Sz, SEmpty>>>>;
|
||||
}
|
||||
|
||||
impl<T: Num> FbstrHelper<Mod, Mod> for T {
|
||||
type Result = SCons<SF, SCons<Si, SCons<Sz, SCons<Sz, SCons<SB, SCons<Su, SCons<Sz, SCons<Sz, SEmpty>>>>>>>>;
|
||||
}
|
||||
|
||||
impl<T: Num> FizzbuzzStringified for T {
|
||||
type Result = <T as FbstrHelper<<T as NumMod3>::Result, <T as NumMod5>::Result>>::Result;
|
||||
}
|
||||
|
||||
trait Added<S: Num>: Num {
|
||||
type Result: Num;
|
||||
}
|
||||
|
||||
impl<T: Num, S: Num> Added<S> for T {
|
||||
default type Result = S;
|
||||
}
|
||||
|
||||
impl<S: Num> Added<S> for Zero {
|
||||
type Result = S;
|
||||
}
|
||||
|
||||
impl<T: Num, S: Num> Added<S> for Succ<T> {
|
||||
type Result = Succ<<T as Added<S>>::Result>;
|
||||
}
|
||||
|
||||
|
||||
trait FizzbuzzProgram: Num {
|
||||
type Result: String;
|
||||
}
|
||||
|
||||
impl<T: Num> FizzbuzzProgram for T {
|
||||
default type Result = SBadEval;
|
||||
}
|
||||
|
||||
impl FizzbuzzProgram for Zero {
|
||||
type Result = SEmpty;
|
||||
}
|
||||
|
||||
impl<T: Num> FizzbuzzProgram for Succ<T> {
|
||||
type Result = <<<T as FizzbuzzProgram>::Result as App<<Succ<T> as FizzbuzzStringified>::Result>>::Result as App<SCons<Snl, SEmpty>>>::Result;
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
type One = Succ<Zero>;
|
||||
type Two = Succ<One>;
|
||||
type Four = <Two as Added<Two>>::Result;
|
||||
type Eight = <Four as Added<Four>>::Result;
|
||||
type Sixteen = <Eight as Added<Eight>>::Result;
|
||||
|
||||
type Five = <Four as Added<One>>::Result;
|
||||
type Ten = <Five as Added<Five>>::Result;
|
||||
type Thirty = <<<Sixteen as Added<Eight>>::Result as Added<Four>>::Result as Added<Two>>::Result;
|
||||
type OneHundred = <<<Thirty as Added<Thirty>>::Result as Added<Thirty>>::Result as Added<Ten>>::Result;
|
||||
|
||||
<OneHundred as FizzbuzzProgram>::Result::render();
|
||||
}
|
Loading…
Reference in New Issue