- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
经过 10 年的中断,我正在重新学习 Haskell,部分是为了看看发生了什么变化,部分是为了消除在 C#、SQL 和 JavaScript 中度过的日子,部分是因为它突然变得很酷;-)
我决定将自己的汉诺塔设置为编码卡塔,足够简单的东西,但我已经觉得我的代码是非惯用的,并且很想听听任何 Haskell 老手可能有什么提示和技巧。
为了让套路更有趣,我将问题分成两部分,第一部分,函数 moves
, 生成解决难题所需的移动序列。代码的其余部分旨在为塔建模并执行移动。
我绝对感到不满意的一个部分是 moveDisc
功能,这将是繁琐的扩展到 4 个塔。
Hanoi.hs
module Hanoi
where
import Data.Maybe
type Disc = Integer
type Towers = [[Disc]]
data Column = A | B | C deriving (Eq,Show)
getDisc :: Towers -> Column -> Maybe Disc
getDisc t A = listToMaybe $ t !! 0
getDisc t B = listToMaybe $ t !! 1
getDisc t C = listToMaybe $ t !! 2
validMove :: Towers -> Column -> Column -> Bool
validMove tower from to
| srcDisc == Nothing = False
| destDisc == Nothing = True
| otherwise = srcDisc < destDisc
where srcDisc = getDisc tower from
destDisc = getDisc tower to
moveDisc :: Towers -> Column -> Column -> Towers
moveDisc [a:as, b, c] A B = [as, a:b, c]
moveDisc [a:as, b, c] A C = [as, b, a:c]
moveDisc [a, b:bs, c] B A = [b:a, bs, c]
moveDisc [a, b:bs, c] B C = [a, bs, b:c]
moveDisc [a, b, c:cs] C A = [c:a, b, cs]
moveDisc [a, b, c:cs] C B = [a, c:b, cs]
moves :: Integer -> Column -> Column -> Column -> [(Column,Column)]
moves 1 a _ c = [(a,c)]
moves n a b c = moves (n-1) a c b ++ [(a,c)] ++ moves (n-1) b a c
solve :: Towers -> Towers
solve towers = foldl (\t (from,to) -> moveDisc t from to) towers (moves len A B C)
where len = height towers
height :: Towers -> Integer
height (t:_) = toInteger $ length t
newGame :: Integer -> Towers
newGame n = [[1..n],[],[]]
module TestHanoi
where
import Test.HUnit
import Hanoi
main = runTestTT $ "Hanoi Tests" ~: TestList [
getDisc [[1],[2],[2]] A ~?= Just 1 ,
getDisc [[1],[2],[3]] B ~?= Just 2 ,
getDisc [[1],[2],[3]] C ~?= Just 3 ,
getDisc [[],[2],[3]] A ~?= Nothing ,
getDisc [[1,2,3],[],[]] A ~?= Just 1 ,
validMove [[1,2,3],[],[]] A B ~?= True ,
validMove [[2,3],[1],[]] A B ~?= False ,
validMove [[3],[],[1,2]] A C ~?= False ,
validMove [[],[],[1,2,3]] A C ~?= False ,
moveDisc [[1],[],[]] A B ~?= [[],[1],[]] ,
moveDisc [[],[1],[]] B C ~?= [[],[],[1]] ,
moveDisc [[1,2],[],[]] A B ~?= [[2],[1],[]] ,
moveDisc [[],[2],[1]] C B ~?= [[],[1,2],[]] ,
moveDisc [[1,2],[],[]] A C ~?= [[2],[],[1]] ,
moveDisc [[3],[2],[1]] B A ~?= [[2,3],[],[1]] ,
moves 1 A B C ~?= [(A,C)] ,
moves 2 A B C ~?= [(A,B),(A,C),(B,C)] ,
"acceptance test" ~:
solve [[1,2,3,4,5,6], [], []] ~?= [[],[],[1,2,3,4,5,6]] ,
"is optimal" ~:
length (moves 3 A B C) ~?= 7
]
最佳答案
这是使用替代表示的实现。我没有存储三个挂钉尺寸列表,而是存储一个列列表,其中第一个元素对应于最小圆盘的位置,依此类推。这样做的好处是现在不可能表示非法状态,例如丢失的磁盘、较大的磁盘堆叠在较小的磁盘上等。它还使得许多功能难以实现。
Hanoi.hs
module Hanoi where
import Control.Applicative
import Control.Monad
import Data.List
import Data.Maybe
type Disc = Integer
type Towers = [Column]
data Column = A | B | C deriving (Eq, Show)
getDisc :: Column -> Towers -> Maybe Disc
getDisc c t = (+1) . toInteger <$> elemIndex c t
validMove :: Column -> Column -> Towers -> Bool
validMove from to = isJust . moveDisc from to
moveDisc :: Column -> Column -> Towers -> Maybe Towers
moveDisc from to = foldr check Nothing . tails
where check (c:cs)
| c == from = const . Just $ to : cs
| c == to = const Nothing
| otherwise = fmap (c:)
moves :: Integer -> Column -> Column -> Column -> [(Column,Column)]
moves 1 a _ c = [(a,c)]
moves n a b c = moves (n-1) a c b ++ [(a,c)] ++ moves (n-1) b a c
solve :: Towers -> Towers
solve towers = fromJust $ foldM (\t (from,to) -> moveDisc from to t) towers (moves len A B C)
where len = height towers
height :: Towers -> Integer
height = genericLength
newGame :: Integer -> Towers
newGame n = genericReplicate n A
module HanoiTest where
import Test.HUnit
import Hanoi
main = runTestTT $ "Hanoi Tests" ~: TestList [
getDisc A [A, B, C] ~?= Just 1 ,
getDisc B [A, B, C] ~?= Just 2 ,
getDisc C [A, B, C] ~?= Just 3 ,
getDisc A [B, B, C] ~?= Nothing ,
getDisc A [A, A, A] ~?= Just 1 ,
validMove A B [A, A, A] ~?= True ,
validMove A B [B, A, A] ~?= False ,
validMove A C [C, C, A] ~?= False ,
validMove A C [C, C, C] ~?= False ,
moveDisc A B [A] ~?= Just [B] ,
moveDisc B C [B] ~?= Just [C] ,
moveDisc A B [A, A] ~?= Just [B, A] ,
moveDisc C B [C, B] ~?= Just [B, B] ,
moveDisc A C [A, A] ~?= Just [C, A] ,
moveDisc B A [C, B, A] ~?= Just [C, A, A] ,
moves 1 A B C ~?= [(A,C)] ,
moves 2 A B C ~?= [(A,B),(A,C),(B,C)] ,
"acceptance test" ~:
solve [A, A, A, A, A, A] ~?= [C, C, C, C, C, C] ,
"is optimal" ~:
length (moves 3 A B C) ~?= 7
]
moveDisc
返回总数
Nothing
在无效移动的情况下。这样我就可以轻松实现
validMove
就其而言。我确实觉得有一种更优雅的方式来实现
moveDisc
尽管。
solve
仅当参数是初始位置时才有效。您的代码也是这种情况(由于
moveDisc
中的模式不完整而失败)。我回
Nothing
在这种情况下。
moveDisc
并更改了参数排序以将数据结构放在最后。
关于haskell - 这个 Haskell kata 解决方案可以变得更惯用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5890782/
我是最近的编码训练营学生,我周五毕业。虽然我正在寻找我的第一个职业机会,但我一直在回顾我们为培养解决问题的技能而获得的一些早期 kata,我不得不说我被其中的一些难住了。我已经为这些问题编写了测试,并
Kata 容器试图通过提供更多隔离来使容器安全。 lightweight Virtual Machines (VMs) that feel and perform like containers, b
我正在用 Java 查找奇偶校验 kata。我不知道为什么,但我的 junit 测试失败了,因为它在第一个测试的一部分中返回 -10 而不是 3。如果有人可以请告诉我这是为什么吗?示例 test1 中
大家好,我开始学习一些java。我发现 Codewars.com 是锻炼和学习的好方法。 我收到此说明: accum("abcd") -> "A-Bb-Ccc-Dddd" accum("RqaEzty
我计划以 Kata 的方式学习 Groovy。有没有类似于 RubyQuiz for Groovy Katas 的来源? 最佳答案 另请参阅http://github.com/nadavc/groov
挑战是删除数字末尾的零。两个数字内的零是可以的。例如: 14000 == 14 //all end zeros removed 10300 == 103 // all end zeros remove
最近几个月,我对编码 katas 非常感兴趣。我相信它们是磨练我的编程技能和提高我在工作中编写的代码质量的好方法。 有很多地方可以找到 Katas。像.. http://codekata.pragpr
我正在解决以下问题:编写一个程序,将单词“sum”、“product”、“mean”或“sqrt”中的一个作为第一个参数,进一步的参数是一系列数字。该程序将适当的功能应用于该系列。 我已经解决了它(下
经过 10 年的中断,我正在重新学习 Haskell,部分是为了看看发生了什么变化,部分是为了消除在 C#、SQL 和 JavaScript 中度过的日子,部分是因为它突然变得很酷;-) 我决定将自己
据我了解, Kata Containers Kata Container build a standard implementation of lightweight Virtual Machines
我正在尝试做这个套路 - https://www.codewars.com/kata/organize-a-round-robin-tournament/train/javascript . 任务是创
我正在尝试在 Codewars 上解决这个 Kata:https://www.codewars.com/kata/largest-difference-in-increasing-indexes/tr
我开始在 Everquest TDD Kata ( Github Link) 上编写代码,并且我正在参与 Feature: Character Ability Modifiers Modify Att
friend 们。这就是我正在谈论的卡塔...... https://www.codewars.com/kata/the-hashtag-generator/train/javascript 这是我输
我正在研究代码 war 中的方向减少问题,但我无法弄清楚它给我带来的错误。我知道也有类似的情况,但是当我在 Visual Studio Code 上测试我的代码时,它工作得完美无缺,所以我不确定为什么
对编码非常陌生,所以请多多包涵。我正试图在 Codewars 上解决这个 Kata:https://www.codewars.com/kata/snail/train/javascript 基本上给定
我最近一直在玩 Ruby,我刚刚完成了 http://codekata.pragprog.com 的 Anagrams Code Kata . 该解决方案是测试驱动的,并利用了独特的质因数分解定理,但
资深程序员,C# 新手。刚开始使用 VS2012 和内置测试框架进行 Prime Factors Kata。在第一次测试中,预期和实际匹配,但它被标记为失败。任何人都可以解释为什么,更重要的是解决方法
我是轻量级虚拟机的新手。我将使用 Kata Container Runtime 安装 Knative。可能吗? 我知道 Kubernetes 与 Kata 容器运行时一起工作。但是,Knative 能
我纯粹使用 SqlKata 在 C# 中构建 sql 查询。我想获取我构建的 Query 的输出,获取原始(已编译)的 sql 字符串,并针对 SQL 执行它。 我认为这会做到这一点: var fac
我是一名优秀的程序员,十分优秀!