簡體   English   中英

圖靈機Euclid算法找到最大公約數python

[英]Turing Machine Euclid's Algorithm for finding greatest common divisor python

我的代碼位於底部:(如果某人有足夠的耐心閱讀所有內容,我會感到非常驚訝)

輸出的數字不正確,但是我不知道為什么。 我已經遵循了算法。 輸入必須是2個一元數,例如2和6 =>01101111110。如果有更簡單的方法來編碼此算法,請告訴我。 這是算法(摘自Roger Penrose的《皇帝的新思維》一書)

在此處輸入圖片說明

我的代碼是:

x = input("Dos numeros en sistema unario separado por un 0: ")
x = list(x)
pos = 0
valorMaq = 0
while (True):
    if valorMaq==0 and x[pos]=='0':
        valorMaq=0
        x[pos]='0'
        pos=pos+1
        print(x)

    elif valorMaq==0 and x[pos]=='1':
        valorMaq=11
        x[pos]='0'
        pos=pos-1
        print(x)

    elif valorMaq==1 and x[pos]=='0':
        valorMaq=10
        x[pos]='1'
        pos=pos+1
        print(x)

    elif valorMaq==1 and x[pos]=='1':
        valorMaq=1
        x[pos]='1'
        pos=pos-1
        print(x)
############################################
    elif valorMaq==10 and x[pos]=='0':
        valorMaq=1010
        x[pos]='0'
        pos=pos+1
        print(x)

    elif valorMaq==10 and x[pos]=='1':
        valorMaq=11
        x[pos]='0'
        pos=pos+1
        print(x)

    elif valorMaq==11 and x[pos]=='0':
        valorMaq=100
        x[pos]='0'
        pos=pos+1
        print(x)

    elif valorMaq==11 and x[pos]=='1':
        valorMaq=11
        x[pos]='1'
        pos=pos+1
        print(x)
#############################################
    elif valorMaq==100 and x[pos]=='0':
        valorMaq=100
        x[pos]='0'
        pos=pos+1
        print(x)

    elif valorMaq==100 and x[pos]=='1':
        valorMaq=101
        x[pos]='0'
        pos=pos+1
        print(x)

    elif valorMaq==101 and x[pos]=='0':
        valorMaq=111
        x[pos]='0'
        pos=pos-1
        print(x)

    elif valorMaq==101 and x[pos]=='1':
        valorMaq=110
        x[pos]='1'
        pos=pos-1
        print(x)

    elif valorMaq==110 and x[pos]=='0':
        valorMaq=110
        x[pos]='0'
        pos=pos-1
        print(x)

    elif valorMaq==110 and x[pos]=='1':
        valorMaq=1
        x[pos]='1'
        pos=pos-1
        print(x)

    elif valorMaq==111 and x[pos]=='0':
        valorMaq=111
        x[pos]='0'
        pos=pos-1
        print(x)

    elif valorMaq==111 and x[pos]=='1':
        valorMaq=1000
        x[pos]='1'
        pos=pos-1
        print(x)
################################################
    elif valorMaq==1000 and x[pos]=='0':
        valorMaq=1001
        x[pos]='0'
        pos=pos-1
        print(x)

    elif valorMaq==1000 and x[pos]=='1':
        valorMaq=1000
        x[pos]='1'
        pos=pos-1

    elif valorMaq==1001 and x[pos]=='0':
        valorMaq=10
        x[pos]='0'
        pos=pos+1
        print(x)

    elif valorMaq==1001 and x[pos]=='1':
        valorMaq=1
        x[pos]='1'
        pos=pos-1
        print(x)

    elif valorMaq==1010 and x[pos]=='1':
        valorMaq=1010
        x[pos]='1'
        pos=pos+1
        print(x)

    elif valorMaq==1010 and x[pos]=='0':
        valorMaq=0
        x[pos]='0'
        pos=pos+1
        break
        print(x)

x = ''.join(x)
print("Maximo comun divisor: ", x)

盡管您寫了什么,但我確實查看了代碼的每一行。

您對第二條規則的實現不正確。 彭羅斯(Penrose)具有0 1 →1 1 L,但您已將其編程為0 1 →11 0L 。因此,將第12至16行更改為

elif valorMaq==0 and x[pos]=='1':
    valorMaq=1
    x[pos]='1'
    pos=pos-1
    print(x)

