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を勉強して書き直すかも。

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

シェアする

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

フォローする

野村 野村のプロフィール
枕は高いほうがいい。高いほうが本を読みやすいのですよ。なので広めのタオルケットを何重にも折りたたんでその上に枕を載せてその上に頭を載せてたりする。twitterやってます