Partition an integer x into n primes

#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct bit_array_tag {
    uint32_t size;
    uint32_t* array;
} bit_array;

bool bit_array_create(bit_array* b, uint32_t size) {
    uint32_t* array = calloc((size + 31)/32, sizeof(uint32_t));
    if (array == NULL)
        return false;
    b->size = size;
    b->array = array;
    return true;
}

void bit_array_destroy(bit_array* b) {
    free(b->array);
    b->array = NULL;
}

void bit_array_set(bit_array* b, uint32_t index, bool value) {
    assert(index < b->size);
    uint32_t* p = &b->array[index >> 5];
    uint32_t bit = 1 << (index & 31);
    if (value)
        *p |= bit;
    else
        *p &= ~bit;
}

bool bit_array_get(const bit_array* b, uint32_t index) {
    assert(index < b->size);
    uint32_t bit = 1 << (index & 31);
    return (b->array[index >> 5] & bit) != 0;
}

typedef struct sieve_tag {
    uint32_t limit;
    bit_array not_prime;
} sieve;

bool sieve_create(sieve* s, uint32_t limit) {
    if (!bit_array_create(&s->not_prime, limit + 1))
        return false;
    bit_array_set(&s->not_prime, 0, true);
    bit_array_set(&s->not_prime, 1, true);
    for (uint32_t p = 2; p * p <= limit; ++p) {
        if (bit_array_get(&s->not_prime, p) == false) {
            for (uint32_t q = p * p; q <= limit; q += p)
                bit_array_set(&s->not_prime, q, true);
        }
    }
    s->limit = limit;
    return true;
}

void sieve_destroy(sieve* s) {
    bit_array_destroy(&s->not_prime);
}

bool is_prime(const sieve* s, uint32_t n) {
    assert(n <= s->limit);
    return bit_array_get(&s->not_prime, n) == false;
}

bool find_prime_partition(const sieve* s, uint32_t number, uint32_t count,
                          uint32_t min_prime, uint32_t* p) {
    if (count == 1) {
        if (number >= min_prime && is_prime(s, number)) {
            *p = number;
            return true;
        }
        return false;
    }
    for (uint32_t prime = min_prime; prime < number; ++prime) {
        if (!is_prime(s, prime))
            continue;
        if (find_prime_partition(s, number - prime, count - 1,
                                 prime + 1, p + 1)) {
            *p = prime;
            return true;
        }
    }
    return false;
}

void print_prime_partition(const sieve* s, uint32_t number, uint32_t count) {
    assert(count > 0);
    uint32_t* primes = malloc(count * sizeof(uint32_t));
    if (primes == NULL) {
        fprintf(stderr, "Out of memory\n");
        return;
    }
    if (!find_prime_partition(s, number, count, 2, primes)) {
        printf("%u cannot be partitioned into %u primes.\n", number, count);
    } else {
        printf("%u = %u", number, primes[0]);
        for (uint32_t i = 1; i < count; ++i)
            printf(" + %u", primes[i]);
        printf("\n");
    }
    free(primes);
}

int main() {
    const uint32_t limit = 100000;
    sieve s = { 0 };
    if (!sieve_create(&s, limit)) {
        fprintf(stderr, "Out of memory\n");
        return 1;
    }
    print_prime_partition(&s, 99809, 1);
    print_prime_partition(&s, 18, 2);
    print_prime_partition(&s, 19, 3);
    print_prime_partition(&s, 20, 4);
    print_prime_partition(&s, 2017, 24);
    print_prime_partition(&s, 22699, 1);
    print_prime_partition(&s, 22699, 2);
    print_prime_partition(&s, 22699, 3);
    print_prime_partition(&s, 22699, 4);
    print_prime_partition(&s, 40355, 3);
    sieve_destroy(&s);
    return 0;
}

mod bit_array;
mod prime_sieve;

use prime_sieve::PrimeSieve;

fn find_prime_partition(
    sieve: &PrimeSieve,
    number: usize,
    count: usize,
    min_prime: usize,
    primes: &mut Vec<usize>,
    index: usize,
) -> bool {
    if count == 1 {
        if number >= min_prime && sieve.is_prime(number) {
            primes[index] = number;
            return true;
        }
        return false;
    }
    for p in min_prime..number {
        if sieve.is_prime(p)
            && find_prime_partition(sieve, number - p, count - 1, p + 1, primes, index + 1)
        {
            primes[index] = p;
            return true;
        }
    }
    false
}

fn print_prime_partition(sieve: &PrimeSieve, number: usize, count: usize) {
    let mut primes = vec![0; count];
    if !find_prime_partition(sieve, number, count, 2, &mut primes, 0) {
        println!("{} cannot be partitioned into {} primes.", number, count);
    } else {
        print!("{} = {}", number, primes[0]);
        for i in 1..count {
            print!(" + {}", primes[i]);
        }
        println!();
    }
}

fn main() {
    let s = PrimeSieve::new(100000);
    print_prime_partition(&s, 99809, 1);
    print_prime_partition(&s, 18, 2);
    print_prime_partition(&s, 19, 3);
    print_prime_partition(&s, 20, 4);
    print_prime_partition(&s, 2017, 24);
    print_prime_partition(&s, 22699, 1);
    print_prime_partition(&s, 22699, 2);
    print_prime_partition(&s, 22699, 3);
    print_prime_partition(&s, 22699, 4);
    print_prime_partition(&s, 40355, 3);
}


Partition function P

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <gmp.h>

mpz_t* partition(uint64_t n) {
	mpz_t *pn = (mpz_t *)malloc((n + 2) * sizeof(mpz_t));
	mpz_init_set_ui(pn[0], 1);
	mpz_init_set_ui(pn[1], 1);
	for (uint64_t i = 2; i < n + 2; i ++) {
		mpz_init(pn[i]);
		for (uint64_t k = 1, penta; ; k++) {
			penta = k * (3 * k - 1) >> 1;
			if (penta >= i) break;
			if (k & 1) mpz_add(pn[i], pn[i], pn[i - penta]);
			else mpz_sub(pn[i], pn[i], pn[i - penta]);
			penta += k;
			if (penta >= i) break;
			if (k & 1) mpz_add(pn[i], pn[i], pn[i - penta]);
			else mpz_sub(pn[i], pn[i], pn[i - penta]);
		}
	}
	mpz_t *tmp = &pn[n + 1];
	for (uint64_t i = 0; i < n + 1; i ++) mpz_clear(pn[i]);
	free(pn);
	return tmp;
}

int main(int argc, char const *argv[]) {
	clock_t start = clock();
	mpz_t *p = partition(6666);
	gmp_printf("%Zd\n", p);
	printf("Elapsed time: %.04f seconds\n",
		(double)(clock() - start) / (double)CLOCKS_PER_SEC);
	return 0;
}

use rug::Integer;

fn partitions(n: usize) -> Integer {
    let mut p = Vec::with_capacity(n + 1);
    p.push(Integer::from(1));
    for i in 1..=n {
        let mut num = Integer::from(0);
        let mut k = 1;
        loop {
            let mut j = (k * (3 * k - 1)) / 2;
            if j > i {
                break;
            }
            if (k & 1) == 1 {
                num += &p[i - j];
            } else {
                num -= &p[i - j];
            }
            j += k;
            if j > i {
                break;
            }
            if (k & 1) == 1 {
                num += &p[i - j];
            } else {
                num -= &p[i - j];
            }
            k += 1;
        }
        p.push(num);
    }
    p[n].clone()
}

fn main() {
    use std::time::Instant;
    let n = 6666;
    let now = Instant::now();
    let result = partitions(n);
    let time = now.elapsed();
    println!("P({}) = {}", n, result);
    println!("elapsed time: {} microseconds", time.as_micros());
}


Penney's game

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define SEQLEN 3

int getseq(char *s)
{
    int r = 0;
    int i = 1 << (SEQLEN - 1);

    while (*s && i) {
        switch (*s++) {
            case 'H':
            case 'h':
                r |= i;
                break;
            case 'T':
            case 't':

                break;
            default:
                return -1;
        }
        i >>= 1;
    }

    return r;
}

void printseq(int seq)
{
    int i;
    for (i = SEQLEN - 1; i >= 0; --i)
        printf("%c", seq & (1 << i) ? 'h' : 't');
}

int getuser(void)
{
    int user;
    char s[SEQLEN + 1];

    printf("Enter your sequence of %d (h/t): ", SEQLEN);
    while (1) {

        if (scanf("%3s", s) != 1) exit(1);
        if ((user = getseq(s)) != -1) return user;
        printf("Please enter only h/t characters: ");
    }
}

int getai(int user)
{
    int ai;

    printf("Computers sequence of %d is: ", SEQLEN);

    if (user == -1)
        ai = rand() & (1 << SEQLEN) - 1;
    else
        ai = (user >> 1) | ((~user << 1) & (1 << SEQLEN - 1));

    printseq(ai);
    printf("\n");
    return ai;
}

int rungame(int user, int ai)
{

    int last3 = rand() & (1 << SEQLEN) - 1;

    printf("Tossed sequence: ");
    printseq(last3);
    while (1) {
        if (user == last3) {
            printf("\nUser wins!\n");
            return 1;
        }

        if (ai == last3) {
            printf("\nAi wins!\n");
            return 0;
        }

        last3 = ((last3 << 1) & (1 << SEQLEN) - 2) | (rand() & 1);
        printf("%c", last3 & 1 ? 'h' : 't');
    }
}

int main(void)
{
    srand(time(NULL));
    int playerwins = 0;
    int totalgames = 0;

    while (1) {
        int user = -1;
        int ai   = -1;

        printf("\n");
        if (rand() & 1) {
            ai   = getai(user);
            user = getuser();
        }
        else {
            user = getuser();
            ai   = getai(user);
        }

        playerwins += rungame(user, ai);
        totalgames++;

        printf("You have won %d out of %d games\n", playerwins, totalgames);
        printf("=================================\n");
    }

    return 0;
}

extern crate rand;

use std::io::{stdin, stdout, Write};
use std::thread;
use std::time::Duration;

use rand::Rng;

fn toss_coin<R: Rng>(rng: &mut R, print: bool) -> char {
    let c = if rng.gen() { 'H' } else { 'T' };
    if print {
        print!("{}", c);
        stdout().flush().expect("Could not flush stdout");
    }
    c
}

fn gen_sequence<R: Rng>(rng: &mut R, seed: Option<&str>) -> String {
    let mut seq = String::new();
    match seed {
        Some(s) => {
            let mut iter = s.chars();
            let c0 = iter.next().unwrap();
            let next = if c0 == 'H' { 'T' } else { 'H' };
            seq.push(next);
            seq.push(c0);
            seq.push(iter.next().unwrap());
        }
        None => {
            for _ in 0..3 {
                seq.push(toss_coin(rng, false))
            }
        }
    }
    seq
}

fn read_sequence(used_seq: Option<&str>) -> String {
    let mut seq = String::new();
    loop {
        seq.clear();
        println!("Please, enter sequence of 3 coins: H (heads) or T (tails): ");
        stdin().read_line(&mut seq).expect("failed to read line");
        seq = seq.trim().to_uppercase();

        if seq.len() == 3
            && seq.chars().all(|c| c == 'H' || c == 'T')
            && seq != used_seq.unwrap_or("")
        {
            return seq;
        }

        println!("Please enter correct sequence!");
    }
}

fn main() {
    let mut rng = rand::thread_rng();

    println!("--Penney's game--");
    loop {
        let useq: String;
        let aiseq: String;
        if rng.gen::<bool>() {
            println!("You choose first!");
            useq = read_sequence(None);
            println!("Your sequence: {}", useq);
            aiseq = gen_sequence(&mut rng, Some(&useq));
            println!("My sequence: {}", aiseq);
        } else {
            println!("I choose first!");
            aiseq = gen_sequence(&mut rng, None);
            println!("My sequence: {}", aiseq);
            useq = read_sequence(Some(&aiseq));
            println!("Your sequence: {}", useq);
        }
        println!("Tossing coins...");
        let mut coins = String::new();
        for _ in 0..2 {

            coins.push(toss_coin(&mut rng, true));
            thread::sleep(Duration::from_millis(500));
        }
        loop {
            coins.push(toss_coin(&mut rng, true));
            thread::sleep(Duration::from_millis(500));
            if coins.contains(&useq) {
                println!("\nYou win!");
                break;
            }
            if coins.contains(&aiseq) {
                println!("\nI win!");
                break;
            }
        }

        println!(" Play again? 'Y' to play, 'Q' to exit.");
        let mut input = String::new();
        stdin().read_line(&mut input).expect("failed to read line");
        match input.trim_start().chars().next().unwrap() {
            'Y' | 'y' => continue,
            _ => break,
        }
    }
}


Perfect totient numbers

#include<stdlib.h>
#include<stdio.h>

long totient(long n){
	long tot = n,i;

	for(i=2;i*i<=n;i+=2){
		if(n%i==0){
			while(n%i==0)
				n/=i;
			tot-=tot/i;
		}

		if(i==2)
			i=1;
	}

	if(n>1)
		tot-=tot/n;

	return tot;
}

