パズル万華鏡

面白いパズルの紹介と解説をします。

センチュリーパズル問題(2)考察1

 センチュリーパズル問題(1)考察1を示します。

(2)考察1

 1から9までの数を1回ずつ使って帯分数を作り、100を表す方法をすべて求めるプログラムを示す。

●プログラム(century.c)

/* << century.c >> */
/* センチュリーパズル(100以下)*/
#include <stdio.h>
#define N 9   /* 集合{1,2,…,n}の最大個数。*/            
#define M 100 /* 帯分数の最大値。*/
int count,    /* 解の個数。*/
    m,        /* 指定する帯分数の値。*/
    n,        /* 要素数。*/
    p[N+1];   /* 生成される順列。*/
void perm(int k);

int main() {
  int i;

  while( 1 ) {

    /* nの読み込み。*/                         
    scanf("%d",&n);                            
    if( (n <=0 )||(n > N) ) { break; }         

    /* 指定する帯分数の値mの読み込み。*/
    scanf("%d",&m);
    if( (m <= 0)||(m > M) ) { break; }

    /* 初期設定。*/
    for( i=1; i<=n; i++ ) { p[i] = i; }
    count = 0;

    /* 求める帯分数の生成。*/
    perm(1);
    printf("n = %3d m=%3d  count=%5d\n",n,m,count);
  }
}

/* 順列生成の方法を基に、求める帯分数を生成する。*/
void perm(int k) {
  int i,j,
      t,  /* 帯分数の値。*/
      t1, /* 帯分数の整数部分。*/
      t2, /* 帯分数の分子。*/
      t3, /* 帯分数の分母。*/
      w;

  if( k > n ) {

    /* 整数部分t1が1桁の場合、整数部分t1を計算する。*/
    t1 = p[1];

    /* 分子の桁数≧分母の桁数より、jは5から8まで。*/
    for( j=5; j<=8; j++ ) {
      /* 分子t2がj-1桁の場合、分子t2を計算する。*/
      t2 = 0; 
      for( i=2; i<=j; i++ ) { t2 = t2*10 + p[i]; }

      /* 分母t3が9-j桁の場合、分母t3を計算する。*/
      t3 = 0; 
      for( i=j+1; i<=9; i++ ) { t3 = t3*10 + p[i]; }

      /* 帯分数の値tを求める。*/
      t = t1+t2/t3;
      /* 帯分数の値がmを超えた場合、分子/分母の値は、
         増大していくのでループを出る。*/
      if( t > m ) { break; }

      /* 「分子が分母で割りきれる」かつ指定された値mと
     一致する。*/
      if( (t2%t3 == 0)&&(t1+t2/t3 == m) ) {
        count++;
        printf("[%5d] ",count);
        printf("%d + %d/%d\n",t1,t2,t3);
      }
    }

    /* 整数部分t1が2桁の場合、整数部分t1を計算する。*/
    t1 = p[1]*10+p[2];

    /* 分子の桁数≧分母の桁数より、jは6から8まで。*/
    for( j=6; j<=8; j++ ) {
      /* 分子t2がj-2桁の場合、分子t2を計算する。*/         
      t2 = 0; 
      for( i=3; i<=j; i++ ) { t2 = t2*10 + p[i]; }

      /* 分母t3が9-j桁の場合、分子t3を計算する。*/          
      t3 = 0; 
      for( i=j+1; i<=9; i++ ) { t3 = t3*10 + p[i]; }

      /* 帯分数の値tを求める。*/
      t = t1+t2/t3;
      /* 帯分数の値がmを超えた場合、分子/分母の値は、
         増大していくのでループを出る。*/
      if( t > m ) { break; }

      /* 「分子が分母で割りきれる」かつ指定された値mと 
     一致する。*/                                   
      if( (t2%t3 == 0)&&(t1+t2/t3 == m) ) {
        count++;
        printf("[%5d] ",count);
        printf("%d + %d/%d\n",t1,t2,t3);
      }

      /* 整数部分t1が3桁以上の場合は、扱わない。*/
    }
    return;
  }

  for( i=k; i<=n; i++ ) {
    w = p[k]; p[k] = p[i]; p[i] = w;
    perm(k+1);
    w = p[k]; p[k] = p[i]; p[i] = w;
  }
}

実行結果
f:id:isemba:20150308190225j:plain
f:id:isemba:20150308190244j:plain