【C/C++】Twitterで広まっている"あの"問題をC言語で解く
タイトル通りです.
113RT @9rocs: 解けたらrt pic.twitter.com/E2XPIyrwLN
— ふじおサンタ (@fujioburger) 2014, 1月 3
こんな感じのやつです.もちろん法則性を見つけること自体は簡単ですが,これを公式にしろと言われたらどうでしょう.
(x-y)と(x+y)がくっついてるだけじゃん?と.そうです.とりあえず書いてみましょう.
int Calc(int x, int y){ return (x-y)*10 + (x+y); }
これで7と2,6と3などは対処できています.ですが,8と6などはどうでしょう.
桁上りが発生してうまくいかないと思います.
ではどうすればいいか.簡単な話で,(x+y)の桁数を調べることができればいいわけです.
調べた桁数分左に(x-y)をずらせばいいわけですから.
そこで,桁を調べる方法を考えます.と言っても分かる人にはすぐわかるでしょう.
log10ですね.ただし,そのまま使うと小数なので,切り捨てて整数として使ってしまいましょう.
切り捨てるにはintでキャストしてやればOKです.
以上のことを考慮すると以下のコードになります.
int Calc(int x, int y){ return (x-y)*pow(10, (int)log10(x+y)+1) + (x+y); }
pow(a, b)はaのb乗を表します.つまり,10の(int)log10(x+y)+1乗です.
これで値を渡せば正確に算出することができるようになりました.
上記ツイートには記載されていないので挙動が分かりませんが,x < yにすると変な感じになります.あとは両方マイナスの時とか.こういった挙動を防ぎたいのなら,こうすれば問題はないでしょう.
int Calc(unsigned int x, unsigned int y){ return abs(x-y)*pow(10, (int)log10(x+y)+1) + (x+y); }
absは絶対値に直す関数です.
これで算出することができるようになりました.scanfで値を読み込んで,表示するプログラムを書くことは容易ですのでいちいち書かなくてもいいでしょう.
余談ですが,文字で管理するととたんに簡単になります.
// c# String Calc(uint x, uint y){ return Math.abs(x-y).ToString() + (x+y).ToString(); }
これだけ.簡単ですね.