Legnagyobb szorzat egy mátrixban

Használható segédanyagok: Haskell könyvtárainak dokumentációja, (lokális!) Hoogle, a tárgy honlapja és a BE-AD rendszerbe feltöltött beadandók. Ha bármilyen kérdés, észrevétel felmerül, azt a felügyelőknek kell jelezni, nem a diáktársaknak!

A feladatok egymásra épülnek ezért érdemes ezeket a megadásuk sorrendjében megoldani, de legalább megérteni az aktuális feladatot megelőző feladatokat! A függvények definíciójában lehet, sőt javasolt is alkalmazni a korábban definiált függvényeket (függetlenül attól, hogy sikerült-e azokat megadni).

Tekintve, hogy a tesztesetek, bár odafigyelés mellett íródnak, nem fedik le minden esetben a függvény teljes működését, határozottan javasolt még külön próbálgatni a megoldásokat beadás előtt, vagy megkérdezni a felügyelőket!

Részpontszámokat csak az elégséges szint elérése után lehet kapni!

A feladat összefoglaló leírása

Ebben a feladatban egy számokból álló mátrixszal fogunk dolgozni. A feladat megoldása során a mátrix különböző irányaiban vett n elemből álló szorzatokat fogunk előállítani és ezek maximumát keressük.

A mátrixok sor reprezentációval adottak, amelyek elemei egész számok lesznek.

A mátrixokat itt most a következő típussal fogjuk ábrázolni:

type Matrix = [[Int]]

valamint a továbbiakban az alábbi, ilyen típusú konstansokat fogjuk alkalmazni a tesztek során:

matrix1 :: Matrix
matrix1 = [[1,2,3]
          ,[4,5,6]
          ,[7,8,9]
          ]
matrix2 :: Matrix
matrix2 = [[ 1, 2, 3, 4]
          ,[ 5, 6, 7, 8]
          ,[ 9,10,11,12]
          ,[13,14,15,16]]
matrix3 :: Matrix
matrix3 = [[ 1, 2, 3, 4, 5]
          ,[ 6, 7, 8, 9,10]
          ,[11,12,13,14,15]
          ,[16,17,18,19,20]
          ,[21,22,23,24,25]]

Mátrix sorának n hosszúságú részlistái (2 pont)

Adjuk meg azt a függvényt, amely egy adott listának előállítja az összes n hosszúságú részlistáját!

sublists :: Int -> [a] -> [[a]]

Test>
[[1, 2, 3], [2, 3, 4]] :: [[Int]]
Test>
[[1, 2, 3, 4, 5, 6, 7, 8], [2, 3, 4, 5, 6, 7, 8, 9], [3, 4, 5, 6, 7, 8, 9, 10]] :: [[Integer]]

Mátrix sorainak és oszlopainak n hosszúságú részlistái (2 pont)

Az előbb definiált sublists függvény felhasználásával adjuk meg azt a függvényt, amely egy adott mátrix összes sorának és oszlopának előállítja n hosszúságú részlistáit!

sublistsOfRowCol :: Int -> Matrix -> [[Int]]

Test>
[] :: [[Int]]
Test>
[[1, 2, 3], [2, 3, 4], [5, 6, 7], [6, 7, 8], [9, 10, 11], [10, 11, 12], [13, 14, 15], [14, 15, 16], [1, 5, 9], [5, 9, 13], [2, 6, 10], [6, 10, 14], [3, 7, 11], [7, 11, 15], [4, 8, 12], [8, 12, 16]] :: [[Int]]

Megjegyzés. A megoldásban szükség lehet a Data.List modul transpose függvényére.

A mátrixból szükségünk lesz az összes átlóra, ezért megadjuk azokat a függvényeket, amelyek segítségével meg tudjuk határozni ezeket.

A mátrix pozícióit (sor, oszlop) rendezett párként adjuk meg, amelyre bevezetjük a következő szinonimát:

type Position = (Int, Int)

Mátrix főátlójának pozíciói (1 pont)

Adjuk meg azt a függvényt, amely egy négyzetes n x n-es mátrix főátlójának pozícióit adja meg. A pozíciókat a bal felső saroktól a jobb alsó sarok felé növekvő sorrendben kell megadni egy listában.

Megjegyzés. A sorokat és az oszlopokat 0-tól n-1-ig indexeljük, ahol az n a mátrix sorainak/oszlopainak a száma.

mainDiagonalPositions :: Matrix -> [Position]

