#!/usr/bin/perl -w

use PDL;  # http://www.perl.com/CPAN/modules/by-module/PDL

# Tworzymy tablice pieciu macierzy.
@macierze = (pdl ([[1,2],[3,4],[5,6],[7,8],[9,10],[11,12],[13,14]]),
             pdl ([[1,2,3],[4,5,6]]),
             pdl ([[1,2,3],[4,5,6],[7,8,9]]),
             pdl ([[1,2,3,4,5,6],[7,8,9,10,11,12],[13,14,15,16,17,18]]),
             pdl ([[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15],
                  [16,17,18]]));

# Inicjujemy trzy pomocnicze macierze, ktorych uzyjemy do
# przechowywania kosztow (liczby wykonywanych mnozen),
# dotychczasowego ukladu nawiasow, i rozmiarow dotychczasowego 
# iloczynu, gdybysmy go wyliczali.

for ($i = 0; $i < @macierze; $i++) {
    $koszty[$i][$i]  = 0;
    $nawiasy[$i][$i] = '$macierze[' . $i . ']';
    $wymiary[$i][$i]   = [dims $macierze[$i]];
}

# Ustalamy koszty par ($i == 1), potem trojek
# ($i == 2), czworek, i na koncu dla wszystkich 5 macierzy.

for ($i = 1; $i < @macierze; $i++) {

    # Przegladamy wszystkie pozycje na przekatnej.
    #
    for ($j = $i; $j < @macierze; $j++) { # kolumna

        # Ustalamy najlepszy uklad nawiasow dla pozycji
        # w wierszu $j-$i i kolumnie $j.
        #
        for ($k = $j - $i; $k < $j; $k++) {
            ($kol1, $wiersz1) = @{$wymiary[$j-$i][$k]};
            ($kol2, undef) = @{$wymiary[$k+1][$j]};

            # Wyliczamy koszt takiego ukladu nawiasow.
            #
            $proba = $koszty[$j-$i][$k] + $koszty[$k+1][$j] +
                       $wiersz1 * $kol1 * $kol2;

            # To najmniejszy znaleziony koszt (lub pierwszy znaleziony koszt),
            # zapisujemy wiec go wraz z wymiarami i ukladem nawiasow.
            #
            if (!defined $koszty[$j-$i][$j] or $proba < $koszty[$j-$i][$j]) {
                $koszty[$j-$i][$j] = $proba;
                $wymiary[$j-$i][$j] = [$kol2, $wiersz1];
                $nawiasy[$j-$i][$j] = "(" . $nawiasy[$j-$i][$k] . "x" .
                    $nawiasy[$k+1][$j] . ")";
            }
        }
    }
}

# W tym momencie wszystkie informacje musza zostac przeniesione do
# prawego gornego rogu naszej glownej macierzy: zarowno uklad 
# nawiasow, jak i liczba wykonanych operacji mnozenia.

print "Szacowanie:\n", $nawiasy[0][$#matrices], "\n";
print "\tmamy nastepujaca liczbe mnozen: $koszty[0][$#matrices].\n";

# Oceniamy lancuch i na koniec wykonujemy mnozenie!
print eval $nawiasy[0][$#matrices];

__END__
Szacowanie:
($macierze[0]x(($macierze[1]x$macierze[2])x($macierze[3]x$macierze[4])))
        mamy nastepujaca liczbe mnozen: 132.
[
 [ 341010  377460  413910]
 [ 743688  823176  902664]
 [1146366 1268892 1391418]
 [1549044 1714608 1880172]
 [1951722 2160324 2368926]
 [2354400 2606040 2857680]
 [2757078 3051756 3346434]
]

