quinta-feira, 9 de fevereiro de 2012

GO FOR IT /コードで世界は変えられる /人生の時計

プログラムコード (lifeclock.c)


/*********** START *****************************/

#include < stdio.h >

/*日付の構造体 a=,b=,c=*/

struct date {

int a;

int b;

int c;

};

/*このプログラムで使われている関数*/

struct date getdate(int );

int checkdate(struct date );

int leapyear(int ,int );

int countdays(struct date );

int totaldays(struct date ,struct date );

/******* main *************************************/

int main () {

char buff[100];

int n,total,untilnow,second,minute,hour,totalsecond;

double ratio,time;


struct date birth=getdate(1); /*まず誕生日を入力してもらう*/

if (checkdate(birth)==-1) return;


printf("How many years will you live?\n"); /*何歳まで生きるか入力してもらう*/

fgets(buff,sizeof(buff),stdin);

n=atoi(buff);


struct date now=getdate(2); /*現在の日付を入力してもらう*/

if (checkdate(now)==-1) return; /*ライブラリーの関数も使えますが、入力可能にしてみました*/


struct date death; /*ここで死亡の日付の構造体を作る*/

death.a=birth.a+n;

death.b=birth.b;

death.c=birth.c;


total= totaldays(birth,death); /*誕生日から死亡までの日数*/

untilnow= totaldays(birth,now); /*誕生日から現在までの日数*/


ratio = (double)untilnow/total; /*一生の何%が過ぎたかを計算する*/


time=86400*ratio; /*24時間にその比率をかけて、現在何秒過ぎたかを計算する*/

totalsecond = time; /*秒までしか計算したくないので、ここで自然数に変更する*/


second = totalsecond%60; /*秒の計算*/

minute = (totalsecond/60)%60; /*分の計算*/

hour = totalsecond/3600; /*時の計算*/


printf("If your life was compared to 24 hours, now would be %d hour %d minutes %d second\n", hour, minute, second);

return 0;

}

/******* getdate **********************/

/*日付をキーボードから入力する*/


struct date getdate (int i) {


struct date date;

char buff[100];


if (i==1) printf("What year were your born? (1900<=year<=2000)");

else printf("What year is now?\n");

fgets(buff,sizeof(buff),stdin);

date.a=atoi(buff);


if (i==1)printf("What month were your born?\n");

else printf("What month is now?\n");

fgets(buff,8,stdin);

date.b=atoi(buff);


if (i==1) printf("What day were your born?\n");

else printf("What day is today?\n");

fgets(buff,8,stdin);

date.c=atoi(buff);


return (date);

}

/******** checkdate ******************************/

/*記入された日付が有効であるか確認する。問題に「bcは一般的な月日の範囲とします」と指示してあるので、この関数は省略しても良い*/

int checkdate(struct date date){


if (date.a<1900) { /**/

printf("invalid year,try again\n");

return(-1);

}


if (date.b<1 || date.b>12) { /**/

printf("invalid month,try again\n");

return(-1);

}


if (date.c<1 || date.c >31){ /**/

printf("invalid day,try again\n");

return(-1);

}


if (date.b==4 || date.b==6 || date.b==9 || date.b==11) {

if (date.c==31){

printf("invalid day,try again\n");

return(-1);

}

}


if (date.b==2) { /*2月の場合は閏年かどうかをleapyear関数で確認し、29日の有効を確認する*/

if (leapyear(date.a,date.a)==0) {


if (date.c>28) {

printf("invalid day,try again\n");

return(-1);

}


}

else {

if (date.c>29) {

printf("invalid day,try again\n");

return(-1);

}

}

}

}

/******* leapyear ************************************************/

/*ある年からある年までに閏年が何年あるかを調べる*/


int leapyear(int b,int l){


int count=0;

int i;

for (i=b;i<=l;i++){

if (i%100==0 && i%400!=0) i++;

if (i%4==0) {

count++;

}

}

return(count);

}

/********** countdays *********************************************/

/*ここで年の始まりからある日までの日数を数える*/


