操作列表列表

时间:2012-10-16 03:02:36

标签: list haskell

  

可能重复:
  Haskell - Manipulating lists

给定矩阵m,起始位置p1和终点p2。 目标是计算到达最终矩阵的方式(p2 = 1,其他= 0)。为此,每次跳到一个位置时,你会减一。  你最多只能从一个位置跳到另一个位置,最多两个位置,水平或垂直。例如:

   m =             p1=(3,1)  p2=(2,3)
   [0 0 0]
   [1 0 4]
   [2 0 4]

您可以跳到[(3,3),(2,1)]

的位置

当你从一个位置跳过时,你将它减去一个并再次完成。让我们跳到列表的第一个元素。像这样:

    m=              
    [0 0 0]
    [1 0 4]
    [1 0 4]

现在您处于(3,3)位置,您可以跳到[(3,1),(2,3)]

位置

直到最终矩阵:

[0 0 0]
[0 0 0]
[1 0 0]

在这种情况下,获得最终矩阵的不同方式的数量为20。 我创建了以下函数:

import Data.List
type Pos = (Int,Int)
type Matrix = [[Int]]

s::Pos->Pos->Matrix->Int
s (i,j) fim mat = if (mat == (matrizFinal (tamanho mat) fim)) then 1 
                else if (possiveisMov (i,j) mat)/= [] then s (head(possiveisMov (i,j) mat)) fim (decrementaPosicao (i,j) mat)
                 else 0



matrizFinal:: Pos->Pos->Matrix
matrizFinal (m,n) p = [[if (y,x)==p then 1 else 0 | x<-[1..n]]| y<-[1..m]]

movimentos::Pos->[Pos]
movimentos (i,j)= [(i+1,j),(i+2,j),(i-1,j),(i-2,j),(i,j+1),(i,j+2),(i,j-1),(i,j-2)]

decrementaPosicao:: Pos->Matrix->Matrix
decrementaPosicao (1,c) (m:ms) = (decrementa c m):ms
decrementaPosicao (l,c) (m:ms) = m:(decrementaPosicao (l-1,c) ms)

decrementa:: Int->[Int]->[Int]
decrementa 1 (m:ms) = (m-1):ms
decrementa n (m:ms) = m:(decrementa (n-1) ms)

tamanho:: Matrix->Pos
tamanho m = (length m,length.head $ m)

possiveisMov:: Pos->Matrix->[Pos]
possiveisMov p mat = verifica0 ([(a,b)|a<-(dim m),b<-(dim n)]  `intersect` xs) mat
                          where xs = movimentos p
                            (m,n) = tamanho mat
dim:: Int->[Int]
dim 1 = [1]
dim n = n:dim (n-1)

verifica0::[Pos]->Matrix->[Pos]
verifica0 [] m =[]
verifica0 (p:ps) m = if ((pegaAltura m p) == 0) then verifica0 ps m
                                               else p:verifica0 ps m

pegaAltura:: Matrix->Pos->Int
pegaAltura x (i,j)= (x!!(i-1))!!(j-1)

有谁知道为什么函数s不计算解决这个问题的方法有多少?如何修复它或更好的方法来使函数s解决?

1 个答案:

答案 0 :(得分:0)

在我认识到正在玩的游戏是多个令牌弹珠后,我知道通过扩展游戏树来计算从开始到结束的路径数量,如果发现的是最终板,则将其视为其他明智的道路不要。

所以我看到你的s功能只会以一种方式扩展电路板第一个可能的移动而不是所有可能的移动。正确的版本将测试电路板是否处于结束状态并返回1,否则将对所有可能移动的循环结果进行求和,得出计数,如果该移动无效则为0。