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++を独学で習得しようと思っている人におすすめ。

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

シェアする

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

フォローする

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