Fizzbuzz の定番は, 3n, 5n の2種類だが、今回は 7nを追加して3種類にした。以下のコードは、仮に素数が 100種類だったとしても大して長くならないだろう。
Fizzbuzz問題
以下の Fizzbuzz 問題の C/C++ プログラムを書け。
-
数値1から 200 までインクリメント出力する。ただし 下記2. の条件を満たす場合はインクリメント数値ではなく下記2.を出力する。
-
素数 3, 5, 7 についてそれぞれの倍数である場合は 「(素数) n」と出力する。ただしこれら素数の最小公倍数である場合はそちらを優先し「(最小公倍数) n」と出力する。(e.g.参照)
e.g. 210 なら 105n, 70 なら 35n, 63 なら 021n, 14 なら 07n, 30 なら 015n, 10 なら 005n, 6 なら 003n
ビット演算を使う方法
ビット演算を使う方法
#include <iostream>
using namespace std;
int main(void){
char *name[] = { "(reserved)" , "3n" , "5n", "15n", "7n", "21n", "35n", "105n"};
int idx;
for (int n = 1; n <= 200; n++) {
idx= 7*(n !=0) & 4*(n%7 == 0) + 2*(n%5 == 0)+ 1* (n%3 == 0); //入力数字の条件分岐に相当する処理
idx==0 ? cout<< n : cout << name[idx]; cout << endl;
}
}
ビット演算を用いると Fizz-Buzz の条件分岐は ほとんど 1行で済む。条件ごとに 2^n のマスクを取ること。
これは Cじゃなくても同じように書ける。
別解1:三項演算子とポインタ
別解1:三項演算子とポインタ
#include <stdio.h>
int main(){
char *str="105n\n\0 35n\n\0 21n\n\0 15n\n\0 7n\n\0 5n\n\0 3n\n\0 %d\n\0";
for(int i=0;++i<=200;){
printf(str+(i%105?i%35?i%21?i%15?i%7?i%5?i%3?40:35:30:25:19:13:7:0),i);
}
}
これは printf 関数の仕様に、フォーマット指定子があることとそれが char* であることを利用した、ポインタ演算に依る。
char* str は定義せず、printf に直接書いてもよい。
補遺:多次元配列を用いた書き方
#include <iostream>
using namespace std;
int main(void){
char idx;
for (int n = 1; n <= 200; n++) {
idx= (char[2][2][2]){'-', 'B', 'C', 'D','E', 'F', 'G', 'H'}[n%7 == 0][n%5 == 0][n%3 == 0];
(idx =='-' || n ==0) ? cout<< n : cout << idx; cout << endl;
}
}
これは題意には沿わない
元記事