Heutige Computer verbringen ja teilweise wirklich Wunderwerke. Sie rendern Filme, wie der neue Film König der Löwen , lassen uns in realistische 3D Spielewelten eintauchen, lenken Autos, erkennen Krankheiten und ermöglichen uns globale Kommunikation. Doch hinter all dem steckt jeweils immer eine CPU, also eine zentrale datenverarbeitende Steuerelektronik.
Trotz der Komplexität, die diese beherrschen, basieren alle Operationen der CPU lediglich auf simple Manipulationen von Registern in Abhängigkeit von dem aktuellen Zustand. Erst die intelligente Aneinandereihung dieser simplen Operationen gibt dem Ganzen die nötige Komplexität. Diese Operationen müssen nicht zwingend elektrisch realisiert werden, wie in einer CPU. Sie können durchaus auch in anderer Form analog realisiert werden. Zum Beispiel gibt es die mechanische Form der Turing Maschine.
Beim Stöbern im Internet nach mechanischen Turing Maschinen, bin ich auf das Kickstarter Projekt Turing Tumble gestossen. Es bietet einen analogen Computer als Kugelbahn an. Da die Kinder sowieso viel vor ihren Tablets sitzen, Mobilgeräte ja prinzipiell böse sind und wir als Eltern auch nicht gerade mit gutem Beispiel vorran gehen, habe ich uns diese Maschine gekauft, in der Hoffnung den Kindern ein wenig die Grundlage von Computern anhand dieser Kugelbahnmaschine visuell näher bringen zu können.
Die Maschine besteht dabei aus einem Brett mit elf herausragenden Stäbchen in einer Reihe und davon gibt es wiederrum elf Reihen untereinander. An jedes zweite Stäbchen kann eines der folgenden Operatoren gesteckt werden und bilden damit die Worte des analogen Computers. Von oben können jeweils von links oder von rechts eine Kugel in das Brett fallen und je nach Operatorenanordnung das Brett bis zum unteren Ende passieren. Dort gelangen sie je nach der auftreffenden Seite auf einen Hebel. Dieser Hebel lässt beim Betätigen wieder eine Kugel abhängig von seiner Seite von oben herabkullern. Dies geht so lange, bis keine neue Kugel mehr von oben einen der zwei Hebel betätigt oder es keine Kugel mehr oben gibt. Die Kugel kann man mit einem Stromfluss vergleichen.
Der einfachste Operator ist die Rampe. Fällt eine Kugel von oben hinein, so wird sie je nach Einbaurichtung nach links oder rechts weitergeleitet. Dies kann man analog mit einem Stromleiter, wie einen Drahtleitung vergleichen
Dieser Operator ist eine Kreuzung. So könne zwei Leitungen gekreuzt werden. Fällt eine Kugel von links oben hinein, so verlässt sie diese wieder nach rechts unten. Kommt sie von rechts oben, so verlässt die Kugel nach links unten die Kreuzung.
Das Bit ist ein Operator, der eine Ausrichtung hat. Diese wird mit einem Pfeil, je nach Ausrichtung nach links oder nach rechts angezeigt.Zeigt der Pfeil nach links, so läuft die nächste vorbeirollende Kugel unabhängig, von wo sie von oben herkommt nach rechts unten weiter. Ist der Pfeil nach rechts ausgerichtet, so läuft die nächste Kugel nach links unten weiter. Nach jedem Kugeldruchlauf ändert der Bit Operator seine Pfeilrichtung. Die Pfeilrichtung des Bits nennt man auch Zustand.
Damit ein ablaufendes Programm gestoppt werden kann, gibt es den Stopper. Dieser fängt ganz einfach die herabrollende Kugel auf und es kann keine weitere mehr mit den Hebeln aktiviert werden.
Ähnlich dem Bit Operator gibt es diesen noch in der Form mit einem Zahnrad darauf, das Zanradbit. Die Funktionalität entspricht genu der des Bit Operators. Zusätzlich kann aber ein Zahnrad damit angetrieben (siehe unten) werden. Über das Zahnrad kann wieder ein weiteres Zahnradbit angesteuert werden. Damit ist es möglich den Zustand eines Zahnradbits an einer anderen Stellen, wo die Kugel gerade nicht vorbeirollt zu verändern. Mit dieser Konstruktion können sogenannte „Wenn … Dann…“-Operationen (Fallunterscheidungen) realisierte werden, die im Computer Bereich sehr wichtig sind.
Mit dem Zahnrad Operator können weitere Zahnräder oder Zahnradbits verbunden werden. Somit können Zustände über weite Entfernungen auf dem Brett verändert werden.
Einige Beispiele, wie man nun damit Funktionen einer CPU beschreiben kann sind in einem Educator Guide beschrieben. Um mit diesem System etwas spielen zu können, ist es nicht notwendig sich eines anzuschaffen. Im Internet findet man zahlreiche Simulatoren dafür, die auch im Browser laufen. Unten haben ich einen eigenen simplen Turing Tumble Simulator in Python geschrieben, damit ich etwas in diese Skriptsprache hineinkomme.
#!/usr/bin/python3 #------------------------------------------------------------------------------ # Python 3.4.3 #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ # includes #------------------------------------------------------------------------------ import os import sys #------------------------------------------------------------------------------ # definitions #------------------------------------------------------------------------------ lineLength = 11 lineCnt = 11 sign_non = '.' sign_space = 'o' sign_rampL = 'L' sign_rampR = 'R' sign_crossover = 'X' sign_bitL = '<' sign_bitR = '>' sign_interceptor = '-' sign_gear = '*' sign_gearBitL = '(' sign_gearBitR = ')' #------------------------------------------------------------------------------ # classes #------------------------------------------------------------------------------ class Ball : ballOldPosX = 0 ballOldPosY = 0 ballActPosX = 0 ballActPosY = 0 ballColor = 'b' def __init__(self,x,y,comesFrom = 'r',ballColor = 'b') : self.setNewPos(x,y) self.ballColor = ballColor if comesFrom == 'r' : self.ballOldPosX = lineLength def setNewPos(self,x,y) : self.ballOldPosX = self.ballActPosX self.ballOldPosY = self.ballActPosY self.ballActPosX = x self.ballActPosY = y def nextD(self) : self.setNewPos(self.ballActPosX,self.ballActPosY+1) def nextLD(self) : self.setNewPos(self.ballActPosX-1,self.ballActPosY+1) def nextRD(self) : self.setNewPos(self.ballActPosX+1,self.ballActPosY+1) def wasL(self) : if self.ballOldPosX < self.ballActPosX : return True else : return False def isSame(self,ballPos) : if self.ballActPosX == ballPos.ballActPosX : if self.ballActPosY == ballPos.ballActPosY : return True return False def printIt(self) : print("X:",self.ballActPosX," Y:",self.ballActPosY) def printItAll(self) : print("Xa:",self.ballActPosX," Ya:",self.ballActPosY) print("Xo:",self.ballOldPosX," Yo:",self.ballOldPosY) if True == self.wasL() : print("from left") else : print("from right") print("color ",self.ballColor) def getX(self) : return self.ballActPosX def getY(self) : return self.ballActPosY def getColor(self) : return self.ballColor #------------------------------------------------------------------------------ class ConnectedGears : gearList = [] def __init__(self,gearList) : self.gearList = gearList def getGearList(self) : return self.gearList #------------------------------------------------------------------------------ # functions #------------------------------------------------------------------------------ def getFilenameParameter() : datName = "" numBalls = 1 if len(sys.argv) > 1 : datName = sys.argv[1] if len(sys.argv) > 2 : numBalls = int(sys.argv[2]) if len(sys.argv) == 1 : print("Usage:", sys.argv[0], " <PlayGround Filename> [<number Balls>]"); printPlayground() print() print("Non\t\t",sign_non) print("Space\t\t",sign_space) print("Ramp Left\t",sign_rampL) print("Ramp Right\t",sign_rampR) print("Crossover\t",sign_crossover) print("Bit Left\t",sign_bitL) print("Bit Right\t",sign_bitR) print("Interceptor\t",sign_interceptor) print("Gear\t\t",sign_gear) print("Gear Bit Left\t",sign_gearBitL) print("Gear Bit Right\t",sign_gearBitR) exit() return (datName,numBalls) #------------------------------------------------------------------------------ def loadPlayGround(playgroundName) : if os.path.isfile(playgroundName) == False : print("File:", playgroundName, " doesnt exist"); exit() fnDatei = open(playgroundName,"r") playliste = [] for line in fnDatei : line = line.strip() if line[0] != '#' : playliste.append(line) fnDatei.close() return playliste #------------------------------------------------------------------------------ def checkSignPosition(actSign,posX,posY) : countPos = posY * lineLength + posX # gears could have all positions if actSign != sign_gear : if actSign == sign_non : if countPos % 2 == 1 : return False return True #------------------------------------------------------------------------------ def printPlayground() : for y in range(lineCnt) : for x in range(lineLength) : countPos = y * lineLength + x if countPos % 2 == 0 : print(sign_non, end = '') else : print(sign_space, end = '') print() #------------------------------------------------------------------------------ def checkPlayGround(playliste) : signs = [ sign_non, sign_space, sign_rampL, sign_rampR, sign_crossover, sign_bitL, sign_bitR, sign_interceptor, sign_gear, sign_gearBitL, sign_gearBitR] for y in range(len(playliste)) : actLine = playliste[y] if lineLength != len(actLine) : print(y," len", len(actLine), "doesnt equal ",lineLength) exit() for x in range(len(actLine)) : actSign = actLine[x] if actSign not in signs : print("sign",actSign,"not in signs") exit() if checkSignPosition(actSign,x,y) == False: print("Wrong Sign Position x",x," y",y) exit() #------------------------------------------------------------------------------ def printPlayGround(playliste) : for x in range(len(playliste)) : print(x,":\t", end = '') for sign in playliste[x] : print(sign, end = '') print() #------------------------------------------------------------------------------ def printPlayGroundWithBall(playliste,playball) : for x in range(len(playliste)) : if x == playball.ballActPosY : print(x,":\t", end = '') for y in range(len(playliste[x])) : if y == playball.ballActPosX : if playball.getColor() == 'b' : print("b", end = '') else : print("r", end = '') else : print(" ", end = '') print() print(x,":\t", end = '') for sign in playliste[x] : print(sign, end = '') print() #------------------------------------------------------------------------------ def printPlayGroundWithBallInside(playliste,playball, lineNr = False) : for y in range(len(playliste)) : if lineNr : print(y,":\t", end = '') line = playliste[y] for x in range(len(line)) : if y == playball.ballActPosY and \ x == playball.ballActPosX : if playball.getColor() == 'b' : print("b", end = '') else : print("r", end = '') else : print(line[x], end = '') print() #------------------------------------------------------------------------------ def getSign(playliste,playball) : actSign = "" if playball.ballActPosY < len(playliste) and 0 <= playball.ballActPosY : line = playliste[playball.ballActPosY] if playball.ballActPosX < len(line) and 0 <= playball.ballActPosX : actSign = line[playball.ballActPosX] return actSign #------------------------------------------------------------------------------ def setSign(playliste,playball, sign) : if playball.ballActPosY < len(playliste) and 0 <= playball.ballActPosY : line = playliste[playball.ballActPosY] if playball.ballActPosX < len(line) and 0 <= playball.ballActPosX : posX = 0 newLine = [] for i in line : if posX == playball.ballActPosX : newLine.append(sign) else : newLine.append(line[posX]) posX = posX + 1 playliste[playball.ballActPosY] = newLine #------------------------------------------------------------------------------ def singleStep(playliste,playball,ConnectedGearsList) : actSign = getSign(playliste,playball) if actSign == sign_non : playball.nextD() elif actSign == sign_space : playball.nextD() elif actSign == sign_rampL : playball.nextLD() elif actSign == sign_rampR : playball.nextRD() elif actSign == sign_crossover : if playball.wasL() : playball.nextRD() else : playball.nextLD() elif actSign == sign_bitL : setSign(playliste,playball,sign_bitR) playball.nextRD() elif actSign == sign_bitR : setSign(playliste,playball,sign_bitL) playball.nextLD() elif actSign == sign_interceptor : return False elif actSign == sign_gear : playball.nextD() elif actSign == sign_gearBitL : gearList = getConnectedGearListInBall(ConnectedGearsList,playball) changePlaylistGears(playliste,gearList) playball.nextRD() elif actSign == sign_gearBitR : gearList = getConnectedGearListInBall(ConnectedGearsList,playball) changePlaylistGears(playliste,gearList) playball.nextLD() else : playball.nextD() return True #------------------------------------------------------------------------------ # gears and gearBits #------------------------------------------------------------------------------ def printBallList(ballList) : for x in range(len(ballList)) : ballList[x].printIt() #------------------------------------------------------------------------------ def isBallInTheList(ballList,ball) : for elemBall in ballList : if elemBall.isSame(ball) : return True return False #------------------------------------------------------------------------------ def connectLists(listeA,ListeB) : nextList = listeA for elemBall in ListeB : nextList.append(elemBall) return nextList #------------------------------------------------------------------------------ def getConnectedGears(playliste,actBallPos,connectedList) : actConnection = [] actSign = getSign(playliste,actBallPos) if False == isBallInTheList(connectedList,actBallPos) : actConnection.append(actBallPos) if sign_gearBitL == actSign or \ sign_gearBitR == actSign or \ sign_gear == actSign : upPos = Ball(actBallPos.getX(),actBallPos.getY()-1) upSign = getSign(playliste,upPos) if sign_gearBitL == upSign or \ sign_gearBitR == upSign or \ sign_gear == upSign : if False == isBallInTheList(connectedList,upPos) : actConnection.append(upPos) downPos = Ball(actBallPos.getX(),actBallPos.getY()+1) downSign = getSign(playliste,downPos) if sign_gearBitL == downSign or \ sign_gearBitR == downSign or \ sign_gear == downSign : if False == isBallInTheList(connectedList,downPos) : actConnection.append(downPos) leftPos = Ball(actBallPos.getX()-1,actBallPos.getY()) leftSign = getSign(playliste,leftPos) if sign_gearBitL == leftSign or \ sign_gearBitR == leftSign or \ sign_gear == leftSign : if False == isBallInTheList(connectedList,leftPos) : actConnection.append(leftPos) rightPos = Ball(actBallPos.getX()+1,actBallPos.getY()) rightSign = getSign(playliste,rightPos) if sign_gearBitL == rightSign or \ sign_gearBitR == rightSign or \ sign_gear == rightSign : if False == isBallInTheList(connectedList,rightPos) : actConnection.append(rightPos) return actConnection #------------------------------------------------------------------------------ def getConnectedGearList(playliste,actBallPos,connectedList) : actConnected = getConnectedGears(playliste,actBallPos,connectedList) connectedList = connectLists(connectedList,actConnected) for elemBall in actConnected : getConnectedGearList(playliste,elemBall,connectedList) return connectedList #------------------------------------------------------------------------------ def isInConnectedGearsList(ConnectedGearsList,playball) : for connGears in ConnectedGearsList : actGearList = connGears.getGearList() if True == isBallInTheList(actGearList,playball) : return True return False #------------------------------------------------------------------------------ def getConnectedGearsList(playliste) : ConnectedGearsList = [] for y in range(len(playliste)) : actLine = playliste[y] for x in range(len(actLine)) : actSign = actLine[x] if sign_gearBitL == actSign or \ sign_gearBitR == actSign or \ sign_gear == actSign : playball = Ball(x,y) if False == isInConnectedGearsList(ConnectedGearsList,playball) : connectedList = getConnectedGearList(playliste,playball,[]) ConnectedGearsList.append(ConnectedGears(connectedList)) return ConnectedGearsList #------------------------------------------------------------------------------ def getConnectedGearListInBall(ConnectedGearsList,playball) : actGearList = [] for connGears in ConnectedGearsList : actGearList = connGears.getGearList() if True == isBallInTheList(actGearList,playball) : return actGearList return actGearList #------------------------------------------------------------------------------ def printGearLists(ConnectedGearsList) : for connGears in ConnectedGearsList : printBallList(connGears.getGearList()) print() #------------------------------------------------------------------------------ def changePlaylistGears(playliste,gearList) : for actBall in gearList : actSign = getSign(playliste,actBall) if actSign == sign_gearBitL : setSign(playliste,actBall,sign_gearBitR) elif actSign == sign_gearBitR : setSign(playliste,actBall,sign_gearBitL) #------------------------------------------------------------------------------ def getLeftBlueBall() : return Ball(3,0,'l','b') #------------------------------------------------------------------------------ def getRightRedBall() : return Ball(7,0,'r','r') #------------------------------------------------------------------------------ def printBallResultList(playBallResults) : for playBall in playBallResults : print(playBall.getColor(),end = '') print() #------------------------------------------------------------------------------ # main #------------------------------------------------------------------------------ def main() : (datName,numBalls) = getFilenameParameter() playliste = loadPlayGround(datName) checkPlayGround(playliste) ConnectedGearsList = getConnectedGearsList(playliste) playBall = getLeftBlueBall() playBallResults = [] for i in range(numBalls) : storeBall = False while playBall.getY() < lineCnt : printPlayGroundWithBallInside(playliste,playBall) if False == singleStep(playliste,playBall,ConnectedGearsList) : print("Stopp",playBall.getColor()) exit() else : storeBall = True print() if storeBall : playBallResults.append(playBall) if playBall.getX() < lineLength/2 : playBall = getLeftBlueBall() else : playBall = getRightRedBall() printBallResultList(playBallResults) print() #------------------------------------------------------------------------------ # start #------------------------------------------------------------------------------ main() #------------------------------------------------------------------------------
Adder 4Bit
Dieses Programm bildet einen 4Bit Addierer. Die vier Bit Pfeile geben die Zahl an, auf die addiert werden soll. Richtung lenks ist null und rechts eins. Die Anzahl der durchlaufenden Kugeln von links oben wird darauf addiert. Anschließend zeigen die Bit Pfeile das Ergebnis an.
.o.<.o.o.o. o.R.R.o.o.o .o.<.L.o.o. o.R.R.o.o.o .o.<.L.o.o. o.R.R.o.o.o .o.<.L.o.o. o.R.R.o.o.o .o.R.L.o.o. o.o.L.o.o.o .o.R.o.o.o.
Mit python playground.py adder.txt 3 wird das Program ausgeführt und am Ende Ergeben die Bit Pfeile eine drei.
Links:
https://github.com/sky4walk/turingTumbleSim
https://www.turingtumble.com/
https://jessecrossen.github.io/ttsim
Klicke, um auf Turing%20Tumble%20Educator%20Guide%201_0.pdf zuzugreifen