Aar*_*ken 5 functional-programming scala
我正在学习Scala作为我的第一个功能性语言.作为其中一个问题,我试图找到一种生成序列S到n个位置的功能性方法.定义S使得S(1)= 1,并且S(x)= x出现在序列中的次数.(我不记得这是什么,但我之前在编程书中看过它.)
在实践中,序列如下所示:
S = 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7 ...
Run Code Online (Sandbox Code Playgroud)
我可以使用像这样的命令式样式在Scala中很容易地生成这个序列:
def genSequence(numItems: Int) = {
require(numItems > 0, "numItems must be >= 1")
var list: List[Int] = List(1)
var seq_no = 2
var no = 2
var no_nos = 0
var num_made = 1
while(num_made < numItems) {
if(no_nos < seq_no) {
list = list :+ no
no_nos += 1
num_made += 1
} else if(no % 2 == 0) {
no += 1
no_nos = 0
} else {
no += 1
seq_no += 1
no_nos = 0
}
}
list
}
Run Code Online (Sandbox Code Playgroud)
但我真的不知道如何在不使用vars和while循环的情况下编写它.
谢谢!
Kev*_*ght 10
到目前为止,帕维尔的答案最接近,但效率也很低.两个flatMaps和一个zipWithIndex在这里是矫枉过正:)
我对所需输出的理解:
n出现在输出(n/2) + 1时间中正如Pavel正确指出的那样,解决方案是从一开始Stream就使用flatMap:
Stream from 1
Run Code Online (Sandbox Code Playgroud)
这会生成一个Stream可能永无止境的序列,只能按需生成值.在这种情况下,它一直生成1, 2, 3, 4...无限(理论上)或Integer.MAX_VALUE(实际上)
与任何其他集合一样,可以映射流.例如:(Stream from 1) map { 2 * _ }生成偶数流.
您还可以flatMap在Streams上使用,允许您将每个输入元素映射到零个或多个输出元素; 这是解决问题的关键:
val strm = (Stream from 1) flatMap { n => Stream.fill(n/2 + 1)(n) }
Run Code Online (Sandbox Code Playgroud)
那么......这是如何运作的?对于元素3,lambda { n => Stream.fill(n/2 + 1)(n) }将生成输出流3,3.对于前5个整数,您将获得:
1 -> 1
2 -> 2, 2
3 -> 3, 3
4 -> 4, 4, 4
5 -> 5, 5, 5
etc.
Run Code Online (Sandbox Code Playgroud)
因为我们正在使用flatMap,所以这些将被连接起来,产生:
1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, ...
Run Code Online (Sandbox Code Playgroud)
流被记忆,因此一旦计算出给定值,它将被保存以供将来参考.但是,所有前面的值必须至少计算一次.如果你想要完整的序列,那么这不会导致任何问题,但它确实意味着S(10796)从冷启动生成将是缓慢的!(与您的命令式算法共享的问题).如果您需要这样做,那么到目前为止,没有一个解决方案可能适合您.
以下代码生成与您的完全相同的序列:
val seq = Stream.from(1)
.flatMap(Stream.fill(2)(_))
.zipWithIndex
.flatMap(p => Stream.fill(p._1)(p._2))
.tail
Run Code Online (Sandbox Code Playgroud)
但是,如果要生成Golomb序列(符合定义,但与示例代码结果不同),则可以使用以下内容:
val seq = 1 #:: a(2)
def a(n: Int): Stream[Int] = (1 + seq(n - seq(seq(n - 2) - 1) - 1)) #:: a(n + 1)
Run Code Online (Sandbox Code Playgroud)
您可以查看我的文章,了解如何处理函数式数字序列的更多示例.