long* perfectTotients(long n){
	long *ptList = (long*)malloc(n*sizeof(long)), m,count=0,sum,tot;

	for(m=1;count<n;m++){
		 tot = m;
		 sum = 0;
        while(tot != 1){
            tot = totient(tot);
            sum += tot;
        }
        if(sum == m)
			ptList[count++] = m;
        }

		return ptList;
}

long main(long argC, char* argV[])
{
	long *ptList,i,n;

	if(argC!=2)
		printf("Usage : %s <number of perfect Totient numbers required>",argV[0]);
	else{
		n = atoi(argV[1]);

		ptList = perfectTotients(n);

		printf("The first %d perfect Totient numbers are : \n[",n);

		for(i=0;i<n;i++)
			printf(" %d,",ptList[i]);
		printf("\b]");
	}

	return 0;
}

use num::integer::gcd;

static mut CACHE:[i32;10000] = [0; 10000];

fn is_perfect_totient(n: i32) -> bool {
    let mut  tot = 0;
    for i in 1..n {
        if gcd(n, i) == 1 {
            tot += 1
        }
    }
    unsafe {
        let sum = tot + CACHE[tot as usize];
        CACHE[n as usize] = sum;
        return n == sum;
    }
}

fn main() {
    let mut i = 1;
    let mut count = 0;
    while count < 20 {
        if is_perfect_totient(i) {
            print!("{} ", i);
            count += 1;
        }
        i += 1;
    }
    println!("{}", " ")
}


Perlin noise

#include<stdlib.h>
#include<stdio.h>
#include<math.h>

int p[512];

double fade(double t) { return t * t * t * (t * (t * 6 - 15) + 10); }
double lerp(double t, double a, double b) { return a + t * (b - a); }
double grad(int hash, double x, double y, double z) {
      int h = hash & 15;
      double u = h<8 ? x : y,
             v = h<4 ? y : h==12||h==14 ? x : z;
      return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
   }

double noise(double x, double y, double z) {
      int X = (int)floor(x) & 255,
          Y = (int)floor(y) & 255,
          Z = (int)floor(z) & 255;
      x -= floor(x);
      y -= floor(y);
      z -= floor(z);
      double u = fade(x),
             v = fade(y),
             w = fade(z);
      int A = p[X  ]+Y, AA = p[A]+Z, AB = p[A+1]+Z,
          B = p[X+1]+Y, BA = p[B]+Z, BB = p[B+1]+Z;

      return lerp(w, lerp(v, lerp(u, grad(p[AA  ], x  , y  , z   ),
                                     grad(p[BA  ], x-1, y  , z   )),
                             lerp(u, grad(p[AB  ], x  , y-1, z   ),
                                     grad(p[BB  ], x-1, y-1, z   ))),
                     lerp(v, lerp(u, grad(p[AA+1], x  , y  , z-1 ),
                                     grad(p[BA+1], x-1, y  , z-1 )),
                             lerp(u, grad(p[AB+1], x  , y-1, z-1 ),
                                     grad(p[BB+1], x-1, y-1, z-1 ))));
   }

void loadPermutation(char* fileName){
	FILE* fp = fopen(fileName,"r");
	int permutation[256],i;

	for(i=0;i<256;i++)
		fscanf(fp,"%d",&permutation[i]);

	fclose(fp);

	for (int i=0; i < 256 ; i++) p[256+i] = p[i] = permutation[i];
}

int main(int argC,char* argV[])
{
	if(argC!=5)
		printf("Usage : %s <permutation data file> <x,y,z co-ordinates separated by space>");
	else{
		loadPermutation(argV[1]);
		printf("Perlin Noise for (%s,%s,%s) is %.17lf",argV[2],argV[3],argV[4],noise(strtod(argV[2],NULL),strtod(argV[3],NULL),strtod(argV[4],NULL)));
	}

	return 0;
}


Permutations by swapping

#include<stdlib.h>
#include<string.h>
#include<stdio.h>

int flag = 1;

void heapPermute(int n, int arr[],int arrLen){
	int temp;
	int i;

	if(n==1){
		printf("\n[");

		for(i=0;i<arrLen;i++)
			printf("%d,",arr[i]);
		printf("\b] Sign : %d",flag);

		flag*=-1;
	}
	else{
		for(i=0;i<n-1;i++){
			heapPermute(n-1,arr,arrLen);

			if(n%2==0){
				temp = arr[i];
				arr[i] = arr[n-1];
				arr[n-1] = temp;
			}
			else{
				temp = arr[0];
				arr[0] = arr[n-1];
				arr[n-1] = temp;
			}
		}
		heapPermute(n-1,arr,arrLen);
	}
}

int main(int argC,char* argV[0])
{
	int *arr, i=0, count = 1;
	char* token;

	if(argC==1)
		printf("Usage : %s <comma separated list of integers>",argV[0]);
	else{
		while(argV[1][i]!=00){
			if(argV[1][i++]==',')
				count++;
		}

		arr = (int*)malloc(count*sizeof(int));

		i = 0;

		token = strtok(argV[1],",");

		while(token!=NULL){
			arr[i++] = atoi(token);
			token = strtok(NULL,",");
		}

		heapPermute(i,arr,count);
	}

	return 0;
}

fn generate<T, F>(a: &mut [T], output: F)
where
    F: Fn(&[T], isize),
{
    let n = a.len();
    let mut c = vec![0; n];
    let mut i = 1;
    let mut sign = 1;
    output(a, sign);
    while i < n {
        if c[i] < i {
            if (i & 1) == 0 {
                a.swap(0, i);
            } else {
                a.swap(c[i], i);
            }
            sign = -sign;
            output(a, sign);
            c[i] += 1;
            i = 1;
        } else {
            c[i] = 0;
            i += 1;
        }
    }
}

fn print_permutation<T: std::fmt::Debug>(a: &[T], sign: isize) {
    println!("{:?} {}", a, sign);
}

fn main() {
    println!("Permutations and signs for three items:");
    let mut a = vec![0, 1, 2];
    generate(&mut a, print_permutation);

    println!("\nPermutations and signs for four items:");
    let mut b = vec![0, 1, 2, 3];
    generate(&mut b, print_permutation);
}


Plasma effect

#include<windows.h>
#include<stdlib.h>
#include<stdio.h>
#include<time.h>
#include<math.h>

#define pi M_PI

int main()
{
	CONSOLE_SCREEN_BUFFER_INFO info;
    int cols, rows;
	time_t t;
	int i,j;

    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
    cols = info.srWindow.Right - info.srWindow.Left + 1;
    rows = info.srWindow.Bottom - info.srWindow.Top + 1;

	HANDLE console;

	console = GetStdHandle(STD_OUTPUT_HANDLE);

	system("@clear||cls");

	srand((unsigned)time(&t));

	for(i=0;i<rows;i++)
		for(j=0;j<cols;j++){
			SetConsoleTextAttribute(console,fabs(sin(pi*(rand()%254 + 1)/255.0))*254);
			printf("%c",219);
		}

	getchar();

	return 0;
}

extern crate image;

use image::ColorType;
use std::path::Path;

const WIDTH: usize = 640;
const HEIGHT: usize = 480;

fn plasma_pixel(x: f64, y: f64) -> f64 {
    ((x / 16.0).sin()
        + (y / 8.0).sin()
        + ((x + y) / 16.0).sin()
        + ((x * x + y * y).sqrt() / 8.0).sin()
        + 4.0)
        / 8.0
}

fn create_plasma_lut() -> Vec<f64> {
    let mut plasma: Vec<f64> = vec![0.0; WIDTH * HEIGHT];
    for y in 0..HEIGHT {
        for x in 0..WIDTH {
            plasma[(y * WIDTH) + x] = plasma_pixel(x as f64, y as f64);
        }
    }
    plasma
}

fn hsv_to_rgb(hue: f64, saturation: f64, value: f64) -> (u8, u8, u8) {
    let c = value * saturation;
    let h = hue * 6.0;
    let x = c * (1.0 - (h % 2.0 - 1.0).abs());
    let m = value - c;
    let (red, green, blue) = match (h % 6.0).floor() as u32 {
        0 => (c, x, 0.0),
        1 => (x, c, 0.0),
        2 => (0.0, c, x),
        3 => (0.0, x, c),
        4 => (x, 0.0, c),
        _ => (c, 0.0, x),
    };

    (
        ((red + m) * 255.0).round() as u8,
        ((green + m) * 255.0).round() as u8,
        ((blue + m) * 255.0).round() as u8,
    )
}
fn main() {

    let mut framebuffer: Vec<u8> = vec![0; WIDTH * HEIGHT * 3];

    let plasma_lookup_table = create_plasma_lut();

    for (index, rgb) in framebuffer.chunks_mut(3).enumerate() {

        let hue_lookup = plasma_lookup_table[index] % 1.0;
        let (red, green, blue) = hsv_to_rgb(hue_lookup, 1.0, 1.0);
        rgb[0] = red;
        rgb[1] = green;
        rgb[2] = blue;
    }

    let output_path = Path::new("out.png");
    match image::save_buffer(
        output_path,
        framebuffer.as_slice(),
        WIDTH as u32,
        HEIGHT as u32,
        ColorType::RGB(8),
    ) {
        Err(e) => println!("Error writing output image:\n{}", e),
        Ok(_) => println!("Output written to:\n{}", output_path.to_str().unwrap()),
    }
}


Playing cards

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>

int locale_ok = 0;

wchar_t s_suits[] = L"♠♥♦♣";

const char *s_suits_ascii[] = { "S", "H", "D", "C" };
const char *s_nums[] = { "WHAT",
	"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K",
	"OVERFLOW"
};

typedef struct { int suit, number, _s; } card_t, *card;
typedef struct { int n; card_t cards[52]; } deck_t, *deck;

void show_card(card c)
{
	if (locale_ok)
		printf(" %lc%s", s_suits[c->suit], s_nums[c->number]);
	else
		printf(" %s%s", s_suits_ascii[c->suit], s_nums[c->number]);
}

deck new_deck()
{
	int i, j, k;
	deck d = malloc(sizeof(deck_t));
	d->n = 52;
	for (i = k = 0; i < 4; i++)
		for (j = 1; j <= 13; j++, k++) {
			d->cards[k].suit = i;
			d->cards[k].number = j;
		}
	return d;
}

void show_deck(deck d)
{
	int i;
	printf("%d cards:", d->n);
	for (i = 0; i < d->n; i++)
		show_card(d->cards + i);
	printf("\n");
}

int cmp_card(const void *a, const void *b)
{
	int x = ((card)a)->_s, y = ((card)b)->_s;
	return x < y ? -1 : x > y;
}

card deal_card(deck d)
{
	if (!d->n) return 0;
	return d->cards + --d->n;
}

void shuffle_deck(deck d)
{
	int i;
	for (i = 0; i < d->n; i++)
		d->cards[i]._s = rand();
	qsort(d->cards, d->n, sizeof(card_t), cmp_card);
}

int main()
{
	int i, j;
	deck d = new_deck();

	locale_ok = (0 != setlocale(LC_CTYPE, ""));

	printf("New deck, "); show_deck(d);

	printf("\nShuffle and deal to three players:\n");
	shuffle_deck(d);
	for (i = 0; i < 3; i++) {
		for (j = 0; j < 5; j++)
			show_card(deal_card(d));
		printf("\n");
	}
	printf("Left in deck "); show_deck(d);

	return 0;
}

extern crate rand;

use std::fmt;
use rand::Rng;
use Pip::*;
use Suit::*;

#[derive(Copy, Clone, Debug)]
enum Pip { Ace, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King }

#[derive(Copy, Clone, Debug)]
enum Suit { Spades, Hearts, Diamonds, Clubs }

struct Card {
	pip: Pip,
	suit: Suit
}

impl fmt::Display for Card {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?} of {:?}", self.pip, self.suit)
    }
}

struct Deck(Vec<Card>);

impl Deck {
    fn new() -> Deck {
        let mut cards:Vec<Card> = Vec::with_capacity(52);
        for &suit in &[Spades, Hearts, Diamonds, Clubs] {
            for &pip in &[Ace, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King] {
                cards.push( Card{pip: pip, suit: suit} );
            }
        }
        Deck(cards)
    }

    fn deal(&mut self) -> Option<Card> {
        self.0.pop()
    }

    fn shuffle(&mut self) {
        rand::thread_rng().shuffle(&mut self.0)
    }
}

impl fmt::Display for Deck {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for card in self.0.iter() {
            writeln!(f, "{}", card);
        }
        write!(f, "")
    }
}

fn main() {
    let mut deck = Deck::new();
    deck.shuffle();

    for _ in 0..5 {
        println!("{}", deck.deal().unwrap());
    }
}


Poker hand analyser

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>

#define TRUE 1
#define FALSE 0

#define FACES "23456789tjqka"
#define SUITS "shdc"

typedef int bool;

typedef struct {
    int face;
    char suit;
} card;

card cards[5];

int compare_card(const void *a, const void *b) {
    card c1 = *(card *)a;
    card c2 = *(card *)b;
    return c1.face - c2.face;
}

bool equals_card(card c1, card c2) {
    if (c1.face == c2.face && c1.suit == c2.suit) return TRUE;
    return FALSE;
}

