Informatika érettségi 2006. Október
Őszi érettségi, ismét egy többszörösen összetett adattípussal. Cserébe viszont lényegesen könnyebb, mint a korábbi májusi feladat.
A feladatkiírás
A rádióhallgatás ma már egyre inkább zene vagy hírek hallgatására korlátozódik. Ez a feladat három, folyamatosan zenét sugárzó adóról szól, azok egyetlen napi műsorát feldolgozva. A reklám elkerülése érdekében az adókat nevük helyett egyetlen számmal azonosítottuk.
A musor.txt állomány első sorában az olvasható, hogy hány zeneszám (z<=1000) szólt
aznap a rádiókban, majd ezt z darab sor követi. Minden sor négy, egymástól egyetlen szóközzel elválasztott adatot tartalmaz: a rádió sorszámát, amit a szám hossza követ két egész szám (perc és másodperc) formában, majd a játszott szám azonosítója szerepel, ami a szám előadójából és címéből áll. A rádió sorszáma az 1, 2, 3 számok egyike. Az adás minden adón 0 óra 0 perckor kezdődik. Egyik szám sem hosszabb 30 percnél, tehát a perc értéke legfeljebb 30, a másodperc pedig legfeljebb 59 lehet. A szám azonosítója legfeljebb 50 karakter hosszú, benne legfeljebb egy kettőspont szerepel, ami az előadó és a cím között található. A számok az elhangzás sorrendjében szerepelnek az állományban, tehát a később kezdődő szám későbbi sorban található. Az állományban minden zeneszám legfeljebb egyszer szerepel.
Például:
677
1 5 3 Deep Purple:Bad Attitude
2 3 36 Eric Clapton:Terraplane Blues
3 2 46 Eric Clapton:Crazy Country Hop
3 3 25 Omega:Ablakok
…
Készítsen programot zene néven, amely az alábbi kérdésekre válaszol! Ügyeljen arra,
hogy a program forráskódját a megadott helyre mentse!
A képernyőre írást igénylő részfeladatok eredményének megjelenítése előtt írja a képernyőre a feladat sorszámát (például: 3. feladat:). Ha a billentyűzetről olvas be adatot, jelenítse meg a képernyőn, hogy milyen értéket vár.
Az adatszerkezet készítése során vegye figyelembe az Ön által használt programozási környezetben az adatok tárfoglalási igényét!
- Olvassa be a musor.txt állományban talált adatokat, s annak felhasználásával oldja meg a következő feladatokat! Ha az állományt nem tudja beolvasni, akkor a forrás első 10 sorának adatait jegyezze be a programba, s úgy oldja meg a következő feladatokat!
- Írja a képernyőre, hogy melyik csatornán hány számot lehetett meghallgatni!
- Adja meg, mennyi idő telt el az első Eric Clapton szám kezdete és az utolsó Eric Clapton szám vége között az 1. adón! Az eredményt óra:perc:másodperc formában írja a képernyőre!
- Amikor az „Omega:Legenda” című száma elkezdődött, Eszter rögtön csatornát váltott. Írja a képernyőre, hogy a szám melyik adón volt hallható, és azt, hogy a másik két adón milyen számok szóltak ekkor. Mivel a számok a kezdés időpontja szerint növekvő sorrendben vannak, így a másik két adón már elkezdődött a számok lejátszása. Feltételezheti, hogy a másik két adón volt még adás.
- Az egyik rádióműsorban sms-ben, telefonon, de akár képeslapon is kérhető szám. Ám a sokszor csak odafirkált kéréseket olykor nehéz kibetűzni. Előfordul, hogy csak ennyi olvasható: „gaoaf”, tehát ezek a betűk biztosan szerepelnek, mégpedig pontosan ebben a sorrendben. Annyi biztos, hogy először a szerző neve szerepel, majd utána a szám címe.Olvassa be a billentyűzetről a felismert karaktereket, majd írja a keres.txt állományba azokat a számokat, amelyek ennek a feltételnek megfelelnek. Az állomány első sorába a beolvasott karaktersorozat, majd utána soronként egy zeneszám azonosítója kerüljön! A feladat megoldása során ne különböztesse meg a kis- és a nagybetűket!
- Az 1. adón változik a műsor szerkezete: minden számot egy rövid, egyperces bevezető előz majd meg, és műsorkezdéstől minden egész órakor 3 perces híreket mondanak. Természetesen minden szám egy részletben hangzik el továbbra is, közvetlenül a bevezető perc után. Így ha egy szám nem fejeződne be a hírekig, el sem kezdik, az üres időt a műsorvezető tölti ki. Írja a képernyőre óra:perc:másodperc formában, hogy mikor lenne vége az adásnak az új műsorszerkezetben!
Az adatstruktúra
A feladatkiírásból kiderül, hogy rádióműsorok adataival kell dolgoznunk. A többszörös összetettség az időkezelésből akad. Hossz és Kezdet információkat kell nyilvántartanunk. Ezt ha a keretrendszer nem támogatná beépítetten, akkor is érdemes lenne egy külön típusban tárolni. Jelen megoldásban a keretrendszer beépített TimeSpan típusa került alkalmazásra.
A csavar, hogy az egyes számok pontos kezdési idejét nem kapjuk meg, csak azt, hogy a műsor 0:00-kor kezdődött, de több feladat esetén szükségünk lesz a kezdési időre, ezért ezt az adatstruktúrában tároljuk. Kiszámítani és előállítani a beolvasó kód fogja.
public class Musor
{
public int Radio { get; set; }
public TimeSpan Hossza { get; set; }
public TimeSpan Kezdete { get; set; }
public string CimAdat { get; set; }
public Musor()
{
CimAdat = string.Empty;
}
}
A megoldás
- Olvassa be a musor.txt állományban talált adatokat, s annak felhasználásával oldja meg a következő feladatokat! Ha az állományt nem tudja beolvasni, akkor a forrás első 10 sorának adatait jegyezze be a programba, s úgy oldja meg a következő feladatokat!
A beolvasó logikában a bonyolultság talán a kezdő időpontok meghatározása. Itt figyelembe kell vennünk, hogy 3db rádióállomás van és ez alapján kell megállapítani, hogy mikor is kezdődött egy szám. Ez az első esetén gyerekjáték, mert a feladatkiírás szerint 0 óra 0 perckor. Viszont az ezt követő szám már a játszott szám eltelte után kezdődhetett, és így tovább.
Az adatokhoz egy soron belül egyszerű szóközönkénti vágással hozzájutunk.A trükk az, hogy az előadó információkban lehetnek szóközök. Így meghatározott számú különálló adat feldolgozása után a többi adatot össze kell fűznünk egy string.Join segítségével. A műsorokat a megoldás osztályunkban elhelyezett List<Musor> típusú _musorok változó tárolja.
public void Feladat01()
{
using (var file = File.OpenText("musor.txt"))
{
file.ReadLine(); //első sort kihagyjuk, mert nem kell
TimeSpan[] csatornaidok = new TimeSpan[3]
{
new TimeSpan(0),
new TimeSpan(0),
new TimeSpan(0),
};
//kezdési időket is tároljuk csatornánként a számokhoz.
//megkönnyíti a dolgunkat később
string? sor = null;
do
{
sor = file.ReadLine();
if (sor != null)
{
string[] darabok = sor.Split(' ');
var musor = new Musor
{
Radio = int.Parse(darabok[0]),
Hossza = new TimeSpan(0, int.Parse(darabok[1]), int.Parse(darabok[2])),
CimAdat = string.Join(' ', darabok, 3, darabok.Length - 3),
};
musor.Kezdete = csatornaidok[musor.Radio-1];
_musorok.Add(musor);
csatornaidok[musor.Radio-1] += musor.Hossza;
}
}
while (sor != null);
}
}
- Írja a képernyőre, hogy melyik csatornán hány számot lehetett meghallgatni!
LINQ segítségével könnyen meghatározható. A csatornák szerint csoportosítani kell a műsorokat, majd a Count() segítségével megszámolni, hogy melyikben mennyi van.
public void Feladat02()
{
var csatornak = _musorok.GroupBy(cs => cs.Radio);
foreach (var csatorna in csatornak)
{
Console.WriteLine("{0}. csatorna: {1} db szám", csatorna.Key, csatorna.Count());
}
}
- Adja meg, mennyi idő telt el az első Eric Clapton szám kezdete és az utolsó Eric Clapton szám vége között az 1. adón! Az eredményt óra:perc:másodperc formában írja a képernyőre!
Először LINQ segítségével leszűrjük a műsorokból azokat, amelyeket az 1. csatorna sugárzott és a címben szerepel Eric Clapton neve. Ezeket ha a kezdési időpont szerint sorba rendezzük, akkor a lista első eleme a legelső szám lesz és értelemszerűen az utolsó eleme pedig az utolsó szám. Ezt követően már csak némi matek az idővel és meg is van az két szám között eltelt idő.
public void Feladat03()
{
var ericclaptonszamok = _musorok.Where(m => m.Radio == 1 && m.CimAdat.StartsWith("Eric Clapton")).OrderBy(m => m.Kezdete);
Musor elso = ericclaptonszamok.First();
Musor utolso = ericclaptonszamok.Last();
TimeSpan elteltido = (utolso.Kezdete + utolso.Hossza) - elso.Kezdete;
Console.WriteLine("az első Eric Clapton szám kezdete és az utolsó Eric Clapton szám vége között az 1.adón eltelt idő: {0}", elteltido);
}
- Amikor az „Omega:Legenda” című száma elkezdődött, Eszter rögtön csatornát váltott. Írja a képernyőre, hogy a szám melyik adón volt hallható, és azt, hogy a másik két adón milyen számok szóltak ekkor. Mivel a számok a kezdés időpontja szerint növekvő sorrendben vannak, így a másik két adón már elkezdődött a számok lejátszása. Feltételezheti, hogy a másik két adón volt még adás.
A sikeres megoldáshoz először ki kell keresni, hogy az Omega együttes Legenda száma melyik rádióadón szólt. Mivel többször is játszhatták ezt rádiók, még kezdési idő szerint is sorba kell rendezni a találatokat és az elsőt kiválasztani.
Ez alapján megállapítható az a rádióállomás, amelyik először játszotta. A szám kezdési időpontja és hossza alapján meghatározható, hogy milyen idősávban keresünk számokat a másik két rádióállomáson.
A keresés és a szűrés LINQ segítségével pár sor csupán. Ezt követően a találatokat már csak formázottan kell kiírni.
public void Feladat04()
{
Musor omegalegenda = _musorok.Where(m => m.CimAdat == "Omega:Legenda").OrderBy(m => m.Kezdete).FirstOrDefault();
Console.WriteLine("Az Omega:Legenda a {0}. adón szólt", omegalegenda.Radio);
TimeSpan keresettidoEleje = omegalegenda.Kezdete - omegalegenda.Hossza;
TimeSpan keresettidoVege = omegalegenda.Kezdete + omegalegenda.Hossza;
var miszoltekkormashol = _musorok.Where((m) =>
{
return
m.Radio != omegalegenda.Radio
&& m.Kezdete >= keresettidoEleje
&& m.Kezdete < keresettidoVege;
});
Console.WriteLine("Ebben az időben ez szólt másik adókon:");
foreach(var musor in miszoltekkormashol)
{
Console.WriteLine("{0}. adó: {1}", musor.Radio, musor.CimAdat);
}
}
- Az egyik rádióműsorban sms-ben, telefonon, de akár képeslapon is kérhető szám. Ám a sokszor csak odafirkált kéréseket olykor nehéz kibetűzni. Előfordul, hogy csak ennyi olvasható: „gaoaf”, tehát ezek a betűk biztosan szerepelnek, mégpedig pontosan ebben a sorrendben. Annyi biztos, hogy először a szerző neve szerepel, majd utána a szám címe. Olvassa be a billentyűzetről a felismert karaktereket, majd írja a keres.txt állományba azokat a számokat, amelyek ennek a feltételnek megfelelnek. Az állomány első sorába a beolvasott karaktersorozat, majd utána soronként egy zeneszám azonosítója kerüljön! A feladat megoldása során ne különböztesse meg a kis- és a nagybetűket!
Ismét egy fájlolvasás kombinálva egy kis kereséssel. A keresés szintén LINQ segítségével könnyen megvalósítható. Egyetlen buktató lehet, hogy a keresésnél nem kell megkülönböztetni a kis -és nagybetűket. Itt lehetne használni egy .ToLower() megoldást a CimAdat és a keresett változókon. Viszont fényévekkel szebb és hatékonyabb, ha a Contains metódusnak eleve megadjuk a szövegösszehasonlítás módját.
public void Feladat05()
{
Console.WriteLine("Felismert karakterek");
var keresett = Console.ReadLine();
using (var file = File.CreateText("keres.txt"))
{
file.WriteLine("Keresett: {0}", keresett);
var talalatok = _musorok.Where(m => m.CimAdat.Contains(keresett, StringComparison.OrdinalIgnoreCase));
foreach (var talalat in talalatok)
{
file.WriteLine(talalat.CimAdat);
}
}
}
- Az 1. adón változik a műsor szerkezete: minden számot egy rövid, egyperces bevezető előz majd meg, és műsorkezdéstől minden egész órakor 3 perces híreket mondanak. Természetesen minden szám egy részletben hangzik el továbbra is, közvetlenül a bevezető perc után. Így ha egy szám nem fejeződne be a hírekig, el sem kezdik, az üres időt a műsorvezető tölti ki. Írja a képernyőre óra:perc:másodperc formában, hogy mikor lenne vége az adásnak az új műsorszerkezetben!
Először itt meg kell határoznunk az 1-es csatorna régi műsoridejét, majd a feladatban meghatározott logika szerint rászámolni az extra szüneteket.
public void Feladat06()
{
var regimusor = _musorok.Where(m => m.Radio == 1).OrderBy(m => m.Kezdete);
TimeSpan ujmusorido = TimeSpan.FromMinutes(3);
TimeSpan ora = TimeSpan.FromHours(1);
foreach (var elem in regimusor)
{
var ujido = elem.Hossza + TimeSpan.FromMinutes(1);
if ((ora - ujido) > TimeSpan.FromSeconds(0))
{
//A szám lejátszása belefér
ujmusorido += ujido;
ora -= ujido;
}
else
{
//nem fért bele, így a maradék időt beszélni kell
ujmusorido += ora;
//majd 3 percnyi híradó.
ujmusorido += TimeSpan.FromMinutes(3);
ora = TimeSpan.FromHours(1);
}
}
Console.WriteLine("Az új műsorbeosztással ekkor van vége a műsornak: {0}", ujmusorido);
}