Project Euler 33
49/98は面白い分数である. 「分子・分母の9をキャンセルしたので 49/98 = 4/8 が得られた」と経験を積んでいない数学者が誤って思い込んでしまうかもしれないからである. 我々は 30/50 = 3/5 のようなタイプは自明な例だとする. 1より小さく分子・分母がともに2桁の数になるような自明でない分数は 4個ある. その4個の分数の積が約分された形で与えられたとき, 分母の値を答えよ.
Mathematica
ans = {}; For[i = 11, i < 100, i++, For[j = 10, j < i, j++, If[GCD[j, i] != 1 != 10 != 20 != 30 != 40, tmp = Intersection[IntegerDigits[i], IntegerDigits[j]]; If[Length[tmp] != 0, i2 = FromDigits[DeleteCases[IntegerDigits[i], tmp[[1]]]]; j2 = FromDigits[DeleteCases[IntegerDigits[j], tmp[[1]]]]; If[j2/i2 == j/i, ans = Append[ans, {j, i}], {}] ] ] ] ] ans
tmpにはi(分母)とj(分子)で共通している数字が入ります。
i2, j2はそれぞれiとjから共通する数字を消し去った数で、 j2/i2 と j/i が同じ数かどうかを最後のIf文で判定しています。
「無限式が見つかりました」「不定式0ComplexInfinityが見付かりました」のエラーが出ますが無視!
とっても綺麗な答えになります。
C/C++
#include <iostream> #include <deque> #include <algorithm> using namespace std; // xを各桁ごとにばらしてdequeに挿入する。 deque<int> integerDigits(int x){ deque<int> arr; while(x!=0){ arr.push_front(x%10); x/=10; } return arr; } int main(){ deque<int> arra, arrb, v(100); deque<int>::iterator it; for(int a=11; a<99 ; a++){ for(int b=11; b<99 ; b++){ if(a==b || (a%10==0 && b%10==0)) continue; arra.clear(); arrb.clear(); arra = integerDigits(a); arrb = integerDigits(b); sort(arra.begin(), arra.end() ); sort(arrb.begin(), arrb.end() ); it = set_intersection(arra.begin(), arra.end(), arrb.begin(), arrb.end(), v.begin()); if(v.begin() != it){ for(deque<int>::iterator itt=v.begin(); itt != it ; itt++){ remove(arra.begin(), arra.end(), *itt); remove(arrb.begin(), arrb.end(), *itt); } if(arrb[0]==0) break; double k1=(double)a/(double)b; double k2=(double)arra[0]/(double)arrb[0]; if(k1 == k2){ cout << b << "/" << a << endl; cout << arrb[0] << "/" << arra[0] << endl; } } } } int end; cin >> end; }
久しぶりです、ここまで完璧に「ゴミだ!」と思うプログラムは。
途中でありえない反則をしています。2桁でない場合は流用できないし、表示は仮初めで正しいかも知れないけど・・・うう、未解決タグをつけておこう・・・