bool are_distinct() {
    int i, j;
    for (i = 0; i < 4; ++i)
        for (j = i + 1; j < 5; ++j)
            if (equals_card(cards[i], cards[j])) return FALSE;
    return TRUE;
}

bool is_straight() {
    int i;
    qsort(cards, 5, sizeof(card), compare_card);
    if (cards[0].face + 4 == cards[4].face) return TRUE;
    if (cards[4].face == 12 && cards[0].face == 0 &&
        cards[3].face == 3) return TRUE;
    return FALSE;
}

bool is_flush() {
    int i;
    char suit = cards[0].suit;
    for (i = 1; i < 5; ++i) if (cards[i].suit != suit) return FALSE;
    return TRUE;
}

const char *analyze_hand(const char *hand) {
    int i, j, gs = 0;
    char suit, *cp;
    bool found, flush, straight;
    int groups[13];
    if (strlen(hand) != 14) return "invalid";
    for (i = 0; i < 14; i += 3) {
        cp = strchr(FACES, tolower(hand[i]));
        if (cp == NULL) return "invalid";
        j = i / 3;
        cards[j].face = cp - FACES;
        suit = tolower(hand[i + 1]);
        cp = strchr(SUITS, suit);
        if (cp == NULL) return "invalid";
        cards[j].suit = suit;
    }
    if (!are_distinct()) return "invalid";
    for (i = 0; i < 13; ++i) groups[i] = 0;
    for (i = 0; i < 5; ++i) groups[cards[i].face]++;
    for (i = 0; i < 13; ++i) if (groups[i] > 0) gs++;
    switch(gs) {
        case 2:
            found = FALSE;
            for (i = 0; i < 13; ++i) if (groups[i] == 4) {
                found = TRUE;
                break;
            }
            if (found) return "four-of-a-kind";
            return "full-house";
        case 3:
            found = FALSE;
            for (i = 0; i < 13; ++i) if (groups[i] == 3) {
                found = TRUE;
                break;
            }
            if (found) return "three-of-a-kind";
            return "two-pairs";
        case 4:
            return "one-pair";
        default:
            flush = is_flush();
            straight = is_straight();
            if (flush && straight)
                return "straight-flush";
            else if (flush)
                return "flush";
            else if (straight)
                return "straight";
            else
                return "high-card";
    }
}

int main(){
    int i;
    const char *type;
    const char *hands[10] = {
        "2h 2d 2c kc qd",
        "2h 5h 7d 8c 9s",
        "ah 2d 3c 4c 5d",
        "2h 3h 2d 3c 3d",
        "2h 7h 2d 3c 3d",
        "2h 7h 7d 7c 7s",
        "th jh qh kh ah",
        "4h 4s ks 5d ts",
        "qc tc 7c 6c 4c",
        "ah ah 7c 6c 4c"
    };
    for (i = 0; i < 10; ++i) {
        type = analyze_hand(hands[i]);
        printf("%s: %s\n", hands[i], type);
    }
    return 0;
}

fn main() {
    let hands = vec![
        "🂡 🂮 🂭 🂫 🂪",
        "🃏 🃂 🂢 🂮 🃍",
        "🃏 🂵 🃇 🂨 🃉",
        "🃏 🃂 🂣 🂤 🂥",
        "🃏 🂳 🃂 🂣 🃃",
        "🃏 🂷 🃂 🂣 🃃",
        "🃏 🂷 🃇 🂧 🃗",
        "🃏 🂻 🂽 🂾 🂱",
        "🃏 🃔 🃞 🃅 🂪",
        "🃏 🃞 🃗 🃖 🃔",
        "🃏 🃂 🃟 🂤 🂥",
        "🃏 🃍 🃟 🂡 🂪",
        "🃏 🃍 🃟 🃁 🃊",
        "🃏 🃂 🂢 🃟 🃍",
        "🃏 🃂 🂢 🃍 🃍",
        "🃂 🃞 🃍 🃁 🃊",
    ];
    for hand in hands{
        println!("{} {}", hand, poker_hand(hand));
    }
}

fn poker_hand(cards: &str) -> &str {
    let mut suits = vec![0u8; 4];
    let mut faces = vec![0u8; 15];
    let mut hand = vec![];

    for card in cards.chars(){
        if card == ' ' { continue; }
        let values = get_card_value(card);
        if values.0 < 14 && hand.contains(&values) {
            return "invalid";
        }
        hand.push(values);
        faces[values.0 as usize]+=1;
        if values.1 >= 0 {
            suits[values.1 as usize]+=1;
        }
    }
    if hand.len()!=5 {
        return "invalid";
    }
    faces[13] = faces[0];
    let jokers = faces[14];

    let mut colors = suits.into_iter()
        .filter(|&x| x > 0).collect::<Vec<_>>();
    colors.sort_unstable();
    colors[0] += jokers;
    let is_flush = colors[0] == 5;

    let mut is_straight = false;

    let mut ptr = 14;
    while ptr>3{
        let mut jokers_left = jokers;
        let mut straight_cards = 0;
        for i in (0..ptr).rev(){
            if faces[i]==0 {
                if jokers_left == 0 {break;}
                jokers_left -= 1;
            }
            else if i==ptr-1 { ptr-=1; }
            straight_cards+=1;
        }
        ptr-=1;
        if straight_cards == 5 {
            is_straight = true;
            break;
        }
    }

     let mut values = faces.into_iter().enumerate().take(14).filter(|&x| x.1>0).collect::<Vec<_>>();

     values.sort_unstable_by(|a, b| if b.1 == a.1 { (b.0).cmp(&a.0) } else { (b.1).cmp(&a.1)} );
     let first_group = values[0].1 + jokers;
     let second_group = if values.len()>1 {values[1].1} else {0};

     match (is_flush, is_straight, first_group, second_group){
        (_,_,5,_) => "five-of-a-kind",
        (true, true, _, _) => if ptr == 8 {"royal-flush"} else {"straight-flush"},
        (_,_,4,_) => "four-of-a-kind",
        (_,_,3,2) => "full-house",
        (true,_,_,_) => "flush",
        (_,true,_,_) => "straight",
        (_,_,3,_) => "three-of-a-kind",
        (_,_,2,2) => "two-pair",
        (_,_,2,_) => "one-pair",
        _ => "high-card"
     }
}

fn get_card_value(card: char) -> (i8,i8) {

    let base = card as u32 - 0x1F0A1;
    let mut suit = (base / 16) as i8;
    let mut face = (base % 16) as i8;
    if face > 11 && face < 14 { face-=1; }
    if face == 14 { suit = -1; }
    (face, suit)
}


Prime conspiracy

#include <assert.h>
#include <stdbool.h>
#include <stdio.h>

typedef unsigned char byte;

struct Transition {
    byte a, b;
    unsigned int c;
} transitions[100];

void init() {
    int i, j;
    for (i = 0; i < 10; i++) {
        for (j = 0; j < 10; j++) {
            int idx = i * 10 + j;
            transitions[idx].a = i;
            transitions[idx].b = j;
            transitions[idx].c = 0;
        }
    }
}

void record(int prev, int curr) {
    byte pd = prev % 10;
    byte cd = curr % 10;
    int i;

    for (i = 0; i < 100; i++) {
        int z = 0;
        if (transitions[i].a == pd) {
            int t = 0;
            if (transitions[i].b == cd) {
                transitions[i].c++;
                break;
            }
        }
    }
}

void printTransitions(int limit, int last_prime) {
    int i;

    printf("%d primes, last prime considered: %d\n", limit, last_prime);

    for (i = 0; i < 100; i++) {
        if (transitions[i].c > 0) {
            printf("%d->%d  count: %5d  frequency: %.2f\n", transitions[i].a, transitions[i].b, transitions[i].c, 100.0 * transitions[i].c / limit);
        }
    }
}

bool isPrime(int n) {
    int s, t, a1, a2;

    if (n % 2 == 0) return n == 2;
    if (n % 3 == 0) return n == 3;
    if (n % 5 == 0) return n == 5;
    if (n % 7 == 0) return n == 7;
    if (n % 11 == 0) return n == 11;
    if (n % 13 == 0) return n == 13;
    if (n % 17 == 0) return n == 17;
    if (n % 19 == 0) return n == 19;

    t = 23;
    a1 = 96;
    a2 = 216;
    s = t * t;
    while (s <= n) {
        if (n % t == 0) return false;

        s += a1;
        t += 2;
        a1 += 24;
        assert(t * t == s);

        if (s <= n) {
            if (n % t == 0) return false;

            s += a2;
            t += 4;
            a2 += 48;
            assert(t * t == s);
        }
    }

    return true;
}

#define LIMIT 1000000
int main() {
    int last_prime = 3, n = 5, count = 2;

    init();
    record(2, 3);

    while (count < LIMIT) {
        if (isPrime(n)) {
            record(last_prime, n);
            last_prime = n;
            count++;
        }
        n += 2;

        if (count < LIMIT) {
            if (isPrime(n)) {
                record(last_prime, n);
                last_prime = n;
                count++;
            }
            n += 4;
        }
    }

    printTransitions(LIMIT, last_prime);

    return 0;
}

mod bit_array;
mod prime_sieve;

use prime_sieve::PrimeSieve;

fn upper_bound_for_nth_prime(n: usize) -> usize {
    let x = n as f64;
    (x * (x.ln() + x.ln().ln())) as usize
}

fn compute_transitions(limit: usize) {
    use std::collections::BTreeMap;
    let mut transitions = BTreeMap::new();
    let mut prev = 2;
    let mut count = 0;
    let sieve = PrimeSieve::new(upper_bound_for_nth_prime(limit));
    let mut n = 3;
    while count < limit {
        if sieve.is_prime(n) {
            count += 1;
            let digit = n % 10;
            let key = (prev, digit);
            if let Some(v) = transitions.get_mut(&key) {
                *v += 1;
            } else {
                transitions.insert(key, 1);
            }
            prev = digit;
        }
        n += 2;
    }
    println!("First {} prime numbers:", limit);
    for ((from, to), c) in &transitions {
        let freq = 100.0 * (*c as f32) / (limit as f32);
        println!(
            "{} -> {}: count = {:7}, frequency = {:.2} %",
            from, to, c, freq
        );
    }
}

fn main() {
    compute_transitions(1000000);
    println!();
    compute_transitions(100000000);
}


Prime triangle

#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <time.h>

bool is_prime(unsigned int n) {
    assert(n < 64);
    static bool isprime[] = {0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0,
                             0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1,
                             0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1,
                             0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0};
    return isprime[n];
}

void swap(unsigned int* a, size_t i, size_t j) {
    unsigned int tmp = a[i];
    a[i] = a[j];
    a[j] = tmp;
}

bool prime_triangle_row(unsigned int* a, size_t length) {
    if (length == 2)
        return is_prime(a[0] + a[1]);
    for (size_t i = 1; i + 1 < length; i += 2) {
        if (is_prime(a[0] + a[i])) {
            swap(a, i, 1);
            if (prime_triangle_row(a + 1, length - 1))
                return true;
            swap(a, i, 1);
        }
    }
    return false;
}

int prime_triangle_count(unsigned int* a, size_t length) {
    int count = 0;
    if (length == 2) {
        if (is_prime(a[0] + a[1]))
            ++count;
    } else {
        for (size_t i = 1; i + 1 < length; i += 2) {
            if (is_prime(a[0] + a[i])) {
                swap(a, i, 1);
                count += prime_triangle_count(a + 1, length - 1);
                swap(a, i, 1);
            }
        }
    }
    return count;
}

void print(unsigned int* a, size_t length) {
    if (length == 0)
        return;
    printf("%2u", a[0]);
    for (size_t i = 1; i < length; ++i)
        printf(" %2u", a[i]);
    printf("\n");
}

int main() {
    clock_t start = clock();
    for (unsigned int n = 2; n < 21; ++n) {
        unsigned int a[n];
        for (unsigned int i = 0; i < n; ++i)
            a[i] = i + 1;
        if (prime_triangle_row(a, n))
            print(a, n);
    }
    printf("\n");
    for (unsigned int n = 2; n < 21; ++n) {
        unsigned int a[n];
        for (unsigned int i = 0; i < n; ++i)
            a[i] = i + 1;
        if (n > 2)
            printf(" ");
        printf("%d", prime_triangle_count(a, n));
    }
    printf("\n");
    clock_t end = clock();
    double duration = (end - start + 0.0) / CLOCKS_PER_SEC;
    printf("\nElapsed time: %f seconds\n", duration);
    return 0;
}

fn is_prime(n: u32) -> bool {
    assert!(n < 64);
    ((1u64 << n) & 0x28208a20a08a28ac) != 0
}

fn prime_triangle_row(a: &mut [u32]) -> bool {
    if a.len() == 2 {
        return is_prime(a[0] + a[1]);
    }
    for i in (1..a.len() - 1).step_by(2) {
        if is_prime(a[0] + a[i]) {
            a.swap(i, 1);
            if prime_triangle_row(&mut a[1..]) {
                return true;
            }
            a.swap(i, 1);
        }
    }
    false
}

