はじめに
こんにちは、野村です。
今回は、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++を独学で習得しようと思っている人におすすめ。
というわけで、今回はこれにて。