当日のOHP資料です。
Download : sample-001.c ( SJIS 版 )
/*
* 2012/11/09 sample-001.c
*
* 一次方程式 ( a x + b = c ) の解を、虱潰し法で解く
* ただし、解は、一桁の自然数
*
*/
#include <stdio.h>
/*
*
*/
#define YES 1
#define NO 0
/*
* a x + b = c ? : 論理式 P に相当する
*/
int check_formula ( int a, int b, int c, int x ) {
if ( a * x + b == c ) { /* 方程式を満すか ? */
return YES;
}
return NO;
}
/*
* 方程式 a x + b = c の解を、x_min 〜 x_max の範囲で探す
* 見付かったら、その値を返す
* もし見付からなかったら、範囲外の数 ( x_max + 1 ) を返す
*/
int solve_formal ( int a, int b, int c, int x_min, int x_max ) {
int x;
for ( x = x_min; x <= x_max; x++ ) { /* x = x_min 〜 x_max */
if ( check_formula ( a, b, c, x ) == YES ) { /* 見付かった */
return x; /* その値を返す */
}
}
/*
* 見付からなかったので..
*/
return x_max + 1; /* 範囲の外である数を返す */
}
/*
* a x + b = c の整数解を求める
*/
int main ( void ) {
int a;
int b;
int c; /* a x + b = c の a, b, c */
int x_min;
int x_max; /* F = { x | x_min <= x <= x_max } */
int x; /* 答の候補 */
/*
* [Input]
*/
/*
* P(x) == (a x + b = c)
*/
printf ( "方程式 a x + b = c の整数解を搜します。\n" );
printf ( " a の値を入力してください : " );
scanf ( "%d", &a );
printf ( " b の値を入力してください : " );
scanf ( "%d", &b );
printf ( " c の値を入力してください : " );
scanf ( "%d", &c );
/*
* F = { x | x_min <= x <= x_max }
*/
printf ( "x の取り得る範囲を指定してください\n" );
printf ( "\t最小値 : " );
scanf ( "%d", &x_min );
printf ( "\t最大値 : " );
scanf ( "%d", &x_max );
/*
* [Process]
*/
/*
* 「 \exists x \in F[P(x)] 」の探索による証明
*/
x = solve_formal ( a, b, c, x_min, x_max );
/*
* [Output]
*/
if ( x > x_max ) {
printf ( "方程式 %d x + %d = %d の解を %d 〜 %d の範囲の整数からは見つける事ができませんでした。\n", a, \
b, c, x_min, x_max );
} else { /* 答が見つかった */
printf ( "方程式 %d x + %d = %d の解は %d です。\n", a, b, c, x );
}
/*
*
*/
return 0;
}
/*
*
*/
2 3 7 -1 8
C:\usr\c>sample-001< sample-001.in 方程式 a x + b = c の整数解を搜します。 a の値を入力してください : 2 b の値を入力してください : 3 c の値を入力してください : 7 x の取り得る範囲を指定してください 最小値 : -1 最大値 : 8 方程式 2 x + 3 = 7 の解は 2 です。 C:\usr\c>
Download : sample-002.c ( SJIS 版 )
/*
* 2012/11/09 sample-002.c
*
* 二つの自然数 m, n の最大公約数 g=gcd(m,n) を求める
*
*/
#include <stdio.h>
/*
*
*/
#define YES 1
#define NO 0
/*
* min(n,m) は m と n の大きくない方を値として返す
*/
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 でよい ) */
}
/*
* x が m, n の公約数であれば、YES を、そうでなければ NO を返す
*/
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;
}
/*
* n, m の最大公約数を返す
*/
int gcd ( int n, int m ) {
/*
* n と m の最大公約数は、n, m の双方より大きくなく、かつ公約数で最大の物
*/
int g; /* 最大公約数の候補 */
/*
* g の取り得る範囲 (F)
* F = { g | 1 <= g <= min(m,n) }
*/
for ( g = min(n,m); g > 1; g-- ) { /* min(m,n) から 2 まで.. */
/*
* P に相当する ( 「最大」という条件は「探す順」で決る )
*/
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, m の最大公約数 g = gcd(n,m) を求めます\n" );
printf ( " n の値を入力してください : " );
scanf ( "%d", &n );
printf ( " m の値を入力してください : " );
scanf ( "%d", &m );
/*
* [Process]
*/
g = gcd ( n, m );
/*
* [Output]
*/
printf ( " %d と %d の最大公約数は %d です。\n", n, m, g );
/*
*
*/
return 0;
}
/*
*
*/
12 18
C:\usr\c>sample-002< sample-002.in 二つの自然数 n, m の最大公約数 g = gcd(n,m) を求めます n の値を入力してください : 12 m の値を入力してください : 18 12 と 18 の最大公約数は 6 です。 C:\usr\c>
Download : sample-003.c ( SJIS 版 )
/*
* 2012/11/09 sample-003.c
*
* 覆面算の「ぴよ+ぴよ=ひよこ」を解く
*
*/
#include <stdio.h>
/*
*
*/
#define YES 1
#define NO 0
/*
* 答の候補 pi, yo, hi, ko の値が答になっていれば、
* それを出力し、 YES を返す
* そうでなければ NO を返す
*
* 覆面算 (「ピヨ+ピヨ=ヒヨコ」) の条件「P」の部分
*
*/
int calc_check ( int pi, int yo, int hi, int ko ) {
int piyo; /* ぴよ */
int hiyoko; /* ひよこ */
/*
* (条件 1) ピとヒは、数値の先頭なので、零にならない
*/
/* 「ぴ」は先頭なので 0 だと駄目 */
if ( pi == 0 ) {
return NO;
}
/* 「ひ」は先頭なので 0 だと駄目 */
if ( hi == 0 ) {
return NO;
}
/*
* (条件 2) ピ、ヨ、ヒ、コは互いに異る
*/
/* 「ぴ」と「ひ」は別 */
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;
}
/*
* (条件 3) 「ピ*10+ヨ」+「ピ*10+ヨ」=「ヒ*100+ヨ*10+コ」
*/
piyo = pi * 10 + yo; /* 「ぴよ」を求める */
hiyoko = hi * 100 + yo * 10 + ko; /* 「ひよこ」を求める */
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;
}
/*
*
*/
987
C:\usr\c>sample-003< sample-003.in 問 : ぴよ + ぴよ = ひよこ ぴ = 6, ひ = 1, よ = 2, こ = 4 62 + 62 = 124 解けた C:\usr\c>
Download : sample-004-01.c ( SJIS 版 )
/*
* 2012/11/09 sample-004-01.c
*
* 覆面算の「ぴよ+ぴよ=ひよこ」の条件式
*
*/
#include <stdio.h>
#include "hiyoko.h"
/*
* 答の候補 pi, yo, hi, ko の値が答になっていれば、
* それを出力し、 YES を返す
* そうでなければ NO を返す
*
* 覆面算 (「ピヨ+ピヨ=ヒヨコ」) の条件「P」の部分
*
*/
int calc_check ( int pi, int yo, int hi, int ko ) {
int piyo; /* ぴよ */
int hiyoko; /* ひよこ */
/*
* (条件 1) ピとヒは、数値の先頭なので、零にならない
*/
/* 「ぴ」は先頭なので 0 だと駄目 */
if ( pi == 0 ) {
return NO;
}
/* 「ひ」は先頭なので 0 だと駄目 */
if ( hi == 0 ) {
return NO;
}
/*
* (条件 2) ピ、ヨ、ヒ、コは互いに異る
*/
/* 「ぴ」と「ひ」は別 */
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;
}
/*
* (条件 3) 「ピ*10+ヨ」+「ピ*10+ヨ」=「ヒ*100+ヨ*10+コ」
*/
piyo = pi * 10 + yo; /* 「ぴよ」を求める */
hiyoko = hi * 100 + yo * 10 + ko; /* 「ひよこ」を求める */
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 を返す */
}
Download : sample-004-02.c ( SJIS 版 )
/*
* 2012/11/09 sample-004-02.c
*
* 覆面算の「ぴよ+ぴよ=ひよこ」の「こ」の探索
*
*/
#include "hiyoko.h"
/*
* 「こ」の候補を作り、答になっているかどうかを調べる
* 答がみつかったら、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 */
}
Download : sample-004-03.c ( SJIS 版 )
/*
* 2012/11/09 sample-004-03.c
*
* 覆面算の「ぴよ+ぴよ=ひよこ」の「よ」の探索
*
*/
#include "hiyoko.h"
/*
* 「よ」の候補を作り、答になっているかどうかを調べる
* 答がみつかったら、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 */
}
Download : sample-004-04.c ( SJIS 版 )
/*
* 2012/11/09 sample-004-04.c
*
* 覆面算の「ぴよ+ぴよ=ひよこ」の「ひ」の探索
*
*/
#include "hiyoko.h"
/*
* 「ひ」の候補を作り、答になっているかどうかを調べる
* 答がみつかったら、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 */
}
Download : sample-004-05.c ( SJIS 版 )
/*
* 2012/11/09 sample-004-05.c
*
* 覆面算の「ぴよ+ぴよ=ひよこ」の「ひ」の探索
*
*/
#include "hiyoko.h"
/*
* 「ぴ」の候補を作り、答になっているかどうかを調べる
* 答がみつかったら、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 */
}
Download : sample-004.c ( SJIS 版 )
/*
* 2012/11/09 sample-004.c
*
* 覆面算の「ぴよ+ぴよ=ひよこ」を解く
*
*/
#include <stdio.h>
#include "hiyoko.h"
/*
*
*/
int main ( void ) {
/*
*
*/
printf ( "問 : ぴよ + ぴよ = ひよこ\n" ); /* 問題の出力 */
/*
*
*/
/* 「こ」の最初の候補として「0」を指定して答を検索 */
if ( find_pi ( 0 ) == YES ) { /* 答がみつかったら */
printf ( "解けた\n" ); /* 「解けた」と出力 */
} else {
printf ( "解けない\n" ); /* 「解けない」と出力 */
}
/*
* 結果の出力
*/
return 0;
}
/*
*
*/
C:\usr\c>sample-004 問 : ぴよ + ぴよ = ひよこ ぴ = 6, ひ = 1, よ = 2, こ = 4 62 + 62 = 124 解けた C:\usr\c>
Download : hiyoko.h ( SJIS 版 )
/* * 2012/11/09 hiyoko.h */ #define YES 1 #define NO 0 /* * */ extern int calc_check ( int pi, int yo, int hi, int ko ); extern int find_ko ( int pi, int hi, int yo, int ko ); extern int find_yo ( int pi, int hi, int yo ); extern int find_hi ( int pi, int hi ); extern int find_pi ( int pi ); /* * */
Download : makefile.mf
Download : sample-005-01.c ( SJIS 版 )
/*
* 2012/11/09 sample-005-01.c
*
* 覆面算の「ぴよ+ぴよ=ひよこ」の条件式
*
*/
#include <stdio.h>
#include "hiyoko.h"
/*
* 答の候補 pi, yo, hi, ko の値が答になっていれば、
* それを出力し、 YES を返す
* そうでなければ NO を返す
*
* 覆面算 (「ピヨ+ピヨ=ヒヨコ」) の条件「P」の部分
*
*/
int calc_check ( int pi, int yo, int hi, int ko ) {
int piyo; /* ぴよ */
int hiyoko; /* ひよこ */
/*
* (条件 1) ピとヒは、数値の先頭なので、零にならない
*/
/* 「ぴ」は先頭なので 0 だと駄目 */
if ( pi == 0 ) {
return NO;
}
/* 「ひ」は先頭なので 0 だと駄目 */
if ( hi == 0 ) {
return NO;
}
/*
* (条件 2) ピ、ヨ、ヒ、コは互いに異る
*/
/* 「ぴ」と「ひ」は別 */
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;
}
/*
* (条件 3) 「ピ*10+ヨ」+「ピ*10+ヨ」=「ヒ*100+ヨ*10+コ」
*/
piyo = pi * 10 + yo; /* 「ぴよ」を求める */
hiyoko = hi * 100 + yo * 10 + ko; /* 「ひよこ」を求める */
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 を返す */
}
Download : sample-005-02.c ( SJIS 版 )
/*
* 2012/11/09 sample-005-02.c
*
* 覆面算の「ぴよ+ぴよ=ひよこ」を for 文で解く
*
*/
#include <stdio.h>
#include "hiyoko.h"
/*
* 答の候補 pi, yo, hi, ko の値を for 文で検索し、答えがあれば
* それを出力し、 YES を返す
* そうでなければ NO を返す
*
* 覆面算 (「ピヨ+ピヨ=ヒヨコ」) の条件「F」の部分
*
*/
int find ( void ) {
int pi;
int yo;
int hi;
int ko;
for ( pi = 0; pi < 10; pi++ ) {
for ( yo = 0; yo < 10; yo++ ) {
for ( hi = 0; hi < 10; hi++ ) {
for ( ko = 0; ko < 10; ko++ ) {
if ( calc_check ( pi, yo, hi, ko ) == YES ) {
return YES;
}
}
}
}
}
return NO; /* そうでなければ NO を返す */
}
Download : sample-005.c ( SJIS 版 )
/*
* 2012/11/09 sample-005.c
*
* 覆面算の「ぴよ+ぴよ=ひよこ」を解く (for 版)
*
*/
#include <stdio.h>
#include "hiyoko.h"
/*
*
*/
int main ( void ) {
/*
*
*/
printf ( "問 : ぴよ + ぴよ = ひよこ\n" ); /* 問題の出力 */
/*
*
*/
/* 「こ」の最初の候補として「0」を指定して答を検索 */
if ( find () == YES ) { /* 答がみつかったら */
printf ( "解けた\n" ); /* 「解けた」と出力 */
} else {
printf ( "解けない\n" ); /* 「解けない」と出力 */
}
/*
* 結果の出力
*/
return 0;
}
/*
*
*/
C:\usr\c>sample-005 問 : ぴよ + ぴよ = ひよこ ぴ = 6, ひ = 1, よ = 2, こ = 4 62 + 62 = 124 解けた C:\usr\c>
Download : hiyoko.h ( SJIS 版 )
/* * 2012/11/09 hiyoko.h */ #define YES 1 #define NO 0 /* * */ extern int calc_check ( int pi, int yo, int hi, int ko ); extern int find(); /* * */
Download : makefile.mf
Download : sample-006-01.c ( SJIS 版 )
/*
* 2012/11/09 sample-006-01.c
*
* 覆面算の「ぴよ+ぴよ=ひよこ」の条件式 (配列版)
*
*/
#include <stdio.h>
#include "hiyoko.h"
/*
* 答の候補 pi, yo, hi, ko の値が答になっていれば、
* それを出力し、 YES を返す
* そうでなければ NO を返す
*
* 覆面算 (「ピヨ+ピヨ=ヒヨコ」) の条件「P」の部分
*
* ピ : x[PI]
* ヨ : x[YO]
* ヒ : x[HI]
* コ : x[KO]
*
*/
int calc_check ( int x[], int size ) {
int piyo; /* ぴよ */
int hiyoko; /* ひよこ */
int i;
int j;
/*
* (条件 1) ピとヒは、数値の先頭なので、零にならない
*/
/* 「ぴ」は先頭なので 0 だと駄目 */
if ( x[PI] == 0 ) {
return NO;
}
/* 「ひ」は先頭なので 0 だと駄目 */
if ( x[HI] == 0 ) {
return NO;
}
/*
* (条件 2) ピ、ヨ、ヒ、コは互いに異る
*/
for ( i = 0; i < size; i++ ) {
for ( j = i + 1; j < size; j++ ) {
if ( x[i] == x[j] ) {
return NO;
}
}
}
/*
* (条件 3) 「ピ*10+ヨ」+「ピ*10+ヨ」=「ヒ*100+ヨ*10+コ」
*/
piyo = x[PI] * 10 + x[YO]; /* 「ぴよ」を求める */
hiyoko = x[HI] * 100 + x[YO] * 10 + x[KO]; /* 「ひよこ」を求める */
if ( piyo + piyo == hiyoko ) { /* 計算があっていれば */
printf ( "ぴ = %d, ひ = %d, よ = %d, こ = %d\n",
x[PI], x[HI], x[YO], x[KO] );
printf ( "%d + %d = %d\n", piyo, piyo, hiyoko );
/* 答を出力して.. */
return YES; /* YES を返す */
}
return NO; /* そうでなければ NO を返す */
}
Download : sample-006-02.c ( SJIS 版 )
/*
* 2012/11/09 sample-006-02.c
*
* 覆面算の「ぴよ+ぴよ=ひよこ」を同一の再帰で解く
*
*/
#include "hiyoko.h"
/*
*
*/
int find_n ( int x[], int k, int size ) {
int i;
if ( k < size ) {
for ( i = 0; i < 10; i++ ) {
x[k] = i;
if ( find_n ( x, k + 1, size ) == YES ) {
return YES;
}
}
} else {
return calc_check ( x, size );
}
return NO;
}
/*
* 答の候補 pi, yo, hi, ko の値を for 文で検索し、答えがあれば
* それを出力し、 YES を返す
* そうでなければ NO を返す
*
* 覆面算 (「ピヨ+ピヨ=ヒヨコ」) の条件「F」の部分
*
*/
int find ( void ) {
int x[4];
return find_n ( x, 0, 4 );
}
Download : sample-006.c ( SJIS 版 )
/*
* 2012/11/09 sample-006.c
*
* 覆面算の「ぴよ+ぴよ=ひよこ」を解く (for 版)
*
*/
#include <stdio.h>
#include "hiyoko.h"
/*
*
*/
int main ( void ) {
/*
*
*/
printf ( "問 : ピヨ + ピヨ = ヒヨコ\n" ); /* 問題の出力 */
/*
*
*/
/* 「こ」の最初の候補として「0」を指定して答を検索 */
if ( find() == YES ) { /* 答がみつかったら */
printf ( "解けた\n" ); /* 「解けた」と出力 */
} else {
printf ( "解けない\n" ); /* 「解けない」と出力 */
}
/*
* 結果の出力
*/
return 0;
}
/*
*
*/
C:\usr\c>sample-006 問 : ピヨ + ピヨ = ヒヨコ ぴ = 6, ひ = 1, よ = 2, こ = 4 62 + 62 = 124 解けた C:\usr\c>
Download : hiyoko.h ( SJIS 版 )
/* * 2012/11/09 hiyoko.h */ #define YES 1 #define NO 0 /* * */ #define PI 0 #define YO 1 #define HI 2 #define KO 3 /* * */ extern int calc_check ( int x[], int size ); extern int find(void); /* * */
Download : makefile.mf
Download : sample-007-01.c ( SJIS 版 )
/*
* 2012/11/09 sample-007-01.c
*
*/
#include <stdio.h>
#include "hiyoko.h"
/*
* 数の並びから十進数を計算する
*/
int ten ( int a[], int as, int x[] ) {
int i;
int v = 0;
for ( i = 0; i < as; i++ ) {
v = v * 10 + x[a[i]];
}
return v;
}
/*
* 答の候補 x[] が条件を満していれば
* それを出力し、 YES を返す
* そうでなければ NO を返す
*
* 覆面算 A+B=C
*
*/
int calc_check (
char n[], int size, /* 文字の名前 */
int a[], int sa, /* 足される数の個々の桁の番号の配列とサイズ */
int b[], int sb, /* 足す数の個々の桁の番号の配列とサイズ */
int c[], int sc, /* 和の数の個々の桁の番号の配列とサイズ */
int x[] /* 答の候補 */
) {
int va; /* 足される数 */
int vb; /* 足す数 */
int vc; /* 和 */
int i;
int j;
/*
* (条件 1) 個々の数の先頭は 0 でない
*/
if ( x[a[0]] == 0 ) {
return NO;
}
if ( x[b[0]] == 0 ) {
return NO;
}
if ( x[c[0]] == 0 ) {
return NO;
}
/*
* (条件 2) x[i] は互いに異る
*/
for ( i = 0; i < size; i++ ) {
for ( j = i + 1; j < size; j++ ) {
if ( x[i] == x[j] ) {
return NO;
}
}
}
va = ten( a, sa, x );
vb = ten( b, sb, x );
vc = ten( c, sc, x );
if ( va + vb == vc ) {
for ( i = 0; i < size; i++ ) {
printf ( "%c = %d", n[i], x[i] );
if ( i < size - 1 ) {
printf ( ", " );
} else {
printf ( "\n" );
}
}
printf ( "%d + %d = %d\n", va, vb, vc );
/* 答を出力して.. */
return YES; /* YES を返す */
}
return NO; /* そうでなければ NO を返す */
}
Download : sample-007-02.c ( SJIS 版 )
/*
* 2012/11/09 sample-007-02.c
*
*/
#include "hiyoko.h"
/*
*
*/
int find_n ( int x[], int k, int size ) {
int i;
int piyo[] = { PI, YO }; /* piyo */
int hiyoko[] = { HI, YO, KO }; /* hiyoko */
if ( k < size ) {
for ( i = 0; i < 10; i++ ) {
x[k] = i;
if ( find_n ( x, k + 1, size ) == YES ) {
return YES;
}
}
} else {
return calc_check ( "pyhk", 4, piyo, 2, piyo, 2, hiyoko, 3, x );
}
return NO;
}
/*
* 答の候補 pi, yo, hi, ko の値を for 文で検索し、答えがあれば
* それを出力し、 YES を返す
* そうでなければ NO を返す
*
* 覆面算 (「ピヨ+ピヨ=ヒヨコ」) の条件「F」の部分
*
*/
int find ( void ) {
int x[4];
return find_n ( x, 0, 4 );
}
Download : sample-007.c ( SJIS 版 )
/*
* 2012/11/09 sample-007.c
*
* 覆面算の「py+py=hyk」を解く
*
*/
#include <stdio.h>
#include "hiyoko.h"
/*
*
*/
int main ( void ) {
/*
*
*/
printf ( "問 : py + py = hyk\n" ); /* 問題の出力 */
/*
*
*/
/* 「こ」の最初の候補として「0」を指定して答を検索 */
if ( find() == YES ) { /* 答がみつかったら */
printf ( "解けた\n" ); /* 「解けた」と出力 */
} else {
printf ( "解けない\n" ); /* 「解けない」と出力 */
}
/*
* 結果の出力
*/
return 0;
}
/*
*
*/
C:\usr\c>sample-007 問 : py + py = hyk p = 6, y = 2, h = 1, k = 4 62 + 62 = 124 解けた C:\usr\c>
Download : hiyoko.h ( SJIS 版 )
/* * 2012/11/09 hiyoko.h */ #define YES 1 #define NO 0 /* * */ #define PI 0 #define YO 1 #define HI 2 #define KO 3 /* * */ extern int calc_check ( char n[], int size, /* 文字の名前 */ int a[], int sa, /* 足される数の個々の桁の番号の配列とサイズ */ int b[], int sb, /* 足す数の個々の桁の番号の配列とサイズ */ int c[], int sc, /* 和の数の個々の桁の番号の配列とサイズ */ int x[] /* 答の候補 */ ); extern int find(void); /* * */
Download : makefile.mf
Download : sample-008-01.c ( SJIS 版 )
/*
* 2012/11/09 sample-008-01.c
*
*/
#include <stdio.h>
#include "hiyoko.h"
/*
* 数の並びから十進数を計算する
*/
int ten ( int a[], int as, int x[] ) {
int i;
int v = 0;
for ( i = 0; i < as; i++ ) {
v = v * 10 + x[a[i]];
}
return v;
}
/*
* 答の候補 x[] が条件を満していれば
* それを出力し、 YES を返す
* そうでなければ NO を返す
*
* 覆面算 A+B=C
*
*/
int calc_check (
char n[], int size, /* 文字の名前 */
int a[], int sa, /* 足される数の個々の桁の番号の配列とサイズ */
int b[], int sb, /* 足す数の個々の桁の番号の配列とサイズ */
int c[], int sc, /* 和の数の個々の桁の番号の配列とサイズ */
int x[] /* 答の候補 */
) {
int va; /* 足される数 */
int vb; /* 足す数 */
int vc; /* 和 */
int i;
int j;
/*
* (条件 1) 個々の数の先頭は 0 でない
*/
if ( x[a[0]] == 0 ) {
return NO;
}
if ( x[b[0]] == 0 ) {
return NO;
}
if ( x[c[0]] == 0 ) {
return NO;
}
/*
* (条件 2) x[i] は互いに異る
*/
for ( i = 0; i < size; i++ ) {
for ( j = i + 1; j < size; j++ ) {
if ( x[i] == x[j] ) {
return NO;
}
}
}
va = ten( a, sa, x );
vb = ten( b, sb, x );
vc = ten( c, sc, x );
if ( va + vb == vc ) {
for ( i = 0; i < size; i++ ) {
printf ( "%c = %d", n[i], x[i] );
if ( i < size - 1 ) {
printf ( ", " );
} else {
printf ( "\n" );
}
}
printf ( "%d + %d = %d\n", va, vb, vc );
/* 答を出力して.. */
return YES; /* YES を返す */
}
return NO; /* そうでなければ NO を返す */
}
Download : sample-008-02.c ( SJIS 版 )
/*
* 2012/11/09 sample-008-02.c
*
*/
#include "hiyoko.h"
/*
*
*/
int find_n (
char name[], int size,
int a[], int sa,
int b[], int sb,
int c[], int sc,
int x[], int k ) {
int i;
if ( k < size ) {
for ( i = 0; i < 10; i++ ) {
x[k] = i;
if ( find_n ( name, size, a, sa, b, sb, c, sc, x, k + 1 ) == YES ) {
return YES;
}
}
} else {
return calc_check ( name, size, a, sa, b, sb, c, sc, x );
}
return NO;
}
/*
* 答の候補を検索し、答えがあれば
* それを出力し、 YES を返す
* そうでなければ NO を返す
*
* 覆面算の条件「F」の部分
*
*/
int find ( char *ta, char *tb, char *tc ) {
char n[10];
int size;
int a[10];
int sa;
int b[10];
int sb;
int c[10];
int sc;
int i;
int j;
int find;
int x[10];
size = 0;
for ( i = 0; ta[i] != EOS; i++ ) {
find = NO;
for ( j = 0; j < size; j++ ) {
if ( n[j] == ta[i] ) {
a[i] = j;
find = YES;
}
}
if ( find == NO ) {
n[size] = ta[i];
a[i] = size;
size = size + 1;
}
}
sa = i;
for ( i = 0; tb[i] != EOS; i++ ) {
find = NO;
for ( j = 0; j < size; j++ ) {
if ( n[j] == tb[i] ) {
b[i] = j;
find = YES;
}
}
if ( find == NO ) {
n[size] = tb[i];
b[i] = size;
size = size + 1;
}
}
sb = i;
for ( i = 0; tc[i] != EOS; i++ ) {
find = NO;
for ( j = 0; j < size; j++ ) {
if ( n[j] == tc[i] ) {
c[i] = j;
find = YES;
}
}
if ( find == NO ) {
n[size] = tc[i];
c[i] = size;
size = size + 1;
}
}
sc = i;
return find_n ( n, size, a, sa, b, sb, c, sc, x, 0 );
}
Download : sample-008.c ( SJIS 版 )
/*
* 2012/11/09 sample-008.c
*
* 覆面算の「py+py=hyk」を解く
*
*/
#include <stdio.h>
#include "hiyoko.h"
/*
*
*/
int main ( void ) {
/*
*
*/
char a[SSIZE];
char b[SSIZE];
char c[SSIZE];
/*
*
*/
printf ( "足される数 : " );
scanf ( "%s", a );
printf ( "足す数 : " );
scanf ( "%s", b );
printf ( "和 : " );
scanf ( "%s", c );
/*
*
*/
printf ( "問 : %s + %s = %s\n", a, b, c ); /* 問題の出力 */
/*
*
*/
/* 「こ」の最初の候補として「0」を指定して答を検索 */
if ( find( a, b, c ) == YES ) { /* 答がみつかったら */
printf ( "解けた\n" ); /* 「解けた」と出力 */
} else {
printf ( "解けない\n" ); /* 「解けない」と出力 */
}
/*
* 結果の出力
*/
return 0;
}
/*
*
*/
py py hyk
C:\usr\c>sample-008< sample-008.in 足される数 : py 足す数 : py 和 : hyk 問 : py + py = hyk p = 6, y = 2, h = 1, k = 4 62 + 62 = 124 解けた C:\usr\c>
Download : hiyoko.h ( SJIS 版 )
/* * 2012/11/09 hiyoko.h */ #define YES 1 #define NO 0 /* * */ #define EOS '\0' #define SSIZE 100 /* * */ extern int calc_check ( char n[], int size, /* 文字の名前 */ int a[], int sa, /* 足される数の個々の桁の番号の配列とサイズ */ int b[], int sb, /* 足す数の個々の桁の番号の配列とサイズ */ int c[], int sc, /* 和の数の個々の桁の番号の配列とサイズ */ int x[] /* 答の候補 */ ); extern int find ( char *ta, char *tb, char *tc ); /* * */
Download : makefile.mf
Download : 20121116-01.c ( SJIS 版 )
/*
* DATE-DIR-QQQQ.c
*
* ニ次方程式 ( a x^2 + b x + c = 0 ) の解を、虱潰し法で解く
* ただし、解は、一桁の自然数
*
*/
#include <stdio.h>
/*
*
*/
#define YES 1
#define NO 0
/*
* a x^2 + b x + c = 0 ? : 論理式 P に相当する
*/
int check_formula ( int a, int b, int c, int x ) {
/*
** この部分を完成させなさい
*/
return NO;
}
/*
* 方程式 a x^2 + b x + c = 0 の解を、
* x_min 〜 x_max の範囲で探す
* 見付かったら、その値を返す
* もし見付からなかったら、範囲外の数 ( x_max + 1 ) を返す
*/
int solve_formal ( int a, int b, int c, int x_min, int x_max ) {
int x;
for ( x = x_min; x <= x_max; x++ ) { /* x = x_min 〜 x_max */
if ( check_formula ( a, b, c, x ) == YES ) { /* 見付かった */
return x; /* その値を返す */
}
}
/*
* 見付からなかったので..
*/
return x_max + 1; /* 範囲の外である数を返す */
}
/*
* a x^2 + b x + c = 0 の整数解を求める
*/
int main ( void ) {
int a;
int b;
int c; /* a x^2 + b x + c = 0 の a, b, c */
int x_min;
int x_max; /* F = { x | x_min <= x <= x_max } */
int x; /* 答の候補 */
/*
* [Input]
*/
/*
* P(x) == (a x^2 + b x + c = 0)
*/
printf ( "方程式 a x^2 + b x + c = 0 の整数解を搜します。\n" );
printf ( " a の値を入力してください : " );
scanf ( "%d", &a );
printf ( " b の値を入力してください : " );
scanf ( "%d", &b );
printf ( " c の値を入力してください : " );
scanf ( "%d", &c );
/*
* F = { x | x_min <= x <= x_max }
*/
printf ( "x の取り得る範囲を指定してください\n" );
printf ( "\t最小値 : " );
scanf ( "%d", &x_min );
printf ( "\t最大値 : " );
scanf ( "%d", &x_max );
/*
* [Process]
*/
/*
* 「 \exists x \in F[P(x)] 」の探索による証明
*/
x = solve_formal ( a, b, c, x_min, x_max );
/*
* [Output]
*/
if ( x > x_max ) {
printf ( "方程式 %d x^2 + %d x + %d = 0 の解を %d 〜 %d \
の範囲の整数からは見つける事ができませんでした。\n", a, b, c, x_min, x_max );
} else { /* 答が見つかった */
/*
** この部分を完成させなさい
*/
}
/*
*
*/
return 0;
}
/*
*
*/
12 34
C:\usr\c\> 20121116-01
方程式 a x^2 + b x + c = 0 の整数解を搜します。
a の値を入力してください : 12
b の値を入力してください : 34
c の値を入力してください : 1074531517
x の取り得る範囲を指定してください
最小値 : 134516073
最大値 : -1078587784
方程式 12 x^2 + 34 x + 1074531517 = 0 の解を 134516073 〜 -1078587784 \
の範囲の整数からは見つける事ができませんでした。
C:\usr\c\>
Download : 20121109-02.c ( SJIS 版 )
/*
* 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
C:\usr\c\> 20121109-02 問 : こな + ここ = きなこ こ = 5, な = 0, き = 1 50 + 55 = 105 解けた C:\usr\c\>