Powered by SmartDoc

ソフトウェア概論A/B (2012/11/09)
Ver. 1.0

2012年11月9日
栗野 俊一
kurino@math.cst.nihon-u.ac.jp
http://edu-gw2.math.cst.nihon-u.ac.jp/~kurino/2012/soft/soft.html
ソフトウェア概論 A/B2012年11月9日 の資料

目次

講義資料

当日の OHP 資料

当日のOHP資料です。

講義で利用するサンプルプログラム

sample-001

Download : sample-001.c ( SJIS 版 )

sample-001.c
/*
 * 2012/10/26 sample-001.c
 *		「/*」から「*/」の間は「コメント」であり「空白一つ」と扱われる
 */

#include <stdio.h>
	/*
	 *	printf を利用するために、printf の宣言の入った stdio.h を取り込む
	 */

/*
 *
 */

int main ( void ) {
		/* main 関数の宣言 : 引数はなく(void)、返り値は int 型 */

  /*
   *
   */

   printf ( "Hello, World\n" );
		/* 関数呼出
		 *	関数 printf を一つの引数を渡して呼び出す
		 *		 引数は、文字列を表すポインター値
		 * 結果として、画面上に、文字列が表示され、改行(\n)される
		 */

  /*
   *
   */

	return 0;
		/*
		 * 関数を終了し、値として 0 を返す
		 */

  /*
   *
   */
}

/*
 *
 */
sample-001.c の実行結果
C:\usr\c>sample-001
Hello, World
C:\usr\c> 

sample-002

Download : sample-002.c ( SJIS 版 )

sample-002.c
/*
 * 2012/10/26 sample-002.c
 *
 *	Input-Process-Output 型のプログラム
 *		一つの数を入力し、その二倍を出力する
 */

#include <stdio.h>

/*
 *
 */

int main ( void ) {

  /*
   *	「int」 は「整数型」を表わす。
   */

   int input;	/* 入力する(整数)値を保持するための変数 input の宣言 */
   int output;	/* 計算結果を保持し、出力の時に利用される変数 output の宣言 */

		/*
		 * 変数宣言は、ブロック 「{」〜「}」の先頭で行う必要がある
		 */

  /*
   *	[Input]
   *	キーボードから値を入力する場合は、scanf 関数を使う
   */

   printf ( "整数値を入力してください : " );
   scanf ( "%d", &input );	/* scanf にはポインタ値を渡す必要がある */

  /*
   *	[Process]
   *	代入演算子「=」を利用して、変数の値を変更する(代入する)事ができる
   */

   output = input * 2;	/* output には input の二倍の値が入る */

  /*
   *	[Output]
   *	printf を利用すると、書式を指定する事により、
   *	文字列の中に、数値を埋め込んで出力する事ができる。
   */

   printf ( "%d の二倍は %d です。\n", input, output );
						/* 結果を書式付きで出力 */

  /*
   *
   */

    return 0;

}

/*
 *
 */
入力例
123
sample-002.c の実行結果
C:\usr\c>sample-002<  sample-002.in
整数値を入力してください : 123
123 の二倍は 246 です。
C:\usr\c> 

sample-003

Download : sample-003.c ( SJIS 版 )

sample-003.c
/*
 * 2012/10/26 sample-003.c
 *
 *	Process 部分を関数に任せる
 *		結果は関数の値として得られる
 */

#include <stdio.h>

/*
 *
 */

int calc_twice ( int number ) {

		/*
		 * 関数 calc_twice の宣言
		 *		関数の値の型は int 型
		 *		引数の個数は一個で、その名前は number であり、整数型
		 */

	return number * 2;	/* 計算した値を結果として返す */
}

/*
 *
 */

int main ( void ) {

  /*
   *
   */

   int input;
   int output;

  /*
   *	[Input]
   */

   printf ( "整数値を入力してください : " );
   scanf ( "%d", &input );

  /*
   *	[Process]
   *		処理の内容は、関数 calc_twice に委ねられる
   */

   output = calc_twice ( input );
		/*
		 * 関数呼び出し
		 *		関数 calc_twice に引数として input の値を渡す
		 *		関数の値を、変数 output に代入する
		 */

  /*
   *	[Output]
   */

   printf ( "%d の二倍は %d です。\n", input, output );

  /*
   *
   */

    return 0;

}