int countdays (struct date x) {


int year[12] = {31,28,31,30,31,30,31,31,30,31,30,31};

int lyear[12] = {31,29,31,30,31,30,31,31,30,31,30,31};


int sum=0,i;


sum+=(x.c-1);


for (i=0;i<(x.b-1);i++){

if (leapyear(x.a,x.a)==1) sum+=lyear[i];

else sum+=year[i];

}


return (sum);

}

/**************** totaldays ***************************/

/*ここである日から違う日までの日数を3段階で数える*/


int totaldays(struct date birth,struct date death){


/*生まれてからその年が終わるまでの日を数える*/

int x1;

int y=countdays(birth);

if (leapyear(birth.a,birth.a)==1) x1=366-y;

if (leapyear(birth.a,birth.a)==0) x1=365-y;


/*死亡の年が始まってから死亡する日までの日を数える*/

int x2=countdays(death);


/*生まれた年の次の年から死亡した年の前の年までの日を数える*/

int n=(death.a-birth.a);

int leap=leapyear(birth.a+1,death.a-1);

int x3=(366*leap)+(365*(n-leap-1));


int total=x1+x2+x3;

return (total);

}

/******** END ***************************/


出力の例

i)

1990<=a<=2000,n=80のとき、今日は何時何分何秒ですか?

t11m022@s01612h009:~/sony$ ./lifeclock
What year were your born? (1900<=year<=2000)
1960
What month were your born?
10
What day were your born?
14
How many years will you live?
80
What year is now?
2012
What month is now?
2
What day is today?
9
If your life was compared to 24 hours, now would be 15 hour 23 minutes 46 second

ii)

1990<=a<=2000,n=200のとき、今日は何時何分何秒ですか?

t11m022@s01612h009:~/sony$ cc lifeclock.c
t11m022@s01612h009:~/sony$ ./a.out
What year were your born? (1900<=year<=2000)
1950
What month were your born?
4
What day were your born?
2
How many years will you live?
200
What year is now?
2012
What month is now?
2
What day is today?
9
If your life was compared to 24 hours, now would be 7 hour 25 minutes 22 second

アルゴリズムの説明・動作方法

「誕生日から今までの日数」を、「誕生日から死亡までの日数」と割って比率を出している。それから、その比率を24時間の秒数(86400秒)にかけて、今日は何時何分何秒という回答を出している。

日数を数えるのに3段階を使っている。

1-

countdaysでは、年の始めからある月日まで何日過ぎているかを数えている。

例えば、4月15日(0時)なら、1月~3月までの日数(配列の足し算)プラス4月の過ぎた14日。

2-

この同じ関数で、ある日付から年が終わるまでの日数を数えられる。

例えば、1年間の365マイナス今まで過ぎた日数。

ここでは閏年も考慮している。

3-

1と2に数えてない日数を計算する。

例えば、1950年~1970年なら閏年が5年間あるので

(366 x 5) + (365 x 15) で計算できる。

例えば、i)の計算は以下のようになる。

1960年10月14日 ~ 80年間 の一生を24時間にたとえて、

2012年2月9日は何時何分何秒になるか。

1-

1960年10月14日から1961年1月1日までの日数を計算する

1960は閏年なので、31+29+31+30+31+30+31+31+30+13 = 287

366 - 287 = 79日

2-

2012年1月1日から2012年2月9日までの日数を計算する

31+8 = 39日

3-

1961年から2011年までの日数を計算する

閏年が12年間

(366 x 12) + (365 x 40) = 18262日

全部を足したら18380日になる。これが「誕生日から今までの日数」

同じように「誕生日から死亡までの日数」を計算すると28855日になる。

18383/28855 = 0.6371 (63.71%)

これを86400秒にかけると、55043.88秒になる。

これが15時23分46(.88)秒になる。

この問題では秒以下の時間を省略している。

実行環境など

私はLinuxのUbuntuで実行をしましたが、基本的な機能しか使っていないので、C言語のコンパイラがあればどこでも実行できるはずです。

コードを.cファイルに保存して、コンパイルすらば実行できる。

Nenhum comentário:

Postar um comentário