Labdarúgó-világbajnokság selejtező

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

A feladatban a labdarúgó-világbajnokság európai selejtező mérkőzések (UEFA) eredményeinek feldolgozását segítő függvényeket szeretnénk megvalósítani.

A selejtezőn a csapatokat csoportokba osztják, a csoportokon belül pedig körmérkőzéses rendszerben mérkőznek meg, tehát egy csoporton belül mindenki játszik mindenkivel: egyszer hazai pályán, egyszer pedig idegenben. Feladatunk a csoportelső csapatot kiválasztani.

Egy mérkőzés eredményét egy rendezett párban reprezentáljuk: a pár első eleme a hazai csapat által rúgott gólok száma, a második elem pedig az idegenben játszó csapat által rúgott gólok számát jelenti.

type Match = (Int,Int)

Az eredményeket egy mátrixban tudjuk tárolni: az i. sor j. oszlopában lévő eredmény az i. és j. csapat meccsének eredménye, ahol az i. csapat volt a házigazda.

Ezt a mátrixot most meccsek listájának listájával ábrázoljuk, ahol az i. lista az i. csapat hazai meccseit jelenti. Egy csapat önmagával nem játszik, ezt a mátrixban egy (-1,-1) eredménnyel jelöljük.

type MatchTable = [[Match]]

Példa eredménytáblák (a 2014-es eredmények alapján):

groupATable :: MatchTable
groupATable =
    [[(-1,-1), (2,0)  , (1,2)  , (0,1)  , (1,0)  , (2,0)  ]
    ,[(1,1)  , (-1,-1), (0,3)  , (2,0)  , (5,1)  , (6,1)  ]
    ,[(1,1)  , (2,1)  , (-1,-1), (2,0)  , (1,0)  , (1,1)  ]
    ,[(2,0)  , (0,0)  , (0,2)  , (-1,-1), (1,1)  , (1,2)  ]
    ,[(1,2)  , (1,0)  , (0,2)  , (1,2)  , (-1,-1), (2,1)  ]
    ,[(1,2)  , (0,3)  , (0,2)  , (2,1)  , (1,0)  , (-1,-1)]]
groupGTable :: MatchTable
groupGTable =
    [[(-1,-1), (1,0)  , (0,0)  , (2,0)  , (1,0)  , (2,0)  ]
    ,[(0,1)  , (-1,-1), (1,2)  , (1,1)  , (2,1)  , (2,0)  ]
    ,[(3,1)  , (0,1)  , (-1,-1), (3,0)  , (4,1)  , (4,1)  ]
    ,[(0,1)  , (1,1)  , (0,1)  , (-1,-1), (2,0)  , (2,0)  ]
    ,[(1,2)  , (2,2)  , (0,5)  , (2,1)  , (-1,-1), (2,0)  ]
    ,[(0,1)  , (1,1)  , (1,8)  , (0,2)  , (1,1)  , (-1,-1)]]

A csapatok neveit egy Team listában soroljuk fel, ugyanolyan sorrenben, ahogy a táblázatban is előfordulnak.

type Team = String

Példák:

groupANames :: [Team]
groupANames = ["Croatia", "Serbia", "Belgium", "Scotland", "Macedonia", "Wales"]
groupGNames :: [Team]
groupGNames = ["Greece", "Slovakia", "Bosnia and Hercegovina"
              ,"Lithuania", "Latvia", "Liechtenstein"]

Megjegyzés. A type kulcsszó segítségével a Match típus az (Int, Int) típus, a Team típus pedig a String típus egy másik neve lesz. A MatchTable típus a Match típusból alkotott listák listáját fogja jelenteni, hasonlóan a String és [Char] viszonyához. A programban ezek semmilyen további megszorítást nem jelentenek, csupán a beszédesebb függvénytípusok kialakításában segítenek.

Hazai pályán játszott meccsért járó pontszám (1 pont)

Adjuk meg azt a függvényt, amely a paraméterként megadott meccs eredménye alapján kiszámolja, hogy hány pont jár a hazai csapatnak! Győztes meccsért 3 pont, döntetlenért 1 pont, elveszített meccsért pedig semmi nem jár. Ha paraméterben a (-1,-1) eredményt kapjuk, a 0 értéket adja vissza a függvény!

point :: Match -> Int

Test>
0 :: Int
Test>
3 :: Int
Test>
1 :: Int
Test>
0 :: Int

Hazai pályán játszott meccssorozatért járó összpontszám (1 pont)

Adott egy csapatnak az összes hazai pályán játszott meccs eredménye. Összesítsük, hogy ezen meccsek során mennyi pontot szerzett a csapat!

homePoints :: [Match] -> Int

Test>
9 :: Int
Test>
13 :: Int
Test>
6 :: Int
Test>
2 :: Int

Idegenben játszott meccssorozatért járó összpontszám (1 pont)