/*
 *
 */
入力例
987
sample-003.c の実行結果
C:\usr\c>sample-003<  sample-003.in
整数値を入力してください : 987
987 の二倍は 1974 です。
C:\usr\c> 

sample-004

Download : sample-004.c ( SJIS 版 )

sample-004.c
/*
 * 2012/10/26 sample-004.c
 *
 *	関数は何度でも呼び出す事ができる
 */

#include <stdio.h>

/*
 *
 */

int absolute ( int number ) {

	/*
	 * if 文を利用して、条件判断が可能
	 */

	if ( number < 0 ) {		/* 引数の値が負の値ならば.. */
		return - number;	/* 符号を変えて、返す */
							/* 「- X」は「(-1)*X」と同じ */
	}						/* そうでなければ.. */

	return number;			/* そのまま値を返す */

}

/*
 *
 */

int main ( void ) {

  /*
   *
   */

   int i1;		/* 入力を三つ */
   int i2;
   int i3;

   int o1;		/* 出力も三つ */
   int o2;
   int o3;

  /*
   *	[Input]
   */

   printf ( "一つ目の整数値を入力してください : " );
   scanf ( "%d", &i1 );
   printf ( "二つ目の整数値を入力してください : " );
   scanf ( "%d", &i2 );
   printf ( "三つ目の整数値を入力してください : " );
   scanf ( "%d", &i3 );

  /*
   *	[Process]
   */

   o1 = absolute ( i1 );
   o2 = absolute ( i2 );
   o3 = absolute ( i3 );

  /*
   *	[Output]
   */

   printf ( "%d の絶対値は %d です。\n", i1, o1 );
   printf ( "%d の絶対値は %d です。\n", i2, o2 );
   printf ( "%d の絶対値は %d です。\n", i3, o3 );

  /*
   *
   */

    return 0;

}

/*
 *
 */
入力例
456
-739
0
sample-004.c の実行結果
C:\usr\c>sample-004<  sample-004.in
一つ目の整数値を入力してください : 456
二つ目の整数値を入力してください : -739
三つ目の整数値を入力してください : 0
456 の絶対値は 456 です。
-739 の絶対値は 739 です。
0 の絶対値は 0 です。
C:\usr\c> 

sample-005

Download : sample-005.c ( SJIS 版 )

sample-005.c
/*
 * 2012/10/26 sample-005.c
 *
 *	関数は何度でも呼び出す事ができる
 */

#include <stdio.h>

/*
 *
 */

int factrial ( int number ) {

	/*
	 * 再帰を利用した関数定義
	 */

	if ( number < 1 ) {		/* 引数の値が 1 より小さい値ならば.. */
		return 1;			/* 1 を返す */
	}						/* そうでなければ.. */

	return factrial ( number - 1 ) * number;	/* 再帰的に計算 */
}

/*
 *
 */

int main ( void ) {

   int in[5];
   int out[5];
   int no;			/* 何番目の処理か */

   /*
	*	[Input]
	*/

	no = 0;
	while ( no < 5 ) {				/* while 文で繰り返す */
			/**/
		printf ( "%d 番目の整数値を入力してください : ", no + 1 );
		scanf ( "%d", &in[no] );	/* 「&in[no]」の替わりに「in + no」も可 */
			/**/
		no = no + 1;  				/* no の値を一つふやす */
	}
		/* n 回繰り返す典型的なイデオム */

  /*
   *	[Process]
   */

	no = 0;
	while ( no < 5 ) {
		out[no] = factrial ( in[no] );
		no = no + 1;
	}

  /*
   *	[Output]
   */

	no = 0;
	while ( no < 5 ) {
		printf ( "%d の階乗は %d です。\n", in[no], out[no] );
		no = no + 1;
	}

  /*
   *
   */

    return 0;

}

/*
 *
 */
入力例
3
7
2
0
4
sample-005.c の実行結果
C:\usr\c>sample-005<  sample-005.in
1 番目の整数値を入力してください : 3
2 番目の整数値を入力してください : 7
3 番目の整数値を入力してください : 2
4 番目の整数値を入力してください : 0
5 番目の整数値を入力してください : 4
3 の階乗は 6 です。
7 の階乗は 5040 です。
2 の階乗は 2 です。
0 の階乗は 1 です。
4 の階乗は 24 です。
C:\usr\c> 

