# Improved TuringMachine class with debug output and updated transition table per your fix. from dataclasses import dataclass from typing import Dict, Tuple, List, TypeAlias, Literal # === Type Aliases === State: TypeAlias = str Symbol: TypeAlias = str Direction: TypeAlias = Literal["L", "R"] # precise directions only TransitionKey: TypeAlias = Tuple[State, Symbol] TransitionValue: TypeAlias = Tuple[State, Symbol, Direction] TransitionFunction: TypeAlias = Dict[TransitionKey, TransitionValue] Tape: TypeAlias = List[Symbol] @dataclass class TuringMachine: transition_function: TransitionFunction start_state: State accept_state: State reject_state: State blank_symbol: Symbol = " " def run( self, tape_input: str, head: int = 0, max_steps: int = 10_000, verbose: bool = True, ) -> Tuple[State, Tape]: tape: Tape = list(tape_input) + [self.blank_symbol] * 20 state = self.start_state steps = 0 # normalize head position if head < 0: tape = [self.blank_symbol] * (-head) + tape head = 0 elif head >= len(tape): tape += [self.blank_symbol] * (head - len(tape) + 1) def debug_print(): tape_view = "".join(tape).replace(self.blank_symbol, "_") head_marker = " " * head + "^" print( f"[{steps:04}] State: {state} | Head: {head} | Tape:\n{tape_view}\n{head_marker}" ) debug_print() while ( state != self.accept_state and state != self.reject_state and steps < max_steps ): if verbose: debug_print() read = tape[head] key = (state, read) if key not in self.transition_function: print(f"No transition for ({state}, '{read}') — rejecting.") state = self.reject_state break next_state, write, move = self.transition_function[key] tape[head] = write head += 1 if move == "R" else -1 if head < 0: tape.insert(0, self.blank_symbol) head = 0 state = next_state steps += 1 debug_print() return state, tape # Updated transitions transitions_cleaned: TransitionFunction = {} # Scan phase: 1 → X, 0 → Y transitions_cleaned[("scan", "1")] = ("scan", "X", "R") transitions_cleaned[("scan", "0")] = ("scan", "Y", "R") transitions_cleaned[("scan", " ")] = ("back", " ", "L") # Back phase: move left over 0/1/X/Y and turn forward on ' ', 'M', 'N' for sym in ["0", "1", "X", "Y"]: transitions_cleaned[("back", sym)] = ("back", sym, "L") transitions_cleaned[("back", " ")] = ("forward", " ", "R") transitions_cleaned[("back", "M")] = ("forward", "M", "R") transitions_cleaned[("back", "N")] = ("forward", "N", "R") # Forward: if blank, done; if digit → sweep; if mark → prepare copy transitions_cleaned[("forward", " ")] = ("accept", " ", "R") transitions_cleaned[("forward", "0")] = ("sweep", "0", "L") transitions_cleaned[("forward", "1")] = ("sweep", "1", "L") transitions_cleaned[("forward", "X")] = ("fw1", "M", "R") # 1 → M transitions_cleaned[("forward", "Y")] = ("fw0", "N", "R") # 0 → N # Copy phases for sym in ["0", "1", "X", "Y"]: # ts wont ever meet M N transitions_cleaned[("fw1", sym)] = ("fw1", sym, "R") transitions_cleaned[("fw0", sym)] = ("fw0", sym, "R") transitions_cleaned[("fw1", " ")] = ("back", "1", "L") transitions_cleaned[("fw0", " ")] = ("back", "0", "L") # Sweep phase: M → 1, N → 0 transitions_cleaned[("sweep", "M")] = ("sweep", "1", "L") transitions_cleaned[("sweep", "N")] = ("sweep", "0", "L") transitions_cleaned[("sweep", "0")] = ("sweep", "0", "L") transitions_cleaned[("sweep", "1")] = ("sweep", "1", "L") transitions_cleaned[("sweep", " ")] = ("accept", " ", "R") # Build and run the machine with debug output tm = TuringMachine( transition_function=transitions_cleaned, start_state="scan", accept_state="accept", reject_state="reject", ) tape_input = "00110" final_state, final_tape = tm.run(tape_input) print("Final State:", final_state) final_tape_str = "".join(final_tape).strip() print("Final Tape:", final_tape_str) classic: TransitionFunction = {} # ok idk classic[("want_copy", "1")] = ("past_og_1", "X", "R") classic[("want_copy", "0")] = ("past_og_0", "Y", "R") for sym in ["0", "1"]: classic[("past_og_1", sym)] = ("past_og_1", sym, "R") classic[("past_og_0", sym)] = ("past_og_0", sym, "R") classic[("past_og_1", " ")] = ("copy_1", " ", "R") classic[("past_og_0", " ")] = ("copy_0", " ", "R") for sym in ["0", "1"]: classic[("copy_1", sym)] = ("copy_1", sym, "R") classic[("copy_0", sym)] = ("copy_0", sym, "R") classic[("copy_1", " ")] = ("back", "1", "L") classic[("copy_0", " ")] = ("back", "0", "L") for sym in ["0", "1", " "]: classic[("back", sym)] = ("back", sym, "L") for sym, target in [("X", "1"), ("Y", "0")]: classic[("back", sym)] = ("want_copy", target, "R") classic[("want_copy", " ")] = ("accept", " ", "R") tm_classic = TuringMachine( transition_function=classic, start_state="want_copy", accept_state="accept", reject_state="reject", ) final_state, final_tape = tm_classic.run(tape_input) print("Final State (Classic):", final_state) final_tape_str = "".join(final_tape).strip() print("Final Tape (Classic):", final_tape_str) # for now it will copy with a blank in between. so 00110 → 00110 00110, not 0011000110. but it works. and the other one works too. so that's good enough for now. left_shift_1: TransitionFunction = {} left_shift_1[("want_copy", "1")] = ("copy_1", " ", "L") left_shift_1[("want_copy", "0")] = ("copy_0", " ", "L") left_shift_1[("want_copy", " ")] = ("accept", " ", "R") for sym, target in [("copy_0", "0"), ("copy_1", "1")]: # override for now, i can make a wrapping one but i wont left_shift_1[(sym, "1")] = ("going_balls", target, "R") left_shift_1[(sym, "0")] = ("going_balls", target, "R") left_shift_1[(sym, " ")] = ("going_balls", target, "R") left_shift_1[("going_balls", " ")] = ("want_copy", " ", "R") left_shift_machine = TuringMachine( transition_function=left_shift_1, start_state="want_copy", accept_state="accept", reject_state="reject", ) left_shift_input = "101010" left_shift_final_state, left_shift_final_tape = left_shift_machine.run( left_shift_input, head=1 ) print("Final State (Left Shift):", left_shift_final_state) left_shift_final_tape_str = "".join(left_shift_final_tape).strip() print("Final Tape (Left Shift):", left_shift_final_tape_str)