haskell - 生成数字顺序递增的数字列表
问题描述
嗨,我正在尝试生成一个列表
- 所有可能的
n
数字 - 他们的数字是按降序排列的
例如,如果n = 3
输出为 [111 .. 321 .. 543 ..999]。
我最初的尝试是
--attempt1
digits n = map (\x -> read [x] :: Int) (show n)
sorted [] = True
sorted [x] = True
sorted (x:y:xs) = if x <= y then sorted (y:xs) else False
[ x | x <- [ 10^(n-1) .. 10^n ] , sorted $ digits $ x]
然而,随着变量 n 变大,这种方法会以指数方式变慢。
我的第二种方法是(如果 n == 3)
joiner :: [Integer] -> Integer
joiner = read . concatMap show
[ joiner [z,y,x] |
x <- [1..9],
y <- [9,8..x],
z <- [9,8..y]]
但是现在的问题是我如何将这段代码推广到任意n
joiner :: [Integer] -> Integer
joiner = read . concatMap show
[ joiner [a_n,...,a_1] |
a_1 <- [1..9],
a_2 <- [9,8..x],
.
.
.
a_n <- [9,8..a_n-1]
]
谢谢!
解决方案
每次你需要组合 N 个东西(其中 N 是预先未知的)时,答案总是递归。毕竟,这是在 Haskell 中迭代的唯一方法。
首先,我们需要一种将另一个数字附加到给定数字的方法。很简单:
appendDigit x = [ x*10 + d | d <- [0..9] ]
让我们测试一下:
λ appendDigit 2
[20,21,22,23,24,25,26,27,28,29]
λ appendDigit 3
[30,31,32,33,34,35,36,37,38,39]
但还不够好:我们只需要附加小于最后一位的数字。嗯,很容易修改:
appendDigit x = [ x*10 + d | d <- [0..(lastDigit-1)] ]
where lastDigit = x `mod` 10
试试看:
λ appendDigit 2
[20,21]
*Main Lib
λ appendDigit 3
[30,31,32]
*Main Lib
λ appendDigit 8
[80,81,82,83,84,85,86,87]
现在剩下的就是做 N 次,一路连接结果列表:
decDigits 0 = [] -- degenerate case: when N = 0, there are no such numbers
decDigits 1 = [0..9] -- base case: N = 1
decDigits n = concatMap appendDigit $ decDigits (n-1)
推荐阅读
- java - 将多个文件一一拖放到javaFX中
- android - 将 Dagger 2 注入 Worker 类
- macos - 构建并推送多拱 docker 镜像
- python-3.x - 无法使用 tf.restore 恢复预训练模型
- android - 从 SQLite 数据库填充 MPAndroidChart BarChart
- python - Python:WSGI 崩溃且没有错误
- hive - Cloudera Hue - 在 serde 属性规范中无法识别“WITH”“SERDEPROPERTIES”“(”附近的输入
- elasticsearch - 弹性搜索模糊搜索未找到所需结果
- python - 在文本文件中搜索字符串时出现“TypeError:预期的字符串或类似字节的对象”错误-Python
- apache-spark - java.lang.AssertionError:断言失败时加入流Spark