ONLY DO WHAT ONLY YOU CAN DO

こけたら立ちなはれ 立ったら歩きなはれ

Scala で Project Euler Problem 14

まづは、コラッツ数列がどんなものか見てみる

scala> def collatz_list(n: Long): List[Long] = {
     |     if      (n     == 1) List(1L)
     |     else if (n % 2 == 0) n::collatz_list(n / 2)
     |     else                 n::collatz_list(3 * n + 1)
     | }
collatz_list: (n: Long)List[Long]

scala> collatz_list(1)
res0: List[Long] = List(1)

scala> collatz_list(2)
res1: List[Long] = List(2, 1)

scala> collatz_list(3)
res2: List[Long] = List(3, 10, 5, 16, 8, 4, 2, 1)

scala> collatz_list(4)
res3: List[Long] = List(4, 2, 1)

scala> collatz_list(5)
res4: List[Long] = List(5, 16, 8, 4, 2, 1)

scala> collatz_list(6)
res5: List[Long] = List(6, 3, 10, 5, 16, 8, 4, 2, 1)

scala> collatz_list(7)
res6: List[Long] = List(7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1)

scala> collatz_list(8)
res7: List[Long] = List(8, 4, 2, 1)

scala> collatz_list(9)
res8: List[Long] = List(9, 28, 14, 7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1)

scala> collatz_list(10)
res9: List[Long] = List(10, 5, 16, 8, 4, 2, 1)

途中から、同じ数列になるので、毎回作成せずに、辞書に保存しておく

scala> def add_map(lst:List[Long], map:collection.mutable.Map[Long, List[Long]]):Unit = {
     |     if (!lst.isEmpty) {
     |         if (!map.contains(lst.head)) {
     |             map += lst.head -> lst
     |             add_map(lst.tail, map)
     |         }
     |     }
     | }
add_map: (lst: List[Long], map: scala.collection.mutable.Map[Long,List[Long]])Unit
scala> def collatz_list(n:Long, map:collection.mutable.Map[Long, List[Long]]): List[Long] = {
     |     if (n == 1)
     |         List(1L)
     |     else {
     |         if (map.contains(n)) {
     |             map(n)
     |         } else {
     |             if (n % 2 == 0) n::collatz_list(n / 2,     map)
     |             else            n::collatz_list(3 * n + 1, map)
     |         }
     |     }
     | }
collatz_list: (n: Long, map: scala.collection.mutable.Map[Long,List[Long]])List[Long]
scala> val map = collection.mutable.Map[Long, List[Long]] ()
map: scala.collection.mutable.Map[Long,List[Long]] = Map()
scala> var lst = collatz_list(1, map)
lst: List[Long] = List(1)

scala> add_map(lst, map)

scala> map
res11: scala.collection.mutable.Map[Long,List[Long]] = Map(1 -> List(1))
scala> var lst = collatz_list(2, map)
lst: List[Long] = List(2, 1)

scala> add_map(lst, map)

scala> map
res13: scala.collection.mutable.Map[Long,List[Long]] = Map(1 -> List(1), 2 -> List(2, 1))
scala> var lst = collatz_list(3, map)
lst: List[Long] = List(3, 10, 5, 16, 8, 4, 2, 1)

scala> add_map(lst, map)

scala> map
res15: scala.collection.mutable.Map[Long,List[Long]] = Map(16 -> List(16, 8, 4, 2, 1), 5 -> List(5, 16, 8, 4, 2, 1), 10 -> List(10, 5, 16, 8, 4, 2, 1), 8 -> List(8, 4, 2, 1), 3 -> List(3, 10, 5, 16, 8, 4, 2, 1), 4 -> List(4, 2, 1), 1 -> List(1), 2 -> List(2, 1))

まとめ

scala> for (i <- 1 to 9) {
     |     var lst = collatz_list(i, map)
     |     println(lst.length)
     |     add_map(lst, map)
     | }
1
2
8
3
6
9
17
4
20
scala> var max_num = 0
max_num: Int = 0

scala> var max_idx = 0
max_idx: Int = 0

scala> for (i <- 1 to 99) {
     |     var lst = collatz_list(i, map)
     |     if (lst.length > max_num) {
     |         max_num = lst.length
     |         max_idx = i
     |     }
     |     add_map(lst, map)
     | }

scala> println(max_idx + ":" + max_num)
97:119
scala> var max_num = 0
max_num: Int = 0

scala> var max_idx = 0
max_idx: Int = 0

scala> for (i <- 1 to 9999) {
     |     var lst = collatz_list(i, map)
     |     if (lst.length > max_num) {
     |         max_num = lst.length
     |         max_idx = i
     |     }
     |     add_map(lst, map)
     | }

scala> println(max_idx + ":" + max_num)
6171:262
scala> var max_num = 0
max_num: Int = 0

scala> var max_idx = 0
max_idx: Int = 0

scala> for (i <- 1 to 999999) {
     |     var lst = collatz_list(i, map)
     |     if (lst.length > max_num) {
     |         max_num = lst.length
     |         max_idx = i
     |     }
     |     add_map(lst, map)
     | }

scala> println(max_idx + ":" + max_num)
837799:525