un_algebra 0.9.0

Simple implementations of selected abstract algebraic structures--including groups, rings, and fields. Intended for self-study of abstract algebra concepts and not for production use.
//
// # Example: The game of _rock_, _paper_, _scissors_.
//
// The values {`R`,`P`, `S`} representing the choices in a game of rock,
// paper, scissors [RPS] form a _magma_. In this game plays are
// commutative, but _not_ associative, so they do not form a semigroup
// or other derived algebraic structure.
//
// [RPS]: https://en.wikipedia.org/wiki/Commutative_magma
//
#![allow(non_snake_case)]

use proptest_derive::*;
use un_algebra::tests::*;
use un_algebra::prelude::*;


//
// The game choices in rock, paper, scissors.
//
#[derive(Copy, Clone, PartialEq, Debug, Arbitrary)]
pub enum RPS {
  R, P, S
}


//
// Rock, paper, scissors choices form a magma.
//
impl Magma for RPS {

  // Magma operation as per the game rules.
  fn op(&self, other: &Self) -> Self {

    // Redundant branch expressions used for clarity.
    match (self, other) {
      (RPS::R, RPS::R) => RPS::R,
      (RPS::R, RPS::P) => RPS::P,
      (RPS::R, RPS::S) => RPS::R,
      (RPS::P, RPS::R) => RPS::P,
      (RPS::P, RPS::P) => RPS::P,
      (RPS::P, RPS::S) => RPS::S,
      (RPS::S, RPS::R) => RPS::R,
      (RPS::S, RPS::P) => RPS::S,
      (RPS::S, RPS::S) => RPS::S
    }
  }
}


//
// Generative tests of rock, paper, scissors algebraic axioms.
//
proptest! {
  #![proptest_config(config::standard())]


  #[test]
  fn closure((x, y) in any::<(RPS, RPS)>()) {
    prop_assert!(MagmaLaws::closure(&x, &y))
  }


  #[test]
  fn closure_t2([xs, ys] in any::<[(RPS, RPS); 2]>()) {
    prop_assert!(MagmaLaws::closure(&xs, &ys))
  }


  #[test]
  fn closure_a2([xs, ys] in any::<[[RPS; 2]; 2]>()) {
    prop_assert!(MagmaLaws::closure(&xs, &ys))
  }


  #[test]
  fn commutivity((x, y) in any::<(RPS, RPS)>()) {
    prop_assert!(x.op(&y) == y.op(&x))
  }


  #[test]
  fn commutivity_t1((x, y) in any::<(RPS, RPS)>()) {
    prop_assert!((x,).op(&(y,)) == (y,).op(&(x,)))
  }


  #[test]
  fn commutivity_a1((x, y) in any::<(RPS, RPS)>()) {
    prop_assert!([x].op(&[y]) == [y].op(&[x]))
  }
}


fn main() {
}