如何计算黑板上的黑块总数?

时间:2018-05-24 01:53:09

标签: haskell

对于haskell,如果按照下面给出的话,有没有办法计算黑块的数量。

initialBoard =
 Board
 [ Just (Black, 2)
 , Nothing
 , Nothing
 , Nothing
 , Just (Black, 2)
 , Just (White, 5)
 , Nothing
 , Just (White, 3)
 , Nothing
 , Nothing
 , Nothing
 , Just (Black, 5)
 , Just (White, 5)
 , Nothing
 , Nothing
 , Nothing
 , Just (Black, 3)
 , Nothing
 , Just (Black, 5)
 , Nothing
 , Nothing
 , Nothing
 , Nothing
 , Just (White, 2)
 ]

我是haskell的新手,我想知道haskell是否有像python中的for ... in ...循环这样的函数,允许我检查列表中的每一项。谢谢

3 个答案:

答案 0 :(得分:3)

使用filter删除所有NothingJust (White, _)值,然后计算剩下的内容。

isBlack :: Maybe (Color, Int) -> Bool
isBlack (Just (Black, _)) = True
isBlack _ = False

countBlacks :: Board -> Int
countBlacks = length . filter isBlack

有点长,但“明显”,单行定义可能

import Data.Maybe (isJust, fromJust)

-- 1. Get rid of Nothings
-- 2. Extract the tuples from the Just values
-- 3. Extract the colors from the tuples
-- 4. Get rid of the Whites
-- 5. Count what's left.
countBlacks = length . filter (== Black) . map fst . map fromJust . filter isJust

countBlacks = length . filter (== Black) . map (fst . fromJust) . filter isJust

countBlacks = length . filter ((== Black) . fst . fromJust) . filter isJust

利用身份

  • map f . map g == map (f . g)
  • filter f . map g == filter (f . g)

请注意fromJust应谨慎使用; fromJust Nothing未定义,将引发错误。在这里,它是安全的,因为filter isJust保证将fromJust值应用于Just值。

更安全的替换是maybe函数,它提供给定Nothing的默认值。 (您可以将fromJust视为实施为maybe undefined id。)

countBlacks = length . filter (maybe False f)
  where f (Black, _) = True
        f _ = False

因为maybe False f Nothing评估为False

答案 1 :(得分:3)

chepner建议或多或少地建议您过滤Just,然后过滤Black

我建议您将列表[Maybe (Color,Int)]转换为具有相同答案的[Color],然后过滤并计算:

countBlacks = length . filter (== Black) . map (maybe White fst)
                         ^                       ^
                         |                        -- Just (x, _) ~> x
                         |                        -- Nothing     ~> White
                         --- list ~> [Black, Black ... Black]

作为替代方案,您可以转换为代表黑色或白色的一个或零的[Int]和总和:

 countBlacks = sum . map (maybe 0 (fromEnum . (== Black) . fst))

答案 2 :(得分:3)

进行编译的一些设置:

data Color = Black | White deriving Eq

newtype Board = Board [Maybe (Color, Int)]

一次解决一小块;一步到位就没有勇气解决问题。继续寻找改变你拥有的数据的方法,丢弃信息,直到你只剩下你想要的东西为止。

也许从一个只获取棋盘上的棋子的功能开始,从而丢弃我们不关心的位置信息:

import Data.Maybe (catMaybes)

-- | Produce a list of all the pieces on a board.
boardPieces :: Board -> [(Color, Int)]
boardPieces (Board xs) = catMaybes xs

我们只对一种颜色的碎片感兴趣,那么如何获取一个碎片列表并仅返回该颜色的碎片类型的函数 - 从而丢弃有关我们不会生成的另一种颜色的碎片的信息关心。

-- | Given a list of pieces with colors, produce a list
-- that only contains the pieces for a particular color.
filterByColor :: Color -> [(Color, Int)] -> [Int]
filterByColor x = filter (\(y, i) -> x == y)

为了弄清楚棋盘上的黑棋数量,我们可以

  1. 获取棋盘上的棋子列表
  2. 按颜色过滤该列表
  3. 取该列表的长度
  4. -- | The number of black pieces on the board.
    numBlacks :: Board -> Int
    numBlacks = length . filterByColor Black . boardPieces
    

    测试:

    λ> numBlacks initialBoard
    5