2019,江端さんの技術メモ

/*
  g++ -g specific_skill2.cpp -o specific_skill2
*/

/*

*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h> 



typedef struct person{
  int age;
  int type1_lifetime;  // 1号の残り時間
  int retirement_age; // 65歳で引退

  ///////////
  struct person *prev;  /* 前の構造体を示すポインタ */
  struct person *next;  /* 次の構造体を示すポインタ */ 

} PERSON;


int int_max(int a, int b)
{
  if (a < b) 
	return b;
  else 
	return a;
}



PERSON *p_first_person, *p_last_person;  

void init_person_list(PERSON **p_first_person, PERSON **p_last_person)
{
  PERSON *p_top_person = (PERSON *)malloc(sizeof(PERSON));
  if(p_top_person == NULL) {
	printf("メモリが確保できません\n");
	exit(EXIT_FAILURE);
  }
  memset(p_top_person, 0, sizeof(PERSON)); // ゼロクリア


  PERSON *p_tail_person = (PERSON *)malloc(sizeof(PERSON));
  if(p_tail_person == NULL) {
	printf("メモリが確保できません\n");
	exit(EXIT_FAILURE);
  }
  memset(p_tail_person, 0, sizeof(PERSON)); // ゼロクリア

  *p_first_person = p_top_person;
  *p_last_person = p_tail_person;

  (*p_first_person)->prev = NULL;
  (*p_last_person)->next = NULL;
  (*p_first_person)->next = (*p_last_person);
  (*p_last_person)->prev = (*p_first_person);

  return;
}

void add_person(PERSON *p_ref_person)
{

  PERSON *new_p_person = (PERSON *)malloc(sizeof(PERSON));
  if(new_p_person == NULL) {
	printf("メモリが確保できません\n");
	exit(EXIT_FAILURE);
  }
  memset(new_p_person, 0, sizeof(PERSON)); // ゼロクリア
  memcpy(new_p_person, p_ref_person, sizeof(PERSON)); // 引数の動的メモリの内容コピー
 
  // personの追加属性記述ここから
 
  // personの追加属性記述ここまで

  PERSON *p_person = p_last_person->prev;

  p_person->next = new_p_person;
  new_p_person->prev = p_person;

  p_last_person->prev = new_p_person;
  new_p_person->next = p_last_person;

  return;
}

void delete_person(PERSON *p_person)  
{
  // ポインタを貼り替えて
  p_person->prev->next = p_person->next;
  p_person->next->prev = p_person->prev;
  
  // そのメモリを解放する
  free(p_person);

  return;

}

int type1(int k){
  int number = 40000 + 4000 * (k - 2019);
  if (number > 60000){
	number = 60000;
  }
  return number;
}

// 2.1.1 C言語のrand関数を用いた方法
double Uniform( void ){
    return ((double)rand()+1.0)/((double)RAND_MAX+2.0);
}

// 3.3. 正規分布・ガウス分布 (Normal Distribution)
double rand_normal( double mu, double sigma ){
  double z=sqrt( -2.0*log(Uniform()) ) * sin( 2.0*M_PI*Uniform() );
  return mu + sigma*z;
} 


int main()
{
  srand(13);

  // 社員格納用リストの作成
  init_person_list(&p_first_person, &p_last_person); 

  int pass1_number;

  for (int i = 2019; i < 2080; i++){
  // for (int i = 2019; i < 2200; i++){
	// 1号試験パス者の生成
	pass1_number = type1(i);

	for (int k = 0; k < pass1_number; k++){
	  PERSON person;
	  person.age = int_max((int)rand_normal(26.0, 3.5), 18); // 18歳以下は応募できない
	  // printf("person.age = %d\n",person.age);
	  person.type1_lifetime = 5;
	  person.retirement_age = 65;
	  
	  add_person(&person);
	} // for (int k = 0, k < type1(k); k++)
	// 1号試験パス者の生成(ここまで)

    // ===== PERSON ループを回す========
    PERSON* p_person = p_first_person->next;  
    while (p_person != p_last_person){
	  
	  // 1号 強制帰国
	  if (p_person->type1_lifetime == 0){  // 5年を使い果した
		if (Uniform() <= 0.4){   // 2号合格率 40%
		  p_person->type1_lifetime = -1;  // 免責フラグ
		}
		else{
		  PERSON* p_person_prev = p_person->prev;
		  delete_person(p_person);
		  p_person = p_person_prev;
		}
	  }
	  
	  if (p_person->age > 65){  // 65歳以上になったら、強制帰国
		PERSON* p_person_prev = p_person->prev;
		delete_person(p_person);
		p_person = p_person_prev;
	  }

	  // 次のループに回る
	  p_person = p_person->next;
	}

    p_person = p_first_person->next;  
    while (p_person != p_last_person){

	  // 1号 強制帰国を迎えるまでのタイムリミットを減らす
	  if (p_person->type1_lifetime != -1){
		p_person->type1_lifetime -= 1;
	  }

	  // 全員の年齢の加算
	  p_person->age += 1;

	  // 次のループに回る
	  p_person = p_person->next;
	}


	int type1_person_count = 0;
	int type2_person_count = 0;
    p_person = p_first_person->next;  
    while (p_person != p_last_person){

	  if (p_person->type1_lifetime != -1)
		type1_person_count += 1;
	  else
		type2_person_count += 1;		

	  p_person = p_person->next;
	}

	//printf("i:%d, type1:%d, type2:%d\n", i, type1_person_count, type2_person_count);
	printf("%d, %d, %d, %d\n", 
		   i, 
		   type1_person_count, 
		   type2_person_count,
		   type1_person_count + type2_person_count);


  }//   for (int i = 2019; i < 2100; i++){

  return 0;
}