Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sml 使用相互递归求解组合博弈_Sml_Combinatorics_Game Theory - Fatal编程技术网

Sml 使用相互递归求解组合博弈

Sml 使用相互递归求解组合博弈,sml,combinatorics,game-theory,Sml,Combinatorics,Game Theory,这是一场典型的不偏不倚的比赛。两名玩家轮流拾取标记为1到n的棍子,只要拾取了1号棍子,游戏就结束了。规则很简单:PlayerA倒计时到5,然后选择相应的棍子;普拉耶拉数到2,然后拿起相应的棍子。程序试图找到一个初始点,以便最后拾取1号杆 我试图在列表上循环,找出哪个初始位置会给出令人满意的结果,但返回的值似乎不正确。代码有什么问题 fun play(stick) = let val stick_list = n_list(stick) (*n_list(8) will ge

这是一场典型的不偏不倚的比赛。两名玩家轮流拾取标记为1到n的棍子,只要拾取了1号棍子,游戏就结束了。规则很简单:PlayerA倒计时到5,然后选择相应的棍子;普拉耶拉数到2,然后拿起相应的棍子。程序试图找到一个初始点,以便最后拾取1号杆

我试图在列表上循环,找出哪个初始位置会给出令人满意的结果,但返回的值似乎不正确。代码有什么问题

fun play(stick) = 
let 
    val stick_list = n_list(stick) 
    (*n_list(8) will generate an int list [1,2,3,4,5,6,7,8]*)

    fun playerA(x::nil, n) = x
      | playerA(stick_list, n) = 
            let 
                val pos = (n + (5 mod size(stick_list))) mod size(stick_list)
            in
                playerB(delete(stick_list, pos), pos)
            end
    and playerB(x::nil, n) = x
      | playerB(stick_list, n) = 
            let 
                val pos = (n + (~2 mod size(stick_list))) mod size(stick_list)
            in
                playerA(delete(stick_list, pos), pos)
            end
    fun search(n) = if playerA(stick_list, n - 1) = 1 then n + 1 else search(n - 1)
in
    search(stick - 1)
end;

以下是一些建议:

n_list很容易实现为list.tablate stick,fn i=>i+1。 在处理列表时使用长度而不是大小。 考虑记住剩下的棍子数,这样就不需要重新计算长度。例如

fun play nSticks = 
    let val allSticks = List.tabulate (nSticks, fn i => i + 1)

        fun playerA ([stick], _, n) = stick
          | playerA (sticks, sticksLeft, n) =
            let val pos = (n + (5 mod sticksLeft)) mod sticksLeft
            in
              playerB (delete (sticks, pos), sticksLeft - 1, pos)
            end
        ...
除非这是一个相互递归的练习,否则如果您将两个玩家函数合并为一个,您似乎可以避免多次重复,例如

datatype Player = PlayerA | PlayerB
fun player (_, stick::_, 0) = stick
  | player (player, sticks, sticksLeft, pos) = ...
    let val (newPos, otherPlayer) =
            case player of
                PlayerA => ((n + 5) mod sticksLeft, PlayerB)
              | PlayerB => ((sticksLeft + n - 2) mod sticksLeft, PlayerA)
        val newSticks = delete (sticks, pos)
    in player (otherPlayer, newSticks, sticksLeft - 1, newPos) end

但这不是真正的问题。我想你的意思是,这不是问题的主要症结所在。您需要能够解释代码的实际错误,而不是无法获得预期的反馈。有了它,您不仅能够以简洁的方式表达代码中的错误,您的测试的读者将确切地知道预期的结果,而且编写测试的过程将让您洞察可能出现的错误。