fn prime_triangle_count(a: &mut [u32]) -> u32 {
    let mut count = 0;
    if a.len() == 2 {
        if is_prime(a[0] + a[1]) {
            count += 1;
        }
    } else {
        for i in (1..a.len() - 1).step_by(2) {
            if is_prime(a[0] + a[i]) {
                a.swap(i, 1);
                count += prime_triangle_count(&mut a[1..]);
                a.swap(i, 1);
            }
        }
    }
    count
}

fn print(a: &[u32]) {
    if a.is_empty() {
        return;
    }
    print!("{:2}", a[0]);
    for x in &a[1..] {
        print!(" {:2}", x);
    }
    println!();
}

fn main() {
    use std::time::Instant;
    let start = Instant::now();
    for n in 2..21 {
        let mut a: Vec<u32> = (1..=n).collect();
        if prime_triangle_row(&mut a) {
            print(&a);
        }
    }
    println!();
    for n in 2..21 {
        let mut a: Vec<u32> = (1..=n).collect();
        if n > 2 {
            print!(" ");
        }
        print!("{}", prime_triangle_count(&mut a));
    }
    println!();
    let time = start.elapsed();
    println!("\nElapsed time: {} milliseconds", time.as_millis());
}


Primorial numbers

#include <inttypes.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <gmp.h>

int es_check(uint32_t *sieve, uint64_t n)
{
    if ((n != 2 && !(n & 1)) || (n < 2))
        return 0;
    else
        return !(sieve[n >> 6] & (1 << (n >> 1 & 31)));
}

uint32_t *es_sieve(const uint64_t nth, uint64_t *es_size)
{
    *es_size = nth * log(nth) + nth * (log(log(nth)) - 0.9385f) + 1;
    uint32_t *sieve = calloc((*es_size >> 6) + 1, sizeof(uint32_t));

    for (uint64_t i = 3; i < sqrt(*es_size) + 1; i += 2)
        if (!(sieve[i >> 6] & (1 << (i >> 1 & 31))))
            for (uint64_t j = i * i; j < *es_size; j += (i << 1))
                sieve[j >> 6] |= (1 << (j >> 1 & 31));

    return sieve;
}

size_t mpz_number_of_digits(const mpz_t op)
{
    char *opstr = mpz_get_str(NULL, 10, op);
    const size_t oplen = strlen(opstr);
    free(opstr);
    return oplen;
}

#define PRIMORIAL_LIMIT 1000000

int main(void)
{

    uint64_t sieve_size;
    uint32_t *sieve = es_sieve(PRIMORIAL_LIMIT, &sieve_size);

    mpz_t primorial;
    mpz_init_set_ui(primorial, 1);

    uint64_t prime_count = 0;
    int print = 1;
    double unused;

    for (uint64_t i = 2; i < sieve_size && prime_count <= PRIMORIAL_LIMIT; ++i) {
        if (print) {
            if (prime_count < 10)
                gmp_printf("Primorial(%" PRIu64 ") = %Zd\n", prime_count, primorial);

            else if (!modf(log10(prime_count), &unused))
                printf("Primorial(%" PRIu64 ") has %zu digits\n", prime_count, mpz_number_of_digits(primorial));
            print = 0;
        }

        if (es_check(sieve, i)) {
            mpz_mul_ui(primorial, primorial, i);
            prime_count++;
            print = 1;
        }

    }

    free(sieve);
    mpz_clear(primorial);
    return 0;
}

extern crate primal;
extern crate rayon;
extern crate rug;

use rayon::prelude::*;
use rug::Integer;

fn partial(p1 : usize, p2 : usize) -> String {
    let mut aux = Integer::from(1);
    let (_, hi) = primal::estimate_nth_prime(p2 as u64);
    let sieve = primal::Sieve::new(hi as usize);
    let prime1 = sieve.nth_prime(p1);
    let prime2 = sieve.nth_prime(p2);

    for i in sieve.primes_from(prime1).take_while(|i| *i <= prime2) {
        aux = Integer::from(aux * i as u32);
    }
    aux.to_string_radix(10)
}

fn main() {
    let mut j1 = Integer::new();
    for k in [2,3,5,7,11,13,17,19,23,29].iter() {
        j1.assign_primorial(*k);
        println!("Primorial : {}", j1);
    }
    println!("Digits of primorial 10 : {}", partial(1, 10).chars().fold(0, |n, _| n + 1));
    println!("Digits of primorial 100 : {}", partial(1, 100).chars().fold(0, |n, _| n + 1));
    println!("Digits of primorial 1_000 : {}", partial(1, 1_000).chars().fold(0, |n, _| n + 1));
    println!("Digits of primorial 10_000 : {}", partial(1, 10_000).chars().fold(0, |n, _| n + 1));
    println!("Digits of primorial 100_000 : {}", partial(1, 100_000).chars().fold(0, |n, _| n + 1));

    let mut auxi = Integer::from(1);
    let ranges = vec![[1, 300_000], [300_001, 550_000], [550_001, 800_000], [800_001, 1_000_000]];
    let v = ranges.par_iter().map(|value| partial(value[0], value[1])).collect::<Vec<_>>();
    for i in v.iter() {
        auxi =Integer::from(&auxi * i.parse::<Integer>().unwrap());
    }
    let result = auxi.to_string_radix(10).chars().fold(0, |n, _| n+1);
    println!("Digits of primorial 1_000_000 : {}",result);
}


Pythagoras tree

#include<graphics.h>
#include<stdlib.h>
#include<stdio.h>
#include<time.h>

typedef struct{
	double x,y;
}point;

void pythagorasTree(point a,point b,int times){

	point c,d,e;

	c.x = b.x - (a.y -  b.y);
	c.y = b.y - (b.x - a.x);

	d.x = a.x - (a.y -  b.y);
	d.y = a.y - (b.x - a.x);

	e.x = d.x +  ( b.x - a.x - (a.y -  b.y) ) / 2;
	e.y = d.y -  ( b.x - a.x + a.y -  b.y ) / 2;

	if(times>0){
		setcolor(rand()%15 + 1);

		line(a.x,a.y,b.x,b.y);
		line(c.x,c.y,b.x,b.y);
		line(c.x,c.y,d.x,d.y);
		line(a.x,a.y,d.x,d.y);

		pythagorasTree(d,e,times-1);
		pythagorasTree(e,c,times-1);
	}
}

int main(){

	point a,b;
	double side;
	int iter;

	time_t t;

	printf("Enter initial side length : ");
	scanf("%lf",&side);

	printf("Enter number of iterations : ");
	scanf("%d",&iter);

	a.x = 6*side/2 - side/2;
	a.y = 4*side;
	b.x = 6*side/2 + side/2;
	b.y = 4*side;

	initwindow(6*side,4*side,"Pythagoras Tree ?");

	srand((unsigned)time(&t));

	pythagorasTree(a,b,iter);

	getch();

	closegraph();

	return 0;

}

use svg::node::element::{Group, Polygon};

fn main() {
    let mut doc = svg::Document::new().set("stroke", "white");
    let mut base: Vec<[(f64, f64); 2]> = vec![[(-200.0, 0.0), (200.0, 0.0)]];
    for lvl in 0..12u8 {
        let rg = |step| lvl.wrapping_mul(step).wrapping_add(80 - step * 2);
        let mut group = Group::new().set("fill", format!("#{:02X}{:02X}18", rg(20), rg(30)));
        let mut next_base = Vec::new();
        for [a, b] in base {
            let v = (b.0 - a.0, b.1 - a.1);
            let c = (a.0 + v.1, a.1 - v.0);
            let d = (c.0 + v.0, c.1 + v.1);
            let e = (c.0 + 0.5 * (v.0 + v.1), c.1 + 0.5 * (v.1 - v.0));
            group = group.add(Polygon::new().set("points", vec![a, c, e, d, c, d, b]));
            next_base.extend([[c, e], [e, d]]);
        }
        base = next_base;
        doc = doc.add(group);
    }
    let (x0, y0) = (base.iter()).fold((0.0, 0.0), |(x0, y0), [(x, y), _]| (x.min(x0), y.min(y0)));
    let file = "pythagoras_tree.svg";
    match svg::save(file, &doc.set("viewBox", (x0, y0, -x0 * 2.0, -y0))) {
        Ok(_) => println!("{file} file written successfully!"),
        Err(e) => println!("failed to write {file}: {e}"),
    }
}


Pythagorean quadruples

#include <stdio.h>
#include <math.h>
#include <string.h>

#define N 2200

int main(int argc, char **argv){
   int a,b,c,d;
   int r[N+1];
   memset(r,0,sizeof(r));
   for(a=1; a<=N; a++){
      for(b=a; b<=N; b++){
	 int aabb;
	 if(a&1 && b&1) continue;
	 aabb=a*a + b*b;
	 for(c=b; c<=N; c++){
	    int aabbcc=aabb + c*c;
	    d=(int)sqrt((float)aabbcc);
	    if(aabbcc == d*d && d<=N) r[d]=1;
	 }
      }
   }
   for(a=1; a<=N; a++)
      if(!r[a]) printf("%d ",a);
   printf("\n");
}


RPG attributes generator

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int compareInts(const void *i1, const void *i2) {
    int a = *((int *)i1);
    int b = *((int *)i2);
    return a - b;
}

int main() {
    int i, j, nsum, vsum, vcount, values[6], numbers[4];
    srand(time(NULL));
    for (;;) {
        vsum = 0;
        for (i = 0; i < 6; ++i) {
            for (j = 0; j < 4; ++j) {
                numbers[j] = 1 + rand() % 6;
            }
            qsort(numbers, 4, sizeof(int), compareInts);
            nsum = 0;
            for (j = 1; j < 4; ++j) {
                nsum += numbers[j];
            }
            values[i] = nsum;
            vsum += values[i];
        }
        if (vsum < 75) continue;
        vcount = 0;
        for (j = 0; j < 6; ++j) {
            if (values[j] >= 15) vcount++;
        }
        if (vcount < 2) continue;
        printf("The 6 random numbers generated are:\n");
        printf("[");
        for (j = 0; j < 6; ++j) printf("%d ", values[j]);
        printf("\b]\n");
        printf("\nTheir sum is %d and %d of them are >= 15\n", vsum, vcount);
        break;
    }
    return 0;
}

use rand::distributions::Uniform;
use rand::prelude::{thread_rng, ThreadRng};
use rand::Rng;

fn main() {
    for _ in 0..=10 {
        attributes_engine();
    }
}

#[derive(Copy, Clone, Debug)]
pub struct Dice {
    amount: i32,
    range: Uniform<i32>,
    rng: ThreadRng,
}

impl Dice {

    pub fn new(amount: i32, size: i32) -> Self {
        Self {
            amount,
            range: Uniform::new(1, size + 1),
            rng: thread_rng(),
        }
    }

    fn roll_pool(mut self) -> Vec<i32> {
        (0..self.amount)
            .map(|_| self.rng.sample(self.range))
            .collect()
    }

    fn attribute_out(&self) -> i32 {

        let mut attribute_array: Vec<i32> = self.roll_pool();
        attribute_array.sort();
        attribute_array.drain(1..=3).sum()
    }
}

fn attributes_finalizer() -> (Vec<i32>, i32, bool) {
    let die: Dice = Dice::new(4, 6);
    let mut attributes: Vec<i32> = Vec::new();

    for _ in 0..6 {
        attributes.push(die.attribute_out())
    }

    let attributes_total: i32 = attributes.iter().sum();

    let numerical_condition: bool = attributes
        .iter()
        .filter(|attribute| **attribute >= 15)
        .count()
        >= 2;

    (attributes, attributes_total, numerical_condition)
}

fn attributes_engine() {
    loop {
        let (attributes, attributes_total, numerical_condition) = attributes_finalizer();
        if (attributes_total >= 75) && (numerical_condition) {
            println!(
                "{:?} | sum: {:?}",
                attributes, attributes_total
            );
            break;
        } else {
            continue;
        }
    }
}


#include <assert.h>
#include <math.h>
#include <stdio.h>

typedef struct point_tag {
    double x;
    double y;
} point_t;

double perpendicular_distance(point_t p, point_t p1, point_t p2) {
    double dx = p2.x - p1.x;
    double dy = p2.y - p1.y;
    double d = sqrt(dx * dx + dy * dy);
    return fabs(p.x * dy - p.y * dx + p2.x * p1.y - p2.y * p1.x)/d;
}

size_t douglas_peucker(const point_t* points, size_t n, double epsilon,
                       point_t* dest, size_t destlen) {
    assert(n >= 2);
    assert(epsilon >= 0);
    double max_dist = 0;
    size_t index = 0;
    for (size_t i = 1; i + 1 < n; ++i) {
        double dist = perpendicular_distance(points[i], points[0], points[n - 1]);
        if (dist > max_dist) {
            max_dist = dist;
            index = i;
        }
    }
    if (max_dist > epsilon) {
        size_t n1 = douglas_peucker(points, index + 1, epsilon, dest, destlen);
        if (destlen >= n1 - 1) {
            destlen -= n1 - 1;
            dest += n1 - 1;
        } else {
            destlen = 0;
        }
        size_t n2 = douglas_peucker(points + index, n - index, epsilon, dest, destlen);
        return n1 + n2 - 1;
    }
    if (destlen >= 2) {
        dest[0] = points[0];
        dest[1] = points[n - 1];
    }
    return 2;
}

