覆面算の計算で各桁をテンプレートで生成してやることにした.これでソースは見やすくなった.しかも,全部を展開してあった前のコードより若干速いらしい.ちなみに,関数テンプレートの部分特化(Partial Specialization)は禁止されているようなので,部分的にインスタンス化するため仕方なくクラスを使う羽目になった.ま,次は答えをテンプレートで生成だな.
#include <iostream> using namespace std; template<const int m, const int l> class Calc{ public: inline void calc(unsigned int &x, unsigned int &y, unsigned int (&digits)[m]) { const int n = m/4*3 - l*3; unsigned int d0 = digits[n]; for(int i0 = n; i0 < m; i0++){ digits[n] = digits[i0]; digits[i0] = d0; x = (digits[n]<<(4*(n/3))) | (x&((1<<(4*(n/3)))-1)); unsigned int d1 = digits[n+1]; for(int j0 = n+1; j0 < m; j0++){ digits[n+1] = digits[j0]; digits[j0] = d1; y = (digits[n+1]<<(4*(n/3))) | (y&((1<<(4*(n/3)))-1)); if(n==0 && y >= x) { // omit symmetric pattern digits[j0] = digits[n+1]; continue; } unsigned int z1 = ((x * y) >> (4*(n/3)))& 0xf; int k1 = n+2; for(; k1 < m; k1++) if (digits[k1]==z1) break; if(k1 >= m) { digits[j0] = digits[n+1]; continue; } digits[k1] = digits[n+2]; digits[n+2] = z1; Calc<m,l-1>().calc(x, y, digits); digits[n+2] = digits[k1]; digits[k1] = z1; digits[j0] = digits[n+1]; } digits[n+1] = d1; digits[i0] = digits[n]; } x &=((1<<(4*(n/3)))-1); digits[n] = d0; } }; template<const int m> class Calc<m,0>{ public: inline void calc(unsigned int &x, unsigned int &y, unsigned int (&digits)[m]) { const int n = m/4*3; unsigned int z4 = ((x * y) >> (4*(n/3))); unsigned int ds[m-n]; for(int i = 0; i < (m-n); i++){ ds[i] = digits[i+n]; } int i = 0; for(; i < m-n; i++){ int k4 = i; unsigned int z5 = z4&0xf; z4>>=4; for(; k4 < m-n; k4++) if (ds[k4]==z5) break; if(k4 >= m-n) break; ds[k4] = ds[i]; } if(i >=m-n && ds[m-n-1]!=0){ cout << x << " * " << y << " = " << x*y << endl; cout << y << " * " << x << " = " << x*y << endl; } } }; int main(int argc, char *argv[]) { const int m = 16; cout << hex; unsigned int digits[m]; for(int i = 0; i < m; i++){ digits[i] = i; } unsigned int x = 0; unsigned int y = 0; Calc<m,m/4>().calc(x,y,digits); return 0; }
- Newer: ことはじめ