我被困在做作业上了。我必须编写一个包含两个字符串的函数。列表字符串包含3个字符:
第一个字符串列表用于黑色片段,第二个字符串列表用于白片。板的自由字段由“.”表示。黑色棋子将上装,白色棋子将下套。
在船上打印1-8和and是不必要的。
这是必需的函数类型:
chess :: [String] -> [String] -> [String]我们有这个打印功能
pp :: Result -> IO ()
pp x = putStr (concat (map (++"\n") x))这是IO示例:
Prelude> pp( chess["Ke1","Ra1","Rh1","Pa2","Be5"] ["Ke8","Ra8","Rh8","Pa7","Qd8","Bc8","Nb8"])
8rnbqk..r
7p.......
6........
5....B...
4........
3........
2P.......
1R...K..R
abcdefgh我试过什么?
chess :: [String] -> [String] -> [String]
chess _ [] = []
chess [] _ = []
chess ((x1:x2:x3:_):xs) ((y1:y2:y3:y3s):ys)
| 'a' == x2 && '1' == x3 = [x1] : chess xs ys
| 'a' == y2 && '1' == y3 = [y1] : chess xs ys
| 'b' == x2 && '1' == x3 = [x1] : chess xs ys
| 'c' == x2 && '1' == x3 = [x1] : chess xs ys
| 'd' == x2 && '1' == x3 = [x1] : chess xs ys
| 'e' == x2 && '1' == x3 = [x1] : chess xs ys
| 'e' == x2 && '1' == x3 = [x1] : chess xs ys
| 'g' == x2 && '1' == x3 = [x1] : chess xs ys
| otherwise = ['.'] : chess xs ys输入为:国际象棋“Ke1”、"Ra1“、"Rh1”、"Pa2“、"Be1”输出:"K“、"R”、".“、".”、"B“。
再来一个..。
chess :: [String] -> [String] -> [String]
chess _ [] = []
chess [] _ = []
chess ((x1:x2:x3:_):xs) ((y1:y2:y3:y3s):ys)
| (x2 == 'a' && x3 == ['1']) = [x1] : chess (xs) (ys)
| (x2 == 'a' && x3 == ['2']) = [x1] : chess (xs) (ys)
| (x2 == 'a' && x3 == ['3']) = [x1] : chess (xs) (ys)
| (x2 == 'a' && x3 == ['4']) = [x1] : chess (xs) (ys)
| (x2 == 'a' && x3 == ['5']) = [x1] : chess (xs) (ys)
| (x2 == 'a' && x3 == ['6']) = [x1] : chess (xs) (ys)
| (x2 == 'a' && x3 == ['7']) = [x1] : chess (xs) (ys)
| (x2 == 'a' && x3 == ['8']) = [x1] : chess (xs) (ys)
| otherwise = chess (xs) (ys)输入:国际象棋“Ke1”、"Ra1“、"Rh1”、"Pa2“、"Be1”输出:K
他们都不像我想的那样工作。我试过先检查一行,然后检查每一列( each )--我认为这是对的,因为我需要打印“K.q.”、“P.”之类的内容--每个元素都是一行。如果我检查一下。黑色,如果没有黑色,也可以是白色的,所以我需要在打印'.‘之前检查第二个字符串中的白色片段。帮帮忙,我很困惑。我试过像4个函数那样编写代码,但它们花了超过4个小时。谢谢
发布于 2019-11-03 22:16:23
前言。
我会给你一个概述,并允许我留下一些细节未打磨。请根据你的喜好调整我的建议。
我的回答将是这样的:
在现实生活中,我的过程是“辩证法”,所有这些思路都是通过尝试和错误同时成长的。
好主意。
我在想,给定两个字段,每个字段都有一些部分,我总是可以将这些字段“放在一起”,这样每个字段在接收到的字段中的位置都与在给定字段中的位置相同。(除非同一地方有两块,在这种情况下,行为是没有定义的。)一旦我可以用这种方式添加两个字段,我就可以添加任意数量的字段。而且用一块一块来生产一块地也不应该太难。这种技术被称为“折叠一个单样体”,你会看到它在Haskell中的大量使用。
战略。
我就是这样解决这个问题的:
piece.
getPiece函数来读取一个getPiece函数,一个putPiece函数显示一个带有一个piece.
overlay函数。
类型。
type Piece = (Char, Int, Int) -- Piece, row, column.
type Field = [String] -- Rows.
getPiece :: String -> Piece
putPiece :: Piece -> Field
overlay :: Field -> Field -> Field
chess :: [String] -> [String] -> Field这可能是值得你的时间,采取一张纸,并画一些图片,这些类型和功能如何可能连接。
定义。
getPiece :: String -> Piece
getPiece [v, x, y] = (piece, row, column)
where
piece = v
row = (Char.ord y - 48)
column = (Char.ord x - 96)
putPiece :: Piece -> Field
putPiece (v, x, y) = reverse
$ replaceAt (x - 1) (replaceAt (y - 1) v blank) (replicate 8 blank)
where
blank = replicate 8 ' '
replaceAt :: Int -> a -> [a] -> [a]
replaceAt i y xs =
let (before, (_: after)) = List.splitAt i xs
in before ++ y: after
overlay :: Field -> Field -> Field
overlay u v = zipWith (zipWith overlayOne) u v
where
overlayOne ' ' y = y
overlayOne x _ = x
chess :: [String] -> [String] -> Field
chess white black = List.foldl1' overlay . fmap putPiece $ pieces
where
pieces = fmap (makeWhite . getPiece) white ++ fmap getPiece black
makeWhite :: Piece -> Piece
makeWhite (c, x, y) = (Char.toLower c, x, y)这里一个棘手的部分是如何将两个zipWith函数组合起来,以实现列表列表上的"zip“效果。还请注意,当我认为帮助函数replaceAt将使主函数变得非常简单时,我毫不犹豫地定义它。
结论。
我发现用正确的抽象工具箱来处理一个简单的问题是最舒服的。在这种情况下,我们使用了一个单半群(由overlay__定义)和一个递归方案(__List.foldl'是“变态”的一个实例)。我相信,在您的编程实践中,您会遇到更多的情况,在这些情况下,可以使用这些思想。
如果有些事情是不平易近人的,或者解释得不好,请给我留言。
好好享受Haskell!
P.S.也看到了另一个,algorithmically faster approach到一个非常相似的问题。
发布于 2022-11-01 13:19:49
考虑以这种方式构造代码:
-- given the three characters you describe, figure out the position and
-- piece name (do whatever you want with nonsense)
--
-- e.g. decode "Ke8" would return ((5, 8), 'k')
-- decode "Kz92" and decode "f" can return anything convenient
decode :: String -> ((Int, Int), Char)
decode = undefined
-- given a key, find all the values in a list associated with that key
--
-- e.g. assoc (5, 8) [((3, 4), 'q'), ((5, 8), 'k'), ((1, 2), 'p')]
-- would return ['k']
--
-- in non-homeworks, don't use this; instead, use the pre-existing
-- Prelude.lookup or the containers' package's Data.Map
assoc :: Eq k => k -> [(k, v)] -> [v]
assoc = undefined
-- if there's a single good choice for character at a given board position,
-- return it; otherwise, use a . to mark an empty space
--
-- e.g. choose ['k'] would return 'k'
-- choose [] would return '.'
-- choose ['k', 'P'] can return anything convenient
choose :: String -> Char
choose = undefined
chess :: [String] -> [String] -> [String]
chess white_ black_ = [[undefined | col <- [1..8]] | row <- [8,7..1]] where
white = [(pos, toUpper piece) | (pos, piece) <- decode white_]
black = [(pos, toLower piece) | (pos, piece) <- decode black_]https://stackoverflow.com/questions/58684290
复制相似问题