void print_points(const point_t* points, size_t n) {
    for (size_t i = 0; i < n; ++i) {
        if (i > 0)
            printf(" ");
        printf("(%g, %g)", points[i].x, points[i].y);
    }
    printf("\n");
}

int main() {
    point_t points[] = {
        {0,0}, {1,0.1}, {2,-0.1}, {3,5}, {4,6},
        {5,7}, {6,8.1}, {7,9}, {8,9}, {9,9}
    };
    const size_t len = sizeof(points)/sizeof(points[0]);
    point_t out[len];
    size_t n = douglas_peucker(points, len, 1.0, out, len);
    print_points(out, n);
    return 0;
}

#[derive(Copy, Clone)]
struct Point {
    x: f64,
    y: f64,
}

use std::fmt;

impl fmt::Display for Point {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "({}, {})", self.x, self.y)
    }
}

fn perpendicular_distance(p: &Point, p1: &Point, p2: &Point) -> f64 {
    let dx = p2.x - p1.x;
    let dy = p2.y - p1.y;
    (p.x * dy - p.y * dx + p2.x * p1.y - p2.y * p1.x).abs() / dx.hypot(dy)
}

fn rdp(points: &[Point], epsilon: f64, result: &mut Vec<Point>) {
    let n = points.len();
    if n < 2 {
        return;
    }
    let mut max_dist = 0.0;
    let mut index = 0;
    for i in 1..n - 1 {
        let dist = perpendicular_distance(&points[i], &points[0], &points[n - 1]);
        if dist > max_dist {
            max_dist = dist;
            index = i;
        }
    }
    if max_dist > epsilon {
        rdp(&points[0..=index], epsilon, result);
        rdp(&points[index..n], epsilon, result);
    } else {
        result.push(points[n - 1]);
    }
}

fn ramer_douglas_peucker(points: &[Point], epsilon: f64) -> Vec<Point> {
    let mut result = Vec::new();
    if points.len() > 0 && epsilon >= 0.0 {
        result.push(points[0]);
        rdp(points, epsilon, &mut result);
    }
    result
}

fn main() {
    let points = vec![
        Point { x: 0.0, y: 0.0 },
        Point { x: 1.0, y: 0.1 },
        Point { x: 2.0, y: -0.1 },
        Point { x: 3.0, y: 5.0 },
        Point { x: 4.0, y: 6.0 },
        Point { x: 5.0, y: 7.0 },
        Point { x: 6.0, y: 8.1 },
        Point { x: 7.0, y: 9.0 },
        Point { x: 8.0, y: 9.0 },
        Point { x: 9.0, y: 9.0 },
    ];
    for p in ramer_douglas_peucker(&points, 1.0) {
        println!("{}", p);
    }
}


Ray-casting algorithm

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

typedef struct { double x, y; } vec;
typedef struct { int n; vec* v; } polygon_t, *polygon;

#define BIN_V(op, xx, yy) vec v##op(vec a,vec b){vec c;c.x=xx;c.y=yy;return c;}
#define BIN_S(op, r) double v##op(vec a, vec b){ return r; }
BIN_V(sub, a.x - b.x, a.y - b.y);
BIN_V(add, a.x + b.x, a.y + b.y);
BIN_S(dot, a.x * b.x + a.y * b.y);
BIN_S(cross, a.x * b.y - a.y * b.x);

vec vmadd(vec a, double s, vec b)
{
	vec c;
	c.x = a.x + s * b.x;
	c.y = a.y + s * b.y;
	return c;
}

int intersect(vec x0, vec x1, vec y0, vec y1, double tol, vec *sect)
{
	vec dx = vsub(x1, x0), dy = vsub(y1, y0);
	double d = vcross(dy, dx), a;
	if (!d) return 0;

	a = (vcross(x0, dx) - vcross(y0, dx)) / d;
	if (sect)
		*sect = vmadd(y0, a, dy);

	if (a < -tol || a > 1 + tol) return -1;
	if (a < tol || a > 1 - tol) return 0;

	a = (vcross(x0, dy) - vcross(y0, dy)) / d;
	if (a < 0 || a > 1) return -1;

	return 1;
}

double dist(vec x, vec y0, vec y1, double tol)
{
	vec dy = vsub(y1, y0);
	vec x1, s;
	int r;

	x1.x = x.x + dy.y; x1.y = x.y - dy.x;
	r = intersect(x, x1, y0, y1, tol, &s);
	if (r == -1) return HUGE_VAL;
	s = vsub(s, x);
	return sqrt(vdot(s, s));
}

#define for_v(i, z, p) for(i = 0, z = p->v; i < p->n; i++, z++)

int inside(vec v, polygon p, double tol)
{

	int i, k, crosses, intersectResult;
	vec *pv;
	double min_x, max_x, min_y, max_y;

	for (i = 0; i < p->n; i++) {
		k = (i + 1) % p->n;
		min_x = dist(v, p->v[i], p->v[k], tol);
		if (min_x < tol) return 0;
	}

	min_x = max_x = p->v[0].x;
	min_y = max_y = p->v[1].y;

	for_v(i, pv, p) {
		if (pv->x > max_x) max_x = pv->x;
		if (pv->x < min_x) min_x = pv->x;
		if (pv->y > max_y) max_y = pv->y;
		if (pv->y < min_y) min_y = pv->y;
	}
	if (v.x < min_x || v.x > max_x || v.y < min_y || v.y > max_y)
		return -1;

	max_x -= min_x; max_x *= 2;
	max_y -= min_y; max_y *= 2;
	max_x += max_y;

	vec e;
	while (1) {
		crosses = 0;

		e.x = v.x + (1 + rand() / (RAND_MAX + 1.)) * max_x;
		e.y = v.y + (1 + rand() / (RAND_MAX + 1.)) * max_x;

		for (i = 0; i < p->n; i++) {
			k = (i + 1) % p->n;
			intersectResult = intersect(v, e, p->v[i], p->v[k], tol, 0);

			if (!intersectResult) break;

			if (intersectResult == 1) crosses++;
		}
		if (i == p->n) break;
	}
	return (crosses & 1) ? 1 : -1;
}

int main()
{
	vec vsq[] = {	{0,0}, {10,0}, {10,10}, {0,10},
			{2.5,2.5}, {7.5,0.1}, {7.5,7.5}, {2.5,7.5}};

	polygon_t sq = { 4, vsq },
		sq_hole = { 8, vsq };

	vec c = { 10, 5 };
	vec d = { 5, 5 };

	printf("%d\n", inside(c, &sq, 1e-10));
	printf("%d\n", inside(c, &sq_hole, 1e-10));

	printf("%d\n", inside(d, &sq, 1e-10));
	printf("%d\n", inside(d, &sq_hole, 1e-10));

	return 0;
}

use std::f64;

const _EPS: f64 = 0.00001;
const _MIN: f64 = f64::MIN_POSITIVE;
const _MAX: f64 = f64::MAX;

#[derive(Clone)]
struct Point {
    x: f64,
    y: f64,
}

#[derive(Clone)]
struct Edge {
    pt1: Point,
    pt2: Point,
}

impl Edge {
    fn new(pt1: (f64, f64), pt2: (f64, f64)) -> Edge {
        Edge {
            pt1: Point { x: pt1.0, y: pt1.1 },
            pt2: Point { x: pt2.0, y: pt2.1 },
        }
    }
}

struct Polygon {
    edges: Vec<Edge>,
}

fn pt_in_polygon(pt: &Point, poly: &Polygon) -> bool {
    let count = poly.edges
        .iter()
        .filter(|edge| ray_intersect_seg(pt, edge))
        .count();

    count % 2 == 1
}

fn ray_intersect_seg(p: &Point, edge: &Edge) -> bool {
    let mut pt = p.clone();
    let (mut a, mut b): (&Point, &Point) = (&edge.pt1, &edge.pt2);
    if a.y > b.y {
        std::mem::swap(&mut a, &mut b);
    }
    if pt.y == a.y || pt.y == b.y {
        pt.y += _EPS;
    }

    if (pt.y > b.y || pt.y < a.y) || pt.x > a.x.max(b.x) {
        false
    } else if pt.x < a.x.min(b.x) {
        true
    } else {
        let m_red = if (a.x - b.x).abs() > _MIN {
            (b.y - a.y) / (b.x - a.x)
        } else {
            _MAX
        };
        let m_blue = if (a.x - pt.x).abs() > _MIN {
            (pt.y - a.y) / (pt.x - a.x)
        } else {
            _MAX
        };
        m_blue >= m_red
    }
}

fn main() {
    let p = |x, y| Point { x, y };
    let testpoints = [p(5.0, 5.0), p(5.0, 8.0), p(-10.0, 5.0), p(0.0, 5.0), p(10.0, 5.0), p(8.0, 5.0), p(10.0, 10.0)];
    let poly_square = Polygon {
        edges: vec![
            Edge::new((0.0, 0.0), (10.0, 0.0)),
            Edge::new((10.0, 0.0), (10.0, 10.0)),
            Edge::new((10.0, 10.0), (0.0, 10.0)),
            Edge::new((0.0, 10.0), (0.0, 0.0)),
        ],
    };
    let poly_square_hole = Polygon {
        edges: vec![
            Edge::new((0.0, 0.0), (10.0, 0.0)),
            Edge::new((10.0, 0.0), (10.0, 10.0)),
            Edge::new((10.0, 10.0), (0.0, 10.0)),
            Edge::new((0.0, 10.0), (0.0, 0.0)),
            Edge::new((2.5, 2.5), (7.5, 2.5)),
            Edge::new((7.5, 2.5), (7.5, 7.5)),
            Edge::new((7.5, 7.5), (2.5, 7.5)),
            Edge::new((2.5, 7.5), (2.5, 2.5)),
        ],
    };
    let poly_strange = Polygon {
        edges: vec![
            Edge::new((0.0, 0.0), (2.5, 2.5)),
            Edge::new((2.5, 2.5), (0.0, 10.0)),
            Edge::new((0.0, 10.0), (2.5, 7.5)),
            Edge::new((2.5, 7.5), (7.5, 7.5)),
            Edge::new((7.5, 7.5), (10.0, 10.0)),
            Edge::new((10.0, 10.0), (10.0, 0.0)),
            Edge::new((10.0, 0.0), (2.5, 2.5)),
        ],
    };
    let poly_hexagon = Polygon {
        edges: vec![
            Edge::new((3.0, 0.0), (7.0, 0.0)),
            Edge::new((7.0, 0.0), (10.0, 5.0)),
            Edge::new((10.0, 5.0), (7.0, 10.0)),
            Edge::new((7.0, 10.0), (3.0, 10.0)),
            Edge::new((3.0, 10.0), (0.0, 5.0)),
            Edge::new((0.0, 5.0), (3.0, 0.0)),
        ],
    };
    print!("\nSquare :");
    for pt in &testpoints {
        print!(" {:?}", pt_in_polygon(pt, &poly_square));
    }
    print!("\nSquare with hole:");
    for pt in &testpoints {
        print!(" {:?}", pt_in_polygon(pt, &poly_square_hole));
    }
    print!("\nStrange polygon :");
    for pt in &testpoints {
        print!(" {:?}", pt_in_polygon(pt, &poly_strange));
    }
    print!("\nHexagon :");
    for pt in &testpoints {
        print!(" {:?}", pt_in_polygon(pt, &poly_hexagon));
    }
    println!();
}


Read a configuration file

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <confini.h>

#define rosetta_uint8_t unsigned char

#define FALSE 0
#define TRUE 1

#define CONFIGS_TO_READ 5
#define INI_ARRAY_DELIMITER ','

struct configs {
	char *fullname;
	char *favouritefruit;
	rosetta_uint8_t needspeeling;
	rosetta_uint8_t seedsremoved;
	char **otherfamily;
	size_t otherfamily_len;
	size_t _configs_left_;
};

static char ** make_array (size_t * arrlen, const char * src, const size_t buffsize, IniFormat ini_format) {

	*arrlen = ini_array_get_length(src, INI_ARRAY_DELIMITER, ini_format);
	char ** const dest = *arrlen ? (char **) malloc(*arrlen * sizeof(char *) + buffsize) : NULL;
	if (!dest) { return NULL; }
	memcpy(dest + *arrlen, src, buffsize);
	char * iter = (char *) (dest + *arrlen);
	for (size_t idx = 0; idx < *arrlen; idx++) {
		dest[idx] = ini_array_release(&iter, INI_ARRAY_DELIMITER, ini_format);
		ini_string_parse(dest[idx], ini_format);
	}
	return dest;

}

