Task: 100 prisoners

C: #include<stdbool.h>
#include<stdlib.h>
#include<stdio.h>
#include<time.h>

#define LIBERTY false
#define DEATH true

typedef struct{
	int cardNum;
	bool hasBeenOpened;
}drawer;

drawer *drawerSet;

void initialize(int prisoners){
	int i,j,card;
	bool unique;

	drawerSet = ((drawer*)malloc(prisoners * sizeof(drawer))) -1;

	card = rand()%prisoners + 1;
	drawerSet[1] = (drawer){.cardNum = card, .hasBeenOpened = false};

	for(i=1 + 1;i<prisoners + 1;i++){
		unique = false;
		while(unique==false){
			for(j=0;j<i;j++){
				if(drawerSet[j].cardNum == card){
					card = rand()%prisoners + 1;
					break;
				}
			}
			if(j==i){
				unique = true;
			}
		}
		drawerSet[i] = (drawer){.cardNum = card, .hasBeenOpened = false};
	}

}

void closeAllDrawers(int prisoners){
	int i;
	for(i=1;i<prisoners + 1;i++)
		drawerSet[i].hasBeenOpened = false;
}

bool libertyOrDeathAtRandom(int prisoners,int chances){
	int i,j,chosenDrawer;

	for(i= 1;i<prisoners + 1;i++){
		bool foundCard = false;
		for(j=0;j<chances;j++){
			do{
				chosenDrawer = rand()%prisoners + 1;
			}while(drawerSet[chosenDrawer].hasBeenOpened==true);
			if(drawerSet[chosenDrawer].cardNum == i){
				foundCard = true;
				break;
			}
			drawerSet[chosenDrawer].hasBeenOpened = true;
		}
		closeAllDrawers(prisoners);
		if(foundCard == false)
			return DEATH;
	}

	return LIBERTY;
}

bool libertyOrDeathPlanned(int prisoners,int chances){
	int i,j,chosenDrawer;
	for(i=1;i<prisoners + 1;i++){
		chosenDrawer = i;
		bool foundCard = false;
		for(j=0;j<chances;j++){
			drawerSet[chosenDrawer].hasBeenOpened = true;

			if(drawerSet[chosenDrawer].cardNum == i){
				foundCard = true;
				break;
			}
			if(chosenDrawer == drawerSet[chosenDrawer].cardNum){
				do{
                    chosenDrawer = rand()%prisoners + 1;
				}while(drawerSet[chosenDrawer].hasBeenOpened==true);
			}
			else{
				chosenDrawer = drawerSet[chosenDrawer].cardNum;
			}

		}

		closeAllDrawers(prisoners);
		if(foundCard == false)
			return DEATH;
	}

	return LIBERTY;
}

int main(int argc,char** argv)
{
	int prisoners, chances;
	unsigned long long int trials,i,count = 0;
        char* end;

	if(argc!=4)
		return printf("Usage : %s <Number of prisoners> <Number of chances> <Number of trials>",argv[0]);

	prisoners = atoi(argv[1]);
	chances = atoi(argv[2]);
	trials = strtoull(argv[3],&end,10);

	srand(time(NULL));

	printf("Running random trials...");
	for(i=0;i<trials;i+=1L){
		initialize(prisoners);

		count += libertyOrDeathAtRandom(prisoners,chances)==DEATH?0:1;
	}

	printf("\n\nGames Played : %llu\nGames Won : %llu\nChances : %lf %% \n\n",trials,count,(100.0*count)/trials);

        count = 0;

	printf("Running strategic trials...");
	for(i=0;i<trials;i+=1L){
		initialize(prisoners);

		count += libertyOrDeathPlanned(prisoners,chances)==DEATH?0:1;
	}

	printf("\n\nGames Played : %llu\nGames Won : %llu\nChances : %lf %% \n\n",trials,count,(100.0*count)/trials);
	return 0;
}










Fortran: SUBROUTINE SHUFFLE_ARRAY(INT_ARRAY)
    
    
    IMPLICIT NONE

    INTEGER, DIMENSION(100), INTENT(INOUT) :: INT_ARRAY
    INTEGER, PARAMETER :: N_PASSES = 10
    

    INTEGER :: TEMP_1, TEMP_2   
    INTEGER :: I, J, PASS       
    REAL :: R                   

    CALL RANDOM_SEED()  

    DO PASS=1, N_PASSES
        DO I=1, SIZE(INT_ARRAY)

            
            CALL RANDOM_NUMBER(R)
            J = CEILING(R*SIZE(INT_ARRAY))

            
            
            DO WHILE (J > SIZE(INT_ARRAY))
                J = CEILING(R*SIZE(INT_ARRAY))
            END DO

            
            TEMP_1 = INT_ARRAY(I)
            TEMP_2 = INT_ARRAY(J)
            INT_ARRAY(I) = TEMP_2
            INT_ARRAY(J) = TEMP_1
        ENDDO
    ENDDO