Test>
[(0, 0), (1, 1), (2, 2)] :: [Position]
Test>
[(0, 0), (1, 1), (2, 2), (3, 3)] :: [Position]
Test>
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)] :: [Position]

Mátrix mellékátlójának pozíciói (1 pont)

Adjuk meg azt a függvényt, amely egy négyzetes n x n-es mátrix mellékátlójának pozícióit adja meg. A pozíciókat a bal alsó saroktól a jobb felső sarok felé növekvő sorrendben kell megadni egy listában.

antiDiagonalPositions :: Matrix -> [Position]

Test>
[(2, 0), (1, 1), (0, 2)] :: [Position]
Test>
[(3, 0), (2, 1), (1, 2), (0, 3)] :: [Position]
Test>
[(4, 0), (3, 1), (2, 2), (1, 3), (0, 4)] :: [Position]

Kezdőszeletek transzformálása (2 pont)

Adjuk meg azt a magasabbrendű függvényt, amely egy lista minden elemére újra és újra elvégez egy műveletet az alábbiak szerint:

A függvény eredménye tartalmaz minden, a számítási folyamat során előállt részeredményt.

Egy példán keresztül szemléltetve:

iterateUntilNotNull (+1) [1..4] == [[1+1, 2+1, 3+1], [(1+1)+1, (2+1)+1], [((1+1)+1)+1]]

iterateUntilNotNull :: (a -> a) -> [a] {-nem üres-} -> [[a]]

Test>
[[2, 3, 4], [3, 4], [4]] :: [[Integer]]
Test>
[[(1, 0), (2, 1)], [(2, 0)]] :: [[(Int, Int)]]
Test>
[[(0, 1), (1, 2), (2, 3)], [(0, 2), (1, 3)], [(0, 3)]] :: [[(Int, Int)]]

Minden diagonális megadása (3 pont)

Az előző feladatban megadott iterateUntilNotNull függvény segítségével könnyedén meg tudjuk adni a főátlóval és a mellékátlóval párhuzamosan futó többi átlót.

A főátlóból az alábbi hozzárendelési szabály segítségével állíthatóak elő a vele párhuzamosan futó átlók:

A mellékátlóból az alábbi módon állíthatóak elő a vele párhuzamosan futó átlók:

A következő mátrixra

GridProductac3a375e82ab26856918bd204de011bb.png

a függvény az alábbi eredményt adná:

[[(2,0)], [(1,0),(2,1)], [(0,0),(1,1),(2,2)], [(0,1),(1,2)], [(0,2)]]

++

[[(2,2)], [(2,1),(1,2)], [(2,0),(1,1),(0,2)], [(1,0),(0,1)], [(0,0)]]

A megadási sorrend: főátló szerinti átlók bal alsó saroktól haladva a jobb felső sarokig, majd a jobb alsó sarokból indulva a bal felső sarokig a mellékátló szerint.

diagonalPositions :: Matrix -> [[Position]]

Test>
[[(2, 0)], [(1, 0), (2, 1)], [(0, 0), (1, 1), (2, 2)], [(0, 1), (1, 2)], [(0, 2)], [(2, 2)], [(2, 1), (1, 2)], [(2, 0), (1, 1), (0, 2)], [(1, 0), (0, 1)], [(0, 0)]] :: [[Position]]
Test>
[[(3, 0)], [(2, 0), (3, 1)], [(1, 0), (2, 1), (3, 2)], [(0, 0), (1, 1), (2, 2), (3, 3)], [(0, 1), (1, 2), (2, 3)], [(0, 2), (1, 3)], [(0, 3)], [(3, 3)], [(3, 2), (2, 3)], [(3, 1), (2, 2), (1, 3)], [(3, 0), (2, 1), (1, 2), (0, 3)], [(2, 0), (1, 1), (0, 2)], [(1, 0), (0, 1)], [(0, 0)]] :: [[Position]]

Mátrix összes átlójának elme (2 pont)

Adjuk meg azt a függvényt, amely az adott mátrix összes átlóját megadja! Minden egyes átlót egy-egy listában adunk meg.

diagonals :: Matrix -> [[Int]]

