From 6db1a2cdd3b96731f2e092d55d8c2136eabc52d0 Mon Sep 17 00:00:00 2001
From: Julian T <julian@jtle.dk>
Date: Tue, 11 Feb 2020 12:24:56 +0100
Subject: Rename and cleanup

---
 sem3/BfCI/husk.txt                      |  14 ++
 sem3/BfCI/mm1.md                        | 177 ++++++++++++++++++++++++++
 sem3/BfCI/mm3.md                        |  19 +++
 sem3/algo/.gitignore                    |   2 +
 sem3/algo/graph/Cargo.lock              |   6 +
 sem3/algo/graph/Cargo.toml              |   9 ++
 sem3/algo/graph/src/graph.rs            |  85 +++++++++++++
 sem3/algo/graph/src/main.rs             |  23 ++++
 sem3/algo/lek1/merge.c                  | 115 +++++++++++++++++
 sem3/algo/mm10/bfs.c                    | 163 ++++++++++++++++++++++++
 sem3/algo/mm12/Makefile                 |  31 +++++
 sem3/algo/mm12/dijkstra.c               | 132 +++++++++++++++++++
 sem3/algo/mm12/graph.c                  | 123 ++++++++++++++++++
 sem3/algo/mm12/graph.h                  |  34 +++++
 sem3/algo/mm2/linked/Makefile           |  31 +++++
 sem3/algo/mm2/linked/Readme.md          |  22 ++++
 sem3/algo/mm2/linked/llist.c            |  89 +++++++++++++
 sem3/algo/mm2/linked/llist.h            |  22 ++++
 sem3/algo/mm2/linked/main.c             |  45 +++++++
 sem3/algo/mm2/linked/node.c             |  57 +++++++++
 sem3/algo/mm2/linked/node.h             |  23 ++++
 sem3/algo/mm2/queue.c                   | 100 +++++++++++++++
 sem3/algo/mm3/multiply.c                |  56 ++++++++
 sem3/algo/mm3/opgaver.md                |  49 +++++++
 sem3/algo/mm6/Makefile                  |  31 +++++
 sem3/algo/mm6/main                      | Bin 0 -> 23144 bytes
 sem3/algo/mm6/main.c                    |  37 ++++++
 sem3/algo/mm6/tree.c                    | 155 ++++++++++++++++++++++
 sem3/algo/mm6/tree.h                    |  31 +++++
 sem3/algo/mm9/Untitled.ipynb            | 126 ++++++++++++++++++
 sem3/algo/workshop2/dfs/Makefile        |  41 ++++++
 sem3/algo/workshop2/dfs/dfs             | Bin 0 -> 24960 bytes
 sem3/algo/workshop2/dfs/dfs.c           | 107 ++++++++++++++++
 sem3/algo/workshop2/dfs/graph.c         | 181 ++++++++++++++++++++++++++
 sem3/algo/workshop2/dfs/graph.h         |  45 +++++++
 sem3/algo/workshop2/dijkstra/Makefile   |  31 +++++
 sem3/algo/workshop2/dijkstra/dijkstra.c | 129 +++++++++++++++++++
 sem3/algo/workshop2/dijkstra/graph.c    | 219 ++++++++++++++++++++++++++++++++
 sem3/algo/workshop2/dijkstra/graph.h    |  47 +++++++
 sem3/module.c                           |  12 ++
 sem3/osc/miniproject/cnasm/Makefile     |  30 +++++
 sem3/osc/miniproject/cnasm/ast.c        |  98 ++++++++++++++
 sem3/osc/miniproject/cnasm/ast.h        |  53 ++++++++
 sem3/osc/miniproject/cnasm/codegen.c    | 132 +++++++++++++++++++
 sem3/osc/miniproject/cnasm/codegen.h    |  14 ++
 sem3/osc/miniproject/cnasm/regn.l       |  39 ++++++
 sem3/osc/miniproject/cnasm/regn.y       |  81 ++++++++++++
 sem3/osc/miniproject/cnasm/test.asm     |  39 ++++++
 sem3/osc/mm1/.gitignore                 |  10 ++
 sem3/osc/mm1/mm1/Makefile               |   7 +
 sem3/osc/mm1/mm1/Readme.md              |  34 +++++
 sem3/osc/mm1/mm1/jmod.c                 |  70 ++++++++++
 sem3/osc/mm1/mm2/tprog.c                |  71 +++++++++++
 sem3/osc/mm10/Makefile                  |  25 ++++
 sem3/osc/mm10/opg1.l                    |  22 ++++
 sem3/osc/mm10/opg3.l                    |  36 ++++++
 sem3/osc/mm10/opg4.l                    | 101 +++++++++++++++
 sem3/osc/mm10/opgaver.md                |  55 ++++++++
 sem3/osc/mm10/stateMachine.png          | Bin 0 -> 21881 bytes
 sem3/osc/mm11/opgaver.md                |  32 +++++
 sem3/osc/mm11/regn/Makefile             |  30 +++++
 sem3/osc/mm11/regn/regn.l               |  40 ++++++
 sem3/osc/mm11/regn/regn.y               |  54 ++++++++
 sem3/osc/mm11/regn/symtab.c             |  50 ++++++++
 sem3/osc/mm11/regn/symtab.h             |  20 +++
 sem3/osc/mm11/regn2/Makefile            |  30 +++++
 sem3/osc/mm11/regn2/regn.l              |  27 ++++
 sem3/osc/mm11/regn2/regn.y              |  46 +++++++
 sem3/osc/mm3/opgaver.md                 |  47 +++++++
 sem3/osc/mm8/mm8.ino                    |  47 +++++++
 sem3/osc/mm9/opgaver.md                 | 129 +++++++++++++++++++
 sem3/osc/noter.md                       |  17 +++
 72 files changed, 4105 insertions(+)
 create mode 100644 sem3/BfCI/husk.txt
 create mode 100644 sem3/BfCI/mm1.md
 create mode 100644 sem3/BfCI/mm3.md
 create mode 100644 sem3/algo/.gitignore
 create mode 100644 sem3/algo/graph/Cargo.lock
 create mode 100644 sem3/algo/graph/Cargo.toml
 create mode 100644 sem3/algo/graph/src/graph.rs
 create mode 100644 sem3/algo/graph/src/main.rs
 create mode 100644 sem3/algo/lek1/merge.c
 create mode 100644 sem3/algo/mm10/bfs.c
 create mode 100644 sem3/algo/mm12/Makefile
 create mode 100644 sem3/algo/mm12/dijkstra.c
 create mode 100644 sem3/algo/mm12/graph.c
 create mode 100644 sem3/algo/mm12/graph.h
 create mode 100644 sem3/algo/mm2/linked/Makefile
 create mode 100644 sem3/algo/mm2/linked/Readme.md
 create mode 100644 sem3/algo/mm2/linked/llist.c
 create mode 100644 sem3/algo/mm2/linked/llist.h
 create mode 100644 sem3/algo/mm2/linked/main.c
 create mode 100644 sem3/algo/mm2/linked/node.c
 create mode 100644 sem3/algo/mm2/linked/node.h
 create mode 100644 sem3/algo/mm2/queue.c
 create mode 100644 sem3/algo/mm3/multiply.c
 create mode 100644 sem3/algo/mm3/opgaver.md
 create mode 100644 sem3/algo/mm6/Makefile
 create mode 100755 sem3/algo/mm6/main
 create mode 100644 sem3/algo/mm6/main.c
 create mode 100644 sem3/algo/mm6/tree.c
 create mode 100644 sem3/algo/mm6/tree.h
 create mode 100644 sem3/algo/mm9/Untitled.ipynb
 create mode 100644 sem3/algo/workshop2/dfs/Makefile
 create mode 100755 sem3/algo/workshop2/dfs/dfs
 create mode 100644 sem3/algo/workshop2/dfs/dfs.c
 create mode 100644 sem3/algo/workshop2/dfs/graph.c
 create mode 100644 sem3/algo/workshop2/dfs/graph.h
 create mode 100644 sem3/algo/workshop2/dijkstra/Makefile
 create mode 100644 sem3/algo/workshop2/dijkstra/dijkstra.c
 create mode 100644 sem3/algo/workshop2/dijkstra/graph.c
 create mode 100644 sem3/algo/workshop2/dijkstra/graph.h
 create mode 100644 sem3/module.c
 create mode 100644 sem3/osc/miniproject/cnasm/Makefile
 create mode 100644 sem3/osc/miniproject/cnasm/ast.c
 create mode 100644 sem3/osc/miniproject/cnasm/ast.h
 create mode 100644 sem3/osc/miniproject/cnasm/codegen.c
 create mode 100644 sem3/osc/miniproject/cnasm/codegen.h
 create mode 100644 sem3/osc/miniproject/cnasm/regn.l
 create mode 100644 sem3/osc/miniproject/cnasm/regn.y
 create mode 100644 sem3/osc/miniproject/cnasm/test.asm
 create mode 100644 sem3/osc/mm1/.gitignore
 create mode 100644 sem3/osc/mm1/mm1/Makefile
 create mode 100644 sem3/osc/mm1/mm1/Readme.md
 create mode 100644 sem3/osc/mm1/mm1/jmod.c
 create mode 100644 sem3/osc/mm1/mm2/tprog.c
 create mode 100644 sem3/osc/mm10/Makefile
 create mode 100644 sem3/osc/mm10/opg1.l
 create mode 100644 sem3/osc/mm10/opg3.l
 create mode 100644 sem3/osc/mm10/opg4.l
 create mode 100644 sem3/osc/mm10/opgaver.md
 create mode 100644 sem3/osc/mm10/stateMachine.png
 create mode 100644 sem3/osc/mm11/opgaver.md
 create mode 100644 sem3/osc/mm11/regn/Makefile
 create mode 100644 sem3/osc/mm11/regn/regn.l
 create mode 100644 sem3/osc/mm11/regn/regn.y
 create mode 100644 sem3/osc/mm11/regn/symtab.c
 create mode 100644 sem3/osc/mm11/regn/symtab.h
 create mode 100644 sem3/osc/mm11/regn2/Makefile
 create mode 100644 sem3/osc/mm11/regn2/regn.l
 create mode 100644 sem3/osc/mm11/regn2/regn.y
 create mode 100644 sem3/osc/mm3/opgaver.md
 create mode 100644 sem3/osc/mm8/mm8.ino
 create mode 100644 sem3/osc/mm9/opgaver.md
 create mode 100644 sem3/osc/noter.md

(limited to 'sem3')