sample-006

Download : sample-006.c ( SJIS 版 )

sample-006.c
/*
 * 2012/10/26 sample-006.c
 *
 *	for 文の例 / 蓄積による計算
 */

#include <stdio.h>

/*
 *
 */

int factrial ( int number ) {

	/*
	 * 繰返しを利用した階乗計算
	 */

	int result = 1;

	while ( number > 0 ) {			/* number が 0 より大きいなら */
		result = result * number;	/* result に number をかける */
		number = number - 1;		/* number を 1 減らす */
	}

	return result;					/* 結果を返す */
}

/*
 *
 */

#define	NUMBER_OF_DATA		5	/* define で「マジックナンバー」を消す */

/*
 *
 */

int main ( void ) {

   int in[NUMBER_OF_DATA];
   int out[NUMBER_OF_DATA];
   int no;

   /*
	*	[Input]
	*/

		/*
		 *	for 文の利用 ( while より簡潔にかける )
		 */

	for ( no = 0; no < NUMBER_OF_DATA; no = no + 1 ) {
		printf ( "%d 番目の整数値を入力してください : ", no + 1 );
		scanf ( "%d", &in[no] );
	}
		/* n 回繰り返す典型的なイデオム */

  /*
   *	[Process]
   */

	for ( no = 0; no < NUMBER_OF_DATA; no = no + 1 ) {
		out[no] = factrial ( in[no] );
	}

  /*
   *	[Output]
   */

	for ( no = 0; no < NUMBER_OF_DATA; no = no + 1 ) {
		printf ( "%d の階乗は %d です。\n", in[no], out[no] );
	}

  /*
   *
   */

    return 0;

}

/*
 *
 */
入力例
3
7
2
0
4
sample-006.c の実行結果
C:\usr\c>sample-006<  sample-006.in
1 番目の整数値を入力してください : 3
2 番目の整数値を入力してください : 7
3 番目の整数値を入力してください : 2
4 番目の整数値を入力してください : 0
5 番目の整数値を入力してください : 4
3 の階乗は 6 です。
7 の階乗は 5040 です。
2 の階乗は 2 です。
0 の階乗は 1 です。
4 の階乗は 24 です。
C:\usr\c> 

sample-007

Download : sample-007.c ( SJIS 版 )

sample-007.c
/*
 * 2012/10/26 sample-007.c
 *
 */

#include <stdio.h>

/*
 *
 */

#define	YES		1
#define	NO		0

/*
 *
 */

int is_prime ( int number ) {

	/*
	 * 素数かどうかを判定する関数
	 *		素数なら YES そうでなければ NO を返す
	 */

	int i;

	if ( number < 2 ) {		/* 1 は素数でない ( 自然数以外も.. ) */
		return NO;
	}

	for ( i = 2; i < number; i++ ) {	/* 2 からその数より 1 つ小さい数まで.. */

		  /*
		   * 「i++」は、ほぼ「i = i + 1」と同じと思ってよい。
		   */

		if ( number % i == 0 ) {		/* number が i で割り切れた */
										/* (number を i で割った余りが 0) */
			return NO;					/* i が number の自明でない約数 */
				   						/* つまり number は素数でない */
		}
	}

	/*
	 * どれでも割り切れなかったので、素数である
	 */

	return YES;
}

/*
 *
 */

#define	NUMBER_OF_DATA		5

/*
 *
 */

int main ( void ) {

   int in[NUMBER_OF_DATA];
   int no;

   /*
	*	[Input]
	*/

	for ( no = 0; no < NUMBER_OF_DATA; no++ ) {
		printf ( "%d 番目の整数値を入力してください : ", no + 1 );
		scanf ( "%d", &in[no] );
	}

  /*
   *	[Process]/[Output]
   */

	for ( no = 0; no < NUMBER_OF_DATA; no++ ) {
		if ( is_prime ( in[no] ) == YES ) {
			printf ( "%d は素数です。\n", in[no] );
		}
	}

  /*
   *
   */

    return 0;

}

/*
 *
 */
