diff --git a/turing-machine/css/styles.css b/turing-machine/css/styles.css
new file mode 100644
index 0000000..02279e5
--- /dev/null
+++ b/turing-machine/css/styles.css
@@ -0,0 +1,90 @@
+* {
+ font-family: "Trebuchet MS", sans-serif;
+}
+
+button {
+ background: #bbbbbb;
+ border: 1px solid white;
+ border-radius: 0.2rem;
+ padding: 0.2rem;
+}
+
+button:hover {
+ background: #cccccc;
+}
+
+body {
+ margin: 0;
+ background-color: #aaaaaa;
+}
+
+.container {
+ display: flex;
+ width: 90%;
+ margin-left: auto;
+ margin-right: auto;
+ flex-direction: column;
+
+ padding: 2rem;
+}
+
+.tape {
+ display: flex;
+
+ padding: 1rem;
+
+ align-items: center;
+ gap: 1rem;
+
+ height: 5rem;
+ max-width: 100%;
+
+ border: 1px solid black;
+
+ overflow-x: scroll;
+ overflow-y: hidden;
+}
+
+.cell {
+ position: relative;
+ height: 80%;
+ border: 3px solid black;
+ transition: border 0.1s ease-in-out;
+ transition: background 0.1s ease-in-out;
+
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ flex: 1;
+ gap: 0.2rem;
+
+ padding: 0.2rem;
+}
+
+.circle {
+ position: absolute;
+ bottom: -15px;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 10px;
+ height: 10px;
+ background-color: wheat;
+ border-radius: 50%;
+ opacity: 0.001;
+ transition: opacity 0.1s ease-in-out;
+}
+
+.cell.reading .circle {
+ opacity: 1;
+}
+
+.reading {
+ border-color: green;
+ background-color: wheat;
+}
+
+.cell-input {
+ width: 50px;
+ text-align: center;
+}
diff --git a/turing-machine/index.html b/turing-machine/index.html
new file mode 100644
index 0000000..2f65aa3
--- /dev/null
+++ b/turing-machine/index.html
@@ -0,0 +1,14 @@
+
+
+
+ Turing Machine Simulator
+
+
+
+
+
Simponic's State System
+
+
+
+
+
diff --git a/turing-machine/js/main.js b/turing-machine/js/main.js
new file mode 100644
index 0000000..68aaa39
--- /dev/null
+++ b/turing-machine/js/main.js
@@ -0,0 +1,98 @@
+const DISPLAY_CELLS = 15;
+const TAPE_LEN = 200;
+
+const MESSAGES = {
+ SET_CELL: "SET_CELL",
+ PAUSE: "PAUSE",
+ SIMULATE: "SIMULATE",
+ SET_READER: "SET_READER",
+};
+
+class Observable {
+ constructor() {
+ this.observers = [];
+ }
+
+ subscribe(f) {
+ this.observers.push(f);
+ }
+
+ unsubscribe(f) {
+ this.observers = this.observers.filter((subscriber) => subscriber !== f);
+ }
+
+ notify(data) {
+ this.observers.forEach((observer) => observer(data));
+ }
+}
+
+const state = new Observable();
+
+const tape = Array(TAPE_LEN).fill(0);
+state.subscribe((msg) => {
+ if (msg.type == MESSAGES.SET_CELL) {
+ tape[msg.cellId] = msg.value;
+ }
+});
+
+const tapeEl = document.getElementById("tape");
+
+const inputCellId = (cellId) => `${cellId}-input`;
+const updateCellButtonId = (cellId) => `${cellId}-button-update`;
+
+const setCellFromInput = (cellId, inputId) => {
+ const input = document.getElementById(inputId);
+ tape[cellId] = input.value;
+};
+
+const cell = (cellId, initValue = 0) => {
+ const cellDiv = document.createElement("div");
+ cellDiv.classList.add("cell");
+ cellDiv.id = cellId;
+
+ const readingHead = document.createElement("div");
+ readingHead.classList.add("circle");
+
+ const input = document.createElement("input");
+ const inputId = inputCellId(cellId);
+ input.classList.add("cell-input");
+ input.id = inputId;
+ input.value = initValue;
+
+ input.addEventListener("focusin", () =>
+ state.notify({ type: MESSAGES.PAUSE })
+ );
+ input.addEventListener("focusout", () =>
+ state.notify({ type: MESSAGES.SET_CELL, cell: cellId, value: input.value })
+ );
+ state.subscribe((msg) => {
+ if (msg.type == MESSAGES.SET_CELL && msg.cell == cellId) {
+ input.value = msg.value;
+ }
+ if (msg.type == MESSAGES.SET_READER) {
+ if (msg.cell == cellId) {
+ cellDiv.classList.add("reading");
+ cellDiv.scrollIntoView({
+ behavior: "smooth",
+ });
+ } else cellDiv.classList.remove("reading");
+ }
+ });
+
+ cellDiv.appendChild(input);
+ cellDiv.appendChild(readingHead);
+
+ return cellDiv;
+};
+
+const main = () => {
+ const cells = tape.map((_, cellId) => cell(cellId));
+ for (const cell of cells) {
+ tapeEl.appendChild(cell);
+ }
+ state.notify({ type: MESSAGES.SET_READER, cell: 0 });
+
+ setTimeout(() => {}, 1000);
+};
+
+main();