那是唯一錯誤的規則。 但是,您沒有考慮圖靈機的重要概念:它可能是無限的,並且每當讀取頭從當前定義的磁帶移開時,都會自動將空白單元添加到磁帶的任一端。 您可以通過在更改pos每個代碼段中添加更多行來實現這一點。

但是,我建議您對代碼進行徹底的更改。 您使代碼變得比原本需要的困難。 例如,您可以使用制表符進行縮進,但這在Python中並不是一個好主意-每個縮進級別都使用4個空格。

另外,您有很多重復的代碼,這違反了DRY( 請勿重復自己的原理。用諸如字典等數據結構表示規則來替換算法,並編寫一個使用輸入和該結構的小型引擎來例如, rules[(0, '0')]可以是表示停留在零狀態的元組(0, '0', +1) ,向當前位置寫入一個'0'字符,並將1加到當前位置(即向右移動一個單元格),第二個產生式將狀態1,字符“ 1”的rules[(0, '1')]設為(1, '1', -1) ,然后向左移動STOP動作可以用機器永遠不會移動的東西來表示,例如None(無),這樣的代碼將更容易理解和調試。

這是一些執行此操作的代碼。 我還改進了打印輸出,以顯示磁帶中的當前狀態和位置,並刪除了您的要求,即輸入的兩端必須有一個額外的'0'字符。 我還使代碼更加靈活,可擴展和可測試。 我相信很清楚如何將規則轉換為彭羅斯(Penrose)將其顯示為規則字典中使用的格式,盡管為了方便和空間,我使用十進制數字而非彭羅斯(Penrose)的二進制數字。 此代碼中沒有錯誤檢查。 我用成對的數字(每組從1到50)進行了測試,它始終以一進制格式給出正確的最大公約數。 彭羅斯(Penrose)的算法非常聰明-我從來沒有想過這種算法,它不使用任何額外的字符。

"""Calculate the greatest common divisor of two unary numbers using
Penrose's algorithm for a Turing machine.

Suggested by <https://stackoverflow.com/questions/44467401/turing-
machine-euclids-algorithm-for-finding-greatest-common-divisor-python>
which itself uses Roger Penrose's *The Emperor's New Mind*, Oxford
University Press 1989 (paperback) p.41, the algorithm called EUC.

No error checking is done to the rules dictionary or the input line
that the correct format is followed.

Possible changes:
    1.  Enforce Penrose's requirement that the ending position is to
        the right of the answer (perhaps with blanks between the answer
        and the position).
        a.  Perhaps return ''.join(tape[:pos]).strip(BLANK) which
            removes anything at and right of the ending position.
        b.  Perhaps check that only blanks are at and right of the
            ending position.
"""

# Constants for magic numbers
BLANK = '0'  # blank character
STOP = None  # code to end the calcuation
STATEWIDTH = 3  # number of spaces to print current state in

# A rules dictionary, each entry in the format
#   (oldstate, currentcharacter): (newstate, newcharacter, move_or_stop)
EUC = {
    ( 0, '0'): ( 0, '0', +1),    ( 0, '1'): ( 1, '1', -1),  # state  0 =    0
    ( 1, '0'): ( 2, '1', +1),    ( 1, '1'): ( 1, '1', -1),  # state  1 =    1
    ( 2, '0'): (10, '0', +1),    ( 2, '1'): ( 3, '0', +1),  # state  2 =   10
    ( 3, '0'): ( 4, '0', +1),    ( 3, '1'): ( 3, '1', +1),  # state  3 =   11
    ( 4, '0'): ( 4, '0', +1),    ( 4, '1'): ( 5, '0', +1),  # state  4 =  100
    ( 5, '0'): ( 7, '0', -1),    ( 5, '1'): ( 6, '1', -1),  # state  5 =  101
    ( 6, '0'): ( 6, '0', -1),    ( 6, '1'): ( 1, '1', -1),  # state  6 =  110
    ( 7, '0'): ( 7, '0', -1),    ( 7, '1'): ( 8, '1', -1),  # state  7 =  111
    ( 8, '0'): ( 9, '0', -1),    ( 8, '1'): ( 8, '1', -1),  # state  8 = 1000
    ( 9, '0'): ( 2, '0', +1),    ( 9, '1'): ( 1, '1', -1),  # state  9 = 1001
    (10, '0'): ( 0, '0', STOP),  (10, '1'): (10, '1', +1),  # state 10 = 1010
}

def print_situation(state, tape, pos, printlines):
    if printlines:
        print(str(state).rjust(STATEWIDTH), ''.join(tape))
        print(''.rjust(STATEWIDTH), '^'.rjust(pos + 1))

def turing_machine(inputline, rules, printlines=True):
    tape = list(inputline)
    state = 0
    pos = 0
    print_situation(state, tape, pos, printlines)
    move = 1  # something other than STOP
    while move != STOP:
        # Do the next action
        state, tape[pos], move = rules[(state, tape[pos])]
        if move != STOP:
            pos += move
        else:
            pos += 1  # Penrose says all stops move right once
        # Add any needed blank characters to an end of the tape
        while pos < 0:
            tape.insert(0, BLANK)
            pos += 1  # pos is relative to left end of tape, so adjust both
        while pos >= len(tape):
            tape.append(BLANK)  # left end not changed so pos not adjusted
        # Print current situation
        print_situation(state, tape, pos, printlines)
    return ''.join(tape).strip(BLANK)

print(turing_machine(
        input("Enter two unary numbers separated by a '0': "), EUC))

當我輸入2和6的代碼時, 110111111 ,返回的結果是11 ,這是2的一元代碼,整個打印輸出是:

  0 110111111
    ^
  1 0110111111
    ^
  2 1110111111
     ^
  3 1010111111
      ^
  3 1010111111
       ^
  4 1010111111
        ^
  5 1010011111
         ^
  6 1010011111
        ^
  6 1010011111
       ^
  6 1010011111
      ^
  1 1010011111
     ^
  2 1110011111
      ^
  3 1100011111
       ^
  4 1100011111
        ^
  4 1100011111
         ^
  5 1100001111
          ^
  6 1100001111
         ^
  6 1100001111
        ^
  6 1100001111
       ^
  6 1100001111
      ^
  6 1100001111
     ^
  1 1100001111
    ^
  1 01100001111
    ^
  2 11100001111
     ^
  3 10100001111
      ^
  3 10100001111
       ^
  4 10100001111
        ^
  4 10100001111
         ^
  4 10100001111
          ^
  4 10100001111
           ^
  5 10100000111
            ^
  6 10100000111
           ^
  6 10100000111
          ^
  6 10100000111
         ^
  6 10100000111
        ^
  6 10100000111
       ^
  6 10100000111
      ^
  1 10100000111
     ^
  2 11100000111
      ^
  3 11000000111
       ^
  4 11000000111
        ^
  4 11000000111
         ^
  4 11000000111
          ^
  4 11000000111
           ^
  4 11000000111
            ^
  5 11000000011
             ^
  6 11000000011
            ^
  6 11000000011
           ^
  6 11000000011
          ^
  6 11000000011
         ^
  6 11000000011
        ^
  6 11000000011
       ^
  6 11000000011
      ^
  6 11000000011
     ^
  1 11000000011
    ^
  1 011000000011
    ^
  2 111000000011
     ^
  3 101000000011
      ^
  3 101000000011
       ^
  4 101000000011
        ^
  4 101000000011
         ^
  4 101000000011
          ^
  4 101000000011
           ^
  4 101000000011
            ^
  4 101000000011
             ^
  4 101000000011
              ^
  5 101000000001
               ^
  6 101000000001
              ^
  6 101000000001
             ^
  6 101000000001
            ^
  6 101000000001
           ^
  6 101000000001
          ^
  6 101000000001
         ^
  6 101000000001
        ^
  6 101000000001
       ^
  6 101000000001
      ^
  1 101000000001
     ^
  2 111000000001
      ^
  3 110000000001
       ^
  4 110000000001
        ^
  4 110000000001
         ^
  4 110000000001
          ^
  4 110000000001
           ^
  4 110000000001
            ^
  4 110000000001
             ^
  4 110000000001
              ^
  4 110000000001
               ^
  5 1100000000000
                ^
  7 1100000000000
               ^
  7 1100000000000
              ^
  7 1100000000000
             ^
  7 1100000000000
            ^
  7 1100000000000
           ^
  7 1100000000000
          ^
  7 1100000000000
         ^
  7 1100000000000
        ^
  7 1100000000000
       ^
  7 1100000000000
      ^
  7 1100000000000
     ^
  8 1100000000000
    ^
  8 01100000000000
    ^
  9 001100000000000
    ^
  2 001100000000000
     ^
 10 001100000000000
      ^
 10 001100000000000
       ^
 10 001100000000000
        ^
  0 001100000000000
         ^
11

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM