2017-07-18 3 views
0

Ich fing an, Schläger zu lernen, und ich benutze arbiträre Arity-Bäume und generative Rekursion, um alle möglichen Versionen des Boards von einem bestimmten Board zu bekommen.Schläger -> Python

Also lassen Sie uns sagen, dass ich dieses Board haben, wo falsch bedeutet leer:

(list "X" "X" "O" "O" "X" "O" "X" #false "X") 

Die Lösung für diese entsprechend den Anforderungen sein würde:

(list 
(list "X" "X" "O" "O" "X" "O" "X" "X" "X") 
(list "X" "X" "O" "O" "X" "O" "X" "O" "X")) 

Die Lösung in Schläger funktioniert gut. Ich habe das gleiche in Python versucht, aber es funktioniert nicht ganz wie erwartet.

Ich bekomme ständig Ausgänge wie diese:

[['X', 'X', 'O', 'O', 'X', 'O', 'X', 'X', 'X'], [['X', 'X', 'O', 'O', 'X', 'O', 'X', 'O', 'X'], []]] 

oder

['X', 'X', 'O', 'O', 'X', 'O', 'X', 'X', 'X', 'X', 'X', 'O', 'O', 'X', 'O', 'X', 'O', 'X'] 

oder schlechter.

Ich kann es nicht scheinen, um mir die Ausgabe zu geben, die ich will.

Ich dachte an eine Nachbearbeitung der Ausgabe, wenn nichts anderes funktioniert, aber das würde ich gerne vermeiden.

Was ich brauche, ist dies:

[['X', 'X', 'O', 'O', 'X', 'O', 'X', 'X', 'X'], ['X', 'X', 'O', 'O', 'X', 'O', 'X', 'O', 'X']] 

Auf jeden Fall lassen Sie mich wissen, wenn Sie helfen können.

Hier ist mein Python-Code:

""" 
Brute force solution for tic-tac-toe. 
""" 


""" 
Data definitions: 

;; Value is one of: 
;; - false 
;; - "X" 
;; - "O" 
;; interp. a square is either empty (represented by false) or has and "X" or an "O" 


;; Board is (listof Value) 
;; a board is a list of 9 Values 

""" 

# 
## CONSTANTS 
# 
B0 = [False for i in range(9)] 
B1 = [ 
    False, "X", "O", 
    "O", "X", "O", 
    False, False, "X" 
] 
B2 = [ 
     "X", "X", "O", 
     "O", "X", "O", 
     "X", False, "X", 
     ] 

B3 = [ 
     "X", "O", "X", 
     "O", "O", False, 
     "X", "X", False, 
] 


""" 
PROBLEM 1 

In this problem we want you to design a function that produces all 
possible filled boards that are reachable from the current board. 

In actual tic-tac-toe, O and X alternate playing. For this problem 
you can disregard that. You can also assume that the players keep 
placing Xs and Os after someone has won. This means that boards that 
are completely filled with X, for example, are valid. 

""" 


def fill_board(index, bd): 
    """ 
    Returns a list of 2 board versions with 
    the index filled with "X" and "O" 

    :param index: int; index of position in list to be filled 
    :param bd: Board 
    :return: (listof Board) 
    """ 
    return [ 
     bd[:index] + ["X"] + bd[index+1:], 
     bd[:index] + ["O"] + bd[index + 1:], 
    ] 


assert fill_board(0, B1) == [ 
    [ 
    "X", "X", "O", 
    "O", "X", "O", 
    False, False, "X" 
    ], 
    [ 
    "O", "X", "O", 
    "O", "X", "O", 
    False, False, "X" 
    ], 
] 

assert fill_board(5, B3) == [ 
[ 
     "X", "O", "X", 
     "O", "O", "X", 
     "X", "X", False, 
], 
[ 
     "X", "O", "X", 
     "O", "O", "O", 
     "X", "X", False, 
], 
] 


def find_blank(bd): 
    """ 
    Return the index of the 
    first empty (False) value 
    in the board. 
    ASSUME: there is at least one 
    empty cell. 

    :param bd: Board 
    :return: Index 
    """ 
    return bd.index(False) 

assert find_blank(B0) == 0 
assert find_blank(B2) == 7 
assert find_blank(B3) == 5 


def next_boards(bd): 
    """ 
    Produce the next version of initial board. 
    Finds the first empty (False) cell, and produces 
    2 versions of the board; one with X and one with O 
    :param bd: Board 
    :return: (listof Board) 
    """ 

    return fill_board(find_blank(bd), bd) 


assert next_boards(B0) == [ 
    ["X"] + B0[1:], 
    ["O"] + B0[1:], 
] 


assert next_boards(B3) == [ 
[ 
     "X", "O", "X", 
     "O", "O", "X", 
     "X", "X", False, 
], 
[ 
     "X", "O", "X", 
     "O", "O", "O", 
     "X", "X", False, 
], 
] 


def solve(bd): 
    """ 
    Produce all possible filled boards that are 
    reachable from the current board. 

    :param bd: Board (listof Value) 
    :return: (listof Board) 
    """ 
    def is_full(bd): 
     """ 
     Returns true if board is full; meaning 
     if every value on the board is a string. 

     :param bd: Board (listof Value) 
     :return: Boolean 
     """ 
     return all(type(i) is str for i in bd) 

    def solve__bd(bd): 
     """ 
     Mutually refential function with 
     solve__lobd. This is where all the actual 
     computation takes place. 
     The two functions are responsible for 
     generating and operating on the tree. 
     The tree (arbitraty arity tree) represents 
     another version of the board filled with an 
     additional X or O. 

     :param bd: Board (listof Value) 
     :return: (listof Board) 
     """ 

     if is_full(bd): 
      return list(bd) 

     return solve__lobd(next_boards(bd)) 

    def solve__lobd(lobd): 
     """ 
     Helper function of solve, alongside solve__bd 
     :param lobd: (listof Board) 
     :return:  (listof Board) 
     """ 

     if not lobd: 
      return [] 

     return [solve__bd(lobd[0]), solve__lobd(lobd[1:])] 

    return solve__bd(bd) 


assert solve(B2) == [ 
    [ 
     "X", "X", "O", 
     "O", "X", "O", 
     "X", "X", "X", 
     ], 
    [ 
     "X", "X", "O", 
     "O", "X", "O", 
     "X", "O", "X", 
     ], 
] 


assert solve(B3) == [ 
    [ 
     "X", "O", "X", 
     "O", "O", "X", 
     "X", "X", "X", 
    ], 
    [ 
     "X", "O", "X", 
     "O", "O", "X", 
     "X", "X", "O", 
    ], 
    [ 
     "X", "O", "X", 
     "O", "O", "O", 
     "X", "X", "X", 
    ], 
    [ 
     "X", "O", "X", 
     "O", "O", "O", 
     "X", "X", "O", 
    ], 
] 
+0

Tun Sie einfach z. B. [B1, B2] – perigon

Antwort

0

Das sieht wie eine Wider-Verwirrung. Ich habe nicht getestet, aber ich wette, dass Ihr Problem stellt sich hier:

return [solve__bd(lobd[0]), solve__lobd(lobd[1:])] 

Ich vermute, Sie

wollen
return [solve__bd(lobd[0])] + solve__lobd(lobd[1:])] 

