简单的Haskell练习解决方案输出错误

时间:2015-10-06 15:25:07

标签: haskell

我正在尝试解决这个问题:

  

您将获得4种颜色的N球序列:红色,绿色,黄色   和蓝色。当且仅当所有的序列都充满了颜色   以下条件属实:

     
      
  • 红球和绿球一样多。
  •   
  • 黄球和蓝球一样多。
  •   
  • 序列的每个前缀中的红球和绿球数量之差最多为1。
  •   
  • 序列的每个前缀中黄球和蓝球的数量之差最多为1.
  •   
     

您的任务是编写一个程序,如果某个序列中充满了颜色,则该程序会打印True,否则会打印False

到目前为止我的解决方案是:

module Main where

import Control.Monad

main = do
  s <- readLn :: IO Int
  elements <- replicateM s getLine
  let result = map checkColours elements
  mapM (putStrLn . show) result

checkColours :: String -> Bool
checkColours string = isFullOfColors 0 0 0 0 string

isFullOfColors :: Int -> Int -> Int -> Int -> String -> Bool
isFullOfColors red green yellow blue string
  | (abs (red - green)) > 1 = False
  | (abs (yellow - blue)) > 1 = False
  | (string == []) = if (red /= yellow) || (green /= blue) then True else False
  | (head string == 'R' ) = isFullOfColors (red + 1) green yellow blue (tail string)
  | (head string == 'G' ) = isFullOfColors red  (green + 1) yellow blue (tail string)
  | (head string == 'Y' ) = isFullOfColors red green (yellow + 1) blue (tail string)
  | (head string == 'B' ) = isFullOfColors red green yellow  (blue + 1) (tail string)

但输入"RYBG"失败,返回False而不是True

我做错了什么?

1 个答案:

答案 0 :(得分:3)

除了C. Quilley的评论之外,这里有一些一般性建议和建议以不同方式构建你的函数。保护string == []最好写成null string,因为内置函数null将使用单个模式匹配做出此决定,而不是必须依赖可比较的元素列表(只有当列表的元素本身具有可比性时)。模式if ... then True else False可以缩短为...,因为它已经是具有相同值的布尔值。 通常,尝试使用模式匹配!

我看不到你从哪里派生(red /= yellow) || (green /= blue)。什么时候红球和黄球的数量有共同的限制?

您可能希望创建反映球的数据类型而不是String:

data Ball = Red | Green | Yellow | Blue
          deriving Eq

您可能希望它们与以前一样显示:

instance Show Ball where
    show Red = "R"
    show Green = "G"
    show Yellow = "Y"
    show Blue = "B"

您可能希望在主函数中嵌入辅助函数:

isFullOfColors :: [Ball] -> Bool
isFullOfColors = go (0, 0, 0, 0)
  where
    go :: (Int, Int, Int, Int) -> [Ball] -> Bool
    go (r,g,y,b) (Red:balls) = ...
    go (r,g,y,b) (Green:balls) = ...
    go (r,g,y,b) (Yellow:balls) = ...
    go (r,g,y,b) (Blue:balls) = ...
    go (r,g,y,b) [] = ...

关于逻辑部分的提示:这些可以表示为r,g,y和b之间的比较以及对balls的递归调用。