入力例
3
7
2
0
4
sample-007.c の実行結果
C:\usr\c>sample-007<  sample-007.in
1 番目の整数値を入力してください : 3
2 番目の整数値を入力してください : 7
3 番目の整数値を入力してください : 2
4 番目の整数値を入力してください : 0
5 番目の整数値を入力してください : 4
3 は素数です。
7 は素数です。
2 は素数です。
C:\usr\c> 

sample-008

Download : sample-008.c ( SJIS 版 )

sample-008.c
/*
 * 2012/10/26 sample-008.c
 *
 */

#include <stdio.h>

/*
 *
 */

#define	YES		1
#define	NO		0

/*
 *
 */

int min ( int n, int m ) {

	/*
	 *	n と m の大きくない方を返す
	 */

	if ( n > m ) {		/* m が n より小さい */
	 	return m;		/* m を返す */
	}

	/*
	 *	ここでは、n > m でない、つまり、 n <= m となる
	 */

	return n;		/* n を返せばよい ( n == m の時も n でよい ) */
}

/*
 *
 */

int is_common_divisor ( int n, int m, int x ) {

	/*
	 *	x は n と m の公約数か ?
	 */

	if ( n % x != 0 ) {		/* n は x で割り切れない */
		return NO;			/* n の約数でないから、公約数でない */
	}

	if ( m % x != 0 ) {		/* m は x で割り切れない */
		return NO;			/* m の約数でないから、公約数でない */
	}

	/* x は n の約数であり、m の約数であるので、公約数 */

	return YES;
}

/*
 *
 */

int gcm ( int n, int m ) {

	/*
	 * n と m の最大公約数は、n, m の双方より大きくなく、かつ公約数で最大の物
	 */

	int g;

	for ( g = min(n,m); g > 1; g-- ) {	/* min(m,n) から 2 まで.. */
		if ( is_common_divisor ( n, m, g ) == YES ) {	/* 公約数 */
			return g;		/* 最初に見付かったものが最大 */
		}
	}

	return 1;			/* 1 より大きい公約数がない場合は m,n は素 */
}

/*
 *
 */

int main ( void ) {
	int n;
	int m;
	int g;

   /*
	*	[Input]
	*/

	printf ( " n の値を入力してください : " );
	scanf ( "%d", &n );
	printf ( " m の値を入力してください : " );
	scanf ( "%d", &m );

  /*
   *	[Process]
   */

   g = gcm ( n, m );

  /*
   *	[Output]
   */

   printf ( " %d と %d の最大公約数は %d です。\n", n, m, g );

  /*
   *
   */

    return 0;

}

/*
 *
 */
入力例
12
18
sample-008.c の実行結果
C:\usr\c>sample-008<  sample-008.in
 n の値を入力してください : 12
 m の値を入力してください : 18
 12 と 18 の最大公約数は 6 です。
C:\usr\c> 

sample-009

Download : sample-009.c ( SJIS 版 )

sample-009.c
/*
 * 2012/10/26 sample-009.c
 *
 * 一次方程式 ( a x + b = c ) の解を、虱潰し法で解く
 *		ただし、解は、一桁の自然数
 *
 *	a x + b = c -> a x = c - b -> x = ( c - b ) / x
 *
 */

#include <stdio.h>

/*
 *
 */

#define	YES		1
#define	NO		0

/*
 * a x + b = c ?
 */

int check_formula ( int a, int b, int c, int x ) {

	if ( a * x + b == c ) {	/* 方程式を満すか ? */
		return YES;
	}

	return NO;

}

#define	NOT_FOUND	0		/* みつからなかった */

/*
 *	方程式 a x + b = c の解を、一桁の自然数の中から探す
 *		見付かったら、その値を返す
 *		もし見付からなかったら NOT_FOUND(0) を返す
 */

int solve_formal ( int a, int b, int c ) {
	int x;

	for ( x = 1; x < 10; x++ ) {		/* x = 0 〜 9 */
		if ( check_formula ( a, b, c, x ) == YES ) {	/* 見付かった */
			return x;					/* その値を返す */
		}
	}

	/*
	 * 見付からなかったので..
	 */

	 return 0;	/* 見付からなかったので 1 〜 9 以外の数値 (今回は 0)を返す */ 

}

/*
 *
 */

