2009年10月8日木曜日

第15回 配列① FizzBuzz

お題:
FizzBuzzプログラムを作る。
①数を1からカウントしていく
②カウントする上限を尋ねる
③3の倍数の時、「Fizz」と表示
④5の倍数の時、「Buzz」と表示
⑤3と5の倍数の時、「FizzBuzz」と表示

プログラム実行例:

image

必須事項:
・配列を利用する事

ヒント:
・まず、配列をたくさん用意して、3の倍数、5の倍数、3と5の倍数、それ以外に分類します
・実行例は改行しましたが、あってもなくてもいいです
・配列に関しては第11回の予備知識を参考にしてください

解答は10月10日に掲載します。それまでにプログラムを作成し、
・プログラム文
・その実行ファイル
をメールに添付して以下のアドレスに送ってください。

解答、質問はこちらまで
cosmo-cleaner@za.pial.jp

---------------------------------------------------------------

解答例

1

2
3

4
5

6
7
8
9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

#include <stdio.h>

int main () {
    int a[1000],i,n,k;

    puts("いくつまでfizzbuzzを行いますか?");
    printf("n=");    scanf("%d",&n);

    for(i=0;i<=n;i++){
        a[i]=0;
    }
    for(i=1;3*i<=n;i++){
        a[3*i]=1;
    }
    for(i=1;5*i<=n;i++){
        a[5*i]=2;
    }
    for(i=1;3*5*i<=n;i++){
        a[3*5*i]=3;
    }

    k=1;
    for(i=1;i<=n;i++){
        if(a[i] == 0 )
            printf("%d ",i);
        else if (a[i] == 1)
            printf("fizz ");
        else if (a[i] == 2)
            printf("buzz ");
        else if (a[i] == 3)
            printf("fizzbuzz ");

       if (i == 10*k) {
            printf("\n");
            k++;
        }
    }
}

実行例は上と同じです。

解説

今回使った変数とその役割

a[1000]
i
n
k
数字の属性を記憶する変数
カウントアップする数字そのもの、または倍数処理に利用
カウントアップする数字の上限
数字が10個並んだら改行するための変数

このプログラムは、数字と配列を対応させて、配列に数字の属性を印していきます。
例えば、数字の7なら配列a[7]に7の属性を印します。

この印付けを行っているのが6から17行目の命令です。
まず、a[0]からa[n]までの配列に0をとりあえず入れていきます。
次に、3の倍数の配列に1を入れていきます。
次に、5の倍数の配列に2を入れていきます。
最後に、3と5の倍数の配列に3を入れていきます。
つまり、
0の印が付いた数字はただの数、
1の印が付いた数字は3の倍数、
2の印が付いた数字は5の倍数、
3の印が付いた数字は3と5の倍数、
という事になります。
印をどんどん上書きしていきます。

赤いif文で数字ごとの印を判別してfizz,buzz,fizzbuzzを表示させています。
青いif文は改行用です。iをカウントアップして10の倍数に至った時に、改行を入れます。見やすくするために入れました。

答えられる範囲で質問いつでも受け付けます。
cosmo-cleaner@za.pial.jp

2009年9月29日火曜日

第14回 for文③ 多重ループ

お題:
原点を通る一次関数(y=a*x)のグラフを■で表現する。グラフはx,y軸が正の領域(第一象限)のみ。
①初めにグラフの規模(n*n)を尋ね、設定する。nは整数で、n<100。
②一次関数の傾きaを尋ね、設定する。aは小数点にも対応する。
③グラフを描く。

プログラム実行例:
imageimageimage

必須事項:
・for文を2回以上使う事

注意事項:
・if文なども駆使してください
・全角記号□と■は半角数字の2個分のスペースです
・表現方法はたくさんあるので、上の実行例と全く同じにしなくても大丈夫です

解答は10月3日に掲載します。それまでにプログラムを作成し、
・プログラム文
・その実行ファイル
をメールに添付して以下のアドレスに送ってください。

解答、質問はこちらまで
cosmo-cleaner@za.pial.jp

---------------------------------------------------------------

解答例

1

2
3
4

5
6
7
8

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32

#include <stdio.h>

int main () {
    int n,x,y;
    double a;

    puts("グラフの規模は? n×n");
    printf("n=");    scanf("%d",&n);
    printf("\n直線の傾きは?\n");
    printf("a=");    scanf("%lf",&a);

    for(y=n;y>=0;y--){
        if (y > 9)
            printf("%d",y);
        else
            printf(" %d",y);
       for(x=0;x<=n;x++){
            if (a*x >= y && a*x <y+1){
                printf("■");
            }
            else if (x >= y/a && x - 1< y/a)
                printf("■");
            else
                printf("□");
        }
        printf("\n");
    }

    printf("  ");
    for(x=0;x<=n;x++) {
        if (x < 10)
            printf("%d ",x);
        else
            printf("%d",x);
    }
}

実行例は上と同じです

解説

今回使った変数とその役割

n
x
y

a
グラフの規模(x,y軸の表示する範囲)
xの値
yの値
直線の傾き

紫のfor文はy軸で、青いfor文はx軸です。
グラフはy軸正方向(上)から描いていくので、for文も上からに設定します。なので9行目の通り、y=nから始まり、y=0になるまで1づつ降りて行きます。

青いfor文はx=0からx=nまで1づつ増やしながら■か□を1つづつ表示していきます。
考え方としては、下の図のようなイメージです。
image

現在紫のfor文で実行中のyの値とa*xがぶつかった所に■、それ以外には□を表示します。yは整数なのでa*xが小数の時にも対応するため、15行目のように、”1”の大きさの範囲を設けます。

18行目は直線が途切れなく表示されるためのif文です。これが無いと以下のようになります。

image

なぜ空白があくかというと、下の図のようなイメージです。

image

この時、現在のyに注目し、図の緑の点が現在のxの範囲に入っているかどうかを検討します。それが18行目です。
これさえあれば15行目はいらないのでは?と思うかもしれませんが、18行目だけだと傾きaが1以下の時に、同じような空白が出る現象が起こります。

答えられる範囲で質問いつでも受け付けます。
cosmo-cleaner@za.pial.jp