diff --git a/sem3/BfCI/husk.txt b/sem3/BfCI/husk.txt
new file mode 100644
index 0000000..e5a7b96
--- /dev/null
+++ b/sem3/BfCI/husk.txt
@@ -0,0 +1,14 @@
+
+
+log(log(x^4)) = log(log(x)) 
+
+Husk at 4 flytter sig uden for log(x).
+
+
+x^2-1 = (x-1)(x+1)
+
+lim(to inf) f(x) over g(x) = {
+	0		-> f is O(g)
+	const	-> f(x) = THETA(g(x))
+	INF		-> f is OMEGA(g)
+}
diff --git a/sem3/BfCI/mm1.md b/sem3/BfCI/mm1.md
new file mode 100644
index 0000000..933086c
--- /dev/null
+++ b/sem3/BfCI/mm1.md
@@ -0,0 +1,177 @@
+# Logic
+
+TODO Manger at lave en summary.
+
+## Opgaver
+
+### 1.
+
+A) Yes, T
+B) Yes, T
+C) Yes, T
+D) Yes, T
+E) No
+F) No
+
+### UNKNOWN ORIGIN (12.)
+
+A) if you have the flu, you miss the final examination
+B) you pass the course if and only if you do not miss the final examination
+C) if you miss the final examination, you do not pass the course
+D) you have the flu, miss the final examination and pass the couse
+
+### 15. (13.)
+
+A) ¬p
+B) p ^ ¬q
+C) p -> q
+D) ¬p -> ¬q
+E) p -> q
+F) q ^ ¬p
+G) q -> p
+
+### 20. (18.)
+
+A) T
+B) T
+C) F
+D) T
+
+### UNKNOWN ORIGIN(31.)
+
+A)
+
+| p  | ¬p | p  ^ ¬p |
+| -- | -- | --      |
+| T  | F  | F       |
+| F  | T  | F       |
+
+B)
+
+| p  | ¬p | p v ¬p |
+| -- | -- | --     |
+| T  | F  | T      |
+| F  | T  | T      |
+
+C)
+
+| p  | q  | p v ¬q | ( p v ¬q) -> q |
+| -- | -- | --     | --             |
+| T  | T  | T      | T              |
+| T  | F  | T      | F              |
+| F  | T  | F      | T              |
+| F  | F  | T      | F              |
+
+D)
+
+| p  | q  | ( p v q) -> ( p ^ q ) |
+| -- | -- | --                    |
+| T  | T  | T -> T = T            |
+| T  | F  | T -> F = F            |
+| F  | T  | T -> F = F            |
+| F  | F  | F -> F = T            |
+
+E)
+
+| p  | q  | (p -> q) | (¬q -> ¬p) | (p -> q) <-> (¬q -> ¬p ) |
+| -- | -- | --       | --         | --                       |
+| T  | T  | T        | T          | T                        |
+| T  | F  | F        | F          | T                        |
+| F  | T  | T        | T          | T                        |
+| F  | F  | T        | T          | T                        |
+
+F)
+
+| p  | q  | (p -> q) | ( q -> p ) | (p -> q) -> ( q -> p) |
+| -- | -- | --       | --         | --                    |
+| T  | T  | T        | T          | T                     |
+| T  | F  | F        | T          | T                     |
+| F  | T  | T        | F          | F                     |
+| F  | F  | T        | T          | T                     |
+
+
+### (40. )
+
+All the paranterees must be true, they can be split up.
+
+r is in two parantesees ( q v ¬r ) and ( r v ¬p ).
+
+If r is true q must also be true for ( q v ¬p ).
+
+Therefore in ( p v ¬p ) p must also be true.
+
+Therefore it creates a kind of circle, that also works then one is false.
+
+### (44. )
+
+A) 
+
+ 01011
+ 11011
+v-----
+ 11011
+ 11000
+^-----
+ 11000
+
+B)
+
+ 01111
+ 10101
+^-----
+ 00101
+ 01000
+v-----
+ 01101
+
+C)
+
+ 01010
+ 11011
+x-----
+ 10001
+ 01000
+x-----
+ 11001
+
+D)
+
+ 11011
+ 01010
+v-----
+ 11011
+
+ 10001
+ 11011
+v-----
+ 11011
+
+ 11011
+ 11011
+^-----
+ 11011
+
+
+### (7. )
+
+Already done this
+
+### (9. )
+
+The rest is just stupid.
+
+### (20. )
+
+| p  | q  | p x q | p <-> q |
+| -- | -- | --    | --      |
+| T  | T  | F     | T       |
+| T  | F  | T     | F       |
+| F  | T  | T     | F       |
+| F  | F  | F     | T       |
+
+The two last columns are the negatives of each other thus
+
+p x q = p <-> q
+
+
+
diff --git a/sem3/BfCI/mm3.md b/sem3/BfCI/mm3.md
new file mode 100644
index 0000000..a0bb1b8
--- /dev/null
+++ b/sem3/BfCI/mm3.md
@@ -0,0 +1,19 @@
+# Lektier
+
+## Steps til strong induction bevis
+
+1. *[Basis step]* start med at bevis at P(1) er sandt. Altså hvad resten vil bygge på.
+2. *[Inductive step]* bevis at hvis de første P(1 til k) er sandt er P(k+1) også sandt.
+
+## Recursive function
+
+En funktion der regner factorial. 
+Altså f(x) = 1 * 2 * 3 * .. * x
+
+Her vil f(1) = 1.
+Og resten vil være f(x) = x * f(x-1).
+
+f(1) = 1
+f(2) = 2 * f(1) = 2 * 1 = 2
+f(3) = 3 * f(2) = 3 * 2 = 6
+f(4) = 4 * f(3) = 4 * 6 = 16
diff --git a/sem3/algo/.gitignore b/sem3/algo/.gitignore
new file mode 100644
index 0000000..38aee6d
--- /dev/null
+++ b/sem3/algo/.gitignore
@@ -0,0 +1,2 @@
+**/a.out
+**/build
diff --git a/sem3/algo/graph/Cargo.lock b/sem3/algo/graph/Cargo.lock
new file mode 100644
index 0000000..74fba54
--- /dev/null
+++ b/sem3/algo/graph/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "graph"
+version = "0.1.0"
+
diff --git a/sem3/algo/graph/Cargo.toml b/sem3/algo/graph/Cargo.toml
new file mode 100644
index 0000000..896f437
--- /dev/null
+++ b/sem3/algo/graph/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "graph"
+version = "0.1.0"
+authors = ["Julian T <julian@jtle.dk>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/sem3/algo/graph/src/graph.rs b/sem3/algo/graph/src/graph.rs
new file mode 100644
index 0000000..cefd24f
--- /dev/null
+++ b/sem3/algo/graph/src/graph.rs
@@ -0,0 +1,85 @@
+use std::rc::{Rc, Weak};
+use std::cell::RefCell;
+use std::vec::Vec;
+use std::string::String;
+use std::collections::HashMap;
+use std::fmt;
+
+type EdgeRef = RefCell<Edge>;
+type VertexRef = RefCell<Vertex>;
+
+pub struct Edge {
+    from: Weak<VertexRef>,
+    to: Weak<VertexRef>,
+    weight: i32,
+}
+
+pub struct Vertex {
+    name: String,
+    pub adj: Vec<Rc<EdgeRef>>,
+}
+
+pub struct Graph {
+    vertexes: HashMap<String, Rc<VertexRef>>,
+    edges: Vec<Rc<EdgeRef>>,
+}
+
+impl Vertex {
+    pub fn new(name: &str) -> VertexRef {
+        RefCell::new( Vertex { name: String::from(name), adj: Vec::new() })
+    }
+}
+
+impl Graph {
+    pub fn new() -> Graph {
+        Graph { vertexes: HashMap::new(), edges: Vec::new() }
+    }
+
+    pub fn edge(&mut self, from: &str, to: &str, weight: i32) {
+        let from = match self.vertexes.get(from) {
+            Some(rc) => Rc::clone(rc),
+            None => self.add_vertex(from),
+        };
+
+        let to = match self.vertexes.get(to) {
+            Some(rc) => Rc::clone(rc),
+            None => self.add_vertex(to),
+        };
+
+        // Create edge
+        let e = Rc::new(RefCell::new( Edge { from: Rc::downgrade(&from), to: Rc::downgrade(&to), weight } ));
+
+        // Add to stuff
+        from.borrow_mut().adj.push(Rc::clone(&e));
+        self.edges.push(e);
+        
+    }
+
+    pub fn borrow_vertex(&self, name: &str) -> Option<Rc<VertexRef>> {
+        self.vertexes.get(name).and_then(|rc| Some(Rc::clone(rc)))
+    }
+
+    fn add_vertex(&mut self, name: &str) -> Rc<VertexRef> {
+        let v = Rc::new( Vertex::new(name) );
+
+        // Insert in hashmap
+        self.vertexes.insert(String::from(name), Rc::clone(&v));
+
+        // Return vertex
+        v
+    }
+
+}
+
+impl fmt::Display for Edge {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let rc = self.to.upgrade().unwrap();
+        write!(f, "{}", Rc::clone(&rc).borrow())
+    }
+}
+
+impl fmt::Display for Vertex {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", self.name)
+    }
+}
diff --git a/sem3/algo/graph/src/main.rs b/sem3/algo/graph/src/main.rs
new file mode 100644
index 0000000..4f732e7
--- /dev/null
+++ b/sem3/algo/graph/src/main.rs
@@ -0,0 +1,23 @@
+
+mod graph;
+
+use graph::Graph;
+
+fn main() {
+
+    let mut g = Graph::new();
+
+    g.edge("a", "b", 10);
+    g.edge("a", "c", 10);
+    g.edge("a", "d", 10);
+
+    // Ahh this is hard
+    let v = g.borrow_vertex("a").unwrap();
+    let v23 = v.borrow();
+    let mut it = v23.adj.iter();
+    for e in it {
+        println!("{}", e.borrow());
+    }
+
+    println!("Hello, world!");
+}
diff --git a/sem3/algo/lek1/merge.c b/sem3/algo/lek1/merge.c
new file mode 100644
index 0000000..997bcb8
--- /dev/null
+++ b/sem3/algo/lek1/merge.c
@@ -0,0 +1,115 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <stdint.h>
+
+#define DO_PRINT 0
+
+void printArr(int *arr, size_t len) {
+	printf("{");
+	for(int i = 0; i < len; i++) {
+		printf(" %d%s", arr[i], i+1 == len ? " " : ",");
+	}
+	printf("}\n");
+}
+
+int *genArr(size_t len, int div) {
+	/* Make array */
+	int *arr = (int *) malloc(len * sizeof(int));
+
+	if( arr == NULL) {
+		return NULL;
+	}
+
+	/* Fill it with random */
+	while( len-- ) {
+		arr[len] = div - (rand() % (div*2));
+	}
+
+	return arr;
+
+}
+
+int mergeSort(int *arr, size_t len) {
+	/* Check if len is one(then it's sorted */
+	if (len <= 1) {
+		return 0;
+	}
+	/* Calculate array sizes */
+	size_t q = len/2;
+	size_t rl = len-q;
+
+	/* Make arrays */
+	int *left = (int *) malloc(q * sizeof(int));
+	if( left == NULL ) {
+		return 1;
+	}
+	int *right = (int *) malloc(rl * sizeof(int));
+	if( right == NULL ) {
+		return 1;
+	}
+
+	/* Copy data */
+	memcpy(left, arr, q * sizeof(int));
+	memcpy(right, arr + q, rl * sizeof(int));
+
+	/* Sort each */
+	mergeSort(left, q);
+	mergeSort(right, rl);
+
+	/* Merge them into arr */
+	for(int i=0, j=0, k = 0; k < len; k++) {
+		if( i < q && ( j == rl || left[i] <= right[j] ) ) {
+			arr[k] = left[ i++ ];
+		} else {
+			arr[k] = right[ j++ ];
+		}
+	}
+
+	/* Free the pointers */
+	free(left);
+	free(right);
+
+	return 0;
+}
+
+void test(size_t len) {
+
+	int *a = genArr(len, len);
+
+#if DO_PRINT == 1
+	printArr(a, len);
+	printf("\n\n");
+#endif
+
+	clock_t begin = clock();
+	mergeSort(a, len);
+	clock_t end = clock();
+
+#if DO_PRINT == 1
+	printArr(a, len);
+#endif
+
+	clock_t diff = end - begin;
+	printf("Sorting %d long array took %d : %f s\n", len, diff, (double)diff/CLOCKS_PER_SEC);
+
+	free(a);
+}
+
+void bench() {
+
+	size_t len = SIZE_MAX;
+
+	srand((unsigned) time(NULL));
+	for (int i = 1; i < len; i *= 2) {
+		test(i);
+	}
+}
+
+int main(void) {
+
+	bench();
+
+	return 0;
+}
diff --git a/sem3/algo/mm10/bfs.c b/sem3/algo/mm10/bfs.c
new file mode 100644
index 0000000..982ecef
--- /dev/null
+++ b/sem3/algo/mm10/bfs.c
@@ -0,0 +1,163 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#define COL_WHITE 0
+#define COL_GRAY  1
+#define COL_BLACK 2
+
+typedef struct list_node_t_struct {
+	struct list_node_t_struct *next;
+	void *val;
+} list_node_t;
+
+typedef struct vertex_struct {
+	char ref;
+	int color;
+	int dist;
+	struct vertex_struct *p;
+	list_node_t *adj;
+} vertex_t;
+
+vertex_t *create_vertex(char ref) {
+	// Get some space TODO check for null
+	vertex_t *v = malloc(sizeof(vertex_t));
+
+	// Set values
+	v->ref = ref;
+	v->color = COL_WHITE;
+	v->dist = -1;
+	v->p = NULL;
+	v->adj = NULL;
+}
+
+vertex_t *add_adj(vertex_t *v, vertex_t *add) {
+	list_node_t *oldN = v->adj;
+
+	// Create new list node
+	list_node_t *n = malloc(sizeof(list_node_t));
+	n->val = add;
+	n->next = oldN;
+
+	v->adj = n;
+
+	return add;
+}
+
+void print_adj(vertex_t *v) {
+	list_node_t *n = v->adj;
+	printf("[ ");
+	while(n) {
+		printf("%c ", *((char *)n->val));
+		n = n->next;
+	}
+	printf("]\n");
+}
+
+vertex_t *vertexes[128];
+
+void add_edge(char a, char b) {
+	// Does a exists
+	if( vertexes[a] == NULL ) {
+		vertexes[a] = create_vertex(a);
+	}
+	// What about b
+	if( vertexes[b] == NULL ) {
+		vertexes[b] = create_vertex(b);
+	}
+
+	// Add edge
+	add_adj(vertexes[a], vertexes[b]);
+}
+
+typedef struct {
+	unsigned int len;
+	list_node_t *in;
+	list_node_t *out;
+} queue_t;
+
+void enqueue(queue_t *q, vertex_t *v) {
+	list_node_t *n = malloc(sizeof(list_node_t));
+	n->val = v;
+
+	// Add at end
+	list_node_t *old = q->in;
+	q->in = n;
+	if( old ) {
+		old->next = n;
+	}
+
+	// Make sure we have an out
+	if( q->out == NULL ) {
+		q->out = n;
+	}
+
+	q->len++;
+}
+
+vertex_t *dequeue(queue_t *q) {
+	list_node_t *n = q->out;
+	if( n == NULL ) {
+		return NULL;
+	}
+	vertex_t *v = (vertex_t *)n->val;
+
+	// Move out forward
+	q->out = n->next;
+	q->len--;
+
+	// Free node and return
+	free(n);
+	return v;
+}
+
+void bfs(vertex_t *s) {
+	queue_t q = {0, NULL, NULL };
+	enqueue(&q, s);
+	s->dist = 0;
+	
+	while( q.len ) {
+		vertex_t *u = dequeue(&q);
+		list_node_t *n = u->adj;
+		while( n ) {
+			vertex_t *v = (vertex_t *)n->val;
+			if( v->color == COL_WHITE ) {
+				v->color = COL_GRAY;
+				v->dist = u->dist + 1;
+				v->p = u;
+				enqueue(&q, v);
+			}
+			n = n->next;
+		}
+		u->color = COL_BLACK;
+	}
+	
+}
+
+int main() {
+	add_edge('s', 'd'); // S
+	add_edge('s', 'c');
+	add_edge('s', 'a');
+	add_edge('d', 'e'); // D
+	add_edge('d', 'c');
+	add_edge('e', 'g'); // E
+	add_edge('e', 'f');
+	add_edge('c', 's'); // C
+	add_edge('c', 'g');
+	add_edge('g', 'f'); // G
+
+	//print_adj(vertexes['d']);
+	bfs(vertexes['s']);
+
+	char c;
+	while( (c = getchar()) != EOF) {
+		if( vertexes[c] != NULL ) {
+			print_adj(vertexes[c]);
+			printf("%d\n", vertexes[c]->dist);
+		} else if (c == 10) {
+		} else {
+			printf("Not found\n");
+		}
+	}
+
+
+}
diff --git a/sem3/algo/mm12/Makefile b/sem3/algo/mm12/Makefile
new file mode 100644
index 0000000..7837354
--- /dev/null
+++ b/sem3/algo/mm12/Makefile
@@ -0,0 +1,31 @@
+CC = gcc
+# Enable gdb and pull include files from current dir
+CFLAGS = -ggdb -I.
+LDFLAGS = 
+
+BINARY = dijkstra
+BUILD_DIR = build
+
+# Capture c files 
+c_files = $(wildcard *.c)
+
+# Convert c names to corrosponding o names
+OBJ = $(patsubst %.c, $(BUILD_DIR)/%.o, $(c_files))
+
+# $@ is the %.o file and $^ is the %.c file
+$(BUILD_DIR)/%.o: %.c
+	mkdir -p $(dir $@)
+	$(CC) -c -o $@ $^ $(CFLAGS)
+
+# $@ becomes left part thus linked
+$(BINARY): $(OBJ)
+	$(CC) -o $@ $^ $(LDFLAGS)
+
+.PHONY: clean run
+
+run: $(BINARY)
+	./$(BINARY)
+
+clean:
+	rm -f $(OBJ) $(BINARY)
+	rmdir $(BUILD_DIR)
diff --git a/sem3/algo/mm12/dijkstra.c b/sem3/algo/mm12/dijkstra.c
new file mode 100644
index 0000000..103c700
--- /dev/null
+++ b/sem3/algo/mm12/dijkstra.c
@@ -0,0 +1,132 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "graph.h"
+
+typedef struct list_item {
+	vertex_t *v;
+	struct list_item *next;
+	struct list_item *prev;
+} list_item_t;
+
+typedef struct {
+	int len;
+	struct list_item *begin;
+	struct list_item *end;
+} list_t;
+
+void list_push(list_t *s, vertex_t *v) {
+	// Create 
+	list_item_t *i = malloc(sizeof(list_item_t));
+	i->next = NULL;
+	i->prev = NULL;
+	i->v = v;
+
+	// Link
+	if( s->len == 0 ) {
+		s->begin = i;
+	} else {
+		s->end->next = i;
+		i->prev = s->end;
+	}
+
+	s->end = i;
+	s->len++;
+}
+
+vertex_t *list_pop_smallest(list_t *s) {
+	list_item_t *smallest = s->begin;
+
+	// Search
+	list_item_t *i = s->begin;
+	while( i ) {
+		if( i->v->dist != -1 && i->v->dist < smallest->v->dist ) {
+			smallest = i;
+		}
+		i = i->next;
+	}
+
+	if( smallest == s->begin ) {
+		s->begin = smallest->next;
+	} else {
+		smallest->prev->next = smallest->next;
+	}
+
+	if( smallest == s->end ) {
+		s->end = smallest->prev;
+	} else {
+		smallest->next->prev = smallest->prev;
+	}
+
+	vertex_t *v = smallest->v;
+	free(smallest);
+
+	s->len--;
+
+	return v;
+}
+
+graph_t g;
+
+// Assumes u has an edge to v
+void relax(vertex_t *u, vertex_t *v) {
+	// Get edge between these two guys
+	edge_t *e = u->adj;
+	while(e && e->next && e->to->ref != v->ref) { 
+		e = e->next; 
+	}
+
+	if( v->dist == -1 || v->dist > (u->dist + e->weight) ) {
+		v->dist = u->dist + e->weight;
+		v->p = u;
+	}
+}
+
+void dijkstra(graph_t *g, vertex_t *s) {
+	list_t list;
+	list.len = 0;
+	list.end = list.begin = 0;
+
+	s->dist = 0;
+
+	{
+		vertex_t *v = vertex_next(g, NULL);
+		while( v ) {
+			list_push(&list, v);
+			v = vertex_next(g, v);
+		}
+	}
+
+	while( list.len ) {
+		vertex_t *u = list_pop_smallest(&list);
+		edge_t *e = u->adj;
+		while( e ) {
+			relax(u, e->to );
+			e = e->next;
+		}
+	}
+}
+
+int main() {
+
+	graph_edge(&g, 'a', 'b', 2);
+	graph_edge(&g, 'a', 'f', 1);
+
+	graph_edge(&g, 'b', 'd', 3);
+	graph_edge(&g, 'b', 'c', 4);
+
+	graph_edge(&g, 'd', 'b', 1);
+	graph_edge(&g, 'd', 'e', 8);
+
+	graph_edge(&g, 'c', 'a', 7);
+	graph_edge(&g, 'c', 'd', 7);
+	graph_edge(&g, 'c', 'f', 2);
+
+	graph_edge(&g, 'e', 'c', 2);
+	graph_edge(&g, 'e', 'f', 2);
+
+	dijkstra(&g, g.vertexes['a']);
+
+	graph_to_dot(stdout, &g);
+
+	return 0;
+}
diff --git a/sem3/algo/mm12/graph.c b/sem3/algo/mm12/graph.c
new file mode 100644
index 0000000..299ea24
--- /dev/null
+++ b/sem3/algo/mm12/graph.c
@@ -0,0 +1,123 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "graph.h"
+
+static vertex_t *create_vertex(char ref) {
+	// Get some space TODO check for null
+	vertex_t *v = malloc(sizeof(vertex_t));
+
+	// Set values
+	v->ref = ref;
+	v->dist = -1;
+	v->p = NULL;
+	v->adj = NULL;
+	return v;
+}
+
+static edge_t *create_edge(vertex_t *from, vertex_t *to, int weight) {
+	edge_t *old = from->adj;
+
+	// Create new list node
+	edge_t *e = malloc(sizeof(edge_t));
+	e->weight = weight;
+	e->from = from;
+	e->to = to;
+
+	// Do new link
+	e->next = old;
+	if( old ) {
+		e->prev = old->prev;
+		old->prev = e;
+	} else { e->prev = NULL; }
+	
+	if( e->prev ) {
+		e->prev->next = e;
+	}
+
+	from->adj = e;
+
+	return e;
+}
+
+// For iterating edges
+edge_t *edge_next(graph_t *g, edge_t *e) {
+	if(e == NULL || e->next == NULL ) {
+		// Find next index
+		
+		// Chose starting index 0 if NULL e
+		unsigned char i = e ? e->from->ref+1 : 0;
+		for( ; i < 128; i++ ) {
+			if( g->vertexes[i] && g->vertexes[i]->adj ) {
+				return g->vertexes[i]->adj;
+			}
+		}
+		// No next vertex
+		return NULL;
+	}
+
+	// Not finished with this adj list
+	return e->next;
+}
+
+vertex_t *vertex_next(graph_t *g, vertex_t *v) {
+	unsigned char ref = v ? v->ref+1 : 0;
+	for( ; ref < 128; ref++ ) {
+		if( g->vertexes[ref] ) {
+			return g->vertexes[ref];
+		}
+	}
+
+	return NULL;
+}
+
+void graph_edge(graph_t *g, char from, char to, int weight) {
+	// Does a exists
+	if( g->vertexes[from] == NULL ) {
+		g->vertexes[from] = create_vertex(from);
+	}
+	// What about b
+	if( g->vertexes[to] == NULL ) {
+		g->vertexes[to] = create_vertex(to);
+	}
+
+	// Add edge
+	create_edge(g->vertexes[from], g->vertexes[to], weight);
+}
+
+int graph_print_adj(graph_t *g, char ref) {
+	if( g->vertexes[ref] == NULL ) {
+		return 1;
+	}
+	
+	edge_t *e = g->vertexes[ref]->adj;
+	printf("[ ");
+	while(e && e->from->ref == ref) {
+		printf("%c[%d] ", e->to->ref, e->weight);
+		e = e->next;
+	}
+	printf("]\n");
+
+	return 0;
+}
+
+int graph_to_dot(FILE *f, graph_t *g) {
+	// print pre stuff
+	fprintf(f, "digraph coolgraph {\n");
+
+	// Label all nodes
+	vertex_t *v = vertex_next(g, NULL);
+	while( v ) {
+		fprintf(f, "%c [label=\"%c(%d)\"];\n", v->ref, v->ref, v->dist);
+		v = vertex_next(g, v);
+	}
+	// Print all the edges
+	edge_t *e = edge_next(g, NULL);
+	while( e ) {
+		fprintf(f, "%c -> %c [label = %d%s];\n", e->from->ref, e->to->ref, e->weight, e->to->p == e->from ? " color=blue" : "");
+		e = edge_next(g, e);
+	}
+
+	// done
+	fprintf(f, "}\n");
+}
+
diff --git a/sem3/algo/mm12/graph.h b/sem3/algo/mm12/graph.h
new file mode 100644
index 0000000..e957c4d
--- /dev/null
+++ b/sem3/algo/mm12/graph.h
@@ -0,0 +1,34 @@
+#ifndef GRAPH_H_
+#define GRAPH_H_
+
+struct vertex_struct;
+
+// Linked list
+typedef struct edge_struct {
+	int weight;
+	struct vertex_struct *from;
+	struct vertex_struct *to;
+	// Linked list stuff
+	struct edge_struct *next;
+	struct edge_struct *prev;
+} edge_t;
+
+typedef struct vertex_struct {
+	char ref;
+	int dist;
+	struct vertex_struct *p;
+	edge_t *adj;
+} vertex_t;
+
+typedef struct {
+	vertex_t *vertexes[128];
+
+} graph_t;
+
+int graph_to_dot(FILE *f, graph_t *g);
+int graph_print_adj(graph_t *g, char ref);
+void graph_edge(graph_t *g, char from, char to, int weight);
+edge_t *edge_next(graph_t *g, edge_t *e);
+vertex_t *vertex_next(graph_t *g, vertex_t *v);
+
+#endif // GRAPH_H_
diff --git a/sem3/algo/mm2/linked/Makefile b/sem3/algo/mm2/linked/Makefile
new file mode 100644
index 0000000..881143c
--- /dev/null
+++ b/sem3/algo/mm2/linked/Makefile
@@ -0,0 +1,31 @@
+CC = gcc
+# Enable gdb and pull include files from current dir
+CFLAGS = -ggdb -I.
+LDFLAGS = 
+
+BINARY = linked
+BUILD_DIR = build
+
+# Capture c files 
+c_files = $(wildcard *.c)
+
+# Convert c names to corrosponding o names
+OBJ = $(patsubst %.c, $(BUILD_DIR)/%.o, $(c_files))
+
+# $@ is the %.o file and $^ is the %.c file
+$(BUILD_DIR)/%.o: %.c
+	mkdir -p $(dir $@)
+	$(CC) -c -o $@ $^ $(CFLAGS)
+
+# $@ becomes left part thus linked
+$(BINARY): $(OBJ)
+	$(CC) -o $@ $^ $(LDFLAGS)
+
+.PHONY: clean run
+
+run: $(BINARY)
+	./$(BINARY)
+
+clean:
+	rm -f $(OBJ) $(BINARY)
+	rmdir $(BUILD_DIR)
diff --git a/sem3/algo/mm2/linked/Readme.md b/sem3/algo/mm2/linked/Readme.md
new file mode 100644
index 0000000..679dcf3
--- /dev/null
+++ b/sem3/algo/mm2/linked/Readme.md
@@ -0,0 +1,22 @@
+# Linked list assignment
+
+The linked list stuff is in node.c and higher level list functions in llist.c.
+
+Build with make:
+
+```
+make
+```
+
+To build and run
+
+```
+make run
+```
+
+To clean up when we are done.
+
+```
+make clean
+```
+
diff --git a/sem3/algo/mm2/linked/llist.c b/sem3/algo/mm2/linked/llist.c
new file mode 100644
index 0000000..41ab892
--- /dev/null
+++ b/sem3/algo/mm2/linked/llist.c
@@ -0,0 +1,89 @@
+#include "llist.h"
+
+#include <string.h>
+#include <stdio.h>
+
+
+#define OUT_OFF_BOUNDS 2
+
+void llist_init(llist_t *list) {
+	/* Zero out structure */
+	list->head = list->root = NULL;
+
+	list->len = 0;
+
+}
+
+void llist_append(llist_t *list, int val) {
+	/* Insert node after HEAD */
+	list->head = node_insert(list->head, val);
+
+	/* Check if was list is empty */
+	if( list->len == 0 ) {
+		/* Set root */
+		list->root = list->head;
+	}
+
+	/* Increase count */
+	list->len++;
+}
+
+node_t *llist_get_node(llist_t *list, unsigned int index) {
+	/* Check if we have it */
+	if( index >= list->len ) {
+		return NULL;
+	}
+
+	/* Find the best way to go down the list */
+	int direc = index > (list->len / 2) ? -1 : 1;
+
+	/* Setup start location */
+	int pos = direc > 0 ? 0 : list->len-1;
+	node_t *node = direc > 0 ? list->root : list->head;
+	
+	/* Go to index */
+	while( pos != index ) {
+		/* TODO kinda risky, we trust our math and len */
+		node = direc > 0 ? node->next : node->prev;
+
+		pos += direc;
+	}
+
+	return node;
+}
+
+int llist_get(llist_t *list, unsigned int index) {
+	/* Get node */
+	node_t *node = llist_get_node(list, index);
+	if( node == NULL ) {
+		/* Yes i know this is stupid */
+		return -1;
+	}
+
+	/* Return value */
+	return node->val;
+}
+
+
+int llist_pop(llist_t *list, unsigned int index) {
+	/* Get node */
+	node_t *node = llist_get_node(list, index);
+	if( node == NULL ) {
+		/* Yes i know this is stupid */
+		return -1;
+	}
+
+	/* Update root and head if we delete it */
+	if( node == list->root ) {
+		list->root = node->next;
+	}
+	if( node == list->head ) {
+		list->head = node->prev;
+	}
+	
+	/* Keep len up to date */
+	list->len--;
+
+	/* Delete stuff */
+	return node_pop(node);
+}
diff --git a/sem3/algo/mm2/linked/llist.h b/sem3/algo/mm2/linked/llist.h
new file mode 100644
index 0000000..e52be89
--- /dev/null
+++ b/sem3/algo/mm2/linked/llist.h
@@ -0,0 +1,22 @@
+#ifndef LIST_H
+#define LIST_H
+
+#include "node.h"
+
+typedef struct {
+	node_t *root;
+	node_t *head;
+	unsigned int len;
+} llist_t;
+
+void llist_init(llist_t *list);
+
+void llist_append(llist_t *list, int val);
+
+node_t *llist_get_node(llist_t *list, unsigned int index);
+
+int llist_get(llist_t *list, unsigned int index);
+
+int llist_pop(llist_t *list, unsigned int index);
+
+#endif 
diff --git a/sem3/algo/mm2/linked/main.c b/sem3/algo/mm2/linked/main.c
new file mode 100644
index 0000000..72b62cc
--- /dev/null
+++ b/sem3/algo/mm2/linked/main.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+#include "node.h"
+#include "llist.h"
+
+void list_print(node_t *root) {
+	int index = 0;
+	/* Loop through notes and print them */
+	while( root != NULL ) {
+		/* Print a value */
+		printf("%d: %d\n", index++, root->val);
+
+		/* Next value */
+		root = root->next;
+	}
+}
+
+/* Remove node */
+int main() {
+	
+	/* Do some stuff */
+	llist_t list;
+	llist_init(&list);
+
+	llist_append(&list, 11); // 0
+	llist_append(&list, 22); // 1
+	llist_append(&list, 33); // 2
+	llist_append(&list, 44); // 3
+	llist_append(&list, 89); // 4
+	llist_append(&list, 12); // 5
+	llist_append(&list, 2);  // 6
+	llist_append(&list, 1);  // 7
+	llist_append(&list, 7);  // 8
+	llist_append(&list, 232);// 9
+
+	list_print(list.root);
+	printf("%d\n", llist_get(&list, 5));
+	llist_pop(&list, 9);
+	printf("%d\n", llist_get(&list, 7));
+
+	list_print(list.root);
+
+	while( list.len ) {
+		printf("Popped %d\n", llist_pop(&list, 0));
+	}
+}
diff --git a/sem3/algo/mm2/linked/node.c b/sem3/algo/mm2/linked/node.c
new file mode 100644
index 0000000..cce1be0
--- /dev/null
+++ b/sem3/algo/mm2/linked/node.c
@@ -0,0 +1,57 @@
+#include "node.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+/* Insert after node */
+node_t *node_insert(node_t *node, int val) {
+	/* Create new node */
+	node_t *newNode = (node_t *) malloc( sizeof(node_t) );
+	if( newNode == NULL ) {
+		return NULL;
+	}
+
+
+	newNode->val = val;
+	newNode->prev = node;
+
+	/* Check if there is node before */
+	if( node == NULL ) {
+		/* If not then there is no after */
+		newNode->next = NULL;
+		return newNode;
+	}
+
+	/* Set next node */
+	newNode->next = node->next;
+	node->next = newNode;
+
+	/* Check node after */
+	if( newNode->next != NULL ) {
+		/* Backlink next node */
+		newNode->next->prev = newNode;
+	}
+
+	return newNode;
+}
+
+/* Pop node */
+int node_pop(node_t *node) {
+	int val = node->val;
+
+	/* Check prev */
+	if( node->prev != NULL ) {
+		/* Point last node to next node */
+		node->prev->next = node->next;
+	}
+
+	/* Check next */
+	if( node->next != NULL ) {
+		node->next->prev = node->prev;
+	}
+
+	/* Free memory */
+	free(node);
+
+	return val;
+}
diff --git a/sem3/algo/mm2/linked/node.h b/sem3/algo/mm2/linked/node.h
new file mode 100644
index 0000000..027926b
--- /dev/null
+++ b/sem3/algo/mm2/linked/node.h
@@ -0,0 +1,23 @@
+#ifndef NODE_H
+#define NODE_H
+
+typedef struct node_struct {
+	int val;
+	struct node_struct *next;
+	struct node_struct *prev;
+} node_t;
+
+/** @brief Create a new node after specified node 
+ *  
+ *  @param node Pointer to node where new node should be inserted, can also be NULL
+ *  @param val Value to add to new node
+ */
+node_t *node_insert(node_t *node, int val);
+
+/** @brief Pop node from chain and free's the resource
+ *  
+ *  @return Value in node
+ */
+int node_pop(node_t *node);
+
+#endif 
diff --git a/sem3/algo/mm2/queue.c b/sem3/algo/mm2/queue.c
new file mode 100644
index 0000000..a93f76a
--- /dev/null
+++ b/sem3/algo/mm2/queue.c
@@ -0,0 +1,100 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define EFULL 2
+#define EMPTY 3
+
+/* Queue stuff */
+typedef struct {
+	int head;
+	int tail;
+	int len;
+	int cap;
+	int *buff;
+} queue_t;
+
+/* Queue functions */
+int queue_init(queue_t *q, size_t cap) {
+	/* Make the struct and set i to zero */
+	memset(q, 0, sizeof(queue_t));
+
+	/* Allocate the buffer */
+	q->buff = (int *) malloc(cap * sizeof(int));
+	if( q->buff == NULL ) {
+		return 1;
+	}
+
+	/* Set capacity, the rest should be zero form memset */
+	q->cap = cap;
+	return 0;
+}
+
+void queue_free(queue_t *q) {
+	/* Free the heap buffer */
+	free(q->buff);
+}
+
+int queue_place(queue_t *q, int val) {
+	/* Check if full */
+	printf("len: %d\n", q->len);
+	if( q->len >= q->cap) {
+		printf("ERR: Full\n");
+		return EFULL;
+	}
+
+	/* Add to queue */
+	q->buff[q->head] = val;
+	
+	/* Increase values */
+	q->head = (q->head+1) % q->cap;
+	q->len++;
+
+	return 0;
+}
+
+int queue_get(queue_t *q, int *val) {
+	/* Check if empty */
+	if( !q->len ) {
+		printf("ERR: Empty\n");
+		return EMPTY;
+	}
+
+	/* Read value */
+	if( val != NULL ){
+		*val = q->buff[q->tail];
+	}
+
+	/* Decrease values */
+	q->tail = (q->tail+1) % q->cap;
+	q->len--;
+
+	return 0;
+}
+
+int main(void) {
+	int in;
+	char com;
+
+	queue_t q;
+	queue_init(&q, 16);
+
+	for(;;) {
+		/* Read a command */
+		scanf("%c", &com);
+
+		if( com == 'w') {
+			printf("> ");
+			scanf("%d", &in);
+			queue_place(&q, in);
+		} else if( com == 'r' ) {
+			queue_get(&q, &in);
+			printf("%d\n", in);
+		} else if( com == 'q' ) {
+			break;
+		}
+	}
+
+	queue_free(&q);
+	
+}
diff --git a/sem3/algo/mm3/multiply.c b/sem3/algo/mm3/multiply.c
new file mode 100644
index 0000000..e454de3
--- /dev/null
+++ b/sem3/algo/mm3/multiply.c
@@ -0,0 +1,56 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <time.h>
+
+uint64_t mult(uint64_t x, uint64_t y, unsigned int bits) {
+	/* Check if they expect more than 64 bits. */
+	if( bits > 64 ) {
+		printf("Sorry we cant handle higher than 64 bits\n");
+		exit(1);
+	} else if(bits <= 1) {
+		return x && y;
+	}
+
+	unsigned int newBits = bits >> 1;
+
+#if DO_PRINT == 1
+	printf("\n\n bits: %u, New bits: %u\n", bits, newBits);
+#endif 
+
+	/* Split up into to */
+	uint32_t halvMask = ((uint64_t)1 << newBits) - 1;
+#if DO_PRINT == 1
+	printf("Using mask 0x%08X\n", halvMask);
+#endif 
+	uint32_t a = (x >> (newBits)) & halvMask;
+	uint32_t b = x & halvMask;
+	uint32_t c = (y >> (newBits)) & halvMask;
+	uint32_t d = y & halvMask;
+
+#if DO_PRINT == 1
+	printf("A: 0x%08X, B: 0x%08X, C: 0x%08X, D: 0x%08X\n", a, b, c, d);
+#endif 
+
+	return (mult(a, c, newBits) << bits) + ((mult(a, d, newBits) + mult(b, c, newBits)) << newBits) + mult(b, d, newBits);
+
+}
+
+
+int main(void) {
+
+	uint32_t a = 0xFFFFFF;
+	uint8_t  b = 55;
+	uint64_t res;
+
+	clock_t begin = clock();
+	res = mult(a, b, 64);
+	clock_t end = clock();
+
+	printf("Result: %lld\n", res);
+
+	clock_t diff = end - begin;
+	printf("Took %d which is %f s\n", diff, (double)diff/CLOCKS_PER_SEC);
+	
+	return 0;
+}
diff --git a/sem3/algo/mm3/opgaver.md b/sem3/algo/mm3/opgaver.md
new file mode 100644
index 0000000..a6e560c
--- /dev/null
+++ b/sem3/algo/mm3/opgaver.md
@@ -0,0 +1,49 @@
+# Opgave 1
+
+## Exercise 9.2
+
+**T(n) = 3T(n/2) + n**
+
+a = 3
+b = 2
+d(n) = n
+
+a ? d(b) -> 3 > 2
+
+Svaret er derfor O(n^log2(3)) = O(n^1.59)
+
+**T(n) = 3T(n/2) + n^2**
+
+3 ? 2^2 -> 3 < 4
+
+d(n) = n^2 hvilket betyder at O(n^2)
+
+**T(n) = 8T(n/2) + n^2**
+
+8 ? 2^3 -> 8 = 8
+
+d(n) = n^3 hvilket betyder at O(n^3 log2(n))
+
+## Evercise 9.3
+
+**T(n) = 4T(n/3) + n**
+
+a = 4
+b = 3
+d(n) = n
+
+4 ? 3 -> 4 > 3
+
+Derfor er svaret O(n^log3(4)) = O(n^1.26)
+
+**T(n) = 4T(n/3) + n^2**
+
+4 ? 3^2 -> 4 < 9
+
+d(n) = n^2 hvilket betyder at O(n^2)
+
+**T(n) = 9T(n/3) + n^2**
+
+9 ? 3^2 -> 9 = 9
+
+d(n) = n^2 hvilket betyder at O(n^2 log2(n))
diff --git a/sem3/algo/mm6/Makefile b/sem3/algo/mm6/Makefile
new file mode 100644
index 0000000..c157cef
--- /dev/null
+++ b/sem3/algo/mm6/Makefile
@@ -0,0 +1,31 @@
+CC = gcc
+# Enable gdb and pull include files from current dir
+CFLAGS = -ggdb -I.
+LDFLAGS = 
+
+BINARY = main
+BUILD_DIR = build
+
+# Capture c files 
+c_files = $(wildcard *.c)
+
+# Convert c names to corrosponding o names
+OBJ = $(patsubst %.c, $(BUILD_DIR)/%.o, $(c_files))
+
+# $@ is the %.o file and $^ is the %.c file
+$(BUILD_DIR)/%.o: %.c
+	mkdir -p $(dir $@)
+	$(CC) -c -o $@ $^ $(CFLAGS)
+
+# $@ becomes left part thus linked
+$(BINARY): $(OBJ)
+	$(CC) -o $@ $^ $(LDFLAGS)
+
+.PHONY: clean run
+
+run: $(BINARY)
+	./$(BINARY)
+
+clean:
+	rm -f $(OBJ) $(BINARY)
+	rmdir $(BUILD_DIR)
diff --git a/sem3/algo/mm6/main b/sem3/algo/mm6/main
new file mode 100755
index 0000000..c666ee9
Binary files /dev/null and b/sem3/algo/mm6/main differ
diff --git a/sem3/algo/mm6/main.c b/sem3/algo/mm6/main.c
new file mode 100644
index 0000000..abc8d02
--- /dev/null
+++ b/sem3/algo/mm6/main.c
@@ -0,0 +1,37 @@
+#include <stdio.h>
+
+#include "tree.h"
+
+int main() {
+	tree_t t;
+	t.root = 0;
+
+	node_t *a = tree_insert(&t, 1, "Hej");
+
+	node_t *b = tree_insert(&t, 3, "med");
+
+	tree_insert(&t, 11, "dig");
+	tree_insert(&t, 9, "dig");
+	tree_insert(&t, 12, "dig");
+
+	tree_insert(&t, 10, "hvordan");
+
+	tree_insert(&t, 8, "det");
+
+	tree_insert(&t, 4, "branch");
+
+	tree_insert(&t, 5, "2");
+
+
+	tree_insert(&t, 0, "Og den sidste");
+
+	tree_insert(&t, 2, "Cool nok");
+	tree_print(&t);
+
+	printf("%s\n", tree_search(&t, 10));
+	printf("%s\n", tree_search(&t, 11));
+	printf("%s\n", tree_search(&t, 1));
+	printf("%s\n", tree_search(&t, 0));
+	printf("%s\n", tree_search(&t, 99));
+
+}
diff --git a/sem3/algo/mm6/tree.c b/sem3/algo/mm6/tree.c
new file mode 100644
index 0000000..47378f3
--- /dev/null
+++ b/sem3/algo/mm6/tree.c
@@ -0,0 +1,155 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "tree.h"
+
+static node_t *create_node(unsigned int index, char *val) {
+	node_t *node = malloc( sizeof(node_t) );
+	memset(node, 0, sizeof(node_t));
+
+	node->value = val;
+	node->index = index;
+}
+
+/* Comments are based of dir = CHILD_LEFT */
+void node_rotate(tree_t *tree, node_t *x, int dir) {
+	/* Node below which we should rotate with */
+	node_t *y = x->children[!dir];
+
+	/* Move y's left to x's right */
+	x->children[!dir] = y->children[dir];
+
+	/* Update parent */
+	if( y->children[dir] ) {
+		y->children[dir]->p = x;
+	}
+
+	/* Switch around x and y */
+	y->p = x->p;
+
+	/* Check if y is new root if not update x's parent */
+	if( !y->p ) {
+		tree->root = y;
+	} else if( x == x->p->children[CHILD_LEFT]) {
+		x->p->children[CHILD_LEFT] = y;
+	} else {
+		x->p->children[CHILD_RIGHT] = y;
+	}
+	
+	/* Update y's ref */
+	y->children[dir] = x;
+	x->p = y;
+
+}
+
+static void insert_fixup(tree_t *tree, node_t *z) {
+	while( z->p && z->p->black == false ) {
+		/* Set the right direction */
+		int dir = (z->p == z->p->p->children[CHILD_LEFT]) ? CHILD_RIGHT : CHILD_LEFT;
+
+		/* Get uncle */
+		node_t *y = z->p->p->children[dir];
+		if( y && !y->black ) {
+			/* Case 1 */
+			z->p->black = true;
+			y->black = true;
+			z->p->p->black = false;
+
+			z = z->p->p;
+		} else if( z == z->p->children[dir] ) {
+			/* Case 2 */
+			z = z->p;
+			node_rotate(tree, z, !dir);
+		} else {
+			/* Case 3 */
+			z->p->black = true;
+			z->p->p->black = false;
+			node_rotate(tree, z->p->p, dir);
+		}
+	}
+
+	tree->root->black = true;
+
+}
+
+static node_t *insert_recur(node_t *node, unsigned int index, char *val) {
+	int dir = node->index < index ? CHILD_RIGHT : CHILD_LEFT;
+
+	if( node->children[dir] ) {
+		return insert_recur(node->children[dir], index, val);
+	}
+
+	/* Found stop */
+	node_t *new = create_node(index, val);
+	new->p = node;
+	node->children[dir] = new;
+
+	return new;
+}
+
+node_t *tree_insert_pleb(tree_t *tree, unsigned int index, char *val) {
+	if( !tree->root ) {
+		tree->root = create_node(index, val);
+		return tree->root;
+	}
+
+	return insert_recur(tree->root, index, val); 
+}
+
+node_t *tree_insert(tree_t *tree, unsigned int index, char *val) {
+	if( !tree->root ) {
+		tree->root = create_node(index, val);
+		tree->root->black = true;
+		return tree->root;
+	}
+
+	node_t *new = insert_recur(tree->root, index, val); 
+	insert_fixup(tree, new);
+
+	return new;
+}
+
+char *tree_search(tree_t *tree, unsigned int index) {
+	node_t *z = tree->root;
+	while( z->index != index ) {
+		z = z->children[z->index < index ? CHILD_RIGHT : CHILD_LEFT];
+		if( !z ) {
+			return NULL;
+		}
+	}
+
+	return z->value;
+}
+
+static inline void print_indent(int num) {
+	for( int i = 0; i < num; i++ ) {
+		printf("  ");
+	}
+}
+
+static inline void print_text(node_t *node, bool bold) {
+	if( bold ) {
+		printf("\033[1m%d\033[22m\n", node->index);
+	} else {
+		printf("%d\n", node->index);
+	}
+
+}
+
+static void print_recur(node_t *node, int ident) {
+	if( !node ) {
+		return;
+	}
+	print_recur(node->children[CHILD_RIGHT], ident+1);
+	
+	print_indent(ident);	
+	print_text(node, node->black);
+
+	print_recur(node->children[CHILD_LEFT], ident+1);
+}
+
+void tree_print(tree_t *tree) {
+	print_recur(tree->root, 0);	
+}
+
diff --git a/sem3/algo/mm6/tree.h b/sem3/algo/mm6/tree.h
new file mode 100644
index 0000000..0d1c5c6
--- /dev/null
+++ b/sem3/algo/mm6/tree.h
@@ -0,0 +1,31 @@
+#ifndef TREE_H
+#define TREE_H
+
+#include <stdbool.h>
+
+#define CHILD_LEFT 0
+#define CHILD_RIGHT 1
+
+typedef struct node_struct{
+	struct node_struct *p;
+	struct node_struct *children[2];
+	unsigned int index;
+	bool black;
+	char *value;
+} node_t;
+
+typedef struct {
+	node_t *root;
+} tree_t;
+
+void tree_print(tree_t *tree);
+
+node_t *tree_insert(tree_t *tree, unsigned int index, char *val);
+node_t *tree_insert_pleb(tree_t *tree, unsigned int index, char *val);
+
+void node_rotate(tree_t *tree, node_t *x, int dir);
+
+char *tree_search(tree_t *tree, unsigned int index);
+
+
+#endif 
diff --git a/sem3/algo/mm9/Untitled.ipynb b/sem3/algo/mm9/Untitled.ipynb
new file mode 100644
index 0000000..a2bd59e
--- /dev/null
+++ b/sem3/algo/mm9/Untitled.ipynb
@@ -0,0 +1,126 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Bare lige noget preamble"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import networkx as nx\n",
+    "from networkx.drawing.nx_agraph import to_agraph\n",
+    "from nxpd import draw, nxpdParams\n",
+    "from numpy.linalg\n",
+    "nxpdParams['show'] = 'ipynb'\n",
+    "import warnings\n",
+    "warnings.filterwarnings('ignore')\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "G = nx.DiGraph()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "G.add_edge(1, 2)\n",
+    "G.add_edge(1, 3)\n",
+    "G.add_node(1)\n",
+    "G.add_edge(1, 4)\n",
+    "G.add_edge(1, 4)\n",
+    "G.add_edge(4, 4)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "image/png": "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\n",
+      "text/plain": [
+       "<IPython.core.display.Image object>"
+      ]
+     },
+     "execution_count": 7,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "draw(G)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Okay det ser ud til at virke fint. Nu kan vi printe adjecency matrix."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[[0 1 1 1]\n",
+      " [0 0 0 0]\n",
+      " [0 0 0 0]\n",
+      " [0 0 0 1]]\n"
+     ]
+    }
+   ],
+   "source": [
+    "A = nx.adjacency_matrix(G)\n",
+    "print(A.todense())"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.7.4"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/sem3/algo/workshop2/dfs/Makefile b/sem3/algo/workshop2/dfs/Makefile
new file mode 100644
index 0000000..790bb94
--- /dev/null
+++ b/sem3/algo/workshop2/dfs/Makefile
@@ -0,0 +1,41 @@
+CC = gcc
+# Enable gdb and pull include files from current dir
+CFLAGS = -ggdb -I.
+LDFLAGS = 
+
+BINARY = dfs
+BUILD_DIR = build
+
+# Capture c files 
+c_files = $(wildcard *.c)
+
+# Convert c names to corrosponding o names
+OBJ = $(patsubst %.c, $(BUILD_DIR)/%.o, $(c_files))
+
+# $@ is the %.o file and $^ is the %.c file
+$(BUILD_DIR)/%.o: %.c
+	mkdir -p $(dir $@)
+	$(CC) -c -o $@ $^ $(CFLAGS)
+
+# $@ becomes left part thus linked
+$(BINARY): $(OBJ)
+	$(CC) -o $@ $^ $(LDFLAGS)
+
+.PHONY: clean run
+
+run: $(BINARY)
+	./$(BINARY)
+
+hej.png: hej.dot
+	dot -Tpng hej.dot > hej.png
+
+hej.dot: $(BINARY)
+	./$(BINARY) > hej.dot
+
+draw: hej.png
+	nomacs hej.png
+
+clean:
+	rm -f $(OBJ) $(BINARY)
+	rm hej*
+	rmdir $(BUILD_DIR)
diff --git a/sem3/algo/workshop2/dfs/dfs b/sem3/algo/workshop2/dfs/dfs
new file mode 100755
index 0000000..0d9ff14
Binary files /dev/null and b/sem3/algo/workshop2/dfs/dfs differ
diff --git a/sem3/algo/workshop2/dfs/dfs.c b/sem3/algo/workshop2/dfs/dfs.c
new file mode 100644
index 0000000..1244895
--- /dev/null
+++ b/sem3/algo/workshop2/dfs/dfs.c
@@ -0,0 +1,107 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <time.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "graph.h"
+
+graph_t g;
+graph_t newg;
+int step;
+
+void dfs_visit(graph_t *g, vertex_t *u, bool doprint) {
+	if( doprint ) {
+		printf("dfs_visit( %s )\n", u->ref);
+	}
+	step++;
+	u->dtime = step;
+	u->color = COLOR_GRAY;
+	
+	// For every adj
+	edge_t *e = u->adj;
+	while( e ) {
+		vertex_t *v = e->to;
+		if( v->color == COLOR_WHITE ) {
+			graph_edge(&newg, v->ref, u->ref, 1);
+			dfs_visit(g, v, doprint);
+		}
+		e = e->next;
+	}
+
+	u->color = COLOR_BLACK;
+	step++;
+	u->ftime = step;
+}
+
+
+void dfs(graph_t *g, bool doprint) {
+	step = 0;
+
+	// For every edge
+	vertex_t *u = vertex_next(g, NULL);
+	while( u ) {
+		if( u->color == COLOR_WHITE ) {
+			dfs_visit(g, u, doprint);
+		}
+		u = vertex_next(g, u);
+	}
+}
+
+#define BENCH 9999
+
+int main() {
+
+	// benchmark
+
+	// Start by generating
+	for(int i = 0; i < BENCH; i++) {
+		char from[5];
+		char to[5];
+		sprintf(from, "%d", i);
+		sprintf(to, "%d", rand() % BENCH);
+		graph_edge(&g, from, to, 1);
+	}
+	FILE *f = fopen("hej.dot", "w");
+	graph_to_dot(f, &g);
+
+	{
+		// Timing start
+		clock_t t;
+		t = clock();
+
+		dfs(&g, true);
+
+		// Timing stop
+		t = clock() - t;
+		double time_taken = ((double)t)/CLOCKS_PER_SEC; // in seconds
+		printf("Dfs took %f seconds\n", time_taken);
+	}
+	
+	return 0;
+	
+	graph_edge(&g, "hej", "med", 1);
+	graph_edge(&g, "med", "dig", 1);
+	graph_edge(&g, "dig", "hvordan", 1);
+
+	graph_edge(&g, "det", "hvordan", 1);
+	graph_edge(&g, "hvordan", "det", 1);
+
+	graph_to_dot(stdout, &g);
+	
+	// Timing start
+	clock_t t;
+	t = clock();
+
+	// Dfs slower when printing.
+	dfs(&g, true);
+
+	// Timing stop
+	t = clock() - t;
+	double time_taken = ((double)t)/CLOCKS_PER_SEC; // in seconds
+	printf("Dfs took %f seconds\n", time_taken);
+
+	//graph_to_dot(stdout, &newg);
+
+	return 0;
+}
diff --git a/sem3/algo/workshop2/dfs/graph.c b/sem3/algo/workshop2/dfs/graph.c
new file mode 100644
index 0000000..0f5048c
--- /dev/null
+++ b/sem3/algo/workshop2/dfs/graph.c
@@ -0,0 +1,181 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "graph.h"
+
+// Hashtable
+static unsigned int hash(char *s) {
+	uint32_t hv = 0;
+	for( int i = 0; s[i] != '\0'; i++ ) {
+		// take MSB 6 bits of hv and xors with LSB of s[i]
+		uint32_t v = ( hv >> 26 ) ^ (s[i] & 0x3f);
+
+		// Push those back on hv
+		hv = (hv << 4) | v;
+	}
+	// Return appropriate size
+	return hv % HASHSIZE;
+}
+
+
+static void table_insert(graph_t *g, vertex_t *v, char *var) {
+	unsigned int index = hash(var);
+
+	// Save old value
+	vertex_t *oldSym = g->hashtable[index];
+
+	// Make new
+	g->hashtable[index] = v;
+
+	// Link old one
+	g->hashtable[index]->next = oldSym;
+}
+
+static vertex_t *table_lookup(graph_t *g, char *var) {
+	unsigned int index = hash(var);
+	vertex_t *n = g->hashtable[index];
+
+	// Look trough list
+	while(n != NULL && strcmp(n->ref, var) != 0) {
+		n = n->next;
+	}
+
+	return n;
+}
+
+static vertex_t *create_vertex(char *ref) {
+	// Get some space TODO check for null
+	vertex_t *v = malloc(sizeof(vertex_t));
+
+	// Set values
+	v->ref = strdup(ref);
+	v->color = COLOR_WHITE;
+	v->next = NULL;
+	v->adj = NULL;
+	return v;
+}
+
+static edge_t *create_edge(vertex_t *from, vertex_t *to, int weight) {
+	edge_t *old = from->adj;
+
+	// Create new list node
+	edge_t *e = malloc(sizeof(edge_t));
+	e->weight = weight;
+	e->from = from;
+	e->to = to;
+
+	// Do new link
+	e->next = old;
+	if( old ) {
+		e->prev = old->prev;
+		old->prev = e;
+	} else { e->prev = NULL; }
+	
+	if( e->prev ) {
+		e->prev->next = e;
+	}
+
+	from->adj = e;
+
+	return e;
+}
+
+// For iterating edges
+edge_t *edge_next(graph_t *g, edge_t *e) {
+	if(e == NULL || e->next == NULL ) {
+		// Find next index
+		vertex_t *v = e ? e->from : NULL;
+
+		// Find next vertex
+		v = vertex_next(g, v);
+		while( v ) {
+			// Check if found
+			if( v->adj ) {
+				return v->adj;
+			}
+
+			v = vertex_next(g, v);
+		}
+
+		// No next vertex
+		return NULL;
+	}
+
+	// Not finished with this adj list
+	return e->next;
+}
+
+vertex_t *vertex_next(graph_t *g, vertex_t *v) {
+	if( v == NULL || v->next == NULL) {
+		// Go to next index in hashtable
+		int i = v ? hash(v->ref)+1 : 0;
+		for( ; i < HASHSIZE; i++) {
+			if( g->hashtable[i] ) {
+				return g->hashtable[i];
+			}
+		}
+
+		// No next
+		return NULL;
+	}
+
+	return v->next;
+}
+
+void graph_edge(graph_t *g, char *from, char *to, int weight) {
+	vertex_t *fromv, *tov;
+	// Does a exists
+	if( (fromv = table_lookup(g, from)) == NULL ) {
+		fromv = create_vertex(from);
+		table_insert(g, fromv, from);
+	}
+	// What about b
+	if( (tov = table_lookup(g, to)) == NULL ) {
+		tov = create_vertex(to);
+		table_insert(g, tov, to);
+	}
+
+	// Add edge
+	create_edge(fromv, tov, weight);
+}
+
+int graph_print_adj(graph_t *g, char *ref) {
+	vertex_t *v = table_lookup(g, ref);
+	if( v == NULL ) {
+		return 1;
+	}
+	
+	edge_t *e = v->adj;
+	printf("[ ");
+	while(e && e->from->ref == ref) {
+		printf("%s[%d] ", e->to->ref, e->weight);
+		e = e->next;
+	}
+	printf("]\n");
+
+	return 0;
+}
+
+int graph_to_dot(FILE *f, graph_t *g) {
+	// print pre stuff
+	fprintf(f, "digraph coolgraph {\n");
+
+	// Label all nodes
+	vertex_t *v = vertex_next(g, NULL);
+	while( v ) {
+		fprintf(f, "%s [label=\"%s\"];\n", v->ref, v->ref);
+		v = vertex_next(g, v);
+	}
+	// Print all the edges
+	edge_t *e = edge_next(g, NULL);
+	while( e ) {
+		fprintf(f, "%s -> %s [label = %d];\n", e->from->ref, e->to->ref, e->weight);
+		e = edge_next(g, e);
+	}
+
+	// done
+	fprintf(f, "}\n");
+}
+
diff --git a/sem3/algo/workshop2/dfs/graph.h b/sem3/algo/workshop2/dfs/graph.h
new file mode 100644
index 0000000..e169a8a
--- /dev/null
+++ b/sem3/algo/workshop2/dfs/graph.h
@@ -0,0 +1,45 @@
+#ifndef GRAPH_H_
+#define GRAPH_H_
+
+#define COLOR_WHITE 0
+#define COLOR_GRAY  1
+#define COLOR_BLACK 2
+
+#define HASHSIZE 128
+
+struct vertex_struct;
+
+// Linked list
+typedef struct edge_struct {
+	int weight;
+	struct vertex_struct *from;
+	struct vertex_struct *to;
+	// Linked list stuff
+	struct edge_struct *next;
+	struct edge_struct *prev;
+} edge_t;
+
+typedef struct vertex_struct {
+	char *ref;
+	int color;
+
+	int dtime;
+	int ftime;
+
+	edge_t *adj;
+
+	// Hash table stuff
+	struct vertex_struct *next;
+} vertex_t;
+
+typedef struct {
+	vertex_t *hashtable[128];
+} graph_t;
+
+int graph_to_dot(FILE *f, graph_t *g);
+int graph_print_adj(graph_t *g, char *ref);
+void graph_edge(graph_t *g, char *from, char *to, int weight);
+edge_t *edge_next(graph_t *g, edge_t *e);
+vertex_t *vertex_next(graph_t *g, vertex_t *v);
+
+#endif // GRAPH_H_
diff --git a/sem3/algo/workshop2/dijkstra/Makefile b/sem3/algo/workshop2/dijkstra/Makefile
new file mode 100644
index 0000000..7837354
--- /dev/null
+++ b/sem3/algo/workshop2/dijkstra/Makefile
@@ -0,0 +1,31 @@
+CC = gcc
+# Enable gdb and pull include files from current dir
+CFLAGS = -ggdb -I.
+LDFLAGS = 
+
+BINARY = dijkstra
+BUILD_DIR = build
+
+# Capture c files 
+c_files = $(wildcard *.c)
+
+# Convert c names to corrosponding o names
+OBJ = $(patsubst %.c, $(BUILD_DIR)/%.o, $(c_files))
+
+# $@ is the %.o file and $^ is the %.c file
+$(BUILD_DIR)/%.o: %.c
+	mkdir -p $(dir $@)
+	$(CC) -c -o $@ $^ $(CFLAGS)
+
+# $@ becomes left part thus linked
+$(BINARY): $(OBJ)
+	$(CC) -o $@ $^ $(LDFLAGS)
+
+.PHONY: clean run
+
+run: $(BINARY)
+	./$(BINARY)
+
+clean:
+	rm -f $(OBJ) $(BINARY)
+	rmdir $(BUILD_DIR)
diff --git a/sem3/algo/workshop2/dijkstra/dijkstra.c b/sem3/algo/workshop2/dijkstra/dijkstra.c
new file mode 100644
index 0000000..9609343
--- /dev/null
+++ b/sem3/algo/workshop2/dijkstra/dijkstra.c
@@ -0,0 +1,129 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "graph.h"
+
+typedef struct list_item {
+	vertex_t *v;
+	struct list_item *next;
+	struct list_item *prev;
+} list_item_t;
+
+typedef struct {
+	int len;
+	struct list_item *begin;
+	struct list_item *end;
+} list_t;
+
+void list_push(list_t *s, vertex_t *v) {
+	// Create 
+	list_item_t *i = malloc(sizeof(list_item_t));
+	i->next = NULL;
+	i->prev = NULL;
+	i->v = v;
+
+	// Link
+	if( s->len == 0 ) {
+		s->begin = i;
+	} else {
+		s->end->next = i;
+		i->prev = s->end;
+	}
+
+	s->end = i;
+	s->len++;
+}
+
+vertex_t *list_pop_smallest(list_t *s) {
+	//printf("beginning %s(%d)\n", s->begin->v->ref, s->begin->v->dist);
+	list_item_t *smallest = s->begin;
+
+	// Search
+	list_item_t *i = s->begin;
+	while( i ) {
+		if( smallest->v->dist == -1 || (i->v->dist != -1 && i->v->dist < smallest->v->dist) ) {
+			smallest = i;
+		}
+		i = i->next;
+	}
+
+	if( smallest == s->begin ) {
+		s->begin = smallest->next;
+	} else {
+		smallest->prev->next = smallest->next;
+	}
+
+	if( smallest == s->end ) {
+		s->end = smallest->prev;
+	} else {
+		smallest->next->prev = smallest->prev;
+	}
+
+	vertex_t *v = smallest->v;
+	free(smallest);
+
+	s->len--;
+
+	return v;
+}
+
+graph_t g;
+
+// Assumes u has an edge to v
+void relax(vertex_t *u, vertex_t *v) {
+	// Get edge between these two guys
+	edge_t *e = u->adj;
+	while(e && e->next && strcmp(e->to->ref, v->ref)) { 
+		e = e->next; 
+	}
+
+	if( v->dist == -1 || v->dist > (u->dist + e->weight) ) {
+		v->dist = u->dist + e->weight;
+		v->p = u;
+	}
+}
+
+void dijkstra(graph_t *g, vertex_t *s) {
+	list_t list;
+	list.len = 0;
+	list.end = list.begin = 0;
+
+	s->dist = 0;
+
+	{
+		vertex_t *v = vertex_next(g, NULL);
+		while( v ) {
+			list_push(&list, v);
+			v = vertex_next(g, v);
+		}
+	}
+
+	while( list.len ) {
+		vertex_t *u = list_pop_smallest(&list);
+		edge_t *e = u->adj;
+		while( e ) {
+			relax(u, e->to );
+			e = e->next;
+		}
+	}
+}
+
+int main() {
+
+	int count = graph_from_dot(stdin, &g);
+
+	clock_t start, end;
+	double cpu_time_used;
+
+	start = clock();
+	dijkstra(&g, graph_vertex(&g, "0"));
+	end = clock();
+	cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
+
+	printf("%d;%f\n", count, cpu_time_used);
+
+	//graph_to_dot(stdout, &g);
+
+	return 0;
+}
diff --git a/sem3/algo/workshop2/dijkstra/graph.c b/sem3/algo/workshop2/dijkstra/graph.c
new file mode 100644
index 0000000..3f24ccf
--- /dev/null
+++ b/sem3/algo/workshop2/dijkstra/graph.c
@@ -0,0 +1,219 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "graph.h"
+
+// Hashtable
+static unsigned int hash(char *s) {
+	uint32_t hv = 0;
+	for( int i = 0; s[i] != '\0'; i++ ) {
+		// take MSB 6 bits of hv and xors with LSB of s[i]
+		uint32_t v = ( hv >> 26 ) ^ (s[i] & 0x3f);
+
+		// Push those back on hv
+		hv = (hv << 4) | v;
+	}
+	// Return appropriate size
+	return hv % HASHSIZE;
+}
+
+
+static void table_insert(graph_t *g, vertex_t *v, char *var) {
+	unsigned int index = hash(var);
+
+	// Save old value
+	vertex_t *oldSym = g->hashtable[index];
+
+	// Make new
+	g->hashtable[index] = v;
+
+	// Link old one
+	g->hashtable[index]->next = oldSym;
+}
+
+static vertex_t *table_lookup(graph_t *g, char *var) {
+	unsigned int index = hash(var);
+	vertex_t *n = g->hashtable[index];
+
+	// Look trough list
+	while(n != NULL && strcmp(n->ref, var) != 0) {
+		n = n->next;
+	}
+
+	return n;
+}
+
+static vertex_t *create_vertex(char *ref) {
+	// Get some space TODO check for null
+	vertex_t *v = malloc(sizeof(vertex_t));
+
+	// Set values
+	v->ref = strdup(ref);
+	v->color = COLOR_WHITE;
+	v->p = NULL;
+	v->dist = -1;
+	v->adj = NULL;
+	return v;
+}
+
+static edge_t *create_edge(vertex_t *from, vertex_t *to, int weight) {
+	edge_t *old = from->adj;
+
+	// Create new list node
+	edge_t *e = malloc(sizeof(edge_t));
+	e->weight = weight;
+	e->from = from;
+	e->to = to;
+
+	// Do new link
+	e->next = old;
+	if( old ) {
+		e->prev = old->prev;
+		old->prev = e;
+	} else { e->prev = NULL; }
+	
+	if( e->prev ) {
+		e->prev->next = e;
+	}
+
+	from->adj = e;
+
+	return e;
+}
+
+// For iterating edges
+edge_t *edge_next(graph_t *g, edge_t *e) {
+	if(e == NULL || e->next == NULL ) {
+		// Find next index
+		vertex_t *v = e ? e->from : NULL;
+
+		// Find next vertex
+		v = vertex_next(g, v);
+		while( v ) {
+			// Check if found
+			if( v->adj ) {
+				return v->adj;
+			}
+
+			v = vertex_next(g, v);
+		}
+
+		// No next vertex
+		return NULL;
+	}
+
+	// Not finished with this adj list
+	return e->next;
+}
+
+vertex_t *vertex_next(graph_t *g, vertex_t *v) {
+	if( v == NULL || v->next == NULL) {
+		// Go to next index in hashtable
+		int i = v ? hash(v->ref)+1 : 0;
+		for( ; i < HASHSIZE; i++) {
+			if( g->hashtable[i] ) {
+				return g->hashtable[i];
+			}
+		}
+
+		// No next
+		return NULL;
+	}
+
+	return v->next;
+}
+
+void graph_edge(graph_t *g, char *from, char *to, int weight) {
+	vertex_t *fromv, *tov;
+	// Does a exists
+	if( (fromv = table_lookup(g, from)) == NULL ) {
+		fromv = create_vertex(from);
+		table_insert(g, fromv, from);
+	}
+	// What about b
+	if( (tov = table_lookup(g, to)) == NULL ) {
+		tov = create_vertex(to);
+		table_insert(g, tov, to);
+	}
+
+	// Add edge
+	create_edge(fromv, tov, weight);
+}
+
+int graph_print_adj(graph_t *g, char *ref) {
+	vertex_t *v = table_lookup(g, ref);
+	if( v == NULL ) {
+		return 1;
+	}
+	
+	edge_t *e = v->adj;
+	printf("[ ");
+	while(e && e->from->ref == ref) {
+		printf("%s[%d] ", e->to->ref, e->weight);
+		e = e->next;
+	}
+	printf("]\n");
+
+	return 0;
+}
+
+int graph_to_dot(FILE *f, graph_t *g) {
+	// print pre stuff
+	fprintf(f, "digraph coolgraph {\n");
+
+	// Label all nodes
+	vertex_t *v = vertex_next(g, NULL);
+	while( v ) {
+		fprintf(f, "%s [label=\"%s(%d)\"];\n", v->ref, v->ref, v->dist);
+		v = vertex_next(g, v);
+	}
+	// Print all the edges
+	edge_t *e = edge_next(g, NULL);
+	while( e ) {
+		fprintf(f, "%s -> %s [label = %d%s];\n", e->from->ref, e->to->ref, e->weight, e->to->p == e->from ? " color=blue" : "");
+		e = edge_next(g, e);
+	}
+
+	// done
+	fprintf(f, "}\n");
+}
+
+// This was created in a hurry sorry
+int graph_from_dot(FILE *f, graph_t *g) {
+	char from[100], to[100];
+	int weight;
+	int count = 0;
+	// just fscanf it
+	for(;;) {
+		// Set first to zero
+		*from = 0;
+		*to = 0;
+		weight = 0;
+		int c = fscanf(f, "%s -> %s [label=%d];", from, to, &weight);
+		if( c <= 0 ) {
+			break;
+		}
+		if( *from == 0 || *to == 0 ) {
+			continue;
+		}
+		// Sorry i just want it to work
+		int tolen = strlen(to);
+		if( to[tolen-1] == ';' ) {
+			to[tolen-1] = 0;
+		}
+
+		weight = weight ? weight : 1;
+		//printf("Creating edge from %s to %s with w: %d\n", from, to, weight);
+
+		graph_edge(g, from, to, weight);
+		count++;
+	}
+
+	return count;
+}
+
+vertex_t *graph_vertex(graph_t *g, char *ref) {
+	return table_lookup(g, ref);
+}
diff --git a/sem3/algo/workshop2/dijkstra/graph.h b/sem3/algo/workshop2/dijkstra/graph.h
new file mode 100644
index 0000000..5c078b8
--- /dev/null
+++ b/sem3/algo/workshop2/dijkstra/graph.h
@@ -0,0 +1,47 @@
+#ifndef GRAPH_H_
+#define GRAPH_H_
+
+#define COLOR_WHITE 0
+#define COLOR_GRAY  1
+#define COLOR_BLACK 2
+
+#define HASHSIZE 128
+
+struct vertex_struct;
+
+// Linked list
+typedef struct edge_struct {
+	int weight;
+	struct vertex_struct *from;
+	struct vertex_struct *to;
+	// Linked list stuff
+	struct edge_struct *next;
+	struct edge_struct *prev;
+} edge_t;
+
+typedef struct vertex_struct {
+	char *ref;
+	int color;
+
+	int dist;
+	struct vertex_struct *p;
+
+	edge_t *adj;
+
+	// Hash table stuff
+	struct vertex_struct *next;
+} vertex_t;
+
+typedef struct {
+	vertex_t *hashtable[128];
+} graph_t;
+
+int graph_to_dot(FILE *f, graph_t *g);
+int graph_from_dot(FILE *f, graph_t *g);
+int graph_print_adj(graph_t *g, char *ref);
+void graph_edge(graph_t *g, char *from, char *to, int weight);
+edge_t *edge_next(graph_t *g, edge_t *e);
+vertex_t *vertex_next(graph_t *g, vertex_t *v);
+vertex_t *graph_vertex(graph_t *g, char *ref);
+
+#endif // GRAPH_H_
diff --git a/sem3/module.c b/sem3/module.c
new file mode 100644
index 0000000..3a25d25
--- /dev/null
+++ b/sem3/module.c
@@ -0,0 +1,12 @@
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+module_init(void) {
+	printk(KERN_INFO "COOL_MODULE: Hej med dig\n");
+	return 0;
+}
+
+module_exit(void) {
+	printk(KERN_INFO "COOL_MODULE: Nou moe\n");
+}
diff --git a/sem3/osc/miniproject/cnasm/Makefile b/sem3/osc/miniproject/cnasm/Makefile
new file mode 100644
index 0000000..9ace547
--- /dev/null
+++ b/sem3/osc/miniproject/cnasm/Makefile
@@ -0,0 +1,30 @@
+
+LEX=flex
+YACC=bison
+LIBS=-ly -lfl -lm
+CC=gcc
+
+PROG=regn
+TRASH=lex.yy.c $(PROG).tab.c $(PROG) $(PROG).tab.h $(PROG).output
+
+$(PROG): $(PROG).tab.o lex.yy.o ast.c codegen.c
+		$(CC) -ggdb -o $@ $^ $(LIBS) 
+
+$(PROG).tab.c $(PROG).tab.h: $(PROG).y
+		$(YACC) -d -v $(PROG).y
+
+lex.yy.c: $(PROG).l
+		$(LEX) $(PROG).l
+
+%.o: %.c
+	$(CC) -ggdb -c -o $@ $^
+
+PHONY: clean run
+
+run: $(PROG)
+	./$(PROG)
+
+clean:
+	rm -f *.o
+	rm -f $(TRASH)
+
diff --git a/sem3/osc/miniproject/cnasm/ast.c b/sem3/osc/miniproject/cnasm/ast.c
new file mode 100644
index 0000000..035b75d
--- /dev/null
+++ b/sem3/osc/miniproject/cnasm/ast.c
@@ -0,0 +1,98 @@
+#include "ast.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+static ast_node_t *create_empty_node() {
+	ast_node_t *n = malloc(sizeof(ast_node_t));
+	memset(n, 0, sizeof(ast_node_t));
+}
+
+ast_node_t *insert_ctrl(enum ntype t, cond_t *c, ast_node_t *iftrue, ast_node_t *iffalse) {
+	ast_node_t *n = create_empty_node();
+
+	n->t = t;
+	n->flowctrl.condition = c;
+	n->flowctrl.iftrue = iftrue;
+	n->flowctrl.iffalse = iffalse;
+
+	return n;
+}
+
+ast_node_t *insert_for(char *pre, cond_t *c, char *inc, ast_node_t *stuff) {
+	ast_node_t *n = create_empty_node();
+
+	n->t = TFOR;
+	n->forloop.condition = c;
+	n->forloop.pre = pre;
+	n->forloop.inc = inc;
+	n->forloop.stuff = stuff;
+
+	return n;
+}
+
+ast_node_t *insert_stm(ast_node_t *stm, ast_node_t *stm_list) {
+	ast_node_t *n = create_empty_node();
+
+	n->t = TSTM_LIST;
+	n->list.children[0] = stm_list;
+	n->list.children[1] = stm;
+
+	return n;
+}
+ast_node_t *insert_ident(char *ident) {
+	ast_node_t *n = create_empty_node();
+
+	n->t = TIDENT;
+	n->ident = ident;
+
+	return n;
+}
+
+cond_t *insert_cond(uint8_t cmp, char *a, char *b) {
+	cond_t *c = malloc( sizeof(cond_t));
+
+	c->cmp = cmp;
+	c->a = a;
+	c->b = b;
+}
+
+void node_print(ast_node_t *node) {
+	if( !node ){
+		printf("Nil");
+		return;
+	}
+	switch(node->t) {
+		case TSTM_LIST: 
+			printf("Stm_list(");
+			node_print(node->list.children[0]);
+			printf(",");
+			node_print(node->list.children[1]);
+			printf(")");
+			break;
+		case TIF:
+			printf("If");
+			printf("(%s %c %s) {", node->flowctrl.condition->a,
+					node->flowctrl.condition->cmp,
+					node->flowctrl.condition->b);
+			node_print(node->flowctrl.iftrue);
+			printf("}{");
+			node_print(node->flowctrl.iffalse);
+			printf("}");
+			break;
+		case TIDENT:
+			printf("%s", node->ident);
+			break;
+		case TWHILE:
+			printf("while");
+			printf("(%s %c %s) {", node->flowctrl.condition->a,
+					node->flowctrl.condition->cmp,
+					node->flowctrl.condition->b);
+			node_print(node->flowctrl.iftrue);
+			printf("}");
+			break;
+		default:
+			printf("invalid");
+	}
+}
diff --git a/sem3/osc/miniproject/cnasm/ast.h b/sem3/osc/miniproject/cnasm/ast.h
new file mode 100644
index 0000000..61a8f4f
--- /dev/null
+++ b/sem3/osc/miniproject/cnasm/ast.h
@@ -0,0 +1,53 @@
+#ifndef AST_HEADER
+#define AST_HEADER
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#define CEQ 0x10
+#define CNEQ CEQ ^ 0x80
+#define CGT 0x20
+#define CLT 0x30
+#define CLEQ CGT ^ 0x80
+#define CGEQ CLT ^ 0x80
+
+enum ntype { TSTM_LIST, TIF, TFOR, TIDENT, TWHILE};
+
+typedef struct cond {
+	uint8_t cmp;
+	char *a;
+	char *b;
+} cond_t;
+
+typedef struct ast_node {
+	enum ntype t;
+	// Dependent on type
+	union {
+		struct {
+			cond_t *condition;
+			struct ast_node *iftrue;
+			struct ast_node *iffalse;
+		} flowctrl;
+		struct {
+			cond_t *condition;
+			char *pre;
+			char *inc;
+			struct ast_node *stuff;
+		} forloop;
+		char *ident;
+		struct {
+			struct ast_node *children[2];
+		} list;
+	};
+} ast_node_t;
+
+ast_node_t *insert_ctrl(enum ntype t, cond_t *c, ast_node_t *iftrue, ast_node_t *iffalse);
+ast_node_t *insert_stm(ast_node_t *stm, ast_node_t *stm_list);
+ast_node_t *insert_ident(char *ident);
+ast_node_t *insert_for(char *pre, cond_t *c, char *inc, ast_node_t *stuff);
+
+cond_t *insert_cond(uint8_t cmp, char *a, char *b);
+
+void node_print(ast_node_t *node);
+
+#endif 
diff --git a/sem3/osc/miniproject/cnasm/codegen.c b/sem3/osc/miniproject/cnasm/codegen.c
new file mode 100644
index 0000000..c995df9
--- /dev/null
+++ b/sem3/osc/miniproject/cnasm/codegen.c
@@ -0,0 +1,132 @@
+#include "codegen.h"
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include "ast.h"
+
+static void gencondjmp(FILE *f, cond_t *c, bool neg) {
+	uint8_t cmp = neg ? c->cmp^0x80 : c->cmp;
+	fprintf(f, "cmp %s %s\n", c->a, c->b);
+	switch(cmp) {
+		case CEQ:
+			fprintf(f, "je ");
+			break;
+		case CNEQ:
+			fprintf(f, "jne ");
+			break;
+		case CGT:
+			fprintf(f, "jg ");
+			break;
+		case CLT:
+			fprintf(f, "jl ");
+			break;
+		case CLEQ:
+			fprintf(f, "jle ");
+			break;
+		case CGEQ:
+			fprintf(f, "jge ");
+			break;
+		default:
+			fprintf(stderr, "Invalid cmp type %x", cmp);
+			fprintf(f, "jmp ");
+	}
+}
+
+static void genif(FILE *f, struct genctx *ctx, ast_node_t *n) {
+	bool doElse = n->flowctrl.iffalse;
+	// Create conditional jump
+	gencondjmp(f, n->flowctrl.condition, true);
+	if( doElse ) {
+		fprintf(f, "else_%d\n", ctx->nested);
+	} else {
+		fprintf(f, "end_%d\n", ctx->nested);
+	}
+
+	struct genctx octx = { ctx->nested+1 };
+	// Paste code
+	gentree(f, &octx, n->flowctrl.iftrue);
+	
+	// Do else
+	if( doElse ) {
+		fprintf(f, "jmp end_%d\n", ctx->nested);
+		fprintf(f, "else_%d:\n", ctx->nested);
+		gentree(f, &octx, n->flowctrl.iffalse);
+	}
+
+	// End block
+	fprintf(f, "end_%d:\n", ctx->nested);
+}
+
+static void genwhile(FILE *f, struct genctx *ctx, ast_node_t *n) {
+	// Create loop label
+	fprintf(f, "loop_%d:\n", ctx->nested);
+
+	// Create conditional jump
+	gencondjmp(f, n->flowctrl.condition, true);
+	fprintf(f, "end_%d\n", ctx->nested);
+
+	struct genctx octx = { ctx->nested+1 };
+	// Paste code
+	gentree(f, &octx, n->flowctrl.iftrue);
+
+	// Jump to start
+	fprintf(f, "jmp loop_%d\n", ctx->nested);
+	
+	// End block
+	fprintf(f, "end_%d:\n", ctx->nested);
+}
+
+static void genfor(FILE *f, struct genctx *ctx, ast_node_t *n) {
+	// Do pre stuff
+	fprintf(f, "%s\n", n->forloop.pre);
+
+	// Create loop label
+	fprintf(f, "loop_%d:\n", ctx->nested);
+
+	// Create conditional jump
+	gencondjmp(f, n->flowctrl.condition, true);
+	fprintf(f, "end_%d\n", ctx->nested);
+
+	struct genctx octx = { ctx->nested+1 };
+	// Paste code
+	gentree(f, &octx, n->forloop.stuff);
+
+	// Do inc stuff
+	fprintf(f, "%s\n", n->forloop.inc);
+	// Jump to start
+	fprintf(f, "jmp loop_%d\n", ctx->nested);
+	
+	// End block
+	fprintf(f, "end_%d:\n", ctx->nested);
+}
+
+void gentree(FILE *f, struct genctx *ctx, ast_node_t *n) {
+	if( !n ) {
+		return;
+	}
+	if( ctx == NULL ) {
+		ctx = malloc(sizeof(struct genctx));
+		ctx->nested = 0;
+	}
+	switch(n->t) {
+		case TSTM_LIST: 
+			gentree(f, ctx, n->list.children[0]);
+			gentree(f, ctx, n->list.children[1]);
+			break;
+		case TIF:
+			genif(f, ctx, n);
+			break;
+		case TIDENT:
+			fprintf(f, "%s\n", n->ident);
+			break;
+		case TFOR:
+			genfor(f, ctx, n);
+			break;
+		case TWHILE:
+			genwhile(f, ctx, n);
+			break;
+		default:
+			return;
+	}
+}
diff --git a/sem3/osc/miniproject/cnasm/codegen.h b/sem3/osc/miniproject/cnasm/codegen.h
new file mode 100644
index 0000000..24ad6c4
--- /dev/null
+++ b/sem3/osc/miniproject/cnasm/codegen.h
@@ -0,0 +1,14 @@
+
+#ifndef CODEGEN_HEADER
+#define CODEGEN_HEADER
+
+#include <stdio.h>
+#include "ast.h"
+
+struct genctx {
+	unsigned int nested;
+};
+
+void gentree(FILE *f, struct genctx *ctx, ast_node_t *n);
+
+#endif 
diff --git a/sem3/osc/miniproject/cnasm/regn.l b/sem3/osc/miniproject/cnasm/regn.l
new file mode 100644
index 0000000..00876d6
--- /dev/null
+++ b/sem3/osc/miniproject/cnasm/regn.l
@@ -0,0 +1,39 @@
+%{
+#include <math.h>
+#include <string.h>
+#include "regn.tab.h"
+#include "ast.h"
+%}
+
+id		[a-zA-Z0-9_;]([^\n=><(){}])*
+if		if[ \t]*
+else	else[ \t]*
+for		for[ \t]*
+while	while[ \t]*
+
+%%
+
+{if} {return IFF;};
+{else} {return EELSE;};
+{for} {return FFOR;};
+{while} {return WHILE;};
+"(" {return LP;};
+")" {return RP;};
+"{" {return LCP;};
+"}" {return RCP;};
+"<" {yylval.cmp = CLT; return CMP;};
+">" {yylval.cmp = CGT; return CMP;};
+"=" {yylval.cmp = CEQ; return CMP;};
+"!=" {yylval.cmp = CNEQ; return CMP;};
+{id} {yylval.string = strdup(yytext);return ID;};
+[1-9][0-9]* {yylval.string = yytext;return NO;};
+
+
+
+[ \t\n] ;
+
+.           {return yytext[0];} 
+
+%%
+
+// TODO match normal assembler
diff --git a/sem3/osc/miniproject/cnasm/regn.y b/sem3/osc/miniproject/cnasm/regn.y
new file mode 100644
index 0000000..b72d440
--- /dev/null
+++ b/sem3/osc/miniproject/cnasm/regn.y
@@ -0,0 +1,81 @@
+%{
+#include "ast.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include "codegen.h"
+
+#define CLEAN_BOTH 2
+#define CLEAN_DST 1
+
+char *strconcat(char *dst, char *src, unsigned int clean) {
+	size_t dstlen = strlen(dst) + 1;
+	size_t srclen = strlen(src) + 1;
+
+	// Create new duplicate
+	char *new = malloc(( dstlen + srclen ) * sizeof(char));
+
+	// Copy stuff
+	memcpy(new, dst, dstlen);
+	strcat(new, src);
+
+	// Free old one
+	if( clean-- ) {
+		free(dst);
+
+		if( clean ) {
+			free(src);
+		}
+	}
+	return new;
+}
+
+// Trace node
+
+%}
+
+%token IFF EELSE FFOR RP RCP RSP LP LCP LSP ID COLON CMP NO WHILE
+
+%union {
+	char				*string;
+	struct ast_node		*node;
+	struct cond			*condition;
+	uint8_t				cmp;
+}
+
+%type <string>	ID 
+%type <node>	statement stm_list 
+%type <cmp>		CMP
+%type <condition> condition
+
+%%
+
+program: stm_list 			{gentree(stdout, NULL, $1);printf("\n");};
+
+stm_list: statement				{ $$ = $1; }
+		| stm_list statement 	{ $$ = insert_stm($2, $1); };
+
+condition: ID CMP ID		{ $$ = insert_cond($2, $1, $3); }
+		 | ID				{ $$ = insert_cond(CNEQ, $1, "0");};
+
+statement: ID																{$$ = insert_ident($1);}
+		 | IFF LP condition RP LCP stm_list RCP								{$$ = insert_ctrl(TIF, $3, $6, NULL);}
+		 | IFF LP condition RP LCP stm_list RCP	EELSE LCP stm_list RCP		{$$ = insert_ctrl(TIF, $3, $6, $10);}
+		 | WHILE LP condition RP LCP stm_list RCP							{$$ = insert_ctrl(TWHILE, $3, $6, NULL);}
+		 | FFOR LP ID LP condition LP ID RP LCP stm_list RCP				{$$ = insert_for($3, $5, $7, $10);};
+
+%%
+
+
+int main() {
+
+	/*for(;;) {
+		int t = yylex();
+		printf("yylex: %d\n", t);
+	} */
+
+	yyparse(); 
+}
+
diff --git a/sem3/osc/miniproject/cnasm/test.asm b/sem3/osc/miniproject/cnasm/test.asm
new file mode 100644
index 0000000..77a3572
--- /dev/null
+++ b/sem3/osc/miniproject/cnasm/test.asm
@@ -0,0 +1,39 @@
+global _start
+
+section .data
+        align 2
+        ; String, which is just a collection of bytes, 0xA is newline
+        str:     db 'Hello, world!',0xA
+        strLen:  equ $-str
+
+section .bss
+
+section .text
+        _start:
+
+        mov     edx, strLen     ; Arg three: the length of the string
+        mov     ecx, str        ; Arg two: the address of the string
+        mov     ebx, 1          ; Arg one: file descriptor, in this case stdout
+        mov     eax, 4          ; Syscall number, in this case the 
+        int     0x80            ; Interrupt 0x80        
+
+		if ( hej = 10 ) {
+			mov     ebx, 0          ; Arg one: the status
+			mov     eax, 1          ; Syscall number:
+			if(cool) {
+				int     0x80
+			}
+		} else {
+			while( lol ) {
+				mov hej, 0
+			}
+		}
+		while( lol ) {
+			mov hej, 0
+		}
+
+		hej
+
+		for(mov a, 0( a < 100( a++ ) {
+			test
+		}
diff --git a/sem3/osc/mm1/.gitignore b/sem3/osc/mm1/.gitignore
new file mode 100644
index 0000000..b18a498
--- /dev/null
+++ b/sem3/osc/mm1/.gitignore
@@ -0,0 +1,10 @@
+jmod.ko
+.jmod.ko.cmd
+jmod.mod.c
+jmod.mod.o
+.jmod.mod.o.cmd
+jmod.o
+.jmod.o.cmd
+modules.order
+Module.symvers
+.tmp_versions
diff --git a/sem3/osc/mm1/mm1/Makefile b/sem3/osc/mm1/mm1/Makefile
new file mode 100644
index 0000000..13c8e62
--- /dev/null
+++ b/sem3/osc/mm1/mm1/Makefile
@@ -0,0 +1,7 @@
+obj-m += jmod.o
+
+all:
+	make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
+clean:
+	make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean
+
diff --git a/sem3/osc/mm1/mm1/Readme.md b/sem3/osc/mm1/mm1/Readme.md
new file mode 100644
index 0000000..fcc6cb3
--- /dev/null
+++ b/sem3/osc/mm1/mm1/Readme.md
@@ -0,0 +1,34 @@
+# Opgaver til operativ systemer
+
+Ligenu er det ikke delt op i mapper. 
+
+## Kør mini kernel modul
+
+Compile med make.
+Husk at peg makefile på din kernel modul mappe.
+Denne er testet på ubuntu server 19.04.
+
+```
+make
+```
+
+Nu burde der være kommet et jmod.ko som kan loades med.
+
+```
+sudo insmod jmod.ko
+```
+
+Hvis du får permission denied kan du få flere information ved at checke `dmesg` loggen.
+
+Nu kan du hente major number ind fra dmesg. Led efter `COOL_MODULE:`.
+Dette nummer bruger du til at assign den en node
+
+```
+sudo mknod /dev/cooldev c MAJOR 0
+```
+
+Dette vil map kernel-modul/driver til cooldev i /dev/ mappen.
+Husk at skriv til MAJOR nummer fra `dmesg` i stedet for MAJOR.
+
+Hvis man læser man pagen kan man se at det bliver lavet som en character unbuffered file. 
+MINOR nummeret er 0 da vores driver alligevel ikke bruger det til noget.
diff --git a/sem3/osc/mm1/mm1/jmod.c b/sem3/osc/mm1/mm1/jmod.c
new file mode 100644
index 0000000..a07077c
--- /dev/null
+++ b/sem3/osc/mm1/mm1/jmod.c
@@ -0,0 +1,70 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+
+static int major_num;
+static int busy;
+
+
+static int cool_open(struct inode *inode, struct file *file) {
+	/* Check if we are already serving someone */
+	if (busy) {
+		return -EBUSY;
+	}
+
+	busy = 1;
+	return 0;
+}
+
+static int cool_release (struct inode *inode, struct file *file) {
+	busy = 0;
+
+	return 0;
+}
+
+static ssize_t cool_read (struct file *filp, char *buffer, size_t len, loff_t *offset) {
+
+	char str[12] = "hej med dig";
+	int i;
+
+	for (i = 0; i < len; i++) {
+		put_user(str[i % 12], buffer++);
+	}
+
+	return i;
+}
+
+static struct file_operations file_ops = {
+	.owner = THIS_MODULE,
+	.read = cool_read,
+	.open = cool_open,
+	.release = cool_release
+};
+
+static int __init jmod_init(void) 
+{
+	printk(KERN_INFO "COOL_MODULE: Registering cooldev\n");
+	
+	major_num = register_chrdev(0, "cooldev", &file_ops);
+	if (major_num < 0) {
+		printk(KERN_ERR "COOL_MODULE: Could not register major\n");
+		return 1;
+	}
+
+	printk(KERN_INFO "COOL_MODULE: Got major %d\n", major_num);
+
+	return 0;
+}
+
+
+static void __exit jmod_exit(void) 
+{
+	printk(KERN_INFO "COOL_MODULE: Nou moe\n");
+	unregister_chrdev(major_num, "cooldev");
+}
+
+module_init( jmod_init );
+module_exit( jmod_exit );
+
diff --git a/sem3/osc/mm1/mm2/tprog.c b/sem3/osc/mm1/mm2/tprog.c
new file mode 100644
index 0000000..377555f
--- /dev/null
+++ b/sem3/osc/mm1/mm2/tprog.c
@@ -0,0 +1,71 @@
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+#define STARTSEC 10
+#define ENDUSEC 500000
+#define SPEED 0.8
+
+struct itimerval timer;
+
+void timer_handler(int signum) {
+    /* Handy structure reference */
+    struct timeval *tv = &timer.it_value;
+    printf("Hey we hit the alarm\n\a");
+
+    /* Calculate new alarm */
+    tv->tv_sec *= SPEED;
+    if (tv->tv_sec == 0) {
+	/* If tv_usec is 0 set i to 1 sec otherwise half it */
+	if (tv->tv_usec == 0) {
+	    tv->tv_usec = 999999;
+	} else if (tv->tv_usec > ENDUSEC) {
+	    tv->tv_usec *= SPEED;
+	    if (tv->tv_usec < ENDUSEC) {
+		tv->tv_usec = ENDUSEC;
+	    }
+	} else {
+	    /* Return letting the timer be set to ENDUSEC */
+	    return;
+	}
+    }
+
+    printf("Set to %d and %d\n", timer.it_value.tv_sec, timer.it_value.tv_usec);
+    /* Set alarm */
+    int err = setitimer(ITIMER_REAL, &timer, NULL);
+    if (err) {
+	printf("Hey we got an error guys\n");
+	exit(1);
+    }
+}
+
+int main() {
+    /* Setup handler for timer */
+    struct sigaction sa;
+    memset(&sa, 0, sizeof(sa)); /* Remeber to set all fields to zero */
+
+    sa.sa_handler = &timer_handler;
+    sigaction(SIGALRM, &sa, NULL);
+
+    /* Setup timer values */
+    timer.it_value.tv_sec = STARTSEC;
+    timer.it_value.tv_usec = 0;
+
+    timer.it_interval.tv_sec = 0;
+    timer.it_interval.tv_usec = ENDUSEC;
+
+    /* Start the timer */
+    setitimer(ITIMER_REAL, &timer, NULL);
+
+    /* Select signals */
+    sigset_t sigset;
+    sigemptyset(&sigset);
+    sigaddset(&sigset, SIGTERM);
+
+    /* Wait for termination */
+    sigwait(&sigset, NULL);
+
+    return 0;
+}
diff --git a/sem3/osc/mm10/Makefile b/sem3/osc/mm10/Makefile
new file mode 100644
index 0000000..99bd635
--- /dev/null
+++ b/sem3/osc/mm10/Makefile
@@ -0,0 +1,25 @@
+opgaver=opg1 opg3 opg4
+
+LEX=flex
+CC=gcc
+LINKFLAG=-lfl
+DEFAULT_TARGET=all
+
+%: %.yy.c
+	$(CC) -o $@ $^ $(LINKFLAG)
+
+%.o: %.c
+	$(CC) -c -o $@ $^
+
+%.yy.c: %.l
+	$(LEX) -o $@ $^
+
+all: $(opgaver)
+
+phony: all clean run
+
+run: $(BIN)
+	./$(BIN)
+
+clean:
+	rm -f $(opgaver)
diff --git a/sem3/osc/mm10/opg1.l b/sem3/osc/mm10/opg1.l
new file mode 100644
index 0000000..b5cb478
--- /dev/null
+++ b/sem3/osc/mm10/opg1.l
@@ -0,0 +1,22 @@
+%{
+
+#include <stdio.h>
+
+%}
+
+ting		(a|b)abcd
+
+%%
+
+{ting}		{ printf("Fandt ting %s\n", yytext); return 1; }
+.			{ printf("Meh"); }
+
+%%
+
+int main(void) {
+
+	printf("yylex: %d\n", yylex());
+
+	return 0;
+	
+}
diff --git a/sem3/osc/mm10/opg3.l b/sem3/osc/mm10/opg3.l
new file mode 100644
index 0000000..1c4b9c7
--- /dev/null
+++ b/sem3/osc/mm10/opg3.l
@@ -0,0 +1,36 @@
+%{
+
+#include <stdio.h>
+
+#define BEGIN_T 1
+#define END_T 2
+#define NUM_T 3
+#define VAR_T 4
+
+%}
+
+VAR			[a-zA-Z][a-zA-Z\_\-0-9]*
+TAL			[0-9]+
+
+%%
+
+begin		{printf("Found a BEGIN\n"); return BEGIN_T;}
+end			{printf("Found a END\n"); return END_T;}
+{VAR}		{printf("Found a variable %s\n", yytext); return VAR_T;}
+{TAL}		{printf("Found a number %d\n", strtol(yytext, NULL, 10)); return NUM_T;}
+
+%%
+
+int main(void) {
+
+	for(;;) {
+		int t = yylex();
+		printf("yylex: %d\n", t);
+		if( t == END_T ) {
+			break;
+		}
+	}
+
+	return 0;
+	
+}
diff --git a/sem3/osc/mm10/opg4.l b/sem3/osc/mm10/opg4.l
new file mode 100644
index 0000000..aeb73b1
--- /dev/null
+++ b/sem3/osc/mm10/opg4.l
@@ -0,0 +1,101 @@
+%{
+
+#include <stdio.h>
+#include <stdint.h>
+
+#define BEGIN_T 1
+#define END_T 2
+#define NUM_T 3
+#define VAR_T 4
+#define HASHSIZE 100
+
+typedef struct symnode_struct {
+	struct symnode_struct *next;
+	char *name;
+} symnode_t;
+
+symnode_t *sym_insert(char *var);
+symnode_t *sym_lookup(char *var);
+
+%}
+
+VAR			[a-zA-Z][a-zA-Z\_\-0-9]*
+TAL			[0-9]+
+
+%%
+
+begin		{printf("Found a BEGIN\n"); return BEGIN_T;}
+end			{printf("Found a END\n"); return END_T;}
+{VAR}		{printf("Found a variable %s\n", yytext); 
+				if( !sym_lookup(yytext) ) { 
+					printf("Not found inserting\n");
+					sym_insert(yytext);
+				}
+				return VAR_T;}
+{TAL}		{printf("Found a number %d\n", strtol(yytext, NULL, 10)); return NUM_T;}
+
+%%
+
+symnode_t *symlist[HASHSIZE];
+
+unsigned int hash(char *s) {
+	uint32_t hv = 0;
+	for( int i = 0; s[i] != '\0'; i++ ) {
+		// take MSB 6 bits of hv and xors with LSB of s[i]
+		uint32_t v = ( hv >> 26 ) ^ (s[i] & 0x3f);
+
+		// Push those back on hv
+		hv = (hv << 4) | v;
+	}
+	// Return appropriate size
+	return hv % HASHSIZE;
+}
+
+
+symnode_t *sym_insert(char *var) {
+	unsigned int index = hash(var);
+
+	// Save old value
+	symnode_t *oldSym = symlist[index];
+
+	// Make new
+	symlist[index] = malloc(sizeof(symnode_t));
+	if( symlist[index] == NULL ) {
+		// If malloc failed
+		symlist[index] = oldSym;
+		return NULL;
+	}
+
+	// Link old one
+	symlist[index]->next = oldSym;
+	symlist[index]->name = var;
+
+	return symlist[index];
+}
+
+symnode_t *sym_lookup(char *var) {
+	unsigned int index = hash(var);
+	symnode_t *n = symlist[index];
+
+	// Look trough list
+	while(n != NULL && strcmp(n->name, var) != 0) {
+		n = n->next;
+	}
+
+	return n;
+}
+
+
+int main(void) {
+
+	for(;;) {
+		int t = yylex();
+		printf("yylex: %d\n", t);
+		if( t == END_T ) {
+			break;
+		}
+	}
+
+	return 0;
+	
+}
diff --git a/sem3/osc/mm10/opgaver.md b/sem3/osc/mm10/opgaver.md
new file mode 100644
index 0000000..b8c8186
--- /dev/null
+++ b/sem3/osc/mm10/opgaver.md
@@ -0,0 +1,55 @@
+# MM10
+
+## Opgave 1
+
+A)
+
+<img src="./stateMachine.png"></img>
+
+B)
+
+Kan ses i den tilhørende opg1.l fil.
+For at compile kør:
+
+```
+make run BIN=opg1
+```
+
+C)
+
+```
+aabcd
+
+Fandt ting aabcd
+yylex: 1
+```
+
+```
+afggfd
+
+MehMehMehMehMehMeh
+```
+
+## Opgave 2
+
+Regulære udtryk for:
+
+```
+c kommentarer: \/\/.*\n
+real konstant: [-+]?[0-9]*(\.[0-9]+)?(e\+[0-9]+)?
+starter med store: [A-Z][a-zA-z]+
+```
+
+## Opgave 3
+
+Dette laver jeg i opg3.l filen.
+
+## Opgave 4
+
+Se opg4.l fil og kør med.
+
+```
+make run BIN=opg4
+```
+
+
diff --git a/sem3/osc/mm10/stateMachine.png b/sem3/osc/mm10/stateMachine.png
new file mode 100644
index 0000000..08c5bf2
Binary files /dev/null and b/sem3/osc/mm10/stateMachine.png differ
diff --git a/sem3/osc/mm11/opgaver.md b/sem3/osc/mm11/opgaver.md
new file mode 100644
index 0000000..276236a
--- /dev/null
+++ b/sem3/osc/mm11/opgaver.md
@@ -0,0 +1,32 @@
+# Opgave 1
+
+Mange af dem er okay.
+
+```
+<program> ::= 'program''(' <ident> ')' <statementlist> 'end'.
+<statementlist> ::= <statement> <statementlist> | e
+<statement> ::= <ident> '=' <exp>;
+
+<exp> ::= <term> <expB>
+<expB> ::= <termopr> <term> <expB> | e
+
+<term> ::= <factor> <termB>
+<termB> ::= <factoropr> <factor> <termB> | e
+<termopr> ::= '+' | '-'
+
+<factor> ::= '(' <exp> ')' | <ident>
+<factoropr> ::= '*' | '/'
+```
+
+# Opgave 2
+
+Denne laver jeg måske senere.
+
+# Opgave 3
+
+Denne er løst i regn mappen. 
+Kør `make run` deri for at køre.
+
+# Opgave 4
+
+I regn2 mappen
diff --git a/sem3/osc/mm11/regn/Makefile b/sem3/osc/mm11/regn/Makefile
new file mode 100644
index 0000000..442feba
--- /dev/null
+++ b/sem3/osc/mm11/regn/Makefile
@@ -0,0 +1,30 @@
+
+LEX=flex
+YACC=bison
+LIBS=-ly -lfl -lm
+CC=gcc
+
+PROG=regn
+TRASH=lex.yy.c $(PROG).tab.c $(PROG) $(PROG).tab.h $(PROG).output
+
+$(PROG): $(PROG).tab.o lex.yy.o symtab.o
+		$(CC) -o $@ $^ $(LIBS) 
+
+$(PROG).tab.c $(PROG).tab.h: $(PROG).y
+		$(YACC) -d -v $(PROG).y
+
+lex.yy.c: $(PROG).l
+		$(LEX) $(PROG).l
+
+%.o: %.c
+	$(CC) -c -o $@ $^
+
+PHONY: clean run
+
+run: $(PROG)
+	./$(PROG)
+
+clean:
+	rm -f *.o
+	rm -f $(TRASH)
+
diff --git a/sem3/osc/mm11/regn/regn.l b/sem3/osc/mm11/regn/regn.l
new file mode 100644
index 0000000..bbaadb8
--- /dev/null
+++ b/sem3/osc/mm11/regn/regn.l
@@ -0,0 +1,40 @@
+%{
+#include <math.h>
+#include <string.h>
+#include "symtab.h"
+#include "regn.tab.h"
+%}
+
+realtal      ([0-9]+|([0-9]*\.[0-9]+))([eE][-+]?[0-9]+)?
+var_begin	 let
+op_log		 log
+op_exp		 exp
+op_sqrt		 sqrt
+var			 [A-Za-z][A-Za-z0-9]*
+
+%%
+{realtal}      {yylval.dval = atof(yytext); 
+                return TAL;}
+{var_begin}	   {return VAR_BEGIN;}
+{op_log}	   {return LOG;}
+{op_exp}	   {return EXP;}
+{op_sqrt}	   {return SQRT;}
+
+{var}		   {yylval.string = strdup(yytext); return VAR;}
+
+[ \t] ;
+
+
+'$'            {return 0;} 
+
+\n|.           {return yytext[0];} 
+
+%%
+
+void init_sym()
+{
+	int  i;
+	for (i = 0; i < HASHSIZE; i++)
+		symbolarray[i] = NULL;
+}
+
diff --git a/sem3/osc/mm11/regn/regn.y b/sem3/osc/mm11/regn/regn.y
new file mode 100644
index 0000000..d0f67eb
--- /dev/null
+++ b/sem3/osc/mm11/regn/regn.y
@@ -0,0 +1,54 @@
+%{
+#include <stdio.h>
+#include <math.h>
+#include "symtab.h"
+#include <string.h>
+%}
+
+%union {
+	char           *string;
+	double          dval;
+}
+
+%token <string> VAR
+%token <dval> TAL
+%token LOG EXP SQRT VAR_BEGIN
+
+%left '-' '+'
+%right LOG EXP SQRT
+%left '*' '/'
+%right UMINUS
+
+%type <dval> expression
+
+%%
+
+statement_list: statement '\n'
+	  | statement_list statement '\n' ;
+
+statement:  expression					{printf("= %f\n",$1);}
+	  | VAR_BEGIN VAR '=' expression	{symnode_t *n = sym_lookup($2);
+										 if( !n ) {n = sym_insert($2); }
+										 n->value = $4;};
+
+expression: expression '+' expression   {$$ = $1 + $3;}
+	  | expression '-' expression   {$$ = $1 - $3;}
+	  | expression '*' expression   {$$ = $1 * $3;}
+	  | expression '/' expression   {if ($3 == 0.0) 
+                                           yyerror("divide dy zero");
+                                         else $$ = $1 / $3;}
+	  | '-' expression %prec UMINUS {$$ =  - $2;}
+	  | '(' expression ')'          {$$= $2;}
+	  | LOG expression				{$$ = log($2);}
+	  | EXP expression				{$$ = exp($2);}
+	  | SQRT expression				{$$ = sqrt($2);}
+          | TAL                         {$$ = $1;}
+	  | VAR							{symnode_t *n = sym_lookup($1);
+									 if( !n ) { yyerror("Var not found"); } else { $$ = n->value;} };
+%%
+
+int main()
+{ 
+  yyparse(); 
+}
+
diff --git a/sem3/osc/mm11/regn/symtab.c b/sem3/osc/mm11/regn/symtab.c
new file mode 100644
index 0000000..8103203
--- /dev/null
+++ b/sem3/osc/mm11/regn/symtab.c
@@ -0,0 +1,50 @@
+#include "symtab.h"
+#include <stdlib.h>
+#include <string.h>
+
+unsigned int hash(char *s) {
+	uint32_t hv = 0;
+	for( int i = 0; s[i] != '\0'; i++ ) {
+		// take MSB 6 bits of hv and xors with LSB of s[i]
+		uint32_t v = ( hv >> 26 ) ^ (s[i] & 0x3f);
+
+		// Push those back on hv
+		hv = (hv << 4) | v;
+	}
+	// Return appropriate size
+	return hv % HASHSIZE;
+}
+
+
+symnode_t *sym_insert(char *var) {
+	unsigned int index = hash(var);
+
+	// Save old value
+	symnode_t *oldSym = symbolarray[index];
+
+	// Make new
+	symbolarray[index] = malloc(sizeof(symnode_t));
+	if( symbolarray[index] == NULL ) {
+		// If malloc failed
+		symbolarray[index] = oldSym;
+		return NULL;
+	}
+
+	// Link old one
+	symbolarray[index]->next = oldSym;
+	symbolarray[index]->name = var;
+
+	return symbolarray[index];
+}
+
+symnode_t *sym_lookup(char *var) {
+	unsigned int index = hash(var);
+	symnode_t *n = symbolarray[index];
+
+	// Look trough list
+	while(n != NULL && strcmp(n->name, var) != 0) {
+		n = n->next;
+	}
+
+	return n;
+}
diff --git a/sem3/osc/mm11/regn/symtab.h b/sem3/osc/mm11/regn/symtab.h
new file mode 100644
index 0000000..c61f3a8
--- /dev/null
+++ b/sem3/osc/mm11/regn/symtab.h
@@ -0,0 +1,20 @@
+#include <stdint.h>
+#define HASHSIZE 100
+
+typedef struct symnode_struct {
+	char *name;
+	struct symnode_struct *next;
+	double value;
+} symnode_t;
+
+symnode_t *sym_insert(char *var);
+symnode_t *sym_lookup(char *var);
+
+struct symnode {
+	struct symnode *next;
+	char *name;
+	int type;
+	double value;
+};
+
+symnode_t *symbolarray[HASHSIZE];
diff --git a/sem3/osc/mm11/regn2/Makefile b/sem3/osc/mm11/regn2/Makefile
new file mode 100644
index 0000000..9640aaa
--- /dev/null
+++ b/sem3/osc/mm11/regn2/Makefile
@@ -0,0 +1,30 @@
+
+LEX=flex
+YACC=bison
+LIBS=-ly -lfl -lm
+CC=gcc
+
+PROG=regn
+TRASH=lex.yy.c $(PROG).tab.c $(PROG) $(PROG).tab.h $(PROG).output
+
+$(PROG): $(PROG).tab.o lex.yy.o
+		$(CC) -o $@ $^ $(LIBS) 
+
+$(PROG).tab.c $(PROG).tab.h: $(PROG).y
+		$(YACC) -d -v $(PROG).y
+
+lex.yy.c: $(PROG).l
+		$(LEX) $(PROG).l
+
+%.o: %.c
+	$(CC) -c -o $@ $^
+
+PHONY: clean run
+
+run: $(PROG)
+	./$(PROG)
+
+clean:
+	rm -f *.o
+	rm -f $(TRASH)
+
diff --git a/sem3/osc/mm11/regn2/regn.l b/sem3/osc/mm11/regn2/regn.l
new file mode 100644
index 0000000..9988ddd
--- /dev/null
+++ b/sem3/osc/mm11/regn2/regn.l
@@ -0,0 +1,27 @@
+%{
+#include <math.h>
+#include <string.h>
+#include "regn.tab.h"
+%}
+
+realtal      ([0-9]+|([0-9]*\.[0-9]+))([eE][-+]?[0-9]+)?
+op_log		 log
+op_exp		 exp
+op_sqrt		 sqrt
+
+%%
+{realtal}      {yylval.dval = atof(yytext); 
+                return TAL;}
+{op_log}	   {return LOG;}
+{op_exp}	   {return EXP;}
+{op_sqrt}	   {return SQRT;}
+
+[ \t] ;
+
+
+'$'            {return 0;} 
+
+\n|.           {return yytext[0];} 
+
+%%
+
diff --git a/sem3/osc/mm11/regn2/regn.y b/sem3/osc/mm11/regn2/regn.y
new file mode 100644
index 0000000..eac24c8
--- /dev/null
+++ b/sem3/osc/mm11/regn2/regn.y
@@ -0,0 +1,46 @@
+%{
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+%}
+
+%union {
+	double          dval;
+}
+
+%token <dval> TAL
+%token LOG EXP SQRT
+
+%left '-' '+'
+%left LOG EXP SQRT
+%left '*' '/'
+%right UMINUS
+
+%type <dval> expression
+
+%%
+
+statement_list: statement '\n'
+	  | statement_list statement '\n' ;
+
+statement:  expression					{printf("out \n");};
+
+expression: expression '+' expression   {printf("sum \n");}
+	  | expression '-' expression		{printf("sub \n");}
+	  | expression '*' expression		{printf("mul \n");}
+	  | expression '/' expression		{if ($3 == 0.0) 
+                                           yyerror("divide dy zero");
+                                         else printf("div \n");}
+	  | '-' expression %prec UMINUS		{printf("neg \n");}
+	  | '(' expression ')'				{;}
+	  | LOG expression					{printf("log \n");}
+	  | EXP expression					{printf("exp \n");}
+	  | SQRT expression					{printf("sqrt \n");}
+          | TAL                         {printf("load %f \n", $$);};
+%%
+
+int main()
+{ 
+  yyparse(); 
+}
+
diff --git a/sem3/osc/mm3/opgaver.md b/sem3/osc/mm3/opgaver.md
new file mode 100644
index 0000000..d9440f8
--- /dev/null
+++ b/sem3/osc/mm3/opgaver.md
@@ -0,0 +1,47 @@
+# Opgave 1
+
+> Et operativsystem anvenderen 2-level page tabel og 4Kbyte pagesize. Det
+virtuelle adresseområde er på 4GByte. De programmer der afvikles på
+computeren er på mellem 64 KByte og 16MByte. Hvor mange bit vil I anvende til
+index ind i hhv. page tabel 1 og pagetabel 2.
+
+Her betyder det at man har en tabel der referere til level 2 tabeller.
+
+Så i level to tabellen ville jeg nok have 4M da det er 1023 pages. 
+Dette betyder at der vil lidt spild med det lille program på 64kb men det større program på 16Mb betøver ikke få så mange pages.
+
+1023 pages kræver tilgængeld 10 bits til indexering hvilket er lidt spild.
+
+For at få op til 4GB skal man igen have 1023 reference i level 1 tabel.
+
+En anden mulighed ville være at have 8 bits til level 2 index, og derfor have 255 pages i level to tabel.
+Dette vil betyde at level to indexen ikke spilder plads from med 10 bit.
+
+En level 1 tabel indexer derfor 4Kb * 255 = 4096 * 255 = 104 4480 = 104Kb
+
+Her vil level 1 tabellen få 4Gb / 104.4480Kb = 4 000 000 000 / 104 4480 =~= 4112
+
+Her skal man bruge 13 bits, hvilket betyder at man spilder 3 bits hvis man bruger 16 bit system.
+
+# Opgave 2
+
+> Diskuter måder at håndtere virtuelle pages på. Kan man optimere software i
+forhold til hvordan et OS håndterer pages? Er der noget i en eller flere
+koncepter I måske kan anvende i jeres projekt?
+
+Læser på wikipedia at dette er en teknik hvor man gemmer under pagene i virtuel memory i stedet for physical.
+Dette vil betyder at den også kan blive swappet til disk osv.
+
+Dette vil tilgengeld kræve at man har nogle pages i physical som skal holder styr på de virtuelle som indeholder andre pages.
+Det vil nok egentlig være lidt bøvlet. 
+
+Man kunne måske have at level 1 tabellen signalere om pagen er i physical eller virtuel.
+
+# Opgave 3
+
+> Skriv et lille program, der allokerer en stadig voksende mængde hukommelse,
+f.eks. start med 8kB, 8MB, 8GB og mere... hvornår løber I ind i problemer?
+Observer evt. med værktøjet ovenstående eller andet der passer til jeres
+platform.
+
+
diff --git a/sem3/osc/mm8/mm8.ino b/sem3/osc/mm8/mm8.ino
new file mode 100644
index 0000000..f47306d
--- /dev/null
+++ b/sem3/osc/mm8/mm8.ino
@@ -0,0 +1,47 @@
+// Spg kernel
+#include <krnl.h>
+
+#define PRIO 10
+#define STACK 100
+
+char stackFast[STACK];
+struct k_t *semFast, *fastTask;
+
+void fast() {
+	/* Gotta go fast(10 Hz) */
+	k_set_sem_timer(semFast, 1000);
+	for(;;) {
+		k_wait(semFast, 0);
+		k_eat_ticks(90);
+	}
+}
+
+void setup() {
+	pinMode(13, OUTPUT);
+
+	PORTB |= 0x20;
+	delay(1000);
+	PORTB &= 0xDF;
+	delay(200);
+
+	k_init(1, 1, 0);
+	
+	fastTask = k_crt_task(fast, PRIO, stackFast, STACK);
+	semFast = k_crt_sem(0, 2);
+
+	k_start(1);
+	PORTB |= 0x20;
+}
+
+void loop() {}
+
+extern "C" {
+
+	void k_breakout() {
+		if( pRun->nr == 0 ) {
+			PORTB |= 0x20;
+		} else {
+			PORTB &= 0xDF;
+		}
+	}
+}
diff --git a/sem3/osc/mm9/opgaver.md b/sem3/osc/mm9/opgaver.md
new file mode 100644
index 0000000..fe2ec99
--- /dev/null
+++ b/sem3/osc/mm9/opgaver.md
@@ -0,0 +1,129 @@
+# Opgave A
+
+Hmm ved ikke lige med projekt men har en fed ide.
+
+Openscad men til 2d graffik som **kompilere** til svg.
+
+Tænker at man vil lave det i et sprog som c, go eller rust. 
+Rust ville være optimalt men det er også lidt svært.
+
+Det skulle være et emperisk sprog med variabler og functioner.
+Funktioner returnere ikke noget, men mere en bestemt figur.
+
+Variables can be strings, floating point numbers.
+
+Lists are defined as list.
+
+Strings begin with big letters. 
+
+Bools are defined as numbers 0 and 1.
+
+Lists are defined as [] and contain all numbers or all strings.
+
+C style comments.
+
+```
+var Black = "#FFFFFF";
+var White = "#000000";
+list Names = [ "nice", "nice2" ];
+
+var radius = 10.2;
+
+func coolCircle(r, Name) {
+	// Defined as circle(radius, fgCol, bgCol)
+	circle(r, Black, White);
+
+	// Defined as insertText(Text, allign, fgCol)
+	insertText(Name, ALIGN_CENTER, Black);
+}
+
+translate(1, 2) {
+	coolCircle(radius / 2, Names[0]);
+}
+
+coolCircle(radius, Names[1]);
+```
+
+The code will generate two circles, one in the center and one on the coordinates 1, 2.
+
+# Opgave B
+
+Der er defineret to globale variabler, men de er ikke på stacken.
+
+Inde i main laver man en pointer til a og sender ind i funktionen.
+Dette betyder at denne pointer enten ligger på stacken eller i et register når funktionen ainc kører.
+
+Men der kan siges sikkert at stacken indeholder en return pointer til main og en reference til den tidelige stack(tror jeg).
+
+
+## Kode i assembly
+
+Jeg har ikke taget højde for integer operationer.
+
+```
+JMP main
+var_a: DB 4
+
+ainc:
+	MOV B, [A]
+	ADD B, 1
+	MOV [A], B
+	RET
+
+main:
+	MOV A, var_a
+	CALL ainc
+
+	HLT
+```
+
+## Forskellige compile trin
+
+Proprocessor har ikke noget at lave.
+
+Start med at compile til assembly:
+
+Læg a og b i starten af programmet.
+
+Compiler funktionen ainc og adec og sæt en label ved dem.
+Dette gøres ved først at lave koden der henter argument ud og gemmer tidligere stack pointer.
+Derefter compiles indholdet i funktionen.
+Slut af med at returner til caller.
+
+Derefter bliver assembly'en assemblet:
+
+De forskellige mnenorics(eller hvad det nu hed) bliver lavet om til opcodes og lags sammen med deres argumenter.
+Dette gøres for alle funktionerne.
+
+a og b bliver placeret i filen.
+
+Derefter placeres main ved entrypoint og de to funktioner bliver lagt ved siden af.
+De forskellige referencer til funktioner og globale variabler bliver byttet ud med deres virkelige værdier i binary.
+
+# Opgave C
+
+Grammastart -> *Viggo* stmList *End*
+stmList -> stm stmList | e
+stm -> ident *=* exp *;*
+ident -> letter symList
+letter -> *a* | ... | *å* | *A* | ... | *Å*
+digit -> *0* | ... | *9*
+symbol -> letter | digit
+symList -> symbol symList | e
+exp -> term expB
+expB -> termopr term expB | e
+termOpr -> *+* | *-*
+term -> factor termB
+termB -> factorOpr factor termB | e
+factorOpr -> _*_ | _/_
+factor -> *(* exp *)* | ident
+
+## C.2
+
+See tree.png
+
+## C.3
+
+
+
+
diff --git a/sem3/osc/noter.md b/sem3/osc/noter.md
new file mode 100644
index 0000000..6e13640
--- /dev/null
+++ b/sem3/osc/noter.md
@@ -0,0 +1,17 @@
+# HUsk
+
+Ikke Deterministisk: Et stadie i kan føre til flere andre states.
+
+Undersøg **kontekst fri**
+
+Leksikal analysen: bruger regulær
+
+Parsing: ikke regulær.
+
+Shift-reduce parser.
+
+3 adress code bruges til mellem kode.
+
+In order: tree (venstre, top, højre)
+preorder: tree (top, venstre, højre)
+postorder: tree (venstre, højre, top)
-- 
cgit v1.2.3