Quantcast
Channel: 円周率近似値の日に生まれて理系じゃないわけないだろ! - knifeのblog
Viewing all articles
Browse latest Browse all 5376

マーティン・ガードナー その4

$
0
0

前記事の結果、100桁では粘度12が見つからなかったので、迷走中である。

とりあえず、何桁でも求められるプログラムを組んでみた。

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

#define KETA  1000
#define K1    KETA/4
#define K2    K1-1
#define K3    K2-1

void calc(void);
void n9(void);
void n8(void);
void n7(void);
void n6(void);
void n5(void);
void n4(void);
void n3(void);
void n2(void);

int x[K1] = {1}, y, z=2;
int n[10] = {0};
int hb = 0;

void calc()
{
  int i, j, k, l, m;

  for (i=9, k=KETA-1; i>0; i--)
  for (j=0; j<n[i]; j++, k--)
  if ( k%4 == 3 && i == 1 ) {
    x[k/4] = 1;
    break;
  } else if ( k%4 == 3 ) {
    x[k/4] = i;
  } else if ( i > 1 ) {
    x[k/4] *= i;
  }
  for (; k>0; k-=4) x[k/4] = 1;
  y = 1;
  while ( x[K2] > 9 ) {
    y ++;
    for (j=K3; j>-1; j--) {
      if ( x[j] > 1 ) {
        m = 0;
        for (k=K2; k>j; k--) {
          l = x[j]*x[k]+m;
          x[k] = l%10000;
          m = l/10000;
        }
        x[j] = m;
      } else if ( x[j] == 1 ) {
        x[j] = 0;
      } else {
        x[K2] = 0;
        break;
      }
    }
    k = 1;
    for (j=0; j<K1; j++) {
      if ( k == 0 ) {
        x[j] = (x[j]/1000)*((x[j]/100)%10)*((x[j]/10)%10)*(x[j]%10);
      } else if ( k && x[j] > 999 ) {
        x[j] = (x[j]/1000)*((x[j]/100)%10)*((x[j]/10)%10)*(x[j]%10);
        k = 0;
      } else if ( k && x[j] > 99 ) {
        x[j] = ((x[j]/100)%10)*((x[j]/10)%10)*(x[j]%10);
        k = 0;
      } else if ( k && x[j] > 9 ) {
        x[j] = ((x[j]/10)%10)*(x[j]%10);
        k = 0;
      } else if ( k && x[j] > 0 ) {
        x[j] = (x[j]%10);
        k = 0;
      } else if ( k && x[j] == 0 ) {
        x[j] = 1;
      }
    }
  }

  if ( y > z ) {
    z = y;
    printf("\r%2d:", z);for (i=2; i<10; i++) for (j=0; j<n[i]; j++) printf("%d", i); printf("\n");
  }
}

void n9()
{
  n[9] = KETA-n[1]-n[2]-n[3]-n[4]-n[5]-n[6]-n[7]-n[8];
  calc();
}

void n8()
{
  if ( !n[5] ) {
    for (n[8]=KETA-n[1]-n[2]-n[3]-n[4]-n[5]-n[6]-n[7]; n[8]>-1; n[8]--) {
      if ( !n[2] && !n[3] && !n[4] && !n[6] ) printf(".8\b\b");
      n9();
    }
  } else {
    n[8] = 0;
    n9();
  }
}

void n7()
{
  for (n[7]=KETA-n[1]-n[2]-n[3]-n[4]-n[5]-n[6]; n[7]>-1; n[7]--) {
    if ( !n[2] && !n[3] && !n[4] && !n[5] && !n[6] ) printf(".7\b\b");
    n8();
  }
}

void n6()
{
  if ( !n[3] ) {
    for (n[6]=min(KETA-n[1]-n[2]-n[3]-n[4]-n[5],1); n[6]>-1; n[6]--) {
      if ( !n[2] && !n[3] && !n[4] ) printf(".6\b\b");
      n7();
    }
  } else {
    n[6] = 0;
    n7();
  }
}

void n5()
{
  for (n[5]=KETA-n[1]-n[2]-n[3]-n[4]; n[5]>0; n[5]--) {
    n[6] = 0;
    n7();
  }
  n[5] = 0;
  n6();
}

void n4()
{
  printf(".4\b\b");
  n[4] = 1;
  n[5] = 0;
  n6();
  n[4] = 0;
  n5();
}

void n3()
{
  printf(".3\b\b");
  n[3] = 1;
  n[4] = 0;
  n5();
  n[3] = 0;
  n4();
}

void n2()
{
  printf(".2\b\b");
  n[2] = 1;
  n[3] = 0;
  n[4] = 0;
  n[5] = 0;
  n6();
  n[2] = 0;
  n3();
}

int main(int argc, char *argv[])
{
  int a = -1, b = -1;

  if ( argc >= 2 ) a = atoi(argv[1]);
  if ( argc == 3 ) b = atoi(argv[2]);

  if ( 15 < a && a < b && b < KETA-2 ) {
    printf(" 1:10\n");
    printf(" 2:25\n");
    for (n[1]=KETA-2; n[1]>KETA-16; n[1]--) {
      printf("\r%d", KETA-n[1]);
      n2();
    }
    for (n[1]=KETA-a; n[1]>KETA-b-1; n[1]--) {
      printf("\r%d", KETA-n[1]);
      n2();
    }
  } else if ( 15 < a && a < KETA-2 ) {
    printf(" 1:10\n");
    printf(" 2:25\n");
    for (n[1]=KETA-2; n[1]>KETA-16; n[1]--) {
      printf("\r%d", KETA-n[1]);
      n2();
    }
    for (n[1]=KETA-a; n[1]>-1; n[1]--) {
      printf("\r%d", KETA-n[1]);
      n2();
    }
  } else {
    printf(" 1:10\n");
    printf(" 2:25\n");
    for (n[1]=KETA-2; n[1]>-1; n[1]--) {
      printf("\r%d", KETA-n[1]);
      n2();
    }
  }

  return EXIT_SUCCESS;
}

KETAで4の倍数の桁数を設定し、コンパイルすればよいが、とりあえず、1000にしておく。

前回のプログラムでは、各桁でネストしていたのをやめ、1、2、3、4、5、6、7、8、9が何桁連なるかということで、それぞれをサブルーチンとしてみた。

また、パラメータで桁数を与えることで、途中から開始、途中で終了されられるようにもしてみた。

前回の100桁プログラムで60秒程度掛かっていたものが、今回のプログラムを1000桁設定で100桁まで実行してみたところ、20秒前後とかなりの速度アップはしてはいる。

とはいっても、ある程度の桁数になると速度が低下するので、DOS窓を沢山開いて、各レンジでパラレルで動かしてということも可能ではある。


裏でプログラムで検索しながら、表で粘度12が存在するのかを別角度から検証してみることになるだろう。

つづく

Viewing all articles
Browse latest Browse all 5376

Trending Articles