#!/usr/bin/perl -w

use 5.034;   ### Note: I dont like pseudocode! 
              ### Sorry, Signed: Jesús Lozano Mosterín, Spain, 2020.
              ### v.0                  lun 09 mar 2020 05:42:25 CET


# I use the 5.032 version because utf8 is not utile

# no strict "subs";

# no bigint;

# use bignum;

# no bignum;

my $version = "0.026";  
# v.0.001      lun 09 mar 2020 05:55:01 CET
# v.0.002      lun 09 mar 2020 06:34:22 CET
# v.0.003      mar 10 mar 2020 07:24:38 CET
# v.0.004      dom 15 mar 2020 17:08:44 CET
# v.0.005      first working draft!   lun 16 mar 2020 00:18:47 CET
# v.0.006      let's complicate with + and - rand()
# v.0.007      measure execution time 
# v.0.008      gothic decoration
# v.0.009      WHEN THERE ARE EXPONENTS, TAKE THE LIMIT THERE, AND NOT THE DIGITS
# v.0.010      ubuntu 20.04
# v.0.011      Esta es una versión NULA: es solo un comentario. Se puede dar el caso, por ejemplo
#              para calcular un interés con absurda excesiva precisión pero sin exponente en que
#              alcances una y otra vez la igualdad del número "impreso en pantalla" pero las 
#              iteraciones no paren. Eso hay que tratarlo aparte, porque aquí ya se contabilizan 
#              el número de hits y porque incluir ese caso ralentizaría un montón todo el script
#              que solo regula el criterio de detención. Quizá para más adelante pero no.
# v.0.012      Breve anotación después de __END__ acerca de los límites de magnitudes físicas conocidas ahora
# v.0.014      *Creo* que la correcta y segura conversión de número a string debe ser con sprintf, no vale "$num"
# v.0.015      perlcritic dice que abuso del eval
# v.0.016      poner interrogaciones en el regex porque puede que busque un entero
# v.0.017      buscar minimizar en positivos y negativos
# v.0.018      cleaning up things
# v.0.019      maintainig
# v.0.020      combinig hits and digits w/ (hits * digits) ---> DEAD WAY
# v.0.021      using different precisions & study to truncate the numbers having $hits + $LAST as reference
# v.0.022      bug hunting
# v.0.023      bug hunting + an idea /* treating decimals like integers */
# v.0.024      refining...
# v.0.025      universe 25 - whatif historic histogram
# v.0.026      sin utilizar iteraciones, utilizar los hits para elegir el más máximo o mínimo


my $time0 = time;
my $DEBUG = 0;

my $OSNAME //= "linux ubuntu LTS number 22.04";
my $location = "ULTRA";
my $condition = "-";
$OSNAME .= " ".$location . " ".$condition. " ". $^O;
say "$OSNAME";

my @filent;
$filent[1] = "$0 \n";
# print $filent[1];

print "My Perl version is $] \n";

$filent[2] = "TURING-HALTING-PROBLEM: A HEURISTIC";
$filent[3] = $ARGV[0];
print "JOB NUMBER 2 = RUNNING EXEC FILE -> " . $ARGV[0] . "\n" if defined $filent[3];

say "RUNNING $filent[1] ...";
say "VERSION = v. $version :\n";

say "COMMENT 1 = $filent[1]";
say "COMMENT 2 = $filent[2]";
say "COMMENT 3 = $filent[3]" if defined $filent[3];

my $LAW = "COMMENT 2 = BASIC NOTE INFORMATION -> CONSTITUTION -> LAW PROTECTING BASIC SCIENTIFIC INVESTIGATION";
say "LEY = $LAW";
my $date = scalar localtime();
my $LAW_MAYBE = "SEARCH CSIC acronym entity in http://BOE.es date $date";
say "LEY ~ $LAW_MAYBE"; 

### PISTA: LA HEURISTICA PARA PARAR (STOP RULE = T-H-P HEURISTIC)
##  ES SIMPLEMENTE TRATAR
### NUMERO DECIMAL O NO COMO SI FUESEN CADENA DE CHARS
### ( STRING )
### if (lenght($STRING) = $arbitrary_precision) {
###    say "result = $STRING"; exit 0; 
### }

### wiki: TURING HALTING PROBLEM <----

### KEYWORD: HEURISTICS

my $MIN = 9e99;
my $MAX = -9e99;

my $seed = srand();
say "\nEXAMPLE SEED = $seed";

my $iter = 0;
my $ticks = 0;

my $result_candidate = 0;

my $LAST = 8;                  # this number is the final test to stop and exit the experimental program
# my $number_hits_digits = $LAST;  # number of digits i.e. decimals + 2 ("0. + etc ) you want as 
                             # a CRITERIA TO HALT
                             # and SOLVE THE (abstract, generic) problem 