static int configs_member_handler (IniDispatch *this, void *v_confs) {

	struct configs *confs = (struct configs *) v_confs;

	if (this->type != INI_KEY) {

		return 0;

	}

	if (ini_string_match_si("FULLNAME", this->data, this->format)) {

		if (confs->fullname) { return 0; }
		this->v_len = ini_string_parse(this->value, this->format);
		confs->fullname = strndup(this->value, this->v_len);
		confs->_configs_left_--;

	} else if (ini_string_match_si("FAVOURITEFRUIT", this->data, this->format)) {

		if (confs->favouritefruit) { return 0; }
		this->v_len = ini_string_parse(this->value, this->format);
		confs->favouritefruit = strndup(this->value, this->v_len);
		confs->_configs_left_--;

	} else if (ini_string_match_si("NEEDSPEELING", this->data, this->format)) {

		if (~confs->needspeeling & 0x80) { return 0; }
		confs->needspeeling = ini_get_bool(this->value, TRUE);
		confs->_configs_left_--;

	} else if (ini_string_match_si("SEEDSREMOVED", this->data, this->format)) {

		if (~confs->seedsremoved & 0x80) { return 0; }
		confs->seedsremoved = ini_get_bool(this->value, TRUE);
		confs->_configs_left_--;

	} else if (!confs->otherfamily && ini_string_match_si("OTHERFAMILY", this->data, this->format)) {

		if (confs->otherfamily) { return 0; }
		this->v_len = ini_array_collapse(this->value, INI_ARRAY_DELIMITER, this->format);
		confs->otherfamily = make_array(&confs->otherfamily_len, this->value, this->v_len + 1, this->format);
		confs->_configs_left_--;

	}

	return !confs->_configs_left_;

}

static int populate_configs (struct configs * confs) {

	IniFormat config_format = {
		.delimiter_symbol = INI_ANY_SPACE,
		.case_sensitive = FALSE,
		.semicolon_marker = INI_IGNORE,
		.hash_marker = INI_IGNORE,
		.multiline_nodes = INI_NO_MULTILINE,
		.section_paths = INI_NO_SECTIONS,
		.no_single_quotes = FALSE,
		.no_double_quotes = FALSE,
		.no_spaces_in_names = TRUE,
		.implicit_is_not_empty = TRUE,
		.do_not_collapse_values = FALSE,
		.preserve_empty_quotes = FALSE,
		.disabled_after_space = TRUE,
		.disabled_can_be_implicit = FALSE
	};

	*confs = (struct configs) { NULL, NULL, 0x80, 0x80, NULL, 0, CONFIGS_TO_READ };

	if (load_ini_path("rosetta.conf", config_format, NULL, configs_member_handler, confs) & CONFINI_ERROR) {

		fprintf(stderr, "Sorry, something went wrong :-(\n");
		return 1;

	}

	confs->needspeeling &= 0x7F;
	confs->seedsremoved &= 0x7F;

	return 0;

}

int main () {

	struct configs confs;

	ini_global_set_implicit_value("YES", 0);

	if (populate_configs(&confs)) {

		return 1;

	}

	printf(

		"Full name: %s\n"
		"Favorite fruit: %s\n"
		"Need spelling: %s\n"
		"Seeds removed: %s\n",

		confs.fullname,
		confs.favouritefruit,
		confs.needspeeling ? "True" : "False",
		confs.seedsremoved ? "True" : "False"

	);

	for (size_t idx = 0; idx < confs.otherfamily_len; idx++) {

		printf("Other family[%d]: %s\n", idx, confs.otherfamily[idx]);

	}

	#define FREE_NON_NULL(PTR) if (PTR) { free(PTR); }

	FREE_NON_NULL(confs.fullname);
	FREE_NON_NULL(confs.favouritefruit);
	FREE_NON_NULL(confs.otherfamily);

	return 0;

}

use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;
use std::iter::FromIterator;
use std::path::Path;

fn main() {
    let path = String::from("file.conf");
    let cfg = config_from_file(path);
    println!("{:?}", cfg);
}

fn config_from_file(path: String) -> Config {
    let path = Path::new(&path);
    let file = File::open(path).expect("File not found or cannot be opened");
    let content = BufReader::new(&file);
    let mut cfg = Config::new();

    for line in content.lines() {
        let line = line.expect("Could not read the line");

        let line = line.trim();

        if line.starts_with("#") || line.starts_with(";") || line.is_empty() {
            continue;
        }

        let tokens = Vec::from_iter(line.split_whitespace());
        let name = tokens.first().unwrap();
        let tokens = tokens.get(1..).unwrap();

        let tokens = tokens.iter().filter(|t| !t.starts_with("="));

        let tokens = tokens.take_while(|t| !t.starts_with("#") && !t.starts_with(";"));

        let mut parameters = String::new();
        tokens.for_each(|t| { parameters.push_str(t); parameters.push(' '); });

        let parameters = parameters.split(',').map(|s| s.trim());

        let parameters: Vec<String> = parameters.map(|s| s.to_string()).collect();

        match name.to_lowercase().as_str() {
            "fullname" => cfg.full_name = parameters.get(0).cloned(),
            "favouritefruit" => cfg.favourite_fruit = parameters.get(0).cloned(),
            "needspeeling" => cfg.needs_peeling = true,
            "seedsremoved" => cfg.seeds_removed = true,
            "otherfamily" => cfg.other_family = Some(parameters),
            _ => (),
        }
    }

    cfg
}

#[derive(Clone, Debug)]
struct Config {
    full_name: Option<String>,
    favourite_fruit: Option<String>,
    needs_peeling: bool,
    seeds_removed: bool,
    other_family: Option<Vec<String>>,
}

impl Config {
    fn new() -> Config {
        Config {
            full_name: None,
            favourite_fruit: None,
            needs_peeling: false,
            seeds_removed: false,
            other_family: None,
        }
    }
}


Read a file character by character_UTF8

#include <stdio.h>
#include <wchar.h>
#include <stdlib.h>
#include <locale.h>

int main(void)
{

    char *locale = setlocale(LC_ALL, "");
    FILE *in = fopen("input.txt", "r");

    wint_t c;
    while ((c = fgetwc(in)) != WEOF)
        putwchar(c);
    fclose(in);

    return EXIT_SUCCESS;
}

use std::{
    convert::TryFrom,
    fmt::{Debug, Display, Formatter},
    io::Read,
};

pub struct ReadUtf8<I: Iterator> {
    source: std::iter::Peekable<I>,
}

impl<R: Read> From<R> for ReadUtf8<std::io::Bytes<R>> {
    fn from(source: R) -> Self {
        ReadUtf8 {
            source: source.bytes().peekable(),
        }
    }
}

impl<I, E> Iterator for ReadUtf8<I>
where
    I: Iterator<Item = Result<u8, E>>,
{
    type Item = Result<char, Error<E>>;

    fn next(&mut self) -> Option<Self::Item> {
        self.source.next().map(|next| match next {
            Ok(lead) => self.complete_char(lead),
            Err(e) => Err(Error::SourceError(e)),
        })
    }
}

impl<I, E> ReadUtf8<I>
where
    I: Iterator<Item = Result<u8, E>>,
{
    fn continuation(&mut self) -> Result<u32, Error<E>> {
        if let Some(Ok(byte)) = self.source.peek() {
            let byte = *byte;

            return if byte & 0b1100_0000 == 0b1000_0000 {
                self.source.next();
                Ok((byte & 0b0011_1111) as u32)
            } else {
                Err(Error::InvalidByte(byte))
            };
        }

        match self.source.next() {
            None => Err(Error::InputTruncated),
            Some(Err(e)) => Err(Error::SourceError(e)),
            Some(Ok(_)) => unreachable!(),
        }
    }

    fn complete_char(&mut self, lead: u8) -> Result<char, Error<E>> {
        let a = lead as u32;

        let result = if a & 0b1000_0000 == 0 {
            Ok(a)
        } else if lead & 0b1110_0000 == 0b1100_0000 {
            let b = self.continuation()?;
            Ok((a & 0b0001_1111) << 6 | b)
        } else if a & 0b1111_0000 == 0b1110_0000 {
            let b = self.continuation()?;
            let c = self.continuation()?;
            Ok((a & 0b0000_1111) << 12 | b << 6 | c)
        } else if a & 0b1111_1000 == 0b1111_0000 {
            let b = self.continuation()?;
            let c = self.continuation()?;
            let d = self.continuation()?;
            Ok((a & 0b0000_0111) << 18 | b << 12 | c << 6 | d)
        } else {
            Err(Error::InvalidByte(lead))
        };

        Ok(char::try_from(result?).unwrap())
    }
}

#[derive(Debug, Clone)]
pub enum Error<E> {
    InvalidByte(u8),
    InputTruncated,
    SourceError(E),
}

impl<E: Display> Display for Error<E> {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::InvalidByte(b) => write!(f, "invalid byte 0x{:x}", b),
            Self::InputTruncated => write!(f, "character truncated"),
            Self::SourceError(e) => e.fmt(f),
        }
    }
}

fn main() -> std::io::Result<()> {
    for (index, value) in ReadUtf8::from(std::fs::File::open("test.txt")?).enumerate() {
        match value {
            Ok(c) => print!("{}", c),

            Err(e) => {
                print!("\u{fffd}");
                eprintln!("offset {}: {}", index, e);
            }
        }
    }

    Ok(())
}


Read a specific line from a file

#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <err.h>

int read_file_line(const char *path, int line_no)
{
	struct stat s;
	char *buf;
	off_t start = -1, end = -1;
	size_t i;
	int ln, fd, ret = 1;

	if (line_no == 1) start = 0;
	else if (line_no < 1){
		warn("line_no too small");
		return 0;
	}

	line_no--;

	fd = open(path, O_RDONLY);
	fstat(fd, &s);

	buf = mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);

	madvise(buf, s.st_size, MADV_SEQUENTIAL);

	for (i = ln = 0; i < s.st_size && ln <= line_no; i++) {
		if (buf[i] != '\n') continue;

		if (++ln == line_no) start = i + 1;
		else if (ln == line_no + 1) end = i + 1;
	}

	if (start >= s.st_size || start < 0) {
		warn("file does not have line %d", line_no + 1);
		ret = 0;
	} else {

	}

	munmap(buf, s.st_size);
	close(fd);

	return ret;
}

use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;
use std::io::Error;
use std::path::Path;

fn main() {
    let path = Path::new("file.txt");
    let line_num = 7usize;
    let line = get_line_at(&path, line_num - 1);
    println!("{}", line.unwrap());
}

fn get_line_at(path: &Path, line_num: usize) -> Result<String, Error> {
    let file = File::open(path).expect("File not found or cannot be opened");
    let content = BufReader::new(&file);
    let mut lines = content.lines();
    lines.nth(line_num).expect("No line found at that position")
}


Rep-string

#include <stdio.h>
#include <string.h>

int repstr(char *str)
{
    if (!str) return 0;

    size_t sl = strlen(str) / 2;
    while (sl > 0) {
        if (strstr(str, str + sl) == str)
            return sl;
        --sl;
    }

    return 0;
}

int main(void)
{
    char *strs[] = { "1001110011", "1110111011", "0010010010", "1111111111",
        "0100101101", "0100100", "101", "11", "00", "1" };

    size_t strslen = sizeof(strs) / sizeof(strs[0]);
    size_t i;
    for (i = 0; i < strslen; ++i) {
        int n = repstr(strs[i]);
        if (n)
            printf("\"%s\" = rep-string \"%.*s\"\n", strs[i], n, strs[i]);
        else
            printf("\"%s\" = not a rep-string\n", strs[i]);
    }

    return 0;
}

fn main() {
    let strings = vec![
        String::from("1001110011"),
        String::from("1110111011"),
        String::from("0010010010"),
        String::from("1010101010"),
        String::from("1111111111"),
        String::from("0100101101"),
        String::from("0100100"),
        String::from("101"),
        String::from("11"),
        String::from("00"),
        String::from("1"),
    ];
    for string in strings {
        match rep_string(&string) {
            Some(rep_string) => println!(
                "Longuest rep-string for '{}' is '{}' ({} chars)",
                string,
                rep_string,
                rep_string.len(),
            ),
            None => println!("No rep-string found for '{}'", string),
        };
    }
}

fn rep_string(string: &str) -> Option<&str> {
    let index = string.len() / 2;

    for split_index in (1..=index).rev() {
        let mut is_rep_string = true;
        let (first, last) = string.split_at(split_index);

        let inter = last.chars().collect::<Vec<char>>();
        let mut iter = inter.chunks_exact(split_index);
        for chunk in iter.by_ref() {
            if first != chunk.iter().collect::<String>() {
                is_rep_string = false;
                break;
            }
        }
        let rmnd = iter.remainder().iter().collect::<String>();

        if !first.starts_with(rmnd.as_str()) {
            is_rep_string = false;
        }

        if is_rep_string {
            return Some(first);
        }
    }
    None
}

#[cfg(test)]
mod tests {
    use super::rep_string;
    use std::collections::HashMap;

    #[test]
    fn test_rep_string() {
        let mut results = HashMap::new();
        results.insert(String::from("1001110011"), Some("10011"));
        results.insert(String::from("1110111011"), Some("1110"));
        results.insert(String::from("0010010010"), Some("001"));
        results.insert(String::from("1010101010"), Some("1010"));
        results.insert(String::from("1111111111"), Some("11111"));
        results.insert(String::from("0100101101"), None);
        results.insert(String::from("0100100"), Some("010"));
        results.insert(String::from("101"), None);
        results.insert(String::from("11"), Some("1"));
        results.insert(String::from("00"), Some("0"));
        results.insert(String::from("1"), None);

        for (input, expected) in results {
            assert_eq!(expected, rep_string(&input));
        }
    }
}


