#!/usr/bin/perl

use 5.040.3;
# use utf8;

my $DEBUG = 0;

my $version = 0.02;

if ( @ARGV < 3 || $ARGV[0] =~ /h/i) {
    say "Usage: $0 <numT> <numM> <opt>";
    say "";
    say "The algo search for numTotal - numMayor = numMinor\n";
    say "all the possible natural numbers additions that reach";
    say "numMinor with the <opt> options needed to simplify";
    say "<[repe|norepe|stairs|num]> without Mays, meaning";
    say "repetitions \/ not repetitions \/ a stair level of numbers";    
    say "default is stairs, not elevator \:\-\)\n";
    say "If opt is numeric n, then it uses it to show only combinations";
    say "of n (a round number) factors to add up to numMinor";
    say "What to do with the rests, is a matter of discussion, but";
    say "this is version 0.02 at most";
    exit -1;
}

say 1 if $DEBUG;

die "Error: not numeric" if (0+$ARGV[0] ne $ARGV[0]);
die "Not a round number" unless (int($ARGV[0]) == $ARGV[0]);
die "Error: not numeric" if (0+$ARGV[1] ne $ARGV[1]);
die "Not a round number" unless (int($ARGV[1]) == $ARGV[1]);

say 2 if $DEBUG;

my $opt;
unless ($ARGV[2] =~ /^repe/ ||
    $ARGV[2] =~ /no/ ||
    $ARGV[2] =~ /stair/ ||
    $ARGV[2] =~ /\d+/ ) {
	
	say "Something wrong about $ARGV[2]";
	say "Info: check options <[repe|norepe|stairs|num]>";
	exit -3;
	
	if ($ARGV[2] =~ /(\d+)/){
	    $opt = $1;
	    if (defined $opt){
		say "$opt seems not numeric", exit -4 if ($opt =~ /\D/);  
		say "$opt seems not to be a round number", exit -5 if (int($opt) != $opt);
		say "$opt less or equal than 1", exit -6 if ($opt < 2);
	    }
	}
    }


say 3 if $DEBUG;

my $numT = $ARGV[0];
my $numM = $ARGV[1];
($numT, $numM) = ($numM, $numT) if ($numT < $numM);
die "Error: a zero or negative number used" if $numM <= 0;
$opt //= $ARGV[2];

die "Error: options not defined" unless (defined $opt);

my $numprob = $numT - $numM;

my ($new, $rest, $i, $j);

say 4 if $DEBUG;

### lun 09 feb 2026 00:25:43 CET

say "Empezó" if $DEBUG;

if ($opt =~ /repe/ && index($opt, "no") < 0 ){            # debería ser la opción más generosa en posibilidades
    
    $new = 0;
    say "Entró" if $DEBUG;
    
    while ($new < $numprob ){
	
	$new++;

	print "Option: repetitions; For $new disadder: ";
	print "$numT - $numM = $numprob = ";
	$rest = $numprob;

        while ($rest > 0){
	    if ($rest > $new){
		$rest -= $new;
		print "\+$new ";
	    }else{
		while ($rest > 0){ 
		    $j=1;                                # se opta por lo largo
		    $rest -= $j;
		    print "\+$j " if $rest >= 0;
		    last if $rest == 0;
		}
	    }
	}
	print "\n";
	
    }
    
}elsif (index ($opt, "no") >= 0 ){
    
    say "no" if $DEBUG;

    $j = 0;
    my $iant = 0;
    while ( $iant < $numprob ){

	$i = $iant + 1;
	$iant = $i;
	print "Option: no repetitions; For $i disadder: ";
	print "$numT - $numM = $numprob = ";
	$rest = $numprob;
	
        while ($iant <= $numprob) {
	    if ($rest >= $i){
		$rest -= $i;
		print "\+$i ";
		$i += 2; # No repeticiones pero no escalera
		last if ($rest == 0);
		$j = $i -3;         # se opta por ir acortando decrecientemente
	    }else{
		while ($rest > 0){ 
		    $rest -= $j;
		    if ($rest >= 0){
			print "\+$j ";
			$j -= 2;
		    }else{
			$rest += $j;              # deshacer
			$j--;
		    }
		    goto norepe if $rest == 0;
		}
	    }
	}
norepe:
        say "";
      
    }    
        
}elsif ($opt =~ /stair/) {        # default, in steps

    say "nop" if $DEBUG;
    
    $i = 1;
    print "Option: stairs (one possibility); For $i disadder: ";
    print "$numT - $numM = $numprob = ";
    $rest = $numprob;
    my $jant = 0;
	
    while ($rest > 0){                                       # escalera de subida
	if ($rest >= $i){
	    $rest -= $i;
	    print "\+$i ";
	    $i++;             # No repeticiones pero no escalera
	}else{
	    $jant = $rest;  # por si fuese resto de bajada
	    $j = 1;                                      # de subida, el resto	    
	    while ($rest > 0){ 
		$rest -= $j;
		if ($rest >= 0){
		    print "\+$j ";
		}else{
		    $rest += $j;        # deshacer
		}
		$j++;
		last if $rest == 0;
	    }
	}
    }
    say "";

    
}else{                       # $opt == number of partitions
    
    say "nope" if $DEBUG;

    for my $ii ($opt .. $numprob){
	
	$i = int($numprob/$ii);
	print "Option: parts = $opt; For $i disadder: ";
	print "$numT - $numM = $numprob = ";
	$rest = $numprob;
	   
	# partes principales
	if ($rest >= 0){
	    $rest -= $i * $ii;
	    print ("\+$i " x $ii);
	}
	if ($rest > 0){
	    $j = int($rest/$ii);                           # partes secundarias, el resto
	    $rest -= $j * $ii;
	    print ("\+$j " x $ii) if $j > 0;
	       
	    if ($rest > 0){
		$j = int($rest/$ii);
		if ($rest > 0){
		    $rest -= $j * $ii;
		    print ("\+$j " x $ii) if ($j > 0);
		}
		goto end if ($rest == 0);
		if ($rest > 0){                     # esto debe sobrar
		    $j = $rest;
		    print "\+$j ";
		}
	    }
	}
end:    
	  say "";
    }
    
	   
# }else{
    
#    die "Error in $opt";
    
}
    
exit 3;

__END__
  
Como primera versión as of lun 09 feb 2026 22:18:47 CET
  no todas las combinaciones se muestran. Sólo se intenta
  ayudar a problemas de reparto.
  Otros trabajo tengo publicado sobre el problema de las
  particiones de elementos + - indivisibles.
Básicamente se tienen w[1]..w[20] pesos o valores y hay que
  repartirlos en 3 partes que «pesen» lo mismo. Se puede
  hacer shuffle e ir probando. Ya digo, está arriba.


