#!/usr/bin/perl

use 5.40.3;

$|++;

# El famoso problema de los 100 prisioneros con 100 cajas y que deben sacar todos su no. en menos de 50 intentos
# cada prisionero puede abrir 50 cajas (50 * 100 aperturas potenciales)
# repito el juego $N veces

# La explicación es que la aleatoriedad es muy adversa (1/2)^100 contra la estrategia. Se descubrió el caso en 2003

# Ensayo sobre el salto de probabilidad. (c) Jesús Lozano Mosterín, 2025

my @lista = 0 .. 99;          # $nump = 100
my @histogram = (0) x 101;
my $exito = 0;
my $fail = 0;

my $N = 1_000_000;

for (1 .. $N){
    print "\r$_";
    
    my @cajas = jlm(@lista);

    my $successp = 0;
    
    for my $numerop (@lista){
	
	my $len = 0;
	my $first;
	my $ANTERIOR = $numerop;
	my $count = 0;
	
	for my $i (@cajas){         # contenido de la caja, se supone que nadie más que $p y los jueces lo ven 
	                            # son 100 cajas aunque sólo se permitan 50 por jugador/prisionero
	    my $i1 = $i;                   # estrategia = off    LO QUE SALGA, SIGUIENTE CAJA
	    
	    my $i2 = $cajas[$ANTERIOR];               # estrategia = on     MI NUMERO (o una derivación única) DE CAJA O LO DE LA CAJA ANTERIOR
	
	    $len++;
	    $first = $count++ if $len == 1;
	
	    next unless ( $numerop == $i1 ||           # estrategia no
		$numerop == $i2 ||                     # estrategia sí
		($i == $first && $len > 1)             # un número contiguo al anterior indica "circuito". Hay quien lo exxplica con una red
	    );     # validez en el juego más el cierre de circuito de contenido de la caja aleatoria 

	    
	    $histogram[$len]++;                         # aquí se cierra un circuito o se puntúa y se puede contar algo
	    
	    if ($len <= 50){                            # aquí hay éxito para el juego, por suerte o por estrategia, según reglas
		$successp++;
		last;                                   # siguiente preso
	    }else{
		$fail++;
		goto nextgame;                          # siguiente juego, según el juego, pero lo que interesa es ver también los "circuitos" mayores
	    }
	    
	    $len = 0;                                   # siguiente caja, AUNQUE SEA PARA PARA CALCULAR EL CICLO DE NO ÉXITO
	    $ANTERIOR = $i2;
	    $count = 0;                                 # si tiene alguna interpretación, es número de ciclo o circuito
	}
	
        # CABE LA DUDA DE SI LA "$len" DE CICLOS ABIERTOS DEBE SER CONTADA: creo que no, porque no se mide eso
    }
    $exito++ if $successp == 100;

nextgame:
}

say "\n";

say "LA PROBABILIDAD TOTAL DE ÉXITO ES ", $exito / $N;       # SALE REDONDEANDO 0 SI NO SE UTILIZA ESTRATEGIA

say "\nListado de longitudes, ocurrencias y acumulado, tanto por uno:\n";
my $acum = 0;
for my $i (1 .. 99){
    $acum += $histogram[$i];
    say "$i)   ", $histogram[$i], "   ", $acum / $N;             # MÁXIMO en < 40 de circuito, según cáculo previo
}

exit 2;






sub jlm {
    my @deck = @_;
    my @deck2;
    my $n = scalar(@deck);
    while ($n){
	    my $t = int $n*rand; 
	    push @deck2, splice(@deck,$t,1);
	    --$n;
	}
    return @deck2;
}


__END__

La pequeña trampa es que calculo dos cosas a la vez. Perl-golf.
  No hay mayor diferencia.
  