Adott egy csapatnak az összes idegenben játszott meccs eredménye. Összesítsük, hogy ezen meccsek során mennyi pontot szerzett a csapat!

awayPoints :: [Match] -> Int

Test>
8 :: Int
Test>
12 :: Int
Test>
4 :: Int
Test>
0 :: Int

Pontok összesítése az eredménytábla alapján (2 pont)

Adjuk meg azt a függvény, amely egy eredménytábla alapján képes összesíteni a csapatok pontszámait! A végeredményként előállított listában az egyes csapatok összpontszáma jelenjen meg egy listában olyan sorrendben, ahogy a táblázatban is szerepelnek. Tehát az eredménylista i. eleme az i. csapat összpontszámát tartalmazza az i. sorban lévő hazai, és az i. oszlopban lévő idegenben játszott meccsek alapján.

Segítség. A Data.List modul transpose függvénye képes egy listák listájaként ábrázolt mátrixot elforgatni, azaz a sorokat és az oszlopokat megcserélni.

totals :: MatchTable -> [Int]

Test>
[17, 14, 26, 11, 7, 10] :: [Int]
Test>
[25, 13, 25, 11, 8, 2] :: [Int]

Legmagasabb pontszám a csoportban (1 pont)

Adjuk meg egy eredménytábla alapján, hogy mennyi az adott csoportban elért legmagasabb pontszám!

highestPoint :: MatchTable -> Int

Test>
26 :: Int
Test>
25 :: Int

A legtöbb pontot gyűjtő csaptok sorszámai (2 pont)

Adjuk meg azt a függvényt, amely egy eredménytábla alapján kiválasztja azokat a csapatokat, amelyek a legmagasabb pontszámot érték el! Az eredménylistában szerepeljen a csapatok sorszáma is! A sorszámokat a 0 értékkel kezdjük, majd pedig egyesével nőnek (1, 2, 3, ).

winners :: MatchTable -> [Int]

Test>
[2] :: [Int]
Test>
[0, 2] :: [Int]

Hazai pályán játszott gólok összegzése (2 pont)

Elképzelhető, hogy több csapat ugyanannyi pontot ér el a csoportban. Ekkor a következő szempont a győztes kiválasztásához gólkülönbségek összevetése, amely az összes mérkőzés során rúgott gólok és az összes mérkőzés során kapott gólok különbségéből adódik.

Ennek kiszámításához először definiáljunk egy segédfüggvényt, amely a hazai pályán játszott meccslista alapján összegzi a hazai pályán rúgott és kapott gólok számát (amelyeket aztán egy rendezett párban ad vissza)!

Megjegyzés: Ne feledjük, hogy a meccslista tartalmazza a csapat ,,saját magával játszott’’ (-1,-1) eredményt is, amit nem kell figyelembe venni az összesítés során!

homeGoals :: [Match] -> (Int,Int)

Test>
(6, 3) :: (Int, Int)
Test>
(6, 0) :: (Int, Int)
Test>
(4, 8) :: (Int, Int)
Test>
(3, 13) :: (Int, Int)

Gólkülönbségek összesítése (2 pont)

Egy eredménytábla alapján számoljuk ki az összes csapatnál a gólkülönbségeket, azaz minden csapat esetén összegezzük a hazai pályán és idegenben rúgott gólokat, és vonjuk ki belőle az összes kapott gólt! Tehát az eredményként kapott lista i. eleme legyen az i. csapat gólkülönbsége az összes meccs alapján!

goalDiffs :: MatchTable -> [Int]

Test>
[3, 7, 14, -4, -9, -11] :: [Int]
Test>
[8, 1, 24, -2, -10, -21] :: [Int]

A győztes csapat sorszáma (4 pont)

Adjuk meg azt a függvény, amely egy erdménytábla alapján ki tudja választani a győztes csapatot! Az a csapat győz, akinek a legtöbb pontja van. Ha több csapat áll a pontok alapján holtversenyben, akkor az győz, akinél a legnagyobb volt a gólkülönbség.

winner :: MatchTable -> Int

Test>
2 :: Int
Test>
2 :: Int

Megjegyzés. Előfordulhat, hogy a gólkülönbség alapján még mindig holtverseny áll fenn, a hivatalos szabályok szerint ekkor még további szempontokat is figyelembe kell venni, de ennél a feladatnál nincs ilyen teszteset. Továbbá feltételezhetjük, hogy a paraméterül kapott táblázatban legalább egy nyertes biztosan van.

A győztes csapat neve (1 pont)

Adott egy eredménytábla és a csapatok neveit az eredménytáblának megfelelő sorrendben tartalmazó lista. Válasszuk ki a győztes csapat nevét az előzőleg leírt szempontok alapján!

winnerName :: [Team] -> MatchTable -> Team

Test>
"Belgium" :: Team
Test>
"Bosnia and Hercegovina" :: Team

Pontozás