Rock-paper-scissors

#include <stdio.h>
#include <stdlib.h>
#define LEN 3

int rand_idx(double *p, int n)
{
	double s = rand() / (RAND_MAX + 1.0);
	int i;
	for (i = 0; i < n - 1 && (s -= p[i]) >= 0; i++);
	return i;
}

int main()
{
	int user_action, my_action;
	int user_rec[] = {0, 0, 0};
	const char *names[] = { "Rock", "Paper", "Scissors" };
	char str[2];
	const char *winner[] = { "We tied.", "Meself winned.", "You win." };
	double  p[LEN] = { 1./3, 1./3, 1./3 };

	while (1) {
		my_action = rand_idx(p,LEN);

		printf("\nYour choice [1-3]:\n"
			"  1. Rock\n  2. Paper\n  3. Scissors\n> ");

		if (!scanf("%d", &user_action)) {
			scanf("%1s", str);
			if (*str == 'q') {
				printf("Your choices [rock : %d , paper :  %d , scissors %d] ",user_rec[0],user_rec[1], user_rec[2]);
				return 0;
			}
			continue;
		}
		user_action --;
		if (user_action > 2 || user_action < 0) {
			printf("invalid choice; again\n");
			continue;
		}
		printf("You chose %s; I chose %s. %s\n",
			names[user_action], names[my_action],
			winner[(my_action - user_action + 3) % 3]);

		user_rec[user_action]++;
	}
}

extern crate rand;
#[macro_use]
extern crate rand_derive;

use std::io;
use rand::Rng;
use Choice::*;

#[derive(PartialEq, Clone, Copy, Rand, Debug)]
enum Choice {
    Rock,
    Paper,
    Scissors,
}

fn beats(c1: Choice, c2: Choice) -> bool {
    (c1 == Rock && c2 == Scissors) || (c1 == Scissors && c2 == Paper) || (c1 == Paper && c2 == Rock)
}

fn ai_move<R: Rng>(rng: &mut R, v: [usize; 3]) -> Choice {

    let rand = rng.gen_range(0, v[0] + v[1] + v[2]);
    if rand < v[0] {
        Paper
    } else if rand < v[0] + v[1] {
        Scissors
    } else {
        Rock
    }
}

fn main() {
    let mut rng = rand::thread_rng();

    println!("Rock, paper, scissors!");
    let mut ai_choice: Choice = rng.gen();
    let mut ucf = [0, 0, 0];
    let mut score = [0, 0];

    loop {
        println!("Please input your move: 'r', 'p' or 's'. Type 'q' to quit");

        let mut input = String::new();
        io::stdin()
            .read_line(&mut input)
            .expect("failed to read line");
        let u_choice = match input.to_lowercase().trim() {
            s if s.starts_with('r') => {
                ucf[0] += 1;
                Rock
            }
            s if s.starts_with('p') => {
                ucf[1] += 1;
                Paper
            }
            s if s.starts_with('s') => {
                ucf[2] += 1;
                Scissors
            }
            s if s.starts_with('q') => break,
            _ => {
                println!("Please enter a correct choice!");
                continue;
            }
        };
        println!("You chose {:?}, I chose {:?}.", u_choice, ai_choice);
        if beats(u_choice, ai_choice) {
            score[0] += 1;
            println!("You win!");
        } else if u_choice == ai_choice {
            println!("It's a tie!");
        } else {
            score[1] += 1;
            println!("I win!");
        }
        println!("-Score: You {}, Me {}", score[0], score[1]);

        ai_choice = ai_move(&mut rng, ucf);
    }
    println!("Thank you for the game!");
}


SHA-256 Merkle tree

#include <glib.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

guchar* sha256_merkle_tree(FILE* in, size_t block_size) {
    gchar* buffer = g_malloc(block_size);
    GPtrArray* hashes = g_ptr_array_new_with_free_func(g_free);
    gssize digest_length = g_checksum_type_get_length(G_CHECKSUM_SHA256);
    GChecksum* checksum = g_checksum_new(G_CHECKSUM_SHA256);
    size_t bytes;
    while ((bytes = fread(buffer, 1, block_size, in)) > 0) {
        g_checksum_reset(checksum);
        g_checksum_update(checksum, (guchar*)buffer, bytes);
        gsize len = digest_length;
        guchar* digest = g_malloc(len);
        g_checksum_get_digest(checksum, digest, &len);
        g_ptr_array_add(hashes, digest);
    }
    g_free(buffer);
    guint hashes_length = hashes->len;
    if (hashes_length == 0) {
        g_ptr_array_free(hashes, TRUE);
        g_checksum_free(checksum);
        return NULL;
    }
    while (hashes_length > 1) {
        guint j = 0;
        for (guint i = 0; i < hashes_length; i += 2, ++j) {
            guchar* digest1 = g_ptr_array_index(hashes, i);
            guchar* digest_out = g_ptr_array_index(hashes, j);
            if (i + 1 < hashes_length) {
                guchar* digest2 = g_ptr_array_index(hashes, i + 1);
                g_checksum_reset(checksum);
                g_checksum_update(checksum, digest1, digest_length);
                g_checksum_update(checksum, digest2, digest_length);
                gsize len = digest_length;
                g_checksum_get_digest(checksum, digest_out, &len);
            } else {
                memcpy(digest_out, digest1, digest_length);
            }
        }
        hashes_length = j;
    }
    guchar* result = g_ptr_array_steal_index(hashes, 0);
    g_ptr_array_free(hashes, TRUE);
    g_checksum_free(checksum);
    return result;
}

