Javaを使っていろんな数列を表示してみる

はじめに

こんにちは、野村です。

今回は、Javaを使っていくつかの数列を表示させてみます。

普通に書くのは面白くないので、ループ(forやwhile)を禁止してみました。

しかし、ソースがやたらと長くなるのは何とかならないものだろうか?

インストールと実行

インストール

環境はdebian9.2です。
とりあえず、現在のJavaのバージョンを表示してみたら

$ java -version
openjdk version "1.8.0_151"
OpenJDK Runtime Environment (build 1.8.0_151-8u151-b12-1~deb9u1-b12)
OpenJDK 64-Bit Server VM (build 25.151-b12, mixed mode)
$ javac -version
bash: javac: コマンドが見つかりません

javacがなかった。
なので、default-jreとdefault-jdkをインストールしてみる。

$ sudo apt install default-jre
$ sudo apt install default-jdk
$ java -version
openjdk version "1.8.0_151"
OpenJDK Runtime Environment (build 1.8.0_151-8u151-b12-1~deb9u1-b12)
OpenJDK 64-Bit Server VM (build 25.151-b12, mixed mode)
$ javac -version
javac 1.8.0_151

入りました。

実行

例えば、「sosu00.java」というファイルの場合、
ファイルをVimで開いて、コマンドモードに入って以下のコードを実行する。

:!javac %; java sosu00

素数

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

import java.util.stream.Stream;
import java.util.stream.IntStream;
import java.util.stream.Collectors;
import java.util.List;

public class sosu01{
  private static List<Integer> sosu(List<Integer> b, int i){
    int m = b.get(i);
    if (m > Math.sqrt(b.get(b.size()-1))) return b;
    return sosu(b.stream().filter(v -> (v%m!=0) || (v==m) )
        .collect(Collectors.toList()), ++i);
  }

  private static void disp(List<Integer> a){
    a.forEach(b->System.out.print(b+" "));
    System.out.println();
  }

  public static void main(String[] args){
    List<Integer> a = IntStream.range(2,100) // 100未満の素数を表示
      .boxed().collect(Collectors.toList());
    disp(sosu(a, 0));
  }
}
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 java.util.stream.Stream;
import java.util.stream.IntStream;
import java.util.ArrayList;
import java.util.List;

public class twin02{
  private static Boolean chk(int a){
    return IntStream.range(2,a).filter(v -> a%v==0).count() == 0;
  }

  private static List<int[]> loop(List<int[]> a, int f, int c, int i){
    if (c<1) return a;
    if (chk(i) && chk(i+f)){
      int[] b = {i, i+f};
      a.add(b);
      --c;
    }
    return loop(a, f, c, i+1);
  }

  private static List<int[]> twin(int f, int c){
    List<int[]> p = new ArrayList<int[]>();
    return loop(p, f, c, 2);
  }

  private static void disp(List<int[]> a){
    a.forEach(b->System.out.print("("+b[0]+","+b[1]+") "));
    System.out.println();
  }

  public static void main(String[] args){
    disp(twin(2,10)); // 双子素数を10組表示
    disp(twin(4,10)); // いとこ素数を10組表示
    disp(twin(6,10)); // セクシー素数を10組表示
  }
}
(3,5) (5,7) (11,13) (17,19) (29,31) (41,43) (59,61) (71,73) (101,103) (107,109)
(3,7) (7,11) (13,17) (19,23) (37,41) (43,47) (67,71) (79,83) (97,101) (103,107)
(5,11) (7,13) (11,17) (13,19) (17,23) (23,29) (31,37) (37,43) (41,47) (47,53)

幸運数

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

import java.util.stream.IntStream;
import java.util.stream.Collectors;
import java.util.List;

public class lucky00{
  private static List<Integer> luc(List<Integer> a, int i){
    a.add(0,0);
    int s = a.get(i);
    int l = a.size();
    if (s<=l) {
      List<Integer> m = IntStream.range(0,l).filter(v->v%s!=0)
        .map(v->a.get(v)).boxed().collect(Collectors.toList());
      return luc(m,i+1);
    }
    a.remove(0);
    return a;
  }

  private static void disp(List<Integer> a){
    a.forEach(b->System.out.print(b+" "));
    System.out.println();
  }

  public static void main(String[] args){
    List<Integer> a = IntStream.range(0,100).filter(v->v%2!=0)
      .boxed().collect(Collectors.toList());
    disp(luc(a,2));
  }
}
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 までのすべての整数の積。

import java.util.stream.IntStream;

public class fact00{
  private static void disp(IntStream a){
    a.forEach(b->System.out.print(b+" "));
    System.out.println();
  }

  public static void main(String[] args){
    IntStream a = IntStream.range(0,10).map(v->{ // 階乗を10個表示
      return IntStream.range(1,v+1).reduce(1,(i,j)->i*j);
    });
    disp(a);
  }
}
1 1 2 6 24 120 720 5040 40320 362880

フィボナッチ数

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

import java.util.stream.IntStream;

public class fibo00{
  private static int loop(int a, int b, int c){
    if (c==0) return a;
    if (c==1) return b;
    return loop(a,b,c-2)+loop(a,b,c-1);
  }

  private static IntStream fibo(int a, int b, int c){
    return IntStream.range(0,c).map(v->loop(a,b,v));
  }

  private static void disp(IntStream a){
    a.forEach(b->System.out.print(b+" "));
    System.out.println();
  }

  public static void main(String[] args){
    disp(fibo(0,1,10)); // フィボナッチ数を10個表示
    disp(fibo(2,1,10)); // リュカ数を10個表示
  }
}
0 1 1 2 3 5 8 13 21 34
2 1 3 4 7 11 18 29 47 76

パスカルの三角形

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

import java.util.stream.IntStream;
import java.util.stream.Collectors;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;

public class pas00{
  private static List<Integer> pas(int a){
    if (a==0) return new ArrayList<Integer>(Arrays.asList(1));
    List<Integer> b = pas(a-1);
    b.add(0,0);
    b.add(b.size(),0);
    return IntStream.range(1,b.size()).map(v->b.get(v-1)+b.get(v))
      .boxed().collect(Collectors.toList());
  }

  private static void disp(List<Integer> a){
    a.forEach(b->System.out.print(b+" "));
    System.out.println();
  }

  public static void main(String[] args){
    IntStream.range(0,10).forEach(v->disp(pas(v))); // パスカルの三角形を10段表示
  }
}
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1

最後に

以上、Javaを使っていくつかの数列を表示させてみました。

もっとソースを短く、わかりやすくできるはず。
Stream APIを勉強して書き直すかも。

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

シェアする

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

フォローする

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