C"战舰"在10k +迭代之后编程非统计输出

时间:2015-10-21 11:03:20

标签: c algorithm statistics probability

我试图在http://thevirtuosi.blogspot.com/2011/10/linear-theory-of-battleship.html复制调查结果。他的发现是,随后尺寸较小的船舶的观测/经验概率图迫使它们从中心出来,在那里,尺寸越来越大的船舶往往聚集在那里。 虽然他的结果在垂直轴和水平轴之间是对称的,但我编写的代码会产生结果,其中水平轴在船上的位置明显更多 - 即使我正在做所有我能想到的事情来彻底随机化垂直或水平之间的过程第一。任何大小的地图都存在这种不对称性。传达问题的最小代码是171行。这个论坛适合这个吗?这不是家庭作业,工作或课程相关。我对战舰算法很感兴趣。输出是将某个船放置在某个位置的实际迭代次数,此类百分比以及此类的ASCII字符映射 - 以便更容易地观察不对称性。任何方向赞赏。

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

int main(void)
{
clock_t start, end;
double cpu_time_used;
srand(time(NULL));
int obstruction;
int done;
int waysVert=0;
int waysHorz=0;
int counter=0;
int vertCounter=0;
int horzCounter=0;
int iGuess=0;
int jGuess=0;
int shipType=0;
int shotCounter=0;
int hitCounter=0;
int shipCellCounter=0;
int guessCounter=0;
int lenShip=0;
int highestProb=0;
int highestOccur=0;
int iteration=0;
int i=0;//x dimension
int j=0;//y dimension
int k=0;//z dimension and information dimension
int n=0;//number dimension
char shipChar;
char shipName[20]="";
char shipList[]="ABCDS";//question for later: How does placement order affect heat map?
int numberShips=strlen(shipList);
int jShipStart=0;
int iShipStart=0;
int polShipDir=0;
int biasShipDir=0;
int jShipDir=0;
int iShipDir=0;
int NUM_COLS=10;//x dimension
int NUM_ROWS=10;//y dimension
int NUM_LEVS=21;//[0,7] Theoretical Prob. [10,16] Empirical Prob. 20 Presentation Level
char                grid[NUM_LEVS][NUM_ROWS][NUM_COLS];
long int empiricalGrid[NUM_LEVS][NUM_ROWS][NUM_COLS];


for(k=0;k<NUM_LEVS;k++){for(j=0;j<NUM_ROWS;j++){for(i=0;i<NUM_COLS;i++){           grid[k][j][i]=0;}}}//initialize 1-byte levels
for(k=0;k<NUM_LEVS;k++){for(j=0;j<NUM_ROWS;j++){for(i=0;i<NUM_COLS;i++){empiricalGrid[k][j][i]=0;}}}//initialize 4-byte levels
k=20;//k=20 is the presentation level
//for(j=0;j<NUM_ROWS;j++){for(i=0;i<NUM_COLS;i++){grid[k][j][i]='~';}}//initialize water character (first time, single run)

start = clock();
for(iteration=0;iteration<50000;iteration++){//has run at 50000000 iteration//could put scaling onto the printout using digit length of iterations
    for(j=0;j<NUM_ROWS;j++){for(i=0;i<NUM_COLS;i++){grid[k][j][i]='~';}}//initialize water character (every time, in loop)

    //PLACEMENT ROUTINE FOR-LOOP AND DO-WHILE LOOP
    for (shipType = 0; shipType < strlen(shipList); shipType++){
        shipChar=shipList[shipType];

        switch(shipChar){
        case 'A':lenShip=5;break;
        case 'B':lenShip=4;break;
        case 'C':lenShip=3;break;
        case 'D':lenShip=2;break;
        case 'S':lenShip=3;break;//since ran out of 3, think low number as in low elevation, beneath any other ships 
        }
        shipCellCounter+=lenShip;
        k=20;

        do{
            jShipStart=0;
            iShipStart=0;
            polShipDir=0;
            biasShipDir=0;
            jShipDir=0;
            iShipDir=0;
            obstruction=0;//printf("\nSet to no obstruction to %d\n",obstruction);
            if(rand()%2==0){
                jShipStart=rand()%NUM_ROWS;//printf("jShipStart %d starting row (0-%d)\n",jShipStart,NUM_ROWS-1);//
                iShipStart=rand()%NUM_COLS;//printf("iShipStart %d starting col (0-%d)\n",iShipStart,NUM_COLS-1);//
            }
            else{
                iShipStart=rand()%NUM_COLS;//printf("iShipStart %d starting col (0-%d)\n",iShipStart,NUM_COLS-1);//
                jShipStart=rand()%NUM_ROWS;//printf("jShipStart %d starting row (0-%d)\n",jShipStart,NUM_ROWS-1);//
            }
            polShipDir  = (rand()%2) * 90;//printf("polShipDir %d degrees\n",polShipDir);//polarity 00 deg => prop horz, 90 = prop vert
            biasShipDir = (rand()%2) * (-2) + 1;//printf("biasShipDir %d\n",biasShipDir);

            if(rand()%2==0){
                if( polShipDir==90 && jShipStart  > lenShip-1){ jShipDir=(rand()%2) * (-2) + 1; }
                if( polShipDir==90 && jShipStart <= lenShip-1){ jShipDir=(rand()%2) * (-2) + 1; }
                if( polShipDir== 0 && iShipStart  > lenShip-1){ iShipDir=(rand()%2) * (-2) + 1; }
                if( polShipDir== 0 && iShipStart <= lenShip-1){ iShipDir=(rand()%2) * (-2) + 1; }
            }
            else{
                if( polShipDir== 0 && iShipStart <= lenShip-1){ iShipDir=(rand()%2) * (-2) + 1; }
                if( polShipDir== 0 && iShipStart  > lenShip-1){ iShipDir=(rand()%2) * (-2) + 1; }
                if( polShipDir==90 && jShipStart <= lenShip-1){ jShipDir=(rand()%2) * (-2) + 1; }
                if( polShipDir==90 && jShipStart  > lenShip-1){ jShipDir=(rand()%2) * (-2) + 1; }
            }

            for(n=0;n<lenShip;n++){//Check to see if ANY part of the ship runs off map.
                if(rand()%2==0){
                    if( polShipDir== 90 && jShipStart + n * jShipDir >= NUM_ROWS || polShipDir==  0 && iShipStart + n * iShipDir >= NUM_COLS ){
                        obstruction=1;
                    }
                }
                else{
                    if( polShipDir==  0 && iShipStart + n * iShipDir >= NUM_COLS || polShipDir== 90 && jShipStart + n * jShipDir >= NUM_ROWS){
                        obstruction=1;
                    }
                }
            }

            for(n=0;n<lenShip;n++){//Check to see if ANY part of the ship DID NOT hit water.
                if( grid [ k ] [ jShipStart + n * jShipDir ] [ iShipStart + n * iShipDir ] != '~' ){
                obstruction=1;
                }//ANY single obstruction means start over for this ship.
            }

            if(obstruction==0){//If prior loop HAS NOT resulted in ANY obstruction: THEN assign this ship
                for(n=0;n<lenShip;n++){
                    grid [ k ] [ jShipStart + n * jShipDir ] [ iShipStart + n * iShipDir ] = shipChar;
                }
            }
        }
        while(obstruction==1);
    }

    for(i=0;i<NUM_COLS;i++){for(j=0;j<NUM_ROWS;j++){
             if(grid[20][j][i]=='A'){empiricalGrid[15][j][i]++;}
        else if(grid[20][j][i]=='B'){empiricalGrid[14][j][i]++;}
        else if(grid[20][j][i]=='C'){empiricalGrid[13][j][i]++;}
        else if(grid[20][j][i]=='S'){empiricalGrid[10][j][i]++;}//DONT CHANGE THIS RECORD OF SEQUENCE ANYWHERE ELSE. KEEP IT HERE.
        else if(grid[20][j][i]=='D'){empiricalGrid[12][j][i]++;}
        }
    }
}
end = clock();
cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;

for(k=16;k>=10;k--){for(j=0;j<NUM_ROWS;j++){for(i=0;i<NUM_COLS;i++){if(highestOccur<=empiricalGrid[k][j][i]){highestOccur=empiricalGrid[k][j][i];}}}}
printf("Level %d Highest occurance = %d\n",k,highestOccur);

for(j=0;j<NUM_ROWS;j++){for(i=0;i<NUM_COLS;i++){printf("%10lu", empiricalGrid[15][j][i]);}printf("\n");}printf("A\n");
for(j=0;j<NUM_ROWS;j++){for(i=0;i<NUM_COLS;i++){printf("%10lu", empiricalGrid[14][j][i]);}printf("\n");}printf("B\n");
for(j=0;j<NUM_ROWS;j++){for(i=0;i<NUM_COLS;i++){printf("%10lu", empiricalGrid[13][j][i]);}printf("\n");}printf("C\n");
for(j=0;j<NUM_ROWS;j++){for(i=0;i<NUM_COLS;i++){printf("%10lu", empiricalGrid[12][j][i]);}printf("\n");}printf("D\n");
for(j=0;j<NUM_ROWS;j++){for(i=0;i<NUM_COLS;i++){printf("%10lu", empiricalGrid[10][j][i]);}printf("\n");}printf("S\n");
printf("Iterations: %d. CPU time used: %lf seconds. CLOCKS_PER_SEC = %d\n",iteration,cpu_time_used,CLOCKS_PER_SEC);

for(j=0;j<NUM_ROWS;j++){for(i=0;i<NUM_COLS;i++){printf("%2.2lf ", (double) empiricalGrid[15][j][i]/highestOccur);}printf("\n");}printf("A^\n");
for(j=0;j<NUM_ROWS;j++){for(i=0;i<NUM_COLS;i++){printf("%2.2lf ", (double) empiricalGrid[14][j][i]/highestOccur);}printf("\n");}printf("B^\n");
for(j=0;j<NUM_ROWS;j++){for(i=0;i<NUM_COLS;i++){printf("%2.2lf ", (double) empiricalGrid[13][j][i]/highestOccur);}printf("\n");}printf("C^\n");
for(j=0;j<NUM_ROWS;j++){for(i=0;i<NUM_COLS;i++){printf("%2.2lf ", (double) empiricalGrid[12][j][i]/highestOccur);}printf("\n");}printf("D^\n");
for(j=0;j<NUM_ROWS;j++){for(i=0;i<NUM_COLS;i++){printf("%2.2lf ", (double) empiricalGrid[10][j][i]/highestOccur);}printf("\n");}printf("S^\n");
printf("Iterations: %d. CPU time used: %lf seconds. CLOCKS_PER_SEC = %d\n",iteration,cpu_time_used,CLOCKS_PER_SEC);

for(j=0;j<NUM_ROWS;j++){for(i=0;i<NUM_COLS;i++){printf("%2c", 33+(int)(10*((double) empiricalGrid[15][j][i]/highestOccur)));}printf("\n");}printf("A^\n");
for(j=0;j<NUM_ROWS;j++){for(i=0;i<NUM_COLS;i++){printf("%2c", 33+(int)(10*((double) empiricalGrid[14][j][i]/highestOccur)));}printf("\n");}printf("B^\n");
for(j=0;j<NUM_ROWS;j++){for(i=0;i<NUM_COLS;i++){printf("%2c", 33+(int)(10*((double) empiricalGrid[13][j][i]/highestOccur)));}printf("\n");}printf("C^\n");
for(j=0;j<NUM_ROWS;j++){for(i=0;i<NUM_COLS;i++){printf("%2c", 33+(int)(10*((double) empiricalGrid[10][j][i]/highestOccur)));}printf("\n");}printf("S^\n");//SWITCH BACK
for(j=0;j<NUM_ROWS;j++){for(i=0;i<NUM_COLS;i++){printf("%2c", 33+(int)(10*((double) empiricalGrid[12][j][i]/highestOccur)));}printf("\n");}printf("D^\n");

printf("Iterations: %d. CPU time used: %lf seconds. CLOCKS_PER_SEC = %d\n",iteration,cpu_time_used,CLOCKS_PER_SEC);
printf("!=00s, \"=10s, #=20s, $=30s, %%=40s, &=50s, \'=60s, (=70s, )=80s, *=90s\n");
return 0;
}