say "IMPORTANT: The original criteria to stop now is $LAST"; 

# use bignum ("p" , $LAST);

my $hits = 1_000; # EXAMPLE BUT IMPORTANT = NUMBER OF MINIMUM HITS PER DIGIT IN THE MIN_FIT_OBJETIVE SUBROURITE
                                 # actually called algorithm_heuristic()

say "and the number to make the critical decision is $hits"; 
say "";

my $d = 0;  # los inmutables, estas son la variables criticables
my $dcount=1;
my (%hash, @h, $kant);
my ($min, $max) = (9e99, -9e99);
my %maxormin;

# my $hits_limit = $number_hits_digits * $hits;
# say "Hits limit = $hits_limit";

# $result_candidate =         # whatever, one per iteration
# see subroutine called ... search_SDR_example()
# could be a function, could be a external program, 
# a batch program, a simulation, et cetera. 

# my $printer;

while (1) {
    $iter++;
#    $printer = 0;
#    $printer = 1 if ($iter % 1000 == 0);
    print "\r$iter";   #  if $printer;  maybe not a fail but not pretty
    
    
#    $result_candidate = search_SDR_example();  # seen i.e. BUFFA et alii. as an example!!!

    $result_candidate = search_SDR_example();  # seen i.e. BUFFA, E.S. & TAUBERT, W.H. et alii.
                                                   # ancient book with source code called SDR in 
                                                   # FORTRAN language. It could be an exercise for
                                                   # PhD posgraduate student of Computer Science.
                                                   # /* for example AI origin is around 1960 decade */
                                                   # I bought this book from Amazon from University of 
                                                   # Edinburgh Library... time ago.
    
    if ($result_candidate <= $MIN) {

	$ticks++;
	
	$MIN = $result_candidate;
	
	print "\r$iter", " " x 10, "$MIN";
	
	$result_candidate = sprintf("%s", $result_candidate);
	
	my ( $pint, $ent, $pdec, $dec, $pexp, $exp ) = algorithm_heuristic($result_candidate);
        
	$exp //= "e0";
	
	print " " x 10, "$ent.$dec$exp", " " x 10;
    
#	$exp =~ s/e-?//;
	last if ($pexp >= $LAST);
	last if ($pdec >= $LAST);
	last if ($pint >= $LAST);

    }   # end of $MIN reached
}

# I think gothic decoration is important to theory
say "\n";
say "Verified!";
say "";
say "----------------------------";
say "OBJECTIVE MINIMUM REACHED AT $MIN";
say "----------------------------";
say "in iteration number $iter";
printf "Elapsed Time is %.03f minutes\n", (time - $time0)/60;
say "Iterations within selection is $ticks of $iter";
exit 2;


sub search_SDR_example {
    my $proposed;
    if (defined $filent[3]){
	if (-e $filent[3]){
	    $proposed = `$filent[3]`;       # a program
	    $proposed //= do "$filent[3]" unless ($!);      # a perl script
	}
	if (length $filent[3]){
	    $proposed = eval { $filent[3] };  # a simple perl expression
	}
    }
    my $r = $proposed // -10000*(rand()-0.5);   # -1;    # v.0.018 to begin complications...
    return $r;
}









