我正在处理3元组的3元组((a,b,c),(d,e,f),(g,h,i))
。现在我想把这个元组作为输入,并且输出生成一个元组列表,如果元素有一定的值,元素就会变成一个值。
示例:
changefromtovalue :: a -> a -> ((a,a,a),(a,a,a),(a,a,a)) -> [((a,a,a),(a,a,a),(a,a,a))]
changefromtovalue 1 5 ((0,1,2),(1,2,3),(2,3,4)) results in [((0,5,2),(1,2,3),(2,3,4)),((0,1,2)(5,2,3)(2,3,4))]
现在我没有使用整数,但我认为这个想法保持不变。
首先我认为我想要某种地图,但这会立即改变所有值,而不是每个都改变一个元素的列表。
然后我想,我可以做出所有变化(在示例中[((5,x,x)..),((x,5,x)..),((x,x,5)..)]
并以某种方式删除不符合要求的那些,但我无法找到一个干净的方法丢弃不需要的那些。
我已经尝试过搜索并找到了有关为元组制作数据规范的一些信息,但我没有看到它如何真正简化这一特定问题。
转换为列表并使用列表然后转换回来似乎更容易,但它仍然需要一种奇怪的选择。如果可能,我希望避免使用大量转化。
我正在寻找的建议是一种干净的方式,而不是一条完整的代码。
答案 0 :(得分:2)
根据您在评论中提供的其他信息,我们可以使用Richard Bird的方法解决此问题:
我们将网格表示为列表列表。然后,我们用一个我们可以为它做出的选择列表替换网格中的每个元素。在您的示例中,1
变为[1,5]
(我们选择1或5),n
变为[n]
(对于其他所有内容,没有其他选择)。< / p>
choice :: Int -> [Int]
choice 1 = [1,5]
choice n = [n]
然后我们为每个元素做出这个选择:
choices :: [[Int]] -> [[[Int]]]
choices = map (map choice)
现在是棘手的部分。我们将选择网格减少为选择的网格,这可以使用列表中的一般笛卡尔积来完成:
cp :: [[a]] -> [[a]]
cp [] = [[]]
cp (xs:xss) = [y:ys | y <- xs, ys <- cp xss]
我们崩溃了一系列选择:
collapse :: [[[a]]] -> [[[a]]]
collapse = cp . map cp
这首先将选择行列表(也就是选择网格)折叠到行选项列表中,然后将行选择列表折叠成行列表选择,也就是选择网格
最后,我们通过首先做出选择然后折叠它们来指定解算器:
solve :: [[Int]] -> [[[Int]]]
solve = collapse . choices
例如:
> mapM_ print (solve [[0,1,2],[1,2,3],[2,3,4]])
[[0,1,2],[1,2,3],[2,3,4]]
[[0,1,2],[5,2,3],[2,3,4]]
[[0,5,2],[1,2,3],[2,3,4]]
[[0,5,2],[5,2,3],[2,3,4]]
希望这也证明了如何将元组转换为列表列表使这项任务变得更容易。
注意:有些人可能已经注意到cp
为sequence
列表适用。这意味着我们也可以等同地写:
solve' = sequence . map sequence . choices
答案 1 :(得分:0)
使用元组你必须写:
change x y ((a,b,c),(d,e,f),(g,h,i))
= ((z a, z b, z c), (z d, z e, z f), (z g, z h, z i))
where z w = if w == x then y else w
如果使用列表(或数组)来表示3x3网格,生活会更容易。