用 VB.NET 实现的非确定性计算例子

读 SICP 时,一直对非确定性计算比较感兴趣,今天终于有时间做了一个例子。发现用自动回溯的思想是可以很简单的实现的,呵呵。这个解法的代码还不完备,有很多缺陷,但是基本上可以说明问题了。

所谓的非确定性计算的典型例子是“爱因斯坦谜题”,比如这个:

贝克、库伯、弗莱舍、米勒和斯麦尔住在一个五层公寓楼的不同层,贝克不住在顶层,库伯不住在底层,弗莱舍不住在顶层
也不住在底层。米勒住的比库伯高,斯麦尔不住在弗莱舍相邻的层,弗莱舍不住在库伯相邻的层。请问他们各住在哪层?
(SICP Page 290).
(原书题目叙述有误:“米勒住的比库伯高一层” 应该是 “米勒住的比库伯高“)。

 

(注:开发环境 Visual Studio 2010)

 核心实现:

 

Public Class NonDeterministicEngine

    Private _paramDict As New List(Of Tuple(Of String, IEnumerator))
    'Private _predicateDict As New List(Of Tuple(Of Func(Of Object, Boolean), IEnumerable(Of String)))
    Private _predicateDict As New List(Of Tuple(Of Object, IList(Of String)))


    Public Sub AddParam(ByVal name As String, ByVal values As IEnumerable)
        _paramDict.Add(New Tuple(Of String, IEnumerator)(name, values.GetEnumerator()))
    End Sub

    Public Sub AddRequire(ByVal predicate As Func(Of Object, Boolean), ByVal paramNames As IList(Of String))
        CheckParamCount(1, paramNames)
        _predicateDict.Add(New Tuple(Of Object, IList(Of String))(predicate, paramNames))
    End Sub

    Public Sub AddRequire(ByVal predicate As Func(Of Object, Object, Boolean), ByVal paramNames As IList(Of String))
        CheckParamCount(2, paramNames)
        _predicateDict.Add(New Tuple(Of Object, IList(Of String))(predicate, paramNames))
    End Sub

    Public Sub AddRequire(ByVal predicate As Func(Of Object, Object, Object, Boolean), ByVal paramNames As IList(Of String))
        CheckParamCount(3, paramNames)
        _predicateDict.Add(New Tuple(Of Object, IList(Of String))(predicate, paramNames))
    End Sub

    Public Sub AddRequire(ByVal predicate As Func(Of Object, Object, Object, Object, Boolean), ByVal paramNames As IList(Of String))
        CheckParamCount(4, paramNames)
        _predicateDict.Add(New Tuple(Of Object, IList(Of String))(predicate, paramNames))
    End Sub

    Public Sub AddRequire(ByVal predicate As Func(Of Object, Object, Object, Object, Object, Boolean), ByVal paramNames As IList(Of String))
        CheckParamCount(5, paramNames)
        _predicateDict.Add(New Tuple(Of Object, IList(Of String))(predicate, paramNames))
    End Sub

    Public Sub AddRequire(ByVal predicate As Func(Of Object, Object, Object, Object, Object, Object, Boolean), ByVal paramNames As IList(Of String))
        CheckParamCount(6, paramNames)
        _predicateDict.Add(New Tuple(Of Object, IList(Of String))(predicate, paramNames))
    End Sub

    Public Sub AddRequire(ByVal predicate As Func(Of Object, Object, Object, Object, Object, Object, Object, Boolean), ByVal paramNames As IList(Of String))
        CheckParamCount(7, paramNames)
        _predicateDict.Add(New Tuple(Of Object, IList(Of String))(predicate, paramNames))
    End Sub

    Public Sub AddRequire(ByVal predicate As Func(Of Object, Object, Object, Object, Object, Object, Object, Object, Boolean), ByVal paramNames As IList(Of String))
        CheckParamCount(8, paramNames)
        _predicateDict.Add(New Tuple(Of Object, IList(Of String))(predicate, paramNames))
    End Sub

    Sub CheckParamCount(ByVal count As Integer, ByVal paramNames As IList(Of String))
        If paramNames.Count <> count Then
            Throw New Exception("Parameter count does not match.")
        End If
    End Sub

    Public Property IterationOver As Boolean

    Private _firstTime As Boolean = True

    Public ReadOnly Property Current As Dictionary(Of String, Object)
        Get
            If IterationOver Then
                Return Nothing
            Else
                Dim _nextResult = New Dictionary(Of String, Object)

                For Each item In _paramDict
                    Dim iter = item.Item2
                    _nextResult.Add(item.Item1, iter.Current)
                Next
                Return _nextResult
            End If
        End Get
    End Property

    Function MoveNext() As Boolean
        If IterationOver Then
            Return False
        End If

        If _firstTime Then
            For Each item In _paramDict
                Dim iter = item.Item2
                iter.MoveNext()
            Next

            _firstTime = False
            Return True
        Else
            Dim canMoveNext = False
            Dim iterIndex = _paramDict.Count - 1
            canMoveNext = _paramDict(iterIndex).Item2.MoveNext

            If canMoveNext Then
                Return True
            End If

            Do While Not canMoveNext
                iterIndex = iterIndex - 1
                If iterIndex = -1 Then
                    Return False
                    IterationOver = True
                End If
                canMoveNext = _paramDict(iterIndex).Item2.MoveNext

                If canMoveNext Then
                    For i = iterIndex + 1 To _paramDict.Count - 1
                        Dim iter = _paramDict(i).Item2
                        iter.Reset()
                        iter.MoveNext()
                    Next

                    Return True
                End If
            Loop
        End If
    End Function

    Function GetNextResult() As Dictionary(Of String, Object)
        While MoveNext()
            Dim result = Current
            If Satisfy(result) Then
                Return result
            End If
        End While

        Return Nothing
    End Function

    Function Satisfy(ByVal result As Dictionary(Of String, Object)) As Boolean
        For Each item In _predicateDict
            Dim pred = item.Item1

            Select Case item.Item2.Count
                Case 1
                    Dim p1 = DirectCast(pred, Func(Of Object, Boolean))
                    Dim v1 = result(item.Item2(0))

                    If Not p1(v1) Then
                        Return False
                    End If

                Case 2
                    Dim p2 = DirectCast(pred, Func(Of Object, Object, Boolean))
                    Dim v1 = result(item.Item2(0))
                    Dim v2 = result(item.Item2(1))

                    If Not p2(v1, v2) Then
                        Return False
                    End If

                Case 3
                    Dim p3 = DirectCast(pred, Func(Of Object, Object, Object, Boolean))
                    Dim v1 = result(item.Item2(0))
                    Dim v2 = result(item.Item2(1))
                    Dim v3 = result(item.Item2(2))

                    If Not p3(v1, v2, v3) Then
                        Return False
                    End If

                Case 4
                    Dim p4 = DirectCast(pred, Func(Of Object, Object, Object, Object, Boolean))
                    Dim v1 = result(item.Item2(0))
                    Dim v2 = result(item.Item2(1))
                    Dim v3 = result(item.Item2(2))
                    Dim v4 = result(item.Item2(3))

                    If Not p4(v1, v2, v3, v4) Then
                        Return False
                    End If

                Case 5
                    Dim p5 = DirectCast(pred, Func(Of Object, Object, Object, Object, Object, Boolean))
                    Dim v1 = result(item.Item2(0))
                    Dim v2 = result(item.Item2(1))
                    Dim v3 = result(item.Item2(2))
                    Dim v4 = result(item.Item2(3))
                    Dim v5 = result(item.Item2(4))

                    If Not p5(v1, v2, v3, v4, v5) Then
                        Return False
                    End If

                Case 6
                    Dim p6 = DirectCast(pred, Func(Of Object, Object, Object, Object, Object, Object, Boolean))
                    Dim v1 = result(item.Item2(0))
                    Dim v2 = result(item.Item2(1))
                    Dim v3 = result(item.Item2(2))
                    Dim v4 = result(item.Item2(3))
                    Dim v5 = result(item.Item2(4))
                    Dim v6 = result(item.Item2(5))

                    If Not p6(v1, v2, v3, v4, v5, v6) Then
                        Return False
                    End If

                Case 7
                    Dim p7 = DirectCast(pred, Func(Of Object, Object, Object, Object, Object, Object, Object, Boolean))
                    Dim v1 = result(item.Item2(0))
                    Dim v2 = result(item.Item2(1))
                    Dim v3 = result(item.Item2(2))
                    Dim v4 = result(item.Item2(3))
                    Dim v5 = result(item.Item2(4))
                    Dim v6 = result(item.Item2(5))
                    Dim v7 = result(item.Item2(6))

                    If Not p7(v1, v2, v3, v4, v5, v6, v7) Then
                        Return False
                    End If

                Case 8
                    Dim p8 = DirectCast(pred, Func(Of Object, Object, Object, Object, Object, Object, Object, Object, Boolean))
                    Dim v1 = result(item.Item2(0))
                    Dim v2 = result(item.Item2(1))
                    Dim v3 = result(item.Item2(2))
                    Dim v4 = result(item.Item2(3))
                    Dim v5 = result(item.Item2(4))
                    Dim v6 = result(item.Item2(5))
                    Dim v7 = result(item.Item2(6))
                    Dim v8 = result(item.Item2(7))

                    If Not p8(v1, v2, v3, v4, v5, v6, v7, v8) Then
                        Return False
                    End If


                Case Else
                    Throw New NotSupportedException
            End Select
        Next

        Return True
    End Function