sub algorithm_heuristic {
    my ( $string ) = $_[0];
    my ( $entero, $decimal, $exponente );

    if ( $string =~ /^ ( -? \d+ ) \.? (\d+)? ( [e|E]? -? \d+ )? $ /x ){    
	  $entero = $1 // "0";               # exponentes "e" potencias de 10, que 
	  $decimal = $2 // "0";              # esto no es HiperCalc app, coño!
	  $exponente = $3; # // "e0";
          unless (defined $1 || defined $2 || defined $3){
	      die "REGEX warning";
	  }
    }else {
	die "DEBUG: posible error en script";
    }
    
# si $maxormin{ } =   # pensar truco
    if ($string <= $min){
	$min = $string;
	$maxormin{ $string }++;  # ¿?    +$hits y -$hits en máximo y mínimo debería ser. Economode.
salida:	
	if ($maxormin{ $string } > $hits){
	    return ($maxormin{$string}, $entero, $maxormin{$string}, $decimal, $maxormin{$string}, $exponente);
	}
    }elsif ($string >= $max){
	$max = $string;
	$maxormin{ $string }++;  # ¿?    +$hits y -$hits en máximo y mínimo debería ser. Economode.
	goto salida;
    }
    
    if (++$hash{ $entero } < $hits) {
	
	return ($hash{$entero}, $entero, 0, $decimal, 0, $exponente);
	
    }else{
	
	$dcount = length(abs($entero));   # superar el punto y nada más ya que substr empieza en 0
	$d = $dcount;
    }
    
    if ($d) { 

	# decimal part, we inspect digits one by one
		
#	$string =~ /\.(\d+)e?/;	    
#	my $s = $1;
	    
	if ($decimal){
	    
	    my $k = substr ($decimal, $dcount-$d, 1) ;      # decimal, first in left part 
	    
#	    if ($k != $kant){		
#		$h[$dcount][$kant]=0;
#	    }
	    
	    $h[$dcount][$k]++;
	    
	    $h[$dcount][$k] -= history($k);
	    
	    if ($h[$dcount][$k] >= $hits) {
	    
		$dcount++;                          # now $dcount == one more digit, etc...
		
		$kant = $k;    # cont'd

		if (0){ 
#		    Es dudoso que todos los números sean igual de probables. (Benford)
#		      Si estamos en un escenario típico de maximización o minimización,
#		      se me ocurre que 0,1,5,9 son más probables que 3,6 y a su vez más 
#		      probables que los patosos 2,4,8. ;-]
#		      En la v.0.025 se añade $h[$dcount][$k] -= history($k);
		} 
		
		return ($d, $entero, $dcount, $decimal, 0, $exponente);    #  *** POSIBLE ERROR ***        	
		
	    }
	    
	}else{
		
	    warn "No decimals!";
	    
	}
    }

    
    if ($exponente =~ /e/){
	# con bigfloat esto sería lo más importante 
    
#	warn "unexpected branch! Exponents are relevant and not precision...";    
	
	$exponente =~ /e-?(\d+)/;
	
	return ( $d, $entero, $dcount, $decimal, $1, $exponente) ; 

    }else{

	warn "Error de script";
	
	return ($d, $entero, $dcount, $decimal, $1, $exponente);    #  *** POSIBLE ERROR ***        	

    }
    warn "Error en la salida";
}


sub history {
    my $kk = shift;
    for ($kk){
	if (/ [0|1|5|9] /) {
	    return 0;
	}
	if ( /[3|6]/ ) {
	    return 0.1;
	}
	if ( /[2|4|7|8]/ ){
	    return 0.2;
	}else{
	    die "Bad robot!";
	}
    }
}


__END__

Nota 0: Hoy día es perfectamente normal un artículo académico internacional
  aceptado por varios revisores, que solo presente un modelo matemático, haga
  una simulación, presente una o varias tablas 2D, mejor con gráficos y ya 
  está.
  
Pero, matemáticamente en sentido estricto de esa ciencia 'pura' una demostración 
  solo es válida si es simbólica, lógica, etc. Por ejemplo, la prueba de un 
  teorema. Quizá esto ya haya cambiado en alguna revista.

Esto lo digo porque si se coge la teoría de las convergencias y esto, juntos 
  prueban que el halting problem puede dejar de ser un problema general.
  Como no lo es calcular la raiz cuadrada de 2.

Pero lo sorprendente de los criterios de convergencia, que hay varios, es que 
  rand(), aunque no tenga nivel RNG y sea solo PRNG, no debería cumplirla de
  ningún modo, y sin embargo el sistema funciona o sea que igual no es tan malo,
  si no es lentísimo, que parece que no.
  
Una breve investigación de los límites de las magnitudes físicas, por arriba sobre
  el número de quarks en el universo conocido o por abajo en el intervalo de tiempo
  más pequeño posible sin entrar en indeterminación cuántica nos dice que no tiene 
  sentido un campo de búsqueda por encima de 10^100 y por debajo de 10^-50 aprox.
  Esto tiene consecuencias de todo tipo, como que una demostración meramente 
  computacional 'puede' ser posible o que una búsqueda aleatoria o lo que sea puede
  ser detenida con una precisión arbitraria en un contexto realista, con soporte 
  físico. Pero no puedo evitar meter el chiste fácil de que podemos crear números
  absurdamente grandes o tener problemas combinatorios absurdamente grandes que 
  sí que excedan lo que puede ser computable, y además de manera facilona. Y lo que 
  es hacer chiste sobre chiste es que además puede ser útil para cosas prácticas,
  como ganar dinerito. Y aquí hay que volver a ponerse serio, porque crear una 
  eco-coin sobre un índice ecológico medible físicamente, puede ser utilísimo si se
  hace con reconocimiento mundial. Esto es una cosa que tendría fuerte oposición
  por la sencilla razón de que si se 'paga' por no polucionar funciona como una 
  moneda inversa que paga o a los muy listos o a los muy pobres.
  
  
  
  
  
  