... statt.

ABER: Python-Listen sind keine verketteten Listen. cons ist eine effiziente und sinnvolle Möglichkeit, ein Element zu einer Liste in Racket hinzuzufügen, aber das Erstellen einer Liste mit Pythons +-Operator in einer Liste mit einem Element und einer längeren Liste erfordert das Kopieren aller späteren Elemente der Liste.

Für kurze Listen (lineare Operationen auf Listen von weniger als sagen wir 10K Elemente oder quadratische Operationen auf Listen von weniger als 100 Elementen oder so), spielt es keine Rolle. Für längere wird es. Python-Leute werden Ihnen sagen, dass Sie es falsch machen, dass Sie Mutationen für bestehende Arrays verwenden sollten. Racket-Leute werden dir dann erzählen, dass die Python-Leute in der Vergangenheit stecken geblieben sind. Willkommen in der wunderbaren Welt des Programmierens!

+0

Vielen Dank, dass Sie sich die Zeit genommen haben, @John Clements zu beantworten! Ihre Lösung funktionierte für Lösung (B2), aber Lösung (B3) schlägt immer noch fehl.Ich änderte die Zeile auf Ihren Vorschlag zu: return [solve__bd (lobd [0])] + solve__lobd (lobd [1:]), aber die Ausgabe, die ich für B3 bekomme, ist mit 3 Listen wie folgt begraben: [[['X , O, X, O, O, X, X, X, X, X, O, X, O ',' O ',' X ',' X ',' X ',' O ']], [' 'X', 'O', 'X', 'O', 'O', 'O', X, X, X, X, O, X, O, O, O, X, X, O ]]. Ich denke, dass die Portierung der Racket-Lösung auf Python nicht ausreicht, aber ich habe keine einfachere Lösung für dieses Problem gefunden. – bjj