use crate::table::*;
use std::collections::HashSet;
pub fn is_random(f: &Vec<u8>) -> bool {
let mut inc = 0;
let mut big = 0;
for i in 0..255 {
if f[i + 1] > f[i] {
inc += 1;
}
if f[i] > i as u8 {
big += 1;
}
}
if inc < 64 || inc > 192 || big < 64 || big > 192 {
return false;
}
for i in 0..4 {
let sum = f[(0 + i * 64)..(64 + i * 64)].iter().map(|n| *n as u32).sum::<u32>() / 64;
if sum < 64 || sum > 192 {
return false;
}
}
let filtered = f[0..128].iter().filter(|n| *n % 3 == 0).collect::<Vec<&u8>>().len();
if filtered < 21 || filtered > 85 {
return false;
}
true
}
fn def_table(f: &Table) {
assert_eq!(f.0.len(), 256);
let mut outputs = HashSet::with_capacity(256);
for n in f.0.iter() {
assert!(!outputs.contains(n));
outputs.insert(*n);
}
}
#[test]
fn def_table_proof() {
for table in many_tables().iter() {
def_table(table);
}
}
fn def_inverse(f: &Table) {
for a in 0..=255 {
assert_eq!(apply(f, apply(&inverse_table(f), a)), a);
}
}
#[test]
fn def_inverse_proof() {
for table in many_tables().iter() {
def_inverse(table);
}
}
fn def_compose(f: &Table, g: &Table) {
for a in 0..=255 {
assert_eq!(apply(&compose_table(f, g), a), apply(f, apply(g, a)));
}
}
#[test]
fn def_compose_proof() {
for f in many_tables().iter() {
for g in many_tables().iter() {
def_compose(f, g);
}
}
}
fn def_decompose(f: &Table, g: &Table) {
let h = compose_table(f, g);
let new_g = decompose_table(&h, f);
assert_eq!(g, &new_g);
}
#[test]
fn def_decompose_proof() {
for f in many_tables().iter() {
for g in many_tables().iter() {
def_decompose(f, g);
}
}
}
#[test]
fn compose_commutative_proof() {
loop {
let f = random_table();
let g = random_table();
if compose_table(&f, &g) != compose_table(&g, &f) {
break;
}
}
}
fn compose_associativity(f: &Table, g: &Table, h: &Table) {
assert_eq!(compose_table(f, &compose_table(g, h)), compose_table(&compose_table(f, g), h));
}
#[test]
fn compose_associativity_proof() {
for f in many_tables().iter() {
for g in many_tables().iter() {
for h in many_tables().iter() {
compose_associativity(f, g, h);
}
}
}
}
fn compose_id(g: &Table) {
let f = id_table();
assert_eq!(&compose_table(&f, g), g);
assert_eq!(&compose_table(g, &f), g);
}
#[test]
fn compose_id_proof() {
for g in many_tables().iter() {
compose_id(g);
}
}