int main ( void ) {
	int a;
	int b;
	int c;
	int x;

   /*
	*	[Input]
	*/

	printf ( "方程式 a x + b = c の解を 1 〜 9 の中から搜します。\n" );

	printf ( " a の値を入力してください : " );
	scanf ( "%d", &a );
	printf ( " b の値を入力してください : " );
	scanf ( "%d", &b );
	printf ( " c の値を入力してください : " );
	scanf ( "%d", &c );

  /*
   *	[Process]
   */

   x = solve_formal ( a, b, c );

  /*
   *	[Output]
   */

   if ( x == NOT_FOUND ) {	/* NOT_FOUND が帰った */
		printf ( "方程式 %d x + %d = %d の解を一桁の自然数からみつけられませんでした\n", a, b, c );
	} else {	/* 答がみつかった */
		printf ( "方程式 %d x + %d = %d の解は %d です。\n", a, b, c, x );
	}

  /*
   *
   */

    return 0;

}

/*
 *
 */
入力例
2
3
9
sample-009.c の実行結果
C:\usr\c>sample-009<  sample-009.in
方程式 a x + b = c の解を 1 〜 9 の中から搜します。
 a の値を入力してください : 2
 b の値を入力してください : 3
 c の値を入力してください : 9
方程式 2 x + 3 = 9 の解は 3 です。
C:\usr\c> 

sample-010

Download : sample-010.c ( SJIS 版 )

sample-010.c
/*
 * 2012/10/26 sample-010.c
 *
 * 不定方程式 ( a x + b y = gcm(a,b) ) の解を、虱潰し法で解く
 *		ただし、解は、-a <= y <= a, -b <= x <= b の中から探す
 */

#include <stdio.h>

/*
 *
 */

#define	YES		1
#define	NO		0

/*
 *
 */

int min ( int n, int m ) {

	/*
	 *	n と m の大きくない方を返す
	 */

	if ( n > m ) {		/* m が n より小さい */
	 	return m;		/* m を返す */
	}

	/*
	 *	ここでは、n > m でない、つまり、 n <= m となる
	 */

	return n;		/* n を返せばよい ( n == m の時も n でよい ) */
}

/*
 *
 */

int is_common_divisor ( int n, int m, int x ) {

	/*
	 *	x は n と m の公約数か ?
	 */

	if ( n % x != 0 ) {		/* n は x で割り切れない */
		return NO;			/* n の約数でないから、公約数でない */
	}

	if ( m % x != 0 ) {		/* m は x で割り切れない */
		return NO;			/* m の約数でないから、公約数でない */
	}

	/* x は n の約数であり、m の約数であるので、公約数 */

	return YES;
}

/*
 *
 */

int gcm ( int n, int m ) {

	/*
	 * n と m の最大公約数は、n, m の双方より大きくなく、かつ公約数で最大の物
	 */

	int g;

	for ( g = min(n,m); g > 1; g-- ) {	/* min(m,n) から 2 まで.. */
		if ( is_common_divisor ( n, m, g ) == YES ) {	/* 公約数 */
			return g;		/* 最初に見付かったものが最大 */
		}
	}

	return 1;			/* 1 より大きい公約数がない場合は m,n は素 */
}

/*
 * a x + b y = gcm( a, b )
 */

int check_formula ( int a, int b, int x, int y ) { 

		/* 方程式を満すか ? */
	if ( a * x + b * y == gcm( a, b ) ) {
			/* 満すなら結果を表示し.. */

		printf ( "x = %d, y = %d\n", x, y );
		printf ( "%d * %d + %d * %d = %d\n",
			a, x, b, y, gcm( a, b ) );

		return YES;		/* YES を返す */
	}

	return NO;			/* そうでなければ NO を返す */

}

/*
 *	「y」の候補を作り、答になっているかどうかを調べる
 *		答がみつかったら、YES を返す
 *		そうでなければ、次の yを探す
 *		次がなければ NO を返す
 */

int find_y ( int a, int b, int x, int y ) {

					/* 現在の「y」は答か */
	if ( check_formula ( a, b, x, y ) == YES ) {
	   return YES;	/* それなら YES を返して終了 */
	}
					/* そうでないなら.. */

	if ( y < a ) {								/* 次の候補があれば */
		return find_y ( a, b, x, y + 1 );
	}

	return NO;									/* そうでなければ NO */
}