End Class

下面是测试代码:

 (更新:增加了八皇后问题的解法,能求出所有92个解)

Module Module1

    Sub Main()
        Test1()

        Console.WriteLine("====================================================")

        Test2()

        Console.WriteLine("====================================================")

        Test3()

        Console.ReadLine()
    End Sub

    Sub Test1()
        Dim engine = New NonDeterministicEngine()

        engine.AddParam("a", {1, 2, 3, 4, 5, 6})
        engine.AddParam("b", {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})


        engine.AddRequire(Function(a) As Boolean
                              Return a > 2 AndAlso a < 9
                          End Function, {"a"})

        engine.AddRequire(Function(b) As Boolean
                              Return b > 5 AndAlso b <= 10
                          End Function, {"b"})

        engine.AddRequire(Function(a, b) As Boolean
                              Return a = b - 1
                          End Function, {"a", "b"})

        Dim result = engine.GetNextResult()
        While Not result Is Nothing
            Console.WriteLine("a = " & result("a") & ", b = " & result("b"))
            result = engine.GetNextResult()
        End While

        Console.WriteLine("Calculation ended.")
    End Sub

    Sub Test2()
        ' 贝克、库伯、弗莱舍、米勒和斯麦尔住在一个五层公寓楼的不同层,贝克不住在顶层,库伯不住在底层,弗莱舍不住在顶层
        ' 也不住在底层。米勒住的比库伯高,斯麦尔不住在弗莱舍相邻的层,弗莱舍不住在库伯相邻的层。请问他们各住在哪层?
        ' (SICP Page 290).
        ' (原书题目叙述有误:“米勒住的比库伯高一层” 应该是 “米勒住的比库伯高“)。
        Dim engine = New NonDeterministicEngine()

        engine.AddParam("baker", {1, 2, 3, 4, 5})
        engine.AddParam("cooper", {1, 2, 3, 4, 5})
        engine.AddParam("fletcher", {1, 2, 3, 4, 5})
        engine.AddParam("miller", {1, 2, 3, 4, 5})
        engine.AddParam("smith", {1, 2, 3, 4, 5})

        engine.AddRequire(Function(baker) As Boolean
                              Return baker <> 5
                          End Function, {"baker"})

        engine.AddRequire(Function(cooper) As Boolean
                              Return cooper <> 1
                          End Function, {"cooper"})

        engine.AddRequire(Function(fletcher) As Boolean
                              Return fletcher <> 1 And fletcher <> 5
                          End Function, {"fletcher"})

        engine.AddRequire(Function(miller, cooper) As Boolean
                              'Return miller = cooper + 1
                              Return miller > cooper
                          End Function, {"miller", "cooper"})

        engine.AddRequire(Function(smith, fletcher) As Boolean
                              Return smith <> fletcher + 1 And smith <> fletcher - 1
                          End Function, {"smith", "fletcher"})

        engine.AddRequire(Function(fletcher, cooper) As Boolean
                              Return fletcher <> cooper + 1 And fletcher <> cooper - 1
                          End Function, {"fletcher", "cooper"})

        engine.AddRequire(Function(a, b, c, d, e) As Boolean
                              Return a <> b And a <> c And a <> d And a <> e And b <> c And b <> d And b <> e And c <> d And c <> e And d <> e
                          End Function, {"baker", "cooper", "fletcher", "miller", "smith"})

        Dim result = engine.GetNextResult()
        While Not result Is Nothing
            Console.WriteLine(String.Format("baker: {0}, cooper: {1}, fletcher: {2}, miller: {3}, smith: {4}",
                                            result("baker"),
                                            result("cooper"),
                                            result("fletcher"),
                                            result("miller"),
                                            result("smith")))
            result = engine.GetNextResult()
        End While

        Console.WriteLine("Calculation ended.")
    End Sub

    Sub Test3()
        ' 八皇后问题的解法
        Dim engine = New NonDeterministicEngine()

        ' 设 a - h 分别代表第 1 - 8 行上的皇后,则只要对每个皇后求出对应的列号即可。
        engine.AddParam("a", {1, 2, 3, 4, 5, 6, 7, 8})
        engine.AddParam("b", {1, 2, 3, 4, 5, 6, 7, 8})
        engine.AddParam("c", {1, 2, 3, 4, 5, 6, 7, 8})
        engine.AddParam("d", {1, 2, 3, 4, 5, 6, 7, 8})
        engine.AddParam("e", {1, 2, 3, 4, 5, 6, 7, 8})
        engine.AddParam("f", {1, 2, 3, 4, 5, 6, 7, 8})
        engine.AddParam("g", {1, 2, 3, 4, 5, 6, 7, 8})
        engine.AddParam("h", {1, 2, 3, 4, 5, 6, 7, 8})

        ' 检查是否在同一个斜线上
        Dim NotInTheSameDiagonalLine = Function(cols As IList) As Boolean
                                           For i = 0 To cols.Count - 2
                                               For j = i + 1 To cols.Count - 1
                                                   If j - i = Math.Abs(cols(j) - cols(i)) Then
                                                       Return False
                                                   End If
                                               Next
                                           Next

                                           Return True
                                       End Function

        engine.AddRequire(Function(a, b, c, d, e, f, g, h) As Boolean
                              Return a <> b AndAlso a <> c AndAlso a <> d AndAlso a <> e AndAlso a <> f AndAlso a <> g AndAlso a <> h AndAlso b <> c AndAlso b <> d AndAlso b <> e AndAlso b <> f AndAlso b <> g AndAlso b <> h AndAlso c <> d AndAlso c <> e AndAlso c <> f AndAlso c <> g AndAlso c <> h AndAlso d <> e AndAlso d <> f AndAlso d <> g AndAlso d <> h AndAlso e <> f AndAlso e <> g AndAlso e <> h AndAlso f <> g AndAlso f <> h AndAlso g <> h AndAlso NotInTheSameDiagonalLine({a, b, c, d, e, f, g, h})
                          End Function,
                          {"a", "b", "c", "d", "e", "f", "g", "h"})

        Dim result = engine.GetNextResult()
        While Not result Is Nothing
            Console.WriteLine("(1,{0}), (2,{1}), (3,{2}), (4,{3}), (5,{4}), (6,{5}), (7,{6}), (8,{7})",
                              result("a"),
                              result("b"),
                              result("c"),
                              result("d"),
                              result("e"),
                              result("f"),
                              result("g"),
                              result("h"))

            result = engine.GetNextResult()
        End While

        Console.WriteLine("Calculation ended.")
    End Sub
