Home > Blockchain >  Solving project Euler 25 in a functional manner using Scala
Solving project Euler 25 in a functional manner using Scala

Time:07-15

I am currently using Project Euler to learn Scala.
I am stuck on problem 25 with a java.lang.OutOfMemoryError exception.

Here is the question:

What is the index of the first term in the Fibonacci sequence to contain 1000 digits?

What I have come up with:

def fibonacciIndex(numOfDigits: Int): Option[Int] = {
  lazy val fibs: LazyList[Int] = 0 #:: fibs.scanLeft(1)(_   _)
  fibs.find(_.toString.length == numOfDigits)
}

I am trying to do this in a purely functional way.
Has anyone got some suggestions to improve the memory usage?

Thanks in advance!


EDIT: I was overflowing the Int type. Solved like so:

def fibonacciIndex(numOfDigits: Int): Int = {
    lazy val bigFibs: LazyList[BigInt] = BigInt(0) #:: bigFibs.scanLeft(BigInt(1))(_   _)
    bigFibs.indexWhere(_.toString.length == numOfDigits)
}

CodePudding user response:

Let's run your program in parts.

lazy val fibs: LazyList[Int] = 0 #:: fibs.scanLeft(1)(_   _)
fibs.take(100).foreach(println)

It prints:

0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
6765
10946
17711
28657
46368
75025
121393
196418
317811
514229
832040
1346269
2178309
3524578
5702887
9227465
14930352
24157817
39088169
63245986
102334155
165580141
267914296
433494437
701408733
1134903170
1836311903
-1323752223
512559680
-811192543
-298632863
-1109825406
-1408458269
1776683621
368225352
2144908973
-1781832971
363076002
-1418756969
-1055680967
1820529360
764848393
-1709589543
-944741150
1640636603
695895453
-1958435240
-1262539787
1073992269
-188547518
885444751
696897233
1582341984
-2015728079
-433386095
1845853122
1412467027
-1036647147
375819880
-660827267
-285007387
-945834654
-1230842041
2118290601
887448560
-1289228135
-401779575
-1691007710
-2092787285
511172301
-1581614984
-1070442683
1642909629
572466946
-2079590721
-1507123775
708252800
-798870975
-90618175
-889489150

As you can see integer overflows, and so it never outputs more than certain number of digits (11 I think including -). So it keep in computing next value.

Additionally LazyList remembers each value that it computed. It is lazy but memoizes. So each new number that is computed here

fibs.find(_.toString.length == numOfDigits)

is also remembered. It continues until you run out of memory.

To fix that you should replace LazyList with e.g. Iterator or Iterable and store numbers as BigInts.

  • Related