int main(int argc, char** argv) {
    if (argc != 2) {
        fprintf(stderr, "usage: %s filename\n", argv[0]);
        return EXIT_FAILURE;
    }
    FILE* in = fopen(argv[1], "rb");
    if (in) {
        guchar* digest = sha256_merkle_tree(in, 1024);
        fclose(in);
        if (digest) {
            gssize length = g_checksum_type_get_length(G_CHECKSUM_SHA256);
            for (gssize i = 0; i < length; ++i)
                printf("%02x", digest[i]);
            printf("\n");
            g_free(digest);
        }
    } else {
        perror(argv[1]);
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

extern crate crypto;

use crypto::digest::Digest;
use crypto::sha2::Sha256;
use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;

fn sha256_merkle_tree(filename: &str, block_size: usize) -> std::io::Result<Option<Vec<u8>>> {
    let mut md = Sha256::new();
    let mut input = BufReader::new(File::open(filename)?);
    let mut buffer = vec![0; block_size];
    let mut digest = vec![0; md.output_bytes()];
    let mut digests = Vec::new();
    loop {
        let bytes = input.read(&mut buffer)?;
        if bytes == 0 {
            break;
        }
        md.reset();
        md.input(&buffer[0..bytes]);
        md.result(&mut digest);
        digests.push(digest.clone());
    }
    let mut len = digests.len();
    if len == 0 {
        return Ok(None);
    }
    while len > 1 {
        let mut j = 0;
        let mut i = 0;
        while i < len {
            if i + 1 < len {
                md.reset();
                md.input(&digests[i]);
                md.input(&digests[i + 1]);
                md.result(&mut digests[j]);
            } else {
                digests.swap(i, j);
            }
            i += 2;
            j += 1;
        }
        len = j;
    }
    Ok(Some(digests[0].clone()))
}

fn digest_to_string(digest: &[u8]) -> String {
    let mut result = String::new();
    for x in digest {
        result.push_str(&format!("{:02x}", x));
    }
    result
}

fn main() {
    match sha256_merkle_tree("title.png", 1024) {
        Ok(Some(digest)) => println!("{}", digest_to_string(&digest)),
        Ok(None) => {}
        Err(error) => eprintln!("I/O error: {}", error),
    }
}


Safe primes and unsafe primes

#include <stdbool.h>
#include <stdio.h>

int primes[] = {
    2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
    101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199,
    211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331
};
#define PCOUNT (sizeof(primes) / sizeof(int))

bool isPrime(int n) {
    int i;

    if (n < 2) {
        return false;
    }

    for (i = 0; i < PCOUNT; i++) {
        if (n == primes[i]) {
            return true;
        }
        if (n % primes[i] == 0) {
            return false;
        }
        if (n < primes[i] * primes[i]) {
            return true;
        }
    }

    for (i = primes[PCOUNT - 1] + 2; i * i <= n; i += 2) {
        if (n % i == 0) {
            return false;
        }
    }

    return true;
}

int main() {
    int beg, end;
    int i, count;

    beg = 2;
    end = 1000000;
    count = 0;
    printf("First 35 safe primes:\n");
    for (i = beg; i < end; i++) {
        if (isPrime(i) && isPrime((i - 1) / 2)) {
            if (count < 35) {
                printf("%d ", i);
            }
            count++;
        }
    }
    printf("\nThere are  %d safe primes below  %d\n", count, end);

    beg = end;
    end = end * 10;
    for (i = beg; i < end; i++) {
        if (isPrime(i) && isPrime((i - 1) / 2)) {
            count++;
        }
    }
    printf("There are %d safe primes below %d\n", count, end);

    beg = 2;
    end = 1000000;
    count = 0;
    printf("\nFirst 40 unsafe primes:\n");
    for (i = beg; i < end; i++) {
        if (isPrime(i) && !isPrime((i - 1) / 2)) {
            if (count < 40) {
                printf("%d ", i);
            }
            count++;
        }
    }
    printf("\nThere are  %d unsafe primes below  %d\n", count, end);

    beg = end;
    end = end * 10;
    for (i = beg; i < end; i++) {
        if (isPrime(i) && !isPrime((i - 1) / 2)) {
            count++;
        }
    }
    printf("There are %d unsafe primes below %d\n", count, end);

    return 0;
}

fn is_prime(n: i32) -> bool {
	for i in 2..n {
		if i * i > n {
			return true;
		}
		if n % i == 0 {
			return false;
		}
	}
	n > 1
}

fn is_safe_prime(n: i32) -> bool {
	is_prime(n) && is_prime((n - 1) / 2)
}

fn is_unsafe_prime(n: i32) -> bool {
	is_prime(n) && !is_prime((n - 1) / 2)
}

fn next_prime(n: i32) -> i32 {
	for i in (n+1).. {
		if is_prime(i) {
			return i;
		}
	}
	0
}

fn main() {
	let mut safe = 0;
	let mut unsf = 0;
	let mut p = 2;

	print!("first 35 safe primes: ");
	while safe < 35 {
		if is_safe_prime(p) {
			safe += 1;
			print!("{} ", p);
		}
		p = next_prime(p);
	}
	println!("");

	p = 2;

	print!("first 35 unsafe primes: ");
	while unsf < 35 {
		if is_unsafe_prime(p) {
			unsf += 1;
			print!("{} ", p);
		}
		p = next_prime(p);
	}
	println!("");

	p = 2;
	safe = 0;
	unsf = 0;

	while p < 1000000 {
		if is_safe_prime(p) {
			safe += 1;
		} else {
			unsf += 1;
		}
		p = next_prime(p);
	}
	println!("safe primes below 1,000,000: {}", safe);
	println!("unsafe primes below 1,000,000: {}", unsf);

	while p < 10000000 {
		if is_safe_prime(p) {
			safe += 1;
		} else {
			unsf += 1;
		}
		p = next_prime(p);
	}
	println!("safe primes below 10,000,000: {}", safe);
	println!("unsafe primes below 10,000,000: {}", unsf);
}


Self-describing numbers

#include <stdio.h>

inline int self_desc(unsigned long long xx)
{
	register unsigned int d, x;
	unsigned char cnt[10] = {0}, dig[10] = {0};

	for (d = 0; xx > ~0U; xx /= 10)
		cnt[ dig[d++] = xx % 10 ]++;

	for (x = xx; x; x /= 10)
		cnt[ dig[d++] = x % 10 ]++;

	while(d-- && dig[x++] == cnt[d]);

	return d == -1;
}

int main()
{
	int i;
	for (i = 1; i < 100000000; i++)
		if (self_desc(i)) printf("%d\n", i);

	return 0;
}

fn is_self_desc(xx: u64) -> bool
{
    let s: String = xx.to_string();
    let mut count_vec = vec![0; 10];
    for c in s.chars() {
        count_vec[c.to_digit(10).unwrap() as usize] += 1;
    }
    for (i, c) in s.chars().enumerate() {
        if count_vec[i] != c.to_digit(10).unwrap() as usize {
            return false;
        }
    }
    return true;
}

fn main() {
    for i in 1..100000000 {
        if is_self_desc(i) {
            println!("{}", i)
        }
    }
}


Sequence_ smallest number with exactly n divisors

#include <stdio.h>

#define MAX 15

int count_divisors(int n) {
    int i, count = 0;
    for (i = 1; i * i <= n; ++i) {
        if (!(n % i)) {
            if (i == n / i)
                count++;
            else
                count += 2;
        }
    }
    return count;
}

int main() {
    int i, k, n, seq[MAX];
    for (i = 0; i < MAX; ++i) seq[i] = 0;
    printf("The first %d terms of the sequence are:\n", MAX);
    for (i = 1, n = 0; n <  MAX; ++i) {
        k = count_divisors(i);
        if (k <= MAX && seq[k - 1] == 0) {
            seq[k - 1] = i;
            ++n;
        }
    }
    for (i = 0; i < MAX; ++i) printf("%d ", seq[i]);
    printf("\n");
    return 0;
}

use itertools::Itertools;

const PRIMES: [u64; 15] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47];
const MAX_DIVISOR: usize = 64;

struct DivisorSeq {
    max_number_of_divisors: u64,
    index: u64,
}

impl DivisorSeq {
    fn new(max_number_of_divisors: u64) -> DivisorSeq {
        DivisorSeq {
            max_number_of_divisors,
            index: 1,
        }
    }
}

impl Iterator for DivisorSeq {
    type Item = u64;

    fn next(&mut self) -> Option<u64> {
        if self.max_number_of_divisors < self.index {
            return None;
        }
        #[allow(unused_mut)]
        let mut result: u64;
        let divisors_of_divisor = get_divisors(self.index);
        match divisors_of_divisor.len() {
            1 | 2 => {

                result = 2_u64.pow(self.index as u32 - 1);
                self.index += 1;
            }
            3 => {

                result = 6_u64.pow(divisors_of_divisor[1] as u32 - 1);
                self.index += 1;
            }
            4 => {

                result = 2_u64.pow(divisors_of_divisor[2] as u32 - 1)
                    * 3_u64.pow(divisors_of_divisor[1] as u32 - 1);
                self.index += 1;
            }
            8 if divisors_of_divisor
                .iter()
                .filter(|x| PRIMES.contains(x))
                .count()
                == 3 =>
            {

                let first_primes = divisors_of_divisor
                    .iter()
                    .filter(|x| PRIMES.contains(x))
                    .collect::<Vec<_>>();
                result = 2_u64.pow(*first_primes[2] as u32 - 1)
                    * 3_u64.pow(*first_primes[1] as u32 - 1)
                    * 5_u64.pow(*first_primes[0] as u32 - 1);
                self.index += 1;
            }
            _ => {

                let mut x: u64 = 1;
                loop {
                    if get_divisors(x).len() as u64 == self.index {
                        break;
                    }
                    x += 1;
                }

                result = x;
                self.index += 1;
            }
        }
        Some(result)
    }
}

fn get_divisors(n: u64) -> Vec<u64> {
    let mut results = Vec::new();

    for i in 1..(n / 2 + 1) {
        if n % i == 0 {
            results.push(i);
        }
    }
    results.push(n);
    results
}

fn main() {

    let seq_iter = DivisorSeq::new(64);
    println!("Simple method with rules");
    println!("# divisors     Smallest number");
    for (i, x) in seq_iter.enumerate() {
        println!("{:>10}{:20}", i + 1, x);
    }

    let mut min_numbers = vec![0_u64; MAX_DIVISOR];
    (0_usize..MAX_DIVISOR).for_each(|n| min_numbers[n] = 2_u64.pow(n as u32));

    let prime_list = (1..15).map(|i| PRIMES[0..=i].to_vec()).collect::<Vec<_>>();

    for pl in prime_list.iter() {

        let max_exponent = 1 + MAX_DIVISOR as u32 / 2_u32.pow(pl.len() as u32 - 1);

        let exponents = (1_usize..=pl.len())
            .map(|_| 1_u32..=max_exponent)
            .multi_cartesian_product()
            .filter(|elt| {
                let mut prev = None::<&u32>;
                elt.iter().all(|x| match prev {
                    Some(n) if x > n => false,
                    _ => {
                        prev = Some(x);
                        true
                    }
                })
            });

        for exp in exponents {

            let num_of_divisors = exp.iter().map(|x| x + 1).product::<u32>() as usize;

            let num = pl.iter().zip(exp.iter()).fold(1_u64, |mut acc, (p, e)| {

                acc = match acc.checked_mul(p.pow(*e)) {
                    Some(z) => z,
                    _ => 0,
                };
                acc
            });

            if num > 0
                && min_numbers.len() >= num_of_divisors
                && min_numbers[num_of_divisors - 1] > num
            {
                min_numbers[num_of_divisors - 1] = num;
            }
        }
    }

    println!("Advanced method");
    println!("# divisors     Smallest number");
    for (i, x) in min_numbers.iter().enumerate() {
        println!("{:>10}{:20}", i + 1, x);
    }
}


Set of real numbers

#include <math.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

struct RealSet {
    bool(*contains)(struct RealSet*, struct RealSet*, double);
    struct RealSet *left;
    struct RealSet *right;
    double low, high;
};

typedef enum {
    CLOSED,
    LEFT_OPEN,
    RIGHT_OPEN,
    BOTH_OPEN,
} RangeType;

double length(struct RealSet *self) {
    const double interval = 0.00001;
    double p = self->low;
    int count = 0;

    if (isinf(self->low) || isinf(self->high)) return -1.0;
    if (self->high <= self->low) return 0.0;

    do {
        if (self->contains(self, NULL, p)) count++;
        p += interval;
    } while (p < self->high);
    return count * interval;
}

bool empty(struct RealSet *self) {
    if (self->low == self->high) {
        return !self->contains(self, NULL, self->low);
    }
    return length(self) == 0.0;
}

static bool contains_closed(struct RealSet *self, struct RealSet *_, double d) {
    return self->low <= d && d <= self->high;
}

static bool contains_left_open(struct RealSet *self, struct RealSet *_, double d) {
    return self->low < d && d <= self->high;
}

static bool contains_right_open(struct RealSet *self, struct RealSet *_, double d) {
    return self->low <= d && d < self->high;
}

static bool contains_both_open(struct RealSet *self, struct RealSet *_, double d) {
    return self->low < d && d < self->high;
}

static bool contains_intersect(struct RealSet *self, struct RealSet *_, double d) {
    return self->left->contains(self->left, NULL, d) && self->right->contains(self->right, NULL, d);
}

static bool contains_union(struct RealSet *self, struct RealSet *_, double d) {
    return self->left->contains(self->left, NULL, d) || self->right->contains(self->right, NULL, d);
}

static bool contains_subtract(struct RealSet *self, struct RealSet *_, double d) {
    return self->left->contains(self->left, NULL, d) && !self->right->contains(self->right, NULL, d);
}

struct RealSet* makeSet(double low, double high, RangeType type) {
    bool(*contains)(struct RealSet*, struct RealSet*, double);
    struct RealSet *rs;

    switch (type) {
    case CLOSED:
        contains = contains_closed;
        break;
    case LEFT_OPEN:
        contains = contains_left_open;
        break;
    case RIGHT_OPEN:
        contains = contains_right_open;
        break;
    case BOTH_OPEN:
        contains = contains_both_open;
        break;
    default:
        return NULL;
    }

    rs = malloc(sizeof(struct RealSet));
    rs->contains = contains;
    rs->left = NULL;
    rs->right = NULL;
    rs->low = low;
    rs->high = high;
    return rs;
}

struct RealSet* makeIntersect(struct RealSet *left, struct RealSet *right) {
    struct RealSet *rs = malloc(sizeof(struct RealSet));
    rs->contains = contains_intersect;
    rs->left = left;
    rs->right = right;
    rs->low = fmin(left->low, right->low);
    rs->high = fmin(left->high, right->high);
    return rs;
}

struct RealSet* makeUnion(struct RealSet *left, struct RealSet *right) {
    struct RealSet *rs = malloc(sizeof(struct RealSet));
    rs->contains = contains_union;
    rs->left = left;
    rs->right = right;
    rs->low = fmin(left->low, right->low);
    rs->high = fmin(left->high, right->high);
    return rs;
}

struct RealSet* makeSubtract(struct RealSet *left, struct RealSet *right) {
    struct RealSet *rs = malloc(sizeof(struct RealSet));
    rs->contains = contains_subtract;
    rs->left = left;
    rs->right = right;
    rs->low = left->low;
    rs->high = left->high;
    return rs;
}

int main() {
    struct RealSet *a = makeSet(0.0, 1.0, LEFT_OPEN);
    struct RealSet *b = makeSet(0.0, 2.0, RIGHT_OPEN);
    struct RealSet *c = makeSet(1.0, 2.0, LEFT_OPEN);
    struct RealSet *d = makeSet(0.0, 3.0, RIGHT_OPEN);
    struct RealSet *e = makeSet(0.0, 1.0, BOTH_OPEN);
    struct RealSet *f = makeSet(0.0, 1.0, CLOSED);
    struct RealSet *g = makeSet(0.0, 0.0, CLOSED);
    int i;

    for (i = 0; i < 3; ++i) {
        struct RealSet *t;

        t = makeUnion(a, b);
        printf("(0, 1]   union   [0, 2) contains %d is %d\n", i, t->contains(t, NULL, i));
        free(t);

        t = makeIntersect(b, c);
        printf("[0, 2) intersect (1, 2] contains %d is %d\n", i, t->contains(t, NULL, i));
        free(t);

        t = makeSubtract(d, e);
        printf("[0, 3)     -     (0, 1) contains %d is %d\n", i, t->contains(t, NULL, i));
        free(t);

        t = makeSubtract(d, f);
        printf("[0, 3)     -     [0, 1] contains %d is %d\n", i, t->contains(t, NULL, i));
        free(t);

        printf("\n");
    }

    printf("[0, 0] is empty %d\n", empty(g));

    free(a);
    free(b);
    free(c);
    free(d);
    free(e);
    free(f);
    free(g);

    return 0;
}

#[derive(Debug)]
enum SetOperation {
    Union,
    Intersection,
    Difference,
}

#[derive(Debug, PartialEq)]
enum RangeType {
    Inclusive,
    Exclusive,
}

#[derive(Debug)]
struct CompositeSet<'a> {
    operation: SetOperation,
    a: &'a RealSet<'a>,
    b: &'a RealSet<'a>,
}

#[derive(Debug)]
struct RangeSet {
    range_types: (RangeType, RangeType),
    start: f64,
    end: f64,
}

#[derive(Debug)]
enum RealSet<'a> {
    RangeSet(RangeSet),
    CompositeSet(CompositeSet<'a>),
}

impl RangeSet {
    fn compare_start(&self, n: f64) -> bool {
        if self.range_types.0 == RangeType::Inclusive {
            self.start <= n
        } else {
            self.start < n
        }
    }

    fn compare_end(&self, n: f64) -> bool {
        if self.range_types.1 == RangeType::Inclusive {
            n <= self.end
        } else {
            n < self.end
        }
    }
}

impl<'a> RealSet<'a> {
    fn new(start_type: RangeType, start: f64, end: f64, end_type: RangeType) -> Self {
        RealSet::RangeSet(RangeSet {
            range_types: (start_type, end_type),
            start,
            end,
        })
    }

    fn operation(&'a self, other: &'a Self, operation: SetOperation) -> Self {
        RealSet::CompositeSet(CompositeSet {
            operation,
            a: self,
            b: other,
        })
    }

    fn union(&'a self, other: &'a Self) -> Self {
        self.operation(other, SetOperation::Union)
    }

    fn intersection(&'a self, other: &'a Self) -> Self {
        self.operation(other, SetOperation::Intersection)
    }

    fn difference(&'a self, other: &'a Self) -> Self {
        self.operation(other, SetOperation::Difference)
    }

    fn contains(&self, n: f64) -> bool {
        if let RealSet::RangeSet(range) = self {
            range.compare_start(n) && range.compare_end(n)
        } else if let RealSet::CompositeSet(range) = self {
            match range.operation {
                SetOperation::Union => range.a.contains(n) || range.b.contains(n),
                SetOperation::Intersection => range.a.contains(n) && range.b.contains(n),
                SetOperation::Difference => range.a.contains(n) && !range.b.contains(n),
            }
        } else {
            unimplemented!();
        }
    }
}

fn make_contains_phrase(does_contain: bool) -> &'static str {
    if does_contain {
        "contains"
    } else {
        "does not contain"
    }
}

use RangeType::*;

fn main() {
    for (set_name, set) in [
        (
            "(0, 1] ∪ [0, 2)",
            RealSet::new(Exclusive, 0.0, 1.0, Inclusive)
                .union(&RealSet::new(Inclusive, 0.0, 2.0, Exclusive)),
        ),
        (
            "[0, 2) ∩ (1, 2]",
            RealSet::new(Inclusive, 0.0, 2.0, Exclusive)
                .intersection(&RealSet::new(Exclusive, 1.0, 2.0, Inclusive)),
        ),
        (
            "[0, 3) − (0, 1)",
            RealSet::new(Inclusive, 0.0, 3.0, Exclusive)
                .difference(&RealSet::new(Exclusive, 0.0, 1.0, Exclusive)),
        ),
        (
            "[0, 3) − [0, 1]",
            RealSet::new(Inclusive, 0.0, 3.0, Exclusive)
                .difference(&RealSet::new(Inclusive, 0.0, 1.0, Inclusive)),
        ),
    ] {
        println!("Set {}", set_name);

        for i in [0.0, 1.0, 2.0] {
            println!("- {} {}", make_contains_phrase(set.contains(i)), i);
        }
    }
}