看了几本 Haskell 教程,我觉得这些书都没有站在程序员的角度安排内容顺序。其实对于大部分程序员来讲,脑子里就是 C 语言的基本套路。因此, Haskell 的教程应该从 C 语言相近的方式开始课程。等我用 Haskell 开发一个应用系统后,考虑编写一本真正的入门教程。今天发一段 ACM 竞赛题的 Haskell 程序。
除法( Division, UVa 725)
输入正整数 n, 按从小到大的顺序输出所有形如 abcde/ fghij = n 的表达式, 其中 a ~ j 恰好为数字 0 ~ 9 的一个排列(可以有前导 0), 2 ≤ n ≤ 79。
样例输入: 62
样例输出: 79546 / 01283 = 62 94736 / 01528 = 62
-- digitset 整数位数 整数 -> 各位数字构成的集合
-- 例如: digist 3 123 -> [1,2,3]
digitset :: Int -> Int -> [Int]
digitset 0 n = []
digitset k n = mod n 10 : digitset (k-1) (div n 10)-- packset 列表 元素不重复列表
-- 例如: packset [1,2,3,2,1] -> [1,2,3]
packset [] = []
packset (x:xs) = if (elem x xs) then (packset xs) else (x:(packset xs))-- digist 集合x 集合y -> 构成x、y的数字的个数
-- 例如:digist 123 345 -> 5
digits x y = length (packset ((digitset 5 x)++(digitset 5 y)))-- answer n -> 满足问题要求的所有整数对的集合
answer n = [(y, x)|x<-[1234..50000], let y = n*x, y < 99999, (digits x y) == 10]main = doputStr "N = ?"s <- getLinelet n = read s :: Intreturn $ answer n
运行一下,看看结果:
N = ?2
[(13458,6729),(13584,6792),(13854,6927),(14538,7269),(14586,7293),
(14658,7329),(15384,7692),(15846,7923),(15864,7932),(18534,9267),
(18546,9273),(18654,9327),(26970,13485),(27096,13548),(27690,13845),
(29076,14538),(29370,14685),(29670,14835),(29706,14853),
(29730,14865),(30972,15486),(32970,16485),(37092,18546),
(37290,18645),(41358,20679),(41538,20769),(41586,20793),
(46158,23079),(53418,26709),(53814,26907),(54138,27069),
(54186,27093),(54618,27309),(58134,29067),(58146,29073),
(58614,29307),(61458,30729),(61584,30792),(61854,30927),
(62970,31485),(64158,32079),(65418,32709),(65814,32907),
(69702,34851),(70296,35148),(70962,35481),(76290,38145),
(76902,38451),(90276,45138),(90372,45186),(90762,45381),
(92370,46185),(93702,46851),(96270,48135),(96702,48351),
(97026,48513),(97032,48516),(97062,48531),(97230,48615),(97302,48651)]N = ?3
[(17469,5823),(17496,5832),(50382,16794),(53082,17694),
(61749,20583),(69174,23058),(91746,30582),(96174,32058)]N = ?62
[(79546,1283),(94736,1528)]