球拍 - >蟒蛇

时间:2017-07-18 03:16:16

标签: python recursion tree racket mutual-recursion

我开始学习球拍,我正在使用任意的arity树和生成递归来从给定的板上获得每个可能版本的板。

所以让我说我有这个板,其中false表示空:

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

根据要求的解决方案是:

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

球拍的解决方案效果很好。我在Python中尝试过相同的东西,但它并没有像预期的那样工作。

我不断获得这样的输出:

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

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

或更糟。

我似乎无法让它给我想要的输出。

我想在输出上做一些后处理,如果没有其他工作,但我想避免这种情况。

我需要的是:

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

无论如何,请告诉我您是否可以提供帮助。

这是我的python代码:

"""
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",
    ],
]

1 个答案:

答案 0 :(得分:0)

这看起来像是一种混乱的混乱。我没有测试过这个,但我打赌你的问题出现在这里:

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

我猜你想要

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

......而不是。

但是:Python列表不是链表。 cons是一种向Racket中的列表添加元素的有效且合理的方法,但是在单元素列表和更长列表上使用Python的+运算符形成列表将需要复制以后的所有元素清单。

对于简短列表(小于,例如,10K元素或列表的列表上的线性操作 对小于100个元素的列表进行二次运算,这没关系。 对于较长的,它会。 Python人会告诉你,你做错了,你应该在现有数组上使用变异。然后,球拍人员会告​​诉你Python人员过去了。欢迎来到精彩的编程世界!