END SUBROUTINE SHUFFLE_ARRAY

SUBROUTINE RUN_RANDOM(N_ROUNDS)
    
    
    IMPLICIT NONE

    INTEGER, INTENT(IN) :: N_ROUNDS 

    INTEGER :: ROUND, PRISONER, CHOICE, I       
    INTEGER :: N_SUCCESSES                      
    REAL(8) :: TOTAL                            
    LOGICAL :: NUM_FOUND = .FALSE.              

    INTEGER, DIMENSION(100) :: CARDS, CHOICES   
                                                

    
    
    
    
    CARDS = (/(I, I=1, 100, 1)/)
    CHOICES = (/(I, I=1, 100, 1)/)

    N_SUCCESSES = 0
    TOTAL = REAL(N_ROUNDS)

    
    
    
    
    ROUNDS_LOOP: DO ROUND=1, N_ROUNDS
        CALL SHUFFLE_ARRAY(CARDS)
        PRISONERS_LOOP: DO PRISONER=1, 100
            NUM_FOUND = .FALSE.
            CALL SHUFFLE_ARRAY(CHOICES)
            CHOICE_LOOP: DO CHOICE=1, 50
                IF(CARDS(CHOICE) == PRISONER) THEN
                    NUM_FOUND = .TRUE.
                    EXIT CHOICE_LOOP
                ENDIF
            ENDDO CHOICE_LOOP
            IF(.NOT. NUM_FOUND) THEN
                EXIT PRISONERS_LOOP
            ENDIF
        ENDDO PRISONERS_LOOP
        IF(NUM_FOUND) THEN
            N_SUCCESSES = N_SUCCESSES + 1
        ENDIF
    ENDDO ROUNDS_LOOP

    WRITE(*, '(A, F0.3, A)') "Random drawer selection method success rate: ", &
        100*N_SUCCESSES/TOTAL, "%"

END SUBROUTINE RUN_RANDOM

SUBROUTINE RUN_OPTIMAL(N_ROUNDS)
    
    
    
    
    IMPLICIT NONE

    INTEGER, INTENT(IN) :: N_ROUNDS

    INTEGER :: ROUND, PRISONER, CHOICE, I   
    INTEGER :: CURRENT_DRAW                 
    INTEGER :: N_SUCCESSES                  
    REAL(8) :: TOTAL                        
    LOGICAL :: NUM_FOUND = .FALSE.          
    INTEGER, DIMENSION(100) :: CARDS        

    
    
    CARDS = (/(I, I=1, 100, 1)/)

    N_SUCCESSES = 0
    TOTAL = REAL(N_ROUNDS)

    
    
    
    
    ROUNDS_LOOP: DO ROUND=1, N_ROUNDS
        CARDS = (/(I, I=1, 100, 1)/)
        CALL SHUFFLE_ARRAY(CARDS)
        PRISONERS_LOOP: DO PRISONER=1, 100
            CURRENT_DRAW = PRISONER
            NUM_FOUND = .FALSE.
            CHOICE_LOOP: DO CHOICE=1, 50
                IF(CARDS(CURRENT_DRAW) == PRISONER) THEN
                    NUM_FOUND = .TRUE.
                    EXIT CHOICE_LOOP
                ELSE
                    CURRENT_DRAW = CARDS(CURRENT_DRAW)
                ENDIF
            ENDDO CHOICE_LOOP
            IF(.NOT. NUM_FOUND) THEN
                EXIT PRISONERS_LOOP
            ENDIF
        ENDDO PRISONERS_LOOP
        IF(NUM_FOUND) THEN
            N_SUCCESSES = N_SUCCESSES + 1
        ENDIF
    ENDDO ROUNDS_LOOP
    WRITE(*, '(A, F0.3, A)') "Optimal drawer selection method success rate: ", &
        100*N_SUCCESSES/TOTAL, "%"

END SUBROUTINE RUN_OPTIMAL

PROGRAM HUNDRED_PRISONERS
    
    
    IMPLICIT NONE
    INTEGER, PARAMETER :: N_ROUNDS = 50000
    WRITE(*,'(A, I0, A)') "Running simulation for ", N_ROUNDS, " trials..."
    CALL RUN_RANDOM(N_ROUNDS)
    CALL RUN_OPTIMAL(N_ROUNDS)
END PROGRAM HUNDRED_PRISONERS