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

はじめに

こんにちは、野村です。

今回は、c++を使っていくつかの数列を書き出してみます。

forやwhileを使用せず、STLのアルゴリズム関数を使って書いてみました。

実行

ソースファイルをVimで開いてコマンドモードで以下のコマンドを実行する。

:!g++ -std=c++11 %; ./a.out

素数

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

#include <iostream>
#include <algorithm>
#include <vector>
#include <math.h>
#include <numeric>
using namespace std;

vector<int> loop(vector<int> a){
  int min = a[0];
  if (min > sqrt(a[a.size()-1])) return a;
  vector<int> c;
  copy_if(a.begin(), a.end(), back_inserter(c), [min](int i){return i%min!=0;});
  vector<int> d = loop(c);
  d.insert(d.begin(),min);
  return d;
}

vector<int> sosu(int c){
  vector<int> a(c-2);
  iota(a.begin(), a.end(), 2);
  return loop(a);
}

void disp(vector<int> a){
  for (auto i: a) cout<<i<<" ";
  cout<<endl;
}

int main(void){
  disp(sosu(100)); // 100未満の素数を表示
  return 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つの素数の組

#include <iostream>
#include <algorithm>
#include <vector>
#include <math.h>
#include <numeric>
using namespace std;

vector<int> loop(vector<int> a, int i, int f){
  vector<int> c;
  copy_if(a.begin(), a.end(), back_inserter(c), [i](int x){return x<=sqrt(i);});
  bool b0 = all_of(c.begin(), c.end(), [i](int x){return i%x!=0;});
  if (b0) {
    a.push_back(i);
    bool b1 = any_of(a.begin(), a.end(), [i,f](int x){return x==i-f;});
    if (b1) return a;
  }
  return loop(a, i+1, f);
}

void disp(vector<int> a, int f){
  for (auto i: a) cout<<"("<<i-f<<","<<i<<") ";
  cout<<endl;
}

void twin(int f, int c){
  auto lmd = [f](vector<vector<int>> x, int y){
    vector<int> z = loop(x[0], x[0][x[0].size()-1]+1, f);
    x[1].push_back(z[z.size()-1]);
    vector<vector<int>> r = {z,x[1]};
    return r;
  };
  vector<vector<int>> i = {{2},{}};
  vector<int> a(c);
  auto r = accumulate(a.begin(), a.end(), i, lmd);
  disp(r[1], f);
}

int main(void){
  twin(2,10); // 双子素数を10組表示
  twin(4,10); // いとこ素数を10組表示
  twin(6,10); // セクシー素数を10組表示
  return 0;
}
(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)

幸運数

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

#include <iostream>
#include <algorithm>
#include <vector>
#include <numeric>
using namespace std;

vector<int> luc(vector<int> a, int i){
  a.insert(a.begin(),0);
  int s = a[i];
  int l = a.size();
  if (s<=l) {
    vector<int> m(l);
    iota(m.begin(), m.end(), 0);
    vector<int> n;
    copy_if(m.begin(), m.end(), back_inserter(n), [s](int v){return v%s!=0;});
    transform(n.begin(), n.end(), n.begin(), [a](int v){return a[v];});
    return luc(n,i+1);
  }
  a.erase(a.begin());
  return a;
}

void disp(vector<int> a){
  for (auto i: a) cout<<i<<" ";
  cout<<endl;
}

int main(void){
  vector<int> a(100); // 100未満の幸運数を表示
  iota(a.begin(), a.end(), 0);
  vector<int> b;
  copy_if(a.begin(), a.end(), back_inserter(b), [](int i){return i%2!=0;});
  disp(luc(b,2));
  return 0;
}
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 までのすべての整数の積。

#include <iostream>
#include <algorithm>
#include <vector>
#include <numeric>
using namespace std;

vector<int> fact(int c){
  vector<int> a(c);
  iota(a.begin(), a.end(), 0);
  transform(a.begin(), a.end(), a.begin(), [](int x){
    vector<int> b(x);
    iota(b.begin(), b.end(), 1);
    return accumulate(b.begin(), b.end(), 1, [](int m, int n){return m*n;});
  });
  return a;
}

void disp(vector<int> a){
  for (auto i: a) cout<<i<<" ";
  cout<<endl;
}

int main(void){
  disp(fact(10)); // 階乗を10個表示
  return 0;
}
1 1 2 6 24 120 720 5040 40320 362880

フィボナッチ数

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

#include <iostream>
#include <algorithm>
#include <vector>
#include <numeric>
using namespace std;

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);
}

vector<int> fib(int a, int b, int c){
  vector<int> m(c);
  iota(m.begin(), m.end(), 0);
  transform(m.begin(), m.end(), m.begin(), [a,b](int i){return loop(a,b,i);});
  return m;
}

void disp(vector<int> a){
  for (auto i: a) cout<<i<<" ";
  cout<<endl;
}

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

パスカルの三角形

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

#include <iostream>
#include <algorithm>
#include <vector>
#include <numeric>
using namespace std;

vector<int> pas(int c){
  if (c==0) return {1};
  vector<int> b = pas(c-1);
  b.insert(b.begin(),0);
  b.push_back(0);
  vector<int> r(b.size()-1);
  iota(r.begin(), r.end(), 0);
  transform(r.begin(), r.end(), r.begin(), [b](int i){
    return b[i]+b[i+1];
  });
  return r;
}

void disp(vector<int> a){
  for (auto i: a) cout<<i<<" ";
  cout<<endl;
}

int main(void){
  vector<int> c(10); // パスカルの三角形を10段表示
  iota(c.begin(), c.end(), 0);
  for (auto i: c) disp(pas(i));
  return 0;
}
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

最後に

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

STLのアルゴリズム関数については、以下の書籍を参考にしました。

『ゲームプログラマのためのコーディング技術』(技術評論社)
ゲーム制作以外でも参考になります。
他の言語に触れた経験があって、これからc++を独学で習得しようと思っている人におすすめ。

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

シェアする

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

フォローする

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