End Module


 

输出结果如下:

 

a = 5, b = 6
a = 6, b = 7
Calculation ended.
====================================================
baker: 3, cooper: 2, fletcher: 4, miller: 5, smith: 1
Calculation ended.
====================================================
(1,1), (2,5), (3,8), (4,6), (5,3), (6,7), (7,2), (8,4)
(1,1), (2,6), (3,8), (4,3), (5,7), (6,4), (7,2), (8,5)
(1,1), (2,7), (3,4), (4,6), (5,8), (6,2), (7,5), (8,3)
(1,1), (2,7), (3,5), (4,8), (5,2), (6,4), (7,6), (8,3)
(1,2), (2,4), (3,6), (4,8), (5,3), (6,1), (7,7), (8,5)
(1,2), (2,5), (3,7), (4,1), (5,3), (6,8), (7,6), (8,4)
(1,2), (2,5), (3,7), (4,4), (5,1), (6,8), (7,6), (8,3)
(1,2), (2,6), (3,1), (4,7), (5,4), (6,8), (7,3), (8,5)
(1,2), (2,6), (3,8), (4,3), (5,1), (6,4), (7,7), (8,5)
(1,2), (2,7), (3,3), (4,6), (5,8), (6,5), (7,1), (8,4)
(1,2), (2,7), (3,5), (4,8), (5,1), (6,4), (7,6), (8,3)
(1,2), (2,8), (3,6), (4,1), (5,3), (6,5), (7,7), (8,4)
(1,3), (2,1), (3,7), (4,5), (5,8), (6,2), (7,4), (8,6)
(1,3), (2,5), (3,2), (4,8), (5,1), (6,7), (7,4), (8,6)
(1,3), (2,5), (3,2), (4,8), (5,6), (6,4), (7,7), (8,1)
(1,3), (2,5), (3,7), (4,1), (5,4), (6,2), (7,8), (8,6)
(1,3), (2,5), (3,8), (4,4), (5,1), (6,7), (7,2), (8,6)
(1,3), (2,6), (3,2), (4,5), (5,8), (6,1), (7,7), (8,4)
(1,3), (2,6), (3,2), (4,7), (5,1), (6,4), (7,8), (8,5)
(1,3), (2,6), (3,2), (4,7), (5,5), (6,1), (7,8), (8,4)
(1,3), (2,6), (3,4), (4,1), (5,8), (6,5), (7,7), (8,2)
(1,3), (2,6), (3,4), (4,2), (5,8), (6,5), (7,7), (8,1)
(1,3), (2,6), (3,8), (4,1), (5,4), (6,7), (7,5), (8,2)
(1,3), (2,6), (3,8), (4,1), (5,5), (6,7), (7,2), (8,4)
(1,3), (2,6), (3,8), (4,2), (5,4), (6,1), (7,7), (8,5)
(1,3), (2,7), (3,2), (4,8), (5,5), (6,1), (7,4), (8,6)
(1,3), (2,7), (3,2), (4,8), (5,6), (6,4), (7,1), (8,5)
(1,3), (2,8), (3,4), (4,7), (5,1), (6,6), (7,2), (8,5)
(1,4), (2,1), (3,5), (4,8), (5,2), (6,7), (7,3), (8,6)
(1,4), (2,1), (3,5), (4,8), (5,6), (6,3), (7,7), (8,2)
(1,4), (2,2), (3,5), (4,8), (5,6), (6,1), (7,3), (8,7)
(1,4), (2,2), (3,7), (4,3), (5,6), (6,8), (7,1), (8,5)
(1,4), (2,2), (3,7), (4,3), (5,6), (6,8), (7,5), (8,1)
(1,4), (2,2), (3,7), (4,5), (5,1), (6,8), (7,6), (8,3)
(1,4), (2,2), (3,8), (4,5), (5,7), (6,1), (7,3), (8,6)
(1,4), (2,2), (3,8), (4,6), (5,1), (6,3), (7,5), (8,7)
(1,4), (2,6), (3,1), (4,5), (5,2), (6,8), (7,3), (8,7)
(1,4), (2,6), (3,8), (4,2), (5,7), (6,1), (7,3), (8,5)
(1,4), (2,6), (3,8), (4,3), (5,1), (6,7), (7,5), (8,2)
(1,4), (2,7), (3,1), (4,8), (5,5), (6,2), (7,6), (8,3)
(1,4), (2,7), (3,3), (4,8), (5,2), (6,5), (7,1), (8,6)
(1,4), (2,7), (3,5), (4,2), (5,6), (6,1), (7,3), (8,8)
(1,4), (2,7), (3,5), (4,3), (5,1), (6,6), (7,8), (8,2)
(1,4), (2,8), (3,1), (4,3), (5,6), (6,2), (7,7), (8,5)
(1,4), (2,8), (3,1), (4,5), (5,7), (6,2), (7,6), (8,3)
(1,4), (2,8), (3,5), (4,3), (5,1), (6,7), (7,2), (8,6)
(1,5), (2,1), (3,4), (4,6), (5,8), (6,2), (7,7), (8,3)
(1,5), (2,1), (3,8), (4,4), (5,2), (6,7), (7,3), (8,6)
(1,5), (2,1), (3,8), (4,6), (5,3), (6,7), (7,2), (8,4)
(1,5), (2,2), (3,4), (4,6), (5,8), (6,3), (7,1), (8,7)
(1,5), (2,2), (3,4), (4,7), (5,3), (6,8), (7,6), (8,1)
(1,5), (2,2), (3,6), (4,1), (5,7), (6,4), (7,8), (8,3)
(1,5), (2,2), (3,8), (4,1), (5,4), (6,7), (7,3), (8,6)
(1,5), (2,3), (3,1), (4,6), (5,8), (6,2), (7,4), (8,7)
(1,5), (2,3), (3,1), (4,7), (5,2), (6,8), (7,6), (8,4)
(1,5), (2,3), (3,8), (4,4), (5,7), (6,1), (7,6), (8,2)
(1,5), (2,7), (3,1), (4,3), (5,8), (6,6), (7,4), (8,2)
(1,5), (2,7), (3,1), (4,4), (5,2), (6,8), (7,6), (8,3)
(1,5), (2,7), (3,2), (4,4), (5,8), (6,1), (7,3), (8,6)
(1,5), (2,7), (3,2), (4,6), (5,3), (6,1), (7,4), (8,8)
(1,5), (2,7), (3,2), (4,6), (5,3), (6,1), (7,8), (8,4)
(1,5), (2,7), (3,4), (4,1), (5,3), (6,8), (7,6), (8,2)
(1,5), (2,8), (3,4), (4,1), (5,3), (6,6), (7,2), (8,7)
(1,5), (2,8), (3,4), (4,1), (5,7), (6,2), (7,6), (8,3)
(1,6), (2,1), (3,5), (4,2), (5,8), (6,3), (7,7), (8,4)
(1,6), (2,2), (3,7), (4,1), (5,3), (6,5), (7,8), (8,4)
(1,6), (2,2), (3,7), (4,1), (5,4), (6,8), (7,5), (8,3)
(1,6), (2,3), (3,1), (4,7), (5,5), (6,8), (7,2), (8,4)
(1,6), (2,3), (3,1), (4,8), (5,4), (6,2), (7,7), (8,5)
(1,6), (2,3), (3,1), (4,8), (5,5), (6,2), (7,4), (8,7)
(1,6), (2,3), (3,5), (4,7), (5,1), (6,4), (7,2), (8,8)
(1,6), (2,3), (3,5), (4,8), (5,1), (6,4), (7,2), (8,7)
(1,6), (2,3), (3,7), (4,2), (5,4), (6,8), (7,1), (8,5)
(1,6), (2,3), (3,7), (4,2), (5,8), (6,5), (7,1), (8,4)
(1,6), (2,3), (3,7), (4,4), (5,1), (6,8), (7,2), (8,5)
(1,6), (2,4), (3,1), (4,5), (5,8), (6,2), (7,7), (8,3)
(1,6), (2,4), (3,2), (4,8), (5,5), (6,7), (7,1), (8,3)
(1,6), (2,4), (3,7), (4,1), (5,3), (6,5), (7,2), (8,8)
(1,6), (2,4), (3,7), (4,1), (5,8), (6,2), (7,5), (8,3)
(1,6), (2,8), (3,2), (4,4), (5,1), (6,7), (7,5), (8,3)
(1,7), (2,1), (3,3), (4,8), (5,6), (6,4), (7,2), (8,5)
(1,7), (2,2), (3,4), (4,1), (5,8), (6,5), (7,3), (8,6)
(1,7), (2,2), (3,6), (4,3), (5,1), (6,4), (7,8), (8,5)
(1,7), (2,3), (3,1), (4,6), (5,8), (6,5), (7,2), (8,4)
(1,7), (2,3), (3,8), (4,2), (5,5), (6,1), (7,6), (8,4)
(1,7), (2,4), (3,2), (4,5), (5,8), (6,1), (7,3), (8,6)
(1,7), (2,4), (3,2), (4,8), (5,6), (6,1), (7,3), (8,5)
(1,7), (2,5), (3,3), (4,1), (5,6), (6,8), (7,2), (8,4)
(1,8), (2,2), (3,4), (4,1), (5,7), (6,5), (7,3), (8,6)
(1,8), (2,2), (3,5), (4,3), (5,1), (6,7), (7,4), (8,6)
(1,8), (2,3), (3,1), (4,6), (5,2), (6,5), (7,7), (8,4)
(1,8), (2,4), (3,1), (4,3), (5,6), (6,2), (7,7), (8,5)
Calculation ended.

 

 

 

posted on 2010-05-17 18:12  NeilChen  阅读(2130)  评论(4编辑  收藏  举报

导航