Code Snippets

Snippets of code I've put together, all under GPL v3.

I've handwritten a LR(1) parser that acts a simple command line parser. The code is under the name Parsimonious at GitHub.

Crypto

One time pad cipher

#!/usr/bin/python3
import random
 
def modularadd(char1,char2):
    ichar1 = ord(char1.upper())-65
    ichar2 = ord(char2.upper())-65
    result = (ichar1+ichar2) % 26
    return chr(result+65)
 
def modularsub(char1,char2):
    ichar1 = ord(char1.upper())-65
    ichar2 = ord(char2.upper())-65
    result = (ichar1-ichar2) % 26
    return chr(result+65)
 
def encode(text,pad):
    ciphertext = ""
    for t,p in zip(text,pad):
        ciphertext += modularadd(t,p)
    return ciphertext
 
def decode(ciphertext,pad):
    plaintext = ""
    for c,p in zip(ciphertext,pad):
        plaintext += modularsub(c,p)
    return plaintext
 
def generatepad(length):
    pad = ""
    for i in range(length):
        pad += chr(random.randint(0,25)+65)
    return pad
 
message = "THESOONERYOUFALLBEHINDTHEMORETIMEYOUHAVETOCATCHUP"
pad = generatepad(len(message))
ciphertext = encode(message,pad)
print("Pad:",pad)
print("Ciphertext:",ciphertext)
print("Plaintext:",decode(ciphertext,pad))

Vigenère cipher

#!/usr/bin/python3

def modularadd(char1,char2):
    ichar1 = ord(char1.upper())-65
    ichar2 = ord(char2.upper())-65
    result = (ichar1+ichar2) % 26
    return chr(result+65)

def modularsub(char1,char2):
    ichar1 = ord(char1.upper())-65
    ichar2 = ord(char2.upper())-65
    result = (ichar1-ichar2) % 26
    return chr(result+65)

def cipher(text, key):
    ciphertext = [modularadd(text[i], key[i % len(key)]) for i in
                  range(len(text))]
    return "".join(ciphertext)

def decipher(cipher, key):
    plaintext = [modularsub(cipher[i], key[i % len(key)]) for i in
                 range(len(cipher))]
    return "".join(plaintext)

message = "THESOONERYOUFALLBEHINDTHEMORETIMEYOUHAVETOCATCHUP"
key = "SECRET"
ciphertext = cipher(message,key)
print("Key:", key)
print("Ciphertext:", ciphertext)
print("Plaintext:", decipher(ciphertext,key))

Functional programming

Church numerals

(* church booleans *)
fun True x y = x;
fun False x y = y;

(*conditionals*)
fun If b x y = b x y;
fun Or b1 b2 x y        = b1 x (b2 x y);
fun Xor b1 b2 x y       = b1 (b2 y x) (b2 x y);
fun And b1 b2 x y       = b1 (b2 x y) y;
fun Nand b1 b2 x y      = b1 (b2 y x) x;
fun Not b x y           = b y x;

(* church numerals *)
fun Zero f x = x;
fun One f x = f x;
fun Two f x = f (f x);

fun Succ n f x = f (n f x);
fun Add m n f x = m f (n f x);
fun Multiply m n f x = m (n f) x;
fun Exp m n f x = n m f x;
(* swap them or we end up doing n^m *)

fun IsZero n = n (fn(x) => False) True;

(* predecessor and subtraction, translated from lamba notation in IB notes *)
fun Pair x y f = f x y;
fun First p = p True;
fun Second p = p False;

fun Prefn f p = Pair(f(First p)) (First p);
fun Pre n f x = Second(n(Prefn f)(Pair x x));

fun Sub m n = n Pre m;

(* nicer predecessor using normal pairs based on above *)
fun Prefn2 f (a,b) = (b,f b);
fun Pre2 n f x =
let
        val (a,b) = (n (Prefn2 f) (x,x))
in
        a
end;

(* conversion  of numbers *)
fun Churchify 0 f x = x
  | Churchify n f x = f(Churchify (n-1) f x);
fun DeChurchify n = n (fn(x) => x+1) 0;

(* conversion of booleans *)
fun ChurchifyBool true = True;
  | ChurchifyBool false = False
fun DeChurchifyBool n = n true false;

The Tower of Hanoi puzzle

(* write an ML function such that Move(3,"A","B","C") solves the hanoi puzzle*)
load "Int";

fun Move(1,start,other,finish) = ["move 1 from " ^ start ^ " to " ^ finish]
  | Move (x,start,other,finish) =
    Move(x-1,start,finish,other)@
        ["move " ^ (Int.toString x) ^ " from " ^ start ^ " to " ^ finish]@
        Move(x-1,other,start,finish);

Multithreading

Dining Philisophers

class DiningPhilosophers {
    public static void main(String[] args) {
        Fork[] forks = new Fork[5];
        for (int i=0; i<forks.length; i++) {
            forks[i] = new Fork();
        }

        Philosopher p1 = new Philosopher(1,forks[0],forks[1]);
        Philosopher p2 = new Philosopher(2,forks[1],forks[2]);
        Philosopher p3 = new Philosopher(3,forks[2],forks[3]);
        Philosopher p4 = new Philosopher(4,forks[3],forks[4]);
        Philosopher p5 = new Philosopher(5,forks[4],forks[0]);

        p1.start();
        p2.start();
        p3.start();
        p4.start();
        p5.start();

    }
}

class Philosopher extends Thread {
    private Fork l,r;
    private int num;

    public void run() {
        while(true) {
            eat();
        }
    }

    void eat() {
        synchronized(l) {
            synchronized(r) {
                System.out.printf("Philosopher %d eating.\n",num);
                System.out.printf("Current time is %d\n",
                                  System.currentTimeMillis());
            }
        }

    }

    Philosopher(int num, Fork l, Fork r) {
        this.num = num;
        this.l = l;
        this.r = r;
    }
}

class Fork {}

Puzzles

Solving word sums.

#!/usr/bin/python3
 
def generate_solutions(letters, digits):
    if len(letters) == 6:
        if is_solution(letters):
            print("solution",letters)
            return
    else:
        for i in digits:
            remaining_digits = digits[:]
            remaining_digits.remove(i)
            generate_solutions(letters+[i],remaining_digits)
 
def is_solution(letters):
    t = letters[0]
    w = letters[1]
    o = letters[2]
    f = letters[3]
    u = letters[4]
    r = letters[5]
    if 2*(t*100+w*10+o) == f*1000+o*100+u*10+r:
        return True
    return False
 
generate_solutions([],[0,1,2,3,4,5,6,7,8,9])

# there are better ways of iterating through the possibilities
# that are much faster