diff --git a/1 b/1
new file mode 100644
index 0000000..2eb6352
--- /dev/null
+++ b/1
@@ -0,0 +1,5 @@
+00000
+01110
+00000
+00000
+
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 42f2178..a483142 100755
--- a/Makefile
+++ b/Makefile
@@ -50,6 +50,17 @@ sheet08:
 	chmod +x build/sheet08
 	build/sheet08
 
+sheet09:
+	$(CC) src/sheet09.cpp -o build/sheet09
+	chmod +x build/sheet09
+	build/sheet09 src/grid src/grid 1
+
+HTable:
+	$(CC) src/HTable.cpp -o build/HTable
+	chmod +x build/HTable
+	build/HTable src/grid src/grid 1
+
+
 pizza:
 	$(CC) src/pizza.cpp -o build/pizza
 	chmod +x build/pizza
diff --git a/src/HTable.cpp b/src/HTable.cpp
new file mode 100644
index 0000000..411dc73
--- /dev/null
+++ b/src/HTable.cpp
@@ -0,0 +1,127 @@
+#include <iterator>
+#include <stdexcept>
+#include <string>
+#include <vector>
+#include <iostream>
+#include <iterator>
+template<typename T>
+class HTable
+{
+	private:
+		std::vector<std::pair<std::string, T>> data;
+		std::vector<bool> positions_in_use;
+		size_t hash(const std::string &key)
+		{
+			size_t hash_val = 5381;
+			for(const char c : key)
+			{
+				hash_val *= 33 + c;
+			}
+			return hash_val % data.size();
+		}
+
+
+	public:
+		HTable(size_t size) : data(std::vector<std::pair<std::string, T>>(size)), positions_in_use(std::vector<bool>(size,false)) {}
+
+		bool insert(const std::string &key, const T &value)
+		{
+			size_t position = hash(key);
+			for(size_t i=0; i<data.size(); ++i)
+			{
+				if(key == data[position].first)
+				{
+					data[position].second = value;
+					return i==0 ? 0 : 1;
+				}
+				else if(!positions_in_use[position])
+				{
+					data[position] = std::pair<std::string, T>(key,value);
+					positions_in_use[position] = true;
+					return i==0 ? 0 : 1;
+				}
+				else if(++position>=data.size())
+				{
+					position = 0;
+				}
+			}
+			throw std::runtime_error("Can not insert element into a full hash table!");
+		}
+
+		T& get(const std::string &key)
+		{
+			size_t position = hash(key);
+			for(size_t i=0; i<data.size(); ++i)
+			{
+				if(positions_in_use[position] && data[position].first == key)
+				{
+					return data[position].second;
+				}
+
+				if(++position>=data.size())
+				{
+					position = 0;
+				}
+			}
+			throw std::runtime_error("Could not find key!");
+		}
+		
+		friend std::ostream& operator<<(std::ostream &os, const HTable &h)
+		{
+			os << '{';
+			for(auto &pair : h.data)
+			{
+				os << "(\"";
+				os << pair.first;
+				os << "\": ";
+				os << pair.second;
+				if(std::distance(pair, *h.data.end())==1)
+				{ os << ")}"; }
+				else
+				{ os << "), "; }
+			}
+			return os;
+		}
+
+		void erase(const std::string &key)
+		{
+			size_t position = hash(key);
+			for(size_t i=0; i<data.size(); ++i)
+			{
+				if(data[position].first == key)
+				{
+					data.erase(data.begin()+position);
+					positions_in_use[position] = false;
+					return;
+				}
+
+				if(++position>=data.size())
+				{
+					position = 0;
+				}
+			}
+			throw std::runtime_error("Could not find key!");
+	}
+};
+
+int main()
+{
+	HTable<size_t> t1(5);
+
+	std::cout << t1 << '\n';
+
+	for(size_t i=0; i<5;++i)
+	{
+		t1.insert(std::to_string(i), i);
+	}
+
+	std::cout << t1 << '\n';
+
+	t1.insert("1", 10);
+
+	std::cout << t1 << '\n';
+
+	t1.erase("1");
+
+	std::cout << t1 << '\n';
+}
\ No newline at end of file
diff --git a/src/grid b/src/grid
new file mode 100644
index 0000000..62ec37b
--- /dev/null
+++ b/src/grid
@@ -0,0 +1,4 @@
+00000
+01110
+00000
+00000
\ No newline at end of file
diff --git a/src/initial_grid.txt b/src/initial_grid.txt
new file mode 100644
index 0000000..731bb72
--- /dev/null
+++ b/src/initial_grid.txt
@@ -0,0 +1,26 @@
+000000000000000011111111100000000000000000000000000
+000000100000000010100000100001000000000000000000000
+000000000000000011111111100000000010000000000000000
+000000000000000111111111110000000000000100000000000
+000100000000001111111111111000000000000000000000000
+000000000000000110000000110001000101000000000000000
+000000000000001000100010001000001111000000000000000
+000000000000001000001000001000001100000000000000000
+000001111111111111111111110000011000000100000000000
+001000111111111111111110011100110000000000000000000
+000000000000111110001000000011100000000000000000000
+000000000001011100011100000001000000000000000000000
+000000000011111000001000000001001000000000000000000
+000010000111110000011100000011000000000010000000000
+000000001101111000000000001100000000000000000000000
+000001111000011111111111111100000000000000000000000
+000000111001100000001000000011000000100000000000000
+000001010110000000011100000000100000000000000000000
+000000000100000000001000000000010000000000000000000
+000000000100000000011100000000010000000000000000000
+001000000100000000001000000000010000010000000000000
+000000000100000000011100000000010000000000000000000
+000000000010000000000000000000100000000000000000000
+001111111111100000000000000011111111111110000000000
+000000000000011110000000111100000000000000000000000
+000000000000000001111111000000000000000000000000000
diff --git a/src/sheet07.cpp b/src/sheet07.cpp
index f8b3885..7db9786 100644
--- a/src/sheet07.cpp
+++ b/src/sheet07.cpp
@@ -9,7 +9,7 @@
 #include <chrono>
 
 template<typename T>