Test>
[[7], [4, 8], [1, 5, 9], [2, 6], [3], [9], [8, 6], [7, 5, 3], [4, 2], [1]] :: [[Int]]
Test>
[[13], [9, 14], [5, 10, 15], [1, 6, 11, 16], [2, 7, 12], [3, 8], [4], [16], [15, 12], [14, 11, 8], [13, 10, 7, 4], [9, 6, 3], [5, 2], [1]] :: [[Int]]
Test>
[[21], [16, 22], [11, 17, 23], [6, 12, 18, 24], [1, 7, 13, 19, 25], [2, 8, 14, 20], [3, 9, 15], [4, 10], [5], [25], [24, 20], [23, 19, 15], [22, 18, 14, 10], [21, 17, 13, 9, 5], [16, 12, 8, 4], [11, 7, 3], [6, 2], [1]] :: [[Int]]

Mátrix diagonálisainak n hosszúságú részlistái (2 pont)

Definiáljuk azt a függvényt, amely a mátrix összes átlójának megadja n hosszúságú részlistáit!

Megjegyzés. A megoldásban használjuk a korábban megadott sublists függvényt.

sublistsOfDiags :: Int -> Matrix -> [[Int]]

Test>
[[5, 10, 15], [1, 6, 11], [6, 11, 16], [2, 7, 12], [14, 11, 8], [13, 10, 7], [10, 7, 4], [9, 6, 3]] :: [[Int]]
Test>
[[6, 12, 18, 24], [1, 7, 13, 19], [7, 13, 19, 25], [2, 8, 14, 20], [22, 18, 14, 10], [21, 17, 13, 9], [17, 13, 9, 5], [16, 12, 8, 4]] :: [[Int]]

A további teszteléshez bevezetünk egy konstanst egy 20x20-as méretű mátrixot:

matrix4 :: Matrix
matrix4 =
 [[08,02,22,97,38,15,00,40,00,75,04,05,07,78,52,12,50,77,91,08]
 ,[49,49,99,40,17,81,18,57,60,87,17,40,98,43,69,48,04,56,62,00]
 ,[81,49,31,73,55,79,14,29,93,71,40,67,53,88,30,03,49,13,36,65]
 ,[52,70,95,23,04,60,11,42,69,24,68,56,01,32,56,71,37,02,36,91]
 ,[22,31,16,71,51,67,63,89,41,92,36,54,22,40,40,28,66,33,13,80]
 ,[24,47,32,60,99,03,45,02,44,75,33,53,78,36,84,20,35,17,12,50]
 ,[32,98,81,28,64,23,67,10,26,38,40,67,59,54,70,66,18,38,64,70]
 ,[67,26,20,68,02,62,12,20,95,63,94,39,63,08,40,91,66,49,94,21]
 ,[24,55,58,05,66,73,99,26,97,17,78,78,96,83,14,88,34,89,63,72]
 ,[21,36,23,09,75,00,76,44,20,45,35,14,00,61,33,97,34,31,33,95]
 ,[78,17,53,28,22,75,31,67,15,94,03,80,04,62,16,14,09,53,56,92]
 ,[16,39,05,42,96,35,31,47,55,58,88,24,00,17,54,24,36,29,85,57]
 ,[86,56,00,48,35,71,89,07,05,44,44,37,44,60,21,58,51,54,17,58]
 ,[19,80,81,68,05,94,47,69,28,73,92,13,86,52,17,77,04,89,55,40]
 ,[04,52,08,83,97,35,99,16,07,97,57,32,16,26,26,79,33,27,98,66]
 ,[88,36,68,87,57,62,20,72,03,46,33,67,46,55,12,32,63,93,53,69]
 ,[04,42,16,73,38,25,39,11,24,94,72,18,08,46,29,32,40,62,76,36]
 ,[20,69,36,41,72,30,23,88,34,62,99,69,82,67,59,85,74,04,36,16]
 ,[20,73,35,29,78,31,90,01,74,31,49,71,48,86,81,16,23,57,05,54]
 ,[01,70,54,71,83,51,54,69,16,92,33,48,61,43,52,01,89,19,67,48]]

Mátrix n szomszédos eleme, amely a maximális értéket adja (3 pont)

Definiáljuk azt a függvényt, amely egy mátrixból megadja azt az n darab szomszédos elemet, amelynek szorzata maximális a mátrixot tekintve. A maximum meghatározásánál a korábban definiált sorok, oszlopok és az átlók szerint definiált szomszédságot vegyük figyelembe!

maximumProductNeighbours :: Int -> Matrix -> [Int]

Test>
[15, 16] :: [Int]
Test>
[23, 24, 25] :: [Int]
Test>
[87, 97, 94, 89] :: [Int]

Pontozás (elmélet + gyakorlat)