外国人就労拡大で際立つ日本の「ブラック国家ぶり」 のシミュレーション
/*
  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;
}