#!/usr/bin/perl

use 5.040.3;
# use utf8;

my $DEBUG = 0;

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";
    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;
		    $rest -= $j;
		    print "\+$j " if $rest >= 0;
		    last if $rest == 0;
		}
	    }
	}
	print "\n";
	
    }
    
}elsif (index ($opt, "no") >= 0 ){
    
    say "no" if $DEBUG;

#    my %h;
    
    $i = 0;
    
    while ($i < $numprob ){

	$i++;
	print "Option: no repetitions; For $i disadder: ";
	print "$numT - $numM = $numprob = ";
	$rest = $numprob;
	
        while ($rest > 0){
	    if ($rest > $i){
		$rest -= $i;
		print "\+$i ";
		$i += 2; # No repeticiones pero no escalera
	    }else{
		$j = $i -1;
		while ($rest > 0){ 
		    $rest -= $j;
		    if ($rest >= 0){
			print "\+$j ";
		    }else{
			$rest += $j;
		    }
		    $j--;
		    last if $rest == 0;
		}
	    }
	}
        say "";
	
    }    
    
    
}elsif ($opt =~ /stair/) {        # default, in steps

    say "nop" if $DEBUG;

    $i = 0;
    print "Option: stairs; For $i disadder: ";
    print "$numT - $numM = $numprob = ";
    $rest = $numprob;
	
    while ($rest > 0){                                       # escalera de subida
	if ($rest >= $i){
	    $rest -= $i;
	    print "\+$i ";
	    $i++;             # No repeticiones pero no escalera
	}else{
	    $j = $i -1;                                      # de bajada, 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;

    $i = int($numprob/$opt);
    print "Option: parts = $opt; For $i disadder: ";
    print "$numT - $numM = $numprob = ";
    $rest = $numprob;

    # partes principales
    if ($rest >= 0){
	$rest -= $i * $opt;
	print ("\+$i " x $opt);
    }
    
    if ($rest > 0){
	$j = int($rest/$opt);                           # partes secundarias, el resto
	$rest -= $j * $opt;
	print ("\+$j " x $opt);
	
	if ($rest > 0){
	    if ($rest <= $j){
		$j = $rest;
		print "\+$j ";
	    }
	    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.


