はじめまして!大学の課題なんですが、お願いします。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ルーク

はじめまして!大学の課題なんですが、お願いします。

#1

投稿記事 by ルーク » 18年前

nCr において,n=0~6の全ての組み合わせについて求めるプログラムを作成しなさい。

表示例

0C0 = 1

1C0 = 1 1C1= 1

2C0 = 1 2C1 = 2 2C2 = 1

3C0 = 1 3C1 = 3 3C2 = 3 3C3 = 1

4C0 = 1 4C1 = 4 4C2 = 6 4C3 = 4 ・・・

・・・・

という問題なのですが、以下のように自分はプログラムを考えたのですが、
うまく実行できません。どこが間違ってるのでしょうか?

#include<stdio.h>

main(){
int n,r,nC0,a;
for(n=0;n<7;n++){
for(r=0;r<=n;r++){
nC0=1;
a=nC0;
a=(n-r+1)/r*a;
}
}
printf("%dC%d=%d\n",n,r,a);
}

box

Re:はじめまして!大学の課題なんですが、お願いします。

#2

投稿記事 by box » 18年前

> nCr において,n=0~6の全ての組み合わせについて求めるプログラムを作成しなさい。

まずは、nとrで制御する二重のループで、
下記のように出力するコードを書いてみてください。
等号の右にはnCrの値を出力しますが、その方法は別途考えるということで。
0C0= 

1C0= 1C1= 

2C0= 2C1= 2C2= 

3C0= 3C1= 3C2= 3C3= 

4C0= 4C1= 4C2= 4C3= 4C4= 

5C0= 5C1= 5C2= 5C3= 5C4= 5C5= 

6C0= 6C1= 6C2= 6C3= 6C4= 6C5= 6C6=

ルーク

C言語はすごく苦手なので申し訳ありませんが、詳しくやり方を説明していただきたいのですが

#3

投稿記事 by ルーク » 18年前

すみません、二重ループ自体が苦手なのでわからないです。
あと、上から順序良く表示させる方法もわからなです。配列とか使うんですかね?

box

Re:C言語はすごく苦手なので申し訳ありませんが、詳しくやり方を説明していただきたいのですが

#4

投稿記事 by box » 18年前

> すみません、二重ループ自体が苦手なのでわからないです。
> あと、上から順序良く表示させる方法もわからなです。配列とか使うんですかね?

初めに投稿されたコードの、nとrに関する二重のfor文の書き方は正しいです。
ループの中身はちょっと問題ありでしたけど。
以下に示す回答の内容が理解できたら、ループの中身をどう書くかについて別途説明します。
なお、配列を使わなくても今回の問題は解けます。

私が前に回答した出力例を上から順に見てください。
先頭の行はnが0の場合です。
次の行はnが1の場合です。という具合にnが1ずつ増えていって、
一番下の行はnが6の場合です。

さて、今度は各行を右へ見ていきます。
rが0から始まって、どこまであるかというと、その行のnまであります。
よって、二重のfor文は、
nに関するfor文:0~6
各々のnについての、rに関するfor文:0~n
となります。最初の投稿で書かれたfor文の書き方の正しいことがわかります。
ここまではいいですか?

管理人

Re:C言語はすごく苦手なので申し訳ありませんが、詳しくやり方を説明していただきたいのですが

#5

投稿記事 by 管理人 » 18年前

> すみません、二重ループ自体が苦手なのでわからないです。

苦手なのでしたら是非克服してください^^
苦手な分野があればプログラムの場合、

「概念を解説書である程度理解する」→「とにかく自分でプログラムを書いてみる」

の繰り返してマスターできるはずですよ♪

2重ループと言うのは以下の場合、今変数iとjがあったとき、iが1増える間にjは10増える、iが10増える間にjは100増えるといった関係が有ります。
for(i=0;i<10;i++){
    for(j=0;j<10;j++){
        //処理
    }
}
では、このように書いたとき、出力はどうなるでしょうか?
for(i=0;i<10;i++){
    for(j=0;j<10;j++){
        printf("%d %d\n",i,j);
    }
}
出力される結果を想像してみてください。

0 0
0 1
0 2
0 3
0 4
0 5
0 6
0 7
0 8
0 9
0 10
1 0
1 1
1 2
(・・略・・)

こんな感じになるはずですね。では、2重ループを使って、y=xのグラフを書いてみましょう。
for(x=0;x<10;x++){
    for(y=0;y<10;y++){
        if(x==y)
            printf("*");
        else
            printf(" ");
    }
    printf("\n");
}
座標がxが0~10、yが0~10(正確には9まで)の格子点は100個ありますね?
xが0の間にyは0~10を調べ、xが1の間にyは0~10をしらべ・・
つまりこの2重ループで100個全ての格子点が調べられます。
その時、yとxが同じ時に「*」を書き、そうでないときに、「 」(スペース)を書けば、
直線のグラフがかけると思いませんか?