-typename std::enable_if<std::is_arithmetic<T>::value, &operator*>
+// typename std::enable_if<std::is_arithmetic<T>::value, &operator*>
 class matrix
 {
 	public:
@@ -138,8 +138,8 @@ class matrix
 			return out;
 		}
 
-		typename std::enable_if<std::is_arithmetic<T>::value>
-		friend matrix operator* (const matrix &lhs, const matrix &rhs) = delete;
+		// typename std::enable_if<std::is_arithmetic<T>::value>
+		// friend matrix operator* (const matrix &lhs, const matrix &rhs) = delete;
 
 		friend matrix operator* (const matrix &lhs, const matrix &rhs)
 		{
@@ -148,15 +148,23 @@ class matrix
 				throw std::domain_error("type must be arithmetic.");
 			}
 
-			if(lhs.num_columns()!=rhs.num_rws(rows), columns(columns)
-		{
-				for(size_t y=0; y<out.num_rows(); ++y)
+
+			if(lhs.num_columns()==rhs.num_rows())
+			{
+				matrix<T> out(rhs.num_columns(), lhs.num_rows());
+				for(size_t x=0; x<out.num_columns(); ++x)
 				{
-					out(y,x)=dot_product(lhs.row_to_vec(y), rhs.column_to_vec(x));
+					for(size_t y=0; y<out.num_rows(); ++y)
+					{
+						out(y,x)=dot_product(lhs.row_to_vec(y), rhs.column_to_vec(x));
+					}
 				}
+				return out;
+			}
+			else
+			{
+				throw std::domain_error("LHS column amount must match RHS row amount!");
 			}
-			
-			return out;
 		}
 
 		friend bool operator== (const matrix &lhs, const matrix &rhs)
diff --git a/src/sheet09.cpp b/src/sheet09.cpp
new file mode 100644
index 0000000..1785c15
--- /dev/null
+++ b/src/sheet09.cpp
@@ -0,0 +1,143 @@
+#include <fstream>
+#include <string>
+#include <sys/types.h>
+#include <system_error>
+#include <vector>
+#include <iostream>
+#include <stdexcept>
+
+using bool_grid = std::vector<std::vector<bool>>;
+
+bool_grid read_grid(const std::string &filename);
+void print_grid(bool_grid grid);
+bool_grid game_of_life(const bool_grid &grid, const size_t N);
+void write_grid(const std::string &filename, const bool_grid &grid);
+
+int main(int argc, char *argv[])
+{
+	if(argc>3)
+	{
+		bool_grid in = read_grid(argv[1]);
+		write_grid(argv[3],game_of_life(in, std::atoi(argv[2])));
+	}
+	else
+	{
+		std::cout << "Help: sheet09 <inputPath> <Iterations> <outputPath>";
+	}
+}
+
+void print_grid(bool_grid grid)
+{
+	for(const auto &row : grid)
+	{
+		for(const auto &cell : row)
+		{
+			std::cout << cell << ' ';
+		}
+		std::cout<< "\n";
+	}
+}
+
+bool_grid read_grid(const std::string &filename)
+{
+	bool_grid out;
+	std::ifstream file(filename);
+	if(!file.is_open())
+	{
+		throw std::runtime_error("Unable to open file!\n");
+	}
+
+	for(std::string line; std::getline(file,line);)
+	{
+		std::vector<bool> row;
+		for(char cell : line)
+		{
+			row.push_back(cell-'0');
+		}
+		out.push_back(row);
+	}
+	return out;
+}
+
+bool_grid game_of_life(const bool_grid &grid, const size_t N)
+{
+	if(N==0) { return grid; }
+
+	bool_grid current = grid;
+	bool_grid next = grid;
+	for(size_t i=0; i<N;++i)
+	{
+		for(size_t y=0; y<current.size(); ++y)
+		{
+			for(size_t x=0; x<current[0].size(); ++x)
+			{
+				size_t start_y;
+				size_t start_x;
+				size_t end_y;
+				size_t end_x;
+
+				if	(x<1)
+					{ start_x = 0; }
+				else
+					{ start_x = x-1; }
+
+				if	(y<1)
+					{ start_y = 0; }
+				else
+					{ start_y = y-1; }
+
+				if	(x+1>=current[0].size())
+					{ end_x = current[0].size()-1; }
+				else
+					{ end_x = x+1; }
+
+				if	(y+1>=current.size())
+					{ end_y = current.size()-1; }
+				else
+					{ end_y = y+1; }
+
+				size_t sum = 0;
+
+				while(start_y<=end_y)
+				{
+					for(size_t i=start_x; i<=end_x; ++i)
+					{
+						if(i != x || start_y != y)
+						{
+							sum += current[start_y][i];
+						}
+					}
+					start_y++;
+				}
+
+				if		(sum==3 && !current[y][x])
+					{ next[y][x] = true; }
+				else if	((sum<2 || sum>3) && current[y][x])
+					{ next[y][x] = false; }
+			}
+		}
+		
+		if(i<N-1)
+		{
+			std::swap(current, next);
+		}
+	}
+	return next;
+}
+
+void write_grid(const std::string &filename, const bool_grid &grid)
+{
+	std::ofstream ofs(filename);
+	if(!ofs.is_open())
+	{ throw std::domain_error("File could not be opened.");}
+
+	for(const auto &row  : grid)
+	{
+		for(const auto &cell : row)
+		{
+			ofs << cell;
+		}
+		ofs << '\n';
+	}
+	ofs.close();
+}
\ No newline at end of file
diff --git a/test b/test
new file mode 100644
index 0000000..ac05d1c
--- /dev/null
+++ b/test
@@ -0,0 +1,26 @@
+000000000000000011111111100000000000000000000000000
+000000100000000010100000100001000000000000000000000
+000000000000000011111111100000000010000000000000000
+000000000000000111111111110000000000000100000000000
+000100000000001111111111111000000000000000000000000
+000000000000000110000000110001000101000000000000000
+000000000000001000100010001000001111000000000000000
+000000000000001000001000001000001100000000000000000
+000001111111111111111111110000011000000100000000000
+001000111111111111111110011100110000000000000000000
+000000000000111110001000000011100000000000000000000
+000000000001011100011100000001000000000000000000000
+000000000011111000001000000001001000000000000000000
+000010000111110000011100000011000000000010000000000
+000000001101111000000000001100000000000000000000000
+000001111000011111111111111100000000000000000000000
+000000111001100000001000000011000000100000000000000
+000001010110000000011100000000100000000000000000000
+000000000100000000001000000000010000000000000000000
+000000000100000000011100000000010000000000000000000
+001000000100000000001000000000010000010000000000000
+000000000100000000011100000000010000000000000000000
+000000000010000000000000000000100000000000000000000
+001111111111100000000000000011111111111110000000000
+000000000000011110000000111100000000000000000000000
+000000000000000001111111000000000000000000000000000
\ No newline at end of file
