Scalaを使っていろんな数列を書き出してみる

はじめに

こんにちは、野村です。

今回は、Scalaというプログラム言語でいくつかの数列を書き出してみます。

オブジェクト指向言語と関数型言語の特徴を併せ持っている、という何でもありの言語です。
たぶん自分には使いこなせない気がする。

インストールと実行

インストール

管理ユーザになってscalaをインストールします(debian9の場合)。

# apt install scala

javaも一緒にインストールされました。

$ java -version
openjdk version "1.8.0_141"
OpenJDK Runtime Environment (build 1.8.0_141-8u141-b15-1~deb9u1-b15)
OpenJDK 64-Bit Server VM (build 25.141-b15, mixed mode)
$ scala -version
Scala code runner version 2.11.8 -- Copyright 2002-2016, LAMP/EPFL

実行

vimでスクリプトを書いてコマンドモードから以下のコマンドを実行する。

:scala %

素数

・1より大きい自然数で、正の約数が1と自分自身のみである数。

import Math.sqrt

def sosu(a: List[Int]): List[Int] ={
  if (a.head > sqrt(a.last)) a else
    a.head +: sosu(a.tail.filter(_%a.head!=0))
}

println(sosu(2.to(100).toList)) // 100までの素数を表示
List(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97)

双子素数

・双子素数:差が2である2つの素数の組
・いとこ素数:差が4である2つの素数の組
・セクシー素数:差が6である2つの素数の組

import Math.sqrt

def twin(f:Int, n:Int):List[List[Int]] = {
  def loop(a: List[Int], i: Int): List[Int] = {
    val b = if (a.filter{_<=sqrt(i)}.forall{i%_!=0}) a:+i else a
    if (b.last==i && b.exists(_==i-f)) b else loop(b, i+1)
  }
  (1 to n).toList.foldLeft((List[Int](2),List[Int]())){(a,b)=>
    val c = loop(a._1, a._1.last+1)
    (c,a._2:+c.last)
  }._2.map{(a)=>List[Int](a-f,a)}
}

println(twin(2, 10)) // 双子素数を10組表示
println(twin(4, 10)) // いとこ素数を10組表示
println(twin(6, 10)) // セクシー素数を10組表示
List(List(3, 5), List(5, 7), List(11, 13), List(17, 19), List(29, 31), List(41, 43), List(59, 61), List(71, 73), List(101, 103), List(107, 109))
List(List(3, 7), List(7, 11), List(13, 17), List(19, 23), List(37, 41), List(43, 47), List(67, 71), List(79, 83), List(97, 101), List(103, 107))
List(List(5, 11), List(7, 13), List(11, 17), List(13, 19), List(17, 23), List(23, 29), List(31, 37), List(37, 43), List(41, 47), List(47, 53))

幸運数

・ポーランドの数学者スタニスワフ・ウラムによって提案された数列。
・素数の性質を研究するために、素数に似たルールで導き出せる数列を考案したとのこと。

def loop(a: List[Int], n: Int): List[Int] = {
  val b = 0+:a
  val c = for(i<-(0.to(b.length-1)).toList if i%(b(n))!=0) yield (b(i))
  if (c(n)<c.length+1) loop(c,(n+1)) else c
}

def luc(n: Int): List[Int] = {
  val a = (0.to(n)).toList.filter(_%2!=0)
  loop(a,2)
}

println(luc(100)) // 100までの幸運数を表示
List(1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79, 87, 93, 99)

階乗

・1 から n までのすべての整数の積。

def fact(n: Int): List[Int] = {
  (0.to(n-1)).toList.map{(a)=>(1.to(a)).product}
}

println(fact(10)) // 階乗を10個表示
List(1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880)

フィボナッチ数

・フィボナッチ数:イタリアの数学者レオナルド・フィボナッチにちなんで名付けられた数
・リュカ数:フランスの数学者エドゥアール・リュカにちなんで名付けられた数

def fib00(f: List[Int], c: Int): List[Int] = {
  (0.to(c-1)).foldLeft(List[Int]()){ (a,b)=>
    if (b<2) a:+f(b) else a:+(a(b-2)+a(b-1))
  }
}

println(fib00(List[Int](0,1), 10)) // フィボナッチ数を10個表示
println(fib00(List[Int](2,1), 10)) // リュカ数を10個表示
List(0, 1, 1, 2, 3, 5, 8, 13, 21, 34)
List(2, 1, 3, 4, 7, 11, 18, 29, 47, 76)

パスカルの三角形

・二項展開における係数を三角形状に並べたもの。

def pas03(n: Int): List[List[Int]] = {
  (0.to(n-1)).foldLeft(List(List(1))){(i,j)=>
    if (j<1) i else i:+(0+:i.last).zip(i.last:+0).map(a=>a._1+a._2)
  }
}

println(pas03(10)) // パスカルの三角形を10段表示
List(List(1), List(1, 1), List(1, 2, 1), List(1, 3, 3, 1), List(1, 4, 6, 4, 1), List(1, 5, 10, 10, 5, 1), List(1, 6, 15, 20, 15, 6, 1), List(1, 7, 21, 35, 35, 21, 7, 1), List(1, 8, 28, 56, 70, 56, 28, 8, 1), List(1, 9, 36, 84, 126, 126, 84, 36, 9, 1))

終わりに

以上、scalaを使っていくつかの数列を書き出してみました。

今回参考にしたのは、この書籍です。

図書館で借りました。わかりやすいですよ。

というわけで、今回はこれにて。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする

野村 野村のプロフィール
メインPCはWindows10のVirtualBox上のFreeBSD。Linux/Unixの小ネタを求めて日々右往左往してたりする。