ご自分で実際にコンパイルしてみてください。

苦手な分野があれば、それを使わないようにするのではなく、是非克服してみてください^^

ルーク

返信遅れました。

#6

投稿記事 by ルーク » 18年前

はい、そこまでは、わかります。

box

Re:返信遅れました。

#7

投稿記事 by box » 18年前

nとrで制御する二重ループの中身の説明です。
例えば、nが3のときにはこんな行を出力する必要があるわけですね。

> 3C0= 3C1= 3C2= 3C3= 

右辺の内容はさておくとして、左辺と等号までの内容をnとrを
使って書くと、どうなるでしょうか。
Cの左に来るのがnで、右に来るのがrですね。
出力するためのprintf関数の書き方は、例えばこんな感じです。

	printf("%dC%d= ", n, r);

1行分出力し終わったら、つまりrに関するループを抜けたら、
改行します。

ここまではいいですか?
理解できたら、私boxが1月31日の21:13に投稿した出力例のための
コードを書いてみてください。

ルーク

一応書きましたが、これであってますか??

#8

投稿記事 by ルーク » 18年前

#include<stdio.h>
main(){
int n,r;
for(n=0;n<7;n++){
for(r=0;r<=n;r++){
printf("%dC%d= ",n,r);
}
}
}

box

Re:一応書きましたが、これであってますか??

#9

投稿記事 by box » 18年前

サンプルコードを2つほど提示します。解読してみてください。

【1個目】
#include <stdio.h>

int ncr(int n, int r);
int kaijou(int n);

int main(void)
{
	int n, r;
	
	for (n = 0; n <= 6; n++) {
		for (r = 0; r <= n; r++)
			printf("%dC%d=%2d  ", n, r, ncr(n, r));
		printf("\n\n");
	}
	return 0;
}

/* nCrを計算する関数 */
int ncr(int n, int r)
{
	return kaijou(n) / kaijou(r) / kaijou(n-r);
}

/* 階乗を計算する関数 */
int kaijou(int n)
{
	if (n == 0)
		return 1;
	else
		return n * kaijou(n-1);
}


【2個目】
#include <stdio.h>

int ncr(int n, int r);

int main(void)
{
	int n, r;
	
	for (n = 0; n <= 6; n++) {
		for (r = 0; r <= n; r++)
			printf("%dC%d=%2d  ", n, r, ncr(n, r));
		printf("\n\n");
	}
	return 0;
}

/* nCrを計算する関数(パスカルの三角形) */
int ncr(int n, int r)
{
	if (r == 0 || n == r)
		return 1;
	else
		return ncr(n-1, r-1) + ncr(n-1, r);
}

ルーク

丁寧な返信どうもありがとうございます。

#10

投稿記事 by ルーク » 18年前

わかりました!◎
自分は、nCr=(n-r+1)/r*nCr-1 という式を用いて、
ループを回した感じでしあげたいのですが、その場合はどうしたら
よろしいのですか??

box

Re:丁寧な返信どうもありがとうございます。

#11

投稿記事 by box » 18年前

> 自分は、nCr=(n-r+1)/r*nCr-1  という式を用いて、

考え方はこれまでのサンプルと同じです。
使いたい式をそのまま関数化します。

#include <stdio.h>

int ncr(int n, int r);

int main(void)
{
	int n, r;
	
	for (n = 0; n <= 6; n++) {
		for (r = 0; r <= n; r++)
			printf("%dC%d=%2d  ", n, r, ncr(n, r));
		printf("\n\n");
	}
	return 0;
}

int ncr(int n, int r)
{
	if (r == 0 || n == r)
		return 1;
	else
		return ncr(n, r-1) * (n - r + 1) / r;
}

box

Re:丁寧な返信どうもありがとうございます。

#12

投稿記事 by box » 18年前

> 自分は、nCr=(n-r+1)/r*nCr-1  という式を用いて、

別のサンプルコードです。
これがいちばんシンプルかも。

#include <stdio.h>

int main(void)
{
	int n, r;
	
	for (n = 0; n <= 6; n++) {
		for (r = 0; r <= n; r++) {
			int ncr;
			if (r == 0 || n == r)
				ncr = 1;
			else
				ncr = ncr * (n - r + 1) / r;
			printf("%dC%d=%2d  ", n, r, ncr);
		}
		printf("\n\n");
	}
	return 0;
}

ルーク

どうもありがとうございます!!。

#13

投稿記事 by ルーク » 18年前

これで宿題が解決しました。
また、知識も深まりました。ホントにどうもありがとうございました。
また、お世話になることがありましたらよろしくおねがいします◎

閉鎖

“C言語何でも質問掲示板” へ戻る