/*
 *	「x」の候補を作り、答になっているかどうかを調べる
 *		答がみつかったら、YES を返す
 *		そうでなければ、次の yを探す
 *		次がなければ NO を返す
 */

int find_x ( int a, int b, int x ) {

					/* 現在の「x」は答か */
	if ( find_y ( a, b, x, -a ) == YES ) {
	   return YES;	/* それなら 1 を返して終了 */
	}
					/* そうでないなら.. */

	if ( x < b ) {								/* 次の候補があれば */
		return find_x ( a, b, x + 1 );
	}

	return NO;									/* そうでなければ 0 */
}


/*
 *	方程式 a x + b y = gcm(a,b) の解を探す
 *		見付かったら、YES を、そうでなければ NO を返す
 */

int solve_formal ( int a, int b ) {

	return find_x ( a, b, -b );
}

/*
 *
 */

int main ( void ) {
	int a;
	int b;

   /*
	*	[Input]
	*/

	printf ( "方程式 a x + b y = gcm(a,b) の解を搜します\n" );

	printf ( " a の値を入力してください : " );
	scanf ( "%d", &a );
	printf ( " b の値を入力してください : " );
	scanf ( "%d", &b );

  /*
   *	[Process]/[Output]
   */

   if ( solve_formal ( a, b ) == YES ) {
		printf ( "解がみつかりました\n" );
   } else {
		printf ( "解がみつかりませんでした\n" );
   }

  /*
   *
   */

    return 0;

}

/*
 *
 */
入力例
15
10
sample-010.c の実行結果
C:\usr\c>sample-010<  sample-010.in
方程式 a x + b y = gcm(a,b) の解を搜します
 a の値を入力してください : 15
 b の値を入力してください : 10
x = -9, y = 14
15 * -9 + 10 * 14 = 5
解がみつかりました
C:\usr\c> 

sample-011

Download : sample-011.c ( SJIS 版 )

sample-011.c
/*
 * DATE-DIR-QQQQ.c
 * 覆面算の「ぴよ+ぴよ=ひよこ」を解く
 */

#include <stdio.h>

/*
 *
 */

#define	YES	1
#define	NO	0

/*
 *	答の候補 pi, yo, hi, ko の値が答になっていれば、
 *	それを出力し、 YES を返す
 *	そうでなければ NO を返す
 */

int calc_check ( int pi, int yo, int hi, int ko ) {
	int piyo = pi * 10 + yo;	/* 「ぴよ」を求める */
	int hiyoko = hi * 100 + yo * 10 + ko;	/* 「ひよこ」を求める */

						/* 「ぴ」は先頭なので 0 だと駄目 */
	if ( pi == 0 ) {
		return NO;
	}

						/* 「ひ」は先頭なので 0 だと駄目 */
	if ( hi == 0 ) {
		return NO;
	}

						/* 「ぴ」と「ひ」は別 */
	if ( pi == hi ) {
		return NO;
	}

						/* 「ぴ」と「よ」は別 */
	if ( pi == yo ) {
		return NO;
	}

						/* 「ぴ」と「こ」は別 */
	if ( pi == ko ) {
		return NO;
	}

						/* 「ひ」と「よ」は別 */
	if ( hi == yo ) {
		return NO;
	}

						/* 「ひ」と「こ」は別 */
	if ( hi == ko ) {
		return NO;
	}

						/* 「よ」と「こ」は別 */
	if ( yo == ko ) {
		return NO;
	}

	if ( piyo + piyo == hiyoko ) {	/* 計算があっていれば */
		printf ( "ぴ = %d, ひ = %d, よ = %d, こ = %d\n",
			pi, hi, yo, ko );

		printf ( "%d + %d = %d\n", piyo, piyo, hiyoko );
									/* 答を出力して.. */
		return YES;					/* YES を返す */
	}

	return NO;						/* そうでなければ NO を返す */
}

/*
 *	「こ」の候補を作り、答になっているかどうかを調べる
 *		答がみつかったら、YES を返す
 *		そうでなければ、次の「こ」を探す
 *		次がなければ NO を返す
 */