2 个答案:

答案 0 :(得分:1)

我没有看到任何会产生您所讨论的偏见的错误,但我确实看到了一些不必要的并发症,我可以提供一些建议:

  • 正如评论中的wildplasser所建议的那样,使用dear = commands.getoutput('''awk '{print $0}' /home/angad/Desktop/Python_result/%s/%s''' % (genotype,filename)) 从C运行时库cmd_str = '''awk '{print $0}' /home/angad/Desktop/Python_result/%s/%s''' % (genotype,filename) dear = commands.getoutput(cmd_str) 中提取小的随机数通常会给出非常糟糕的性能。尝试更强的RNG,甚至更好的%之类的实际随机性。至少,尝试使用它来播种另一个RNG。

  • 作为快速但未确定的测试,请尝试将rand()更改为/dev/urandom。现在垂直船只的偏见是什么?如果是这样,那么问题肯定是RNG,因为有了一个好的RNG,前面两个语句应该是平均的。

  • 在两个不同的地方,你不必要地随机化执行两项测试顺序无关紧要的顺序!首先:

(显然需要这行格式化......)

polShipDir  = (rand()%2) * 90;

可以简化为

polShipDir  = (1 - rand()%2) * 90;

其次,从注释if(rand()%2==0){ if( polShipDir==90 && jShipStart > lenShip-1){ jShipDir=(rand()%2) * (-2) + 1; } if( polShipDir==90 && jShipStart <= lenShip-1){ jShipDir=(rand()%2) * (-2) + 1; } if( polShipDir== 0 && iShipStart > lenShip-1){ iShipDir=(rand()%2) * (-2) + 1; } if( polShipDir== 0 && iShipStart <= lenShip-1){ iShipDir=(rand()%2) * (-2) + 1; } } else{ if( polShipDir== 0 && iShipStart <= lenShip-1){ iShipDir=(rand()%2) * (-2) + 1; } if( polShipDir== 0 && iShipStart > lenShip-1){ iShipDir=(rand()%2) * (-2) + 1; } if( polShipDir==90 && jShipStart <= lenShip-1){ jShipDir=(rand()%2) * (-2) + 1; } if( polShipDir==90 && jShipStart > lenShip-1){ jShipDir=(rand()%2) * (-2) + 1; } } 开始的循环中发生的情况大致相同。 (顺便说一下,你根本不需要这个测试的循环:它足以检查船的起点和终点是否在有效位置。)

答案 1 :(得分:1)

谢谢大家的一般建议。 感谢wildplasser和j_random_hacker,他们提到了rand()的问题。 我去了一个真正的随机生成器(http://www.makelinux.net/alp/046),问题仍然存在,然后我在代码中发现编程错误。我没有足够的障碍来阻止船只从右侧进行自动换行并在左侧向后退回。这导致了偏见。 我的概率映射与此修复和相同的旧rand()确实重现了所提到的链接的结果,所以这对我来说意味着rand()对我的低级要求不是“那个”坏。 我很高兴听到如果需要,我可以改善随机性。 再次感谢。

我的(4长)B的地图现在为900000(在更高的迭代时收紧)。你可以看到'概述了(5长)A的阴影的位置,以及%侵入侧面并与&amp;相互作用的位置,是(5长)A的另一个阴影。

    " # $ % % % % $ # "
    # $ % & % & & % $ #
    $ % & & & & & & % $
    % & & ' & & ' & & %
    % % & & & & ' & % %
    % % & & & & & & % %
    % & & ' & & ' & & %
    $ % & & & & & & % $
    # $ % & % % & % $ #
    " # $ % % % % $ # "