Biatlon verseny csapateredmények összesítése

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 biatlon versenyek eredményeinek feldolgozását segítő függvényeket szeretnénk megvalósítani. A biatlon vagy sílövészet összetett téli sport, amely sífutásból és lövészetből áll. A hosszabb távú versenyek esetén négy lövészet van, a lövéshibák egy–egy perc időbüntetéssel járnak.

Megjegyzés. A feladatban szereplő számítási módok nem egyeznek meg a hivatalos szabályokkal, a feladat kedvéért változtattunk és egyszerűsítettünk rajtuk.

A sífutás időeredményét egy rendezett párban reprezentáljuk, az első elem a percet, a második a másodpercet jelenti.

type Time = (Int,Int)

Egy versenyző teljesítményét a sífutás időeredménye és a lövések során vétett hibák száma alapján értékeljük. Ezeket az eredményeket egy rendezett párban tároljuk, ahol az első elem az időeredmény, a második pedig egy lista, ahol az egy-egy lövéssorozat során vétett hibák száma szerepel.

type TimeAndFaults = (Time,[Int])

Feladatunkban a különböző nemzetiségű játékosok csapatokat alkotnak, és szeretnénk majd a csapatok közül kiválasztani a legeredményesebbet. Egy-egy csapat eredménylistájában az egyéni eredmények szerepelnek.

Pár csapateredmény:

team1 :: [TimeAndFaults]
team1 = [((10,05),[1,1,0,2])
        ,((11,50),[2,3,1,2])
        ,((09,45),[0,1,1,0])
        ,((10,25),[0,0,0,1])]
team2 :: [TimeAndFaults]
team2 = [((10,15),[0,1,0,2])
        ,((09,50),[2,0,1,2])
        ,((09,45),[0,1,1,0])
        ,((10,25),[0,0,0,1])]
team3 :: [TimeAndFaults]
team3 = [((10,15),[0,1,0,2])
        ,((10,10),[1,0,1,1])
        ,((09,45),[0,1,1,0])
        ,((10,25),[0,0,2,1])]
team4 :: [TimeAndFaults]
team4 = [((10,15),[0,1,0,2])
        ,((10,50),[1,0,1,2])
        ,((09,45),[0,1,1,0])
        ,((10,25),[0,0,0,1])]
teams = [team1, team2, team3, team4]

A csapatok nevei lényegében String értékek lesznek.

type Team = String

Ezeket most egy listában tároljuk.

teamNames :: [Team]
teamNames = ["Anfy Team","Team 17","Core Team","A-Team"]

Megjegyzés. A type kulcsszó segítségével a Time típus az (Int, Int) típus, a TimeAndFaults típus a Time típusból és egy Int listából alkotott rendezett pár, valamint a Team a String típus másik neve lesz, hasonlóan a String és [Char] viszonyához. A programban ez semmilyen további megszorítást nem fog jelenteni, csupán a beszédesebb függvénytípusok kialakításában segít.

Időeredmény konvertálása másodperccé (1 pont)

Adjuk meg azt a függvényt, amely a paraméterül kapott időeredményt átváltja másodpercre! Ha valamelyik érték a rendezett párban nem szabályos, akkor az error függvény segítségével adjunk erről hibajelzést (Invalid Time szöveggel)! A perc nem lehet negatív, a másodperc pedig csak 0 és 59 közti, zárt intervallumbeli érték lehet.

timeToSeconds :: Time -> Int

Test>
80 :: Int
Test>
410 :: Int
Test>
⊥₁ :: Int
⊥₁: timeToSeconds: Invalid Time
CallStack (from HasCallStack):
  error, called at ./Biathlon.lhs:116:34 in main:Biathlon
Test>
⊥₁ :: Int
⊥₁: timeToSeconds: Invalid Time
CallStack (from HasCallStack):
  error, called at ./Biathlon.lhs:116:34 in main:Biathlon
Test>
⊥₁ :: Int
⊥₁: timeToSeconds: Invalid Time
CallStack (from HasCallStack):
  error, called at ./Biathlon.lhs:116:34 in main:Biathlon
Test>
⊥₁ :: Int
⊥₁: timeToSeconds: Invalid Time
CallStack (from HasCallStack):
  error, called at ./Biathlon.lhs:116:34 in main:Biathlon

Másodpercek konvertálása időeredménnyé (1 pont)