int find_ko ( int pi, int hi, int yo, int ko ) {
					/* 現在の「こ」は答か */
	if ( calc_check ( pi, hi, yo, ko ) == YES ) {
	   return YES;	/* それなら YES を返して終了 */
	}
					/* そうでないなら.. */

	if ( ko < 9 ) {								/* 次の候補があれば */
		return find_ko ( pi, hi, yo, ko + 1 );	/* 次を try */
	}

	return NO;									/* そうでなければ NO */
}

/*
 *	「よ」の候補を作り、答になっているかどうかを調べる
 *		答がみつかったら、YES を返す
 *		そうでなければ、次の「よ」を探す
 *		次がなければ NO を返す
 */

int find_yo ( int pi, int hi, int yo ) {
					/* 現在の「よ」は答か */
	if ( find_ko ( pi, hi, yo, 0 ) == YES ) {
	   return YES;	/* それなら YES を返して終了 */
	}
					/* そうでないなら.. */

	if ( yo < 9 ) {								/* 次の候補があれば */
		return find_yo ( pi, hi, yo + 1 );		/* 次を try */
	}

	return NO;									/* そうでなければ NO */
}

/*
 *	「ひ」の候補を作り、答になっているかどうかを調べる
 *		答がみつかったら、YES を返す
 *		そうでなければ、次の「ひ」を探す
 *		次がなければ NO を返す
 */

int find_hi ( int pi, int hi ) {
					/* 現在の「ひ」は答か */
	if ( find_yo ( pi, hi, 0 ) == YES ) {
	   return YES;	/* それなら YES を返して終了 */
	}
					/* そうでないなら.. */

	if ( hi < 9 ) {								/* 次の候補があれば */
		return find_hi ( pi, hi + 1 );		/* 次を try */
	}

	return NO;									/* そうでなければ NO */
}

/*
 *	「ぴ」の候補を作り、答になっているかどうかを調べる
 *		答がみつかったら、YES を返す
 *		そうでなければ、次の「ぴ」を探す
 *		次がなければ NO を返す
 */

int find_pi ( int pi ) {
					/* 現在の「ぴ」は答か */
	if ( find_hi ( pi, 0 ) == YES ) {
	   return YES;	/* それなら YES を返して終了 */
	}
					/* そうでないなら.. */

	if ( pi < 9 ) {								/* 次の候補があれば */
		return find_pi ( pi + 1 );		/* 次を try */
	}

	return NO;									/* そうでなければ NO */
}

/*
 *
 */

int main ( void ) {

	/*
	 *
	 */	

	 printf ( "問 : ぴよ + ぴよ = ひよこ\n" );	/* 問題の出力 */

	/*
	 *
	 */	

		/* 「こ」の最初の候補として「0」を指定して答を検索 */
	if ( find_pi ( 0 ) == YES ) {			/* 答がみつかったら */
		printf ( "解けた\n" );			/* 「解けた」と出力 */
	} else {
		printf ( "解けない\n" );	/* 「解けない」と出力 */
	}

  /*
   *	結果の出力
   */

    return 0;

}

/*
 *
 */
sample-011.c の実行結果
C:\usr\c>sample-011
問 : ぴよ + ぴよ = ひよこ
ぴ = 6, ひ = 1, よ = 2, こ = 4
62 + 62 = 124
解けた
C:\usr\c> 

講義中に作成したサンプルプログラム

本日の課題

課題 20121109-01

Download : 20121109-01.c ( SJIS 版 )

20121109-01.c
/*
 * DATE-DIR-QQQQ.c
 * printf と scanf の利用し、二つの整数を入力し、和を出力する
 */

#include <stdio.h>

/*
 *
 */

int main ( void ) {
	int a;		/* 一つ目の整数値 */
	int b;		/* 二つ目の整数値 */
	int wa;		/* 和の計算結果 */

	printf ( "一つ目の数値 = " );
	scanf ( "%d", &a );

	printf ( "二つ目の数値 = " );

	/*
	**	 この部分を完成させなさい
	*/


  /*
   *	和の計算
   */

   wa = a + b;

  /*
   *	結果の出力
   */


	/*
	**	 この部分を完成させなさい
	*/


    return 0;

}

/*
 *
 */
入力例
12
34
20121109-01.c の実行結果
C:\usr\c\> 20121109-01
一つ目の数値 = 12
二つ目の数値 = 34
12 + 34 = 46
C:\usr\c\> 

課題 20121109-02

Download : 20121109-02.c ( SJIS 版 )

20121109-02.c
/*
 * DATE-DIR-QQQQ.c
 *
 * 覆面算の「こな+ここ=きなこ」を解く
 */

#include <stdio.h>

/*
 *
 */

#define	YES	1
#define	NO	0

/*
 *	答の候補 ko, na, ki の値が答になっていれば、
 *	それを出力し、 YES を返す
 *	そうでなければ NO を返す
 */

int calc_check ( int ko, int na, int ki ) {
	int kona = ko * 10 + na;				/* 「こな」を求める */
	int koko = ko * 10 + ko;				/* 「ここ」を求める */
	int kinako = ki * 100 + na * 10 + ko;	/* 「きなこ」を求める */

						/* 「こ」は先頭なので 0 だと駄目 */
	if ( ko == 0 ) {
		return NO;
	}

						/* 「き」は先頭なので 0 だと駄目 */

	/*
	**	 この部分を完成させなさい
	*/


						/* 「こ」と「な」は別 */
	if ( ko == na ) {
		return NO;
	}

						/* 「こ」と「き」は別 */

	/*
	**	 この部分を完成させなさい
	*/


	if ( na == ki ) {						/* 「な」と「き」は別 */
		return NO;
	}

	if ( kona + koko == kinako ) {	/* 計算があっていれば */

	/*
	**	 この部分を完成させなさい
	*/

									/* 答を出力して.. */
		return YES;					/* 1 を返す */
	}

	return NO;						/* そうでなければ 0 を返す */
}

/*
 *	「き」の候補を作り、答になっているかどうかを調べる
 *		答がみつかったら、YES を返す
 *		そうでなければ、次の「き」を探す
 *		次がなければ NO を返す
 */

int find_ki ( int ko, int na, int ki ) {

					/* 現在の「き」は答か */
	if ( calc_check ( ko, na, ki ) == YES ) {
	   return YES;	/* それなら YES を返して終了 */
	}
					/* そうでないなら.. */

	if ( ki < 9 ) {								/* 次の候補があれば */
		return find_ki ( ko, na, ki + 1 );		/* 次を try */
	}

	return NO;									/* そうでなければ 0 */
}

/*
 *	「な」の候補を作り、答になっているかどうかを調べる
 *		答がみつかったら、YES を返す
 *		そうでなければ、次の「な」を探す
 *		次がなければ NO を返す
 */

int find_na ( int ko, int na ) {

					/* 現在の「な」は答か */

	/*
	**	 この部分を完成させなさい
	*/

					/* そうでないなら.. */
	
	if ( na < 9 ) {							/* 次の候補があれば */
		return find_na ( ko, na + 1 );		/* 次を try */
	}

	return NO;								/* そうでなければ 0 */
}

/*
 *	「こ」の候補を作り、答になっているかどうかを調べる
 *		答がみつかったら、YES を返す
 *		そうでなければ、次の「こ」を探す
 *		次がなければ NO を返す
 */

int find_ko ( int ko ) {

					/* 現在の「こ」は答か */
	if ( find_na ( ko, 0 ) == YES ) {
	   return 1;	/* それなら YES を返して終了 */
	}
					/* そうでないなら.. */
	

	/*
	**	 この部分を完成させなさい
	*/


	return NO;								/* そうでなければ 0 */
}

/*
 *
 */

int main ( void ) {

	/*
	 *
	 */	

	 printf ( "問 : こな + ここ = きなこ\n" );	/* 問題の出力 */

	/*
	 *
	 */	

		/* 「こ」の最初の候補として「0」を指定して答を検索 */
	if ( find_ko ( 0 ) == YES ) {		/* 答がみつかったら */
		printf ( "解けた\n" );			/* 「解けた」と出力 */
	} else {
		printf ( "解けない\n" );	/* 「解けない」と出力 */
	}

  /*
   *	結果の出力
   */

    return 0;

}

/*
 *
 */
入力例
12
34
20121109-02.c の実行結果
C:\usr\c\> 20121109-02
問 : こな + ここ = きなこ
こ = 5, な = 0, き = 1
50 + 55 = 105
解けた
C:\usr\c\>