#!/usr/bin/perl

# prostopadloscian_ograniczajacy_punkty($d, @p)
#   Procedura zwraca prostopadloscian ograniczajacy dla zbioru $d-wymiarowych
#   punktow @p.

sub prostopadloscian_ograniczajacy_punkty {
    my ($d, @punkty) = @_;

    my @bb;

    while (my @p = splice @punkty, 0, $d) {
        @bb = prostopadloscian_ograniczajacy($d, @p, @bb); # Zdefiniowane ponizej.
    }

    return @bb;
}

# prostopadloscian_ograniczajacy($d, @p [,@b])
#   Procedura zwraca prostopadloscian ograniczajacy dla punktow @p w $d wymiarach.
#   @b to opcjonalny, wstepny prostopadloscian ograniczajacy, ktory moze byc uzyty
#   do utworzenia zbiorczego prostopadloscianu ograniczajacego zawierajacego
#   prostopadlosciany odnalezione przez wczesniejsze wywolania tej procedury
#   (ta funkcja jest wykorzystywana przez procedure 
#   prostopadloscian_ograniczajacy_punkty()).
#
#   Prostopadloscian ograniczajacy jest zwracany w postaci listy. Pierwsze
#   $d elementow to minimalne wspolrzedne, a ostatnie $d elementow to wspolrzedne
#   maksymalne.

sub prostopadloscian_ograniczajacy {
    my ( $d, @bb ) = @_; # $d to liczba wymiarow.
    # Usuniecie punktow i pozostawienie prostopadloscianu ograniczajacego.
    my @p = splice( @bb, 0, @bb - 2 * $d );

    @bb = ( @p, @p ) unless @bb;

    # Przeszukanie wszystkich wspolrzednych i zapamietanie ekstremow.
    for ( my $i = 0; $i < $d; $i++ ) {
        for ( my $j = 0; $j < @p; $j += $d ) {
            my $ij = $i + $j;
            # Minima.
            $bb[ $i      ] = $p[ $ij ] if $p[ $ij ] < $bb[ $i      ];
            # Maksima.
            $bb[ $i + $d ] = $p[ $ij ] if $p[ $ij ] > $bb[ $i + $d ];
        }
    }

    return @bb;
}

# prostopadloscian_ograniczajacy_przeciecie($d, @a, @b)
#   Procedura zwraca prawde, jesli podane prostopadlosciany @a i @b przecinaja
#   sie w $d wymiarach. Podprocedura wykorzystana przez funkcje 
#   przeciecie_prostych().

sub prostopadloscian_ograniczajacy_przeciecie {
    my ( $d, @bb ) = @_; # Liczba wymiarow i wspolrzedne prostopadloscianow.
    my @aa = splice( @bb, 0, 2 * $d ); # Pierwszy prostopadloscian.
    # (@bb to drugi prostopadloscian.)

    # Prostopadlosciany musza przecinac sie we wszystkich wymiarach.
    for ( my $i_min = 0; $i_min < $d; $i_min++ ) {
        my $i_max = $i_min + $d; # Indeks dla maksimum.
        return 0 if ( $aa[ $i_max ] + epsilon ) < $bb[ $i_min ];
        return 0 if ( $bb[ $i_max ] + epsilon ) < $aa[ $i_min ];
    }

    return 1;
}

@bb = prostopadloscian_ograniczajacy_punkty(2,
                                1, 2,  5, 4,  3, 5,  2, 3,  1, 7,
                                2, 5,  5, 7,  7, 4,  5, 5,  6, 1), "\n";
print "@bb\n";