Adjuk meg azt a függvényt, amely a paraméterül kapott másodperc eredményt átváltja (perc, másodperc) formába úgy, hogy a másodperc 0 és 59 között legyen!

secondsToTime :: Int -> Time

Test>
(1, 20) :: Time
Test>
(6, 50) :: Time
Test>
⊥₁ :: Time
⊥₁: secondsToTime: negative number
CallStack (from HasCallStack):
  error, called at ./Biathlon.lhs:135:30 in main:Biathlon

Két időeredmény összehasonlítása (1 pont)

Vezessünk be egy speciális operátort annak az eldöntésére, hogy az első paraméterben kapott időeredmény jobb (vagy egyforma)-e a második időeredménynél!

(.<=.) :: Time -> Time -> Bool

Test>
True :: Bool
Test>
False :: Bool
Test>
True :: Bool
Test>
True :: Bool

Egyéni eredmény kiszámítása (1 pont)

Adjuk meg azt a függvény, amely kiszámítja az egyéni eredményt olyan módon, hogy a sífutás időeredményéhez annyi büntetőpercet ad, amennyi hibát összesen vétett a lövések során az adott versenyző!

result :: TimeAndFaults -> Time

Test>
(14, 5) :: Time
Test>
(13, 15) :: Time
Test>
(13, 25) :: Time

Csoporteredmény összesítése (1 pont)

Egy listában szereplő egyéni eredmények alapján számítsuk ki a csapateredményt, ami a büntetőpercekkel megnövelt idők összege!

teamTime :: [TimeAndFaults] -> Time

Test>
(57, 5) :: Time
Test>
(51, 15) :: Time
Test>
(51, 35) :: Time
Test>
(51, 15) :: Time

Segítség. Váltsuk át az egyéni eredmények idejét másodpercekre, ezt összegezzük, majd a végeredményt alakítsuk vissza Time értékké!

Legjobb eredményt elérő csapatok sorszámai (2 pont)

Adjunk meg azt a függvényt, amely paraméterül csapateredmények listáját kapja, és kiválasztja azon csapatokat, amelyeknek az összesített időeredménye a legjobb! Holtverseny is kialakulhat az élen, ekkor az összes legjobb időeredményt elérő csapatot szerepeltetni kell az eredménylistában. A csapatokat a sorszámukkal azonosítjuk, a sorszámozás a 1 értékkel indul, majd egyesével növekszik (2, 3, 4, ).

fastests :: [[TimeAndFaults]] -> [Int]

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

Egy csapat összes lövési hibája (2 pont)

Ha holtverseny alakul ki az összesített időeredmény alapján, akkor az a csapat nyer, amelyiknek a legkevesebb lövési hibája volt összesen. Ennek a kiszámításához először hozzunk létre egy olyan segédfüggvényt, amely összegzi a csapateredményből a hibák számát!

faults :: [TimeAndFaults] -> Int

Test>
15 :: Int
Test>
11 :: Int
Test>
11 :: Int
Test>
10 :: Int

Győztes csapat sorszáma (4 pont)

Adjunk meg azt a függvényt, amely paraméterül csapateredmények listáját kapja, és megadja a győztes csapat sorszámát! Az a csapat győz, amelyiknek a legjobb az összesített időeredménye. Ha több ilyen csapat van, akkor pedig lövési hibák száma dönt.

Megjegyzés. A lövési hibák alapján is előállhat holtverseny, ekkor a hivatalos szabályok szerint még további szempontokat is figyelembe kell venni, de ennél a feladatnál nincs ilyen teszteset. Továbbá feltételezhetjük, hogy legalább egy nyertes biztos van.

winner :: [[TimeAndFaults]] -> Int

Test>
4 :: Int

Győztes csapat neve (1 pont)

Adottak a csapateredmények és a csapatok nevei egy listában, ugyanabban a sorrendben, mint ahogy az eredményeik szerepelnek. Adjuk meg a (fentebbi szempotok szerinti) győztes csapat nevét!

winnerName :: [Team] -> [[TimeAndFaults]] -> Team

Test>
"A-Team" :: Team

Statisztikák (3 pont)

Készítsünk egy függvényt, amely adott csapateredmények listájából egyéni eredményekről tud statisztikákat készíteni! A függvény egy rendezett párban két érdéket adjon vissza:

statistics :: [[TimeAndFaults]] -> (Time, Time)

Test>
((11, 25), (13, 11)) :: (Time, Time)

Pontozás