Druga seminarska naloga - Spletna učilnica FRI 16/17

Algoritmi in podatkovne strukture 1
2016/2017
Seminarska naloga 2
Rok za oddajo programske kode prek učilnice je sobota, 14. 1. 2017.
Zagovori seminarske naloge bodo potekali v terminu vaj v tednu 16. 1. – 20. 1. 2017.
Navodila
Oddana programska rešitev bo avtomatsko testirana, zato je potrebno strogo upoštevati naslednja navodila:






Uporabite programski jezik java (program naj bo skladen z različico JDK 1.7).
Rešitev posamezne naloge mora biti v eni sami datoteki. Torej, za pet nalog morate oddati pet
datotek. Datoteke naj bodo poimenovane v skladu s podanimi izhodišči.
Vsak javni razred mora imeti definirano metodo public static String vrniVpisnoStevilko(), ki vrne vašo
vpisno številko v obliki znakovnega zaporedja.
Uporaba zunanjih knjižnic ni dovoljena. Uporaba internih knjižnic java.* je dovoljena (vključno z
javanskimi zbirkami iz paketa java.util).
Razred naj bo v privzetem (default) paketu. Ne definirajte svojega.
Vaša rešitev ne sme izpisovati na standardni izhod ali uporabljati kakšnih drugih sistemskih klicev.
Ocena nalog je odvisna od pravilnosti izhoda in učinkovitosti implementacije (čas izvajanja). Program za
avtomatsko testiranje bo večkrat zapored klical metode vaših razredov, zato poskrbite za ustrezno
inicializacijo morebitnih statičnih spremenljivk!
Naloga 6
Napišite program, ki iz vhodnega zaporedja celih števil sestavi binarno iskalno drevo. Pri tem upoštevajte: soda
števila vstavljajte levo od lihih (soda so torej "manjša" od lihih), soda (in tudi liha) pa se med seboj običajno
primerjajo. Postopek gradnje drevesa je:
1. Najprej po vrsti vstavite vse elemente v drevo.
2. Potem iz drevesa zbrišite najmanjše liho število (oz. največje sodo, če ni lihih).
3. Izbrisano število vstavite v koren drevesa.
Levo poddrevo bi moralo imeti soda števila, desno pa liha.
Ko zgradite drevo, preberite iz vhodne datoteke pare ključev in za vsak par v novi vrstici izpišite:




vsoto elementov na poti med izbranima ključema (samih ključev ne upoštevajte),
vsoto vseh elementov v drevesu, ki so manjši od obeh ključev (pri tem upoštevajte gornje pravilo, kaj
je večje / manjše),
vsoto elementov, ki so med obema ključema,
vsoto elementov, ki so večji od obeh ključev.
Če katerega od ključev ni v drevesu, izpišite -1.
Napišite razred BST po vzorcu spodaj. Metoda main je nujna, saj bo ime vhodne datoteke podano kot prvi
argument programa (args[0]), ime izhodne pa kot drugi (args[1]).
public class BST {
public static void main(String[] args) {
String vhodnaDatoteka = args[0];
String izhodnaDatoteka = args[1];
...
}
...
}
Vhod
Prva vrstica vhodne datoteke bo vsebovala zaporedje celih števil. Števila ne bodo prevelika, da bi presegla mejo
tipa Integer. Zaporedje bo vsebovalo največ 10000 števil. V preostalih vrsticah bodo pari ključev, ki jih
uporabite za generiranje izpisov (največ 20 parov).
Primer:
7 2 3 1 6 12 4
12 3
1 2
3 9
7 7
Slika prikazuje dve drevesi, prvo drevo nastane po gradnji (točka 1), drugo po brisanju in ponovnem vstavljanju.
Izhod
Za vsak par v izhodno datoteko zapišite zahtevane vrednosti, ločene s presledki:
16 12 1 7
0 0 22 10
-1
0 28 0 0
Naloga 7
Analizirali bomo argumentacijo na sodišču. Imamo tožilca in odvetnika, ki si izmenjujeta argumente in vaša
naloga bo, da analizirate njune argumente in izpeljete končno odločitev sodišča.
Imeli bomo dva tipa argumentov:
a
b
neposredni argumenti, ki trdijo, ali da je obtoženec kriv (tožilčev argument) ali nedolžen (odvetnikov
argument) in
protiargumenti, ki spodbijajo drug argument.
Celotna argumentacija bo zapisana v vhodni datoteki. V prvi vrstici bo zapisano število argumentov, kateri bodo
sledili opisi argumentov. Vsak opis se bo začel z oznako argumenta, kjer bo prva črka določala za čigav
argument gre (T-tožilec ali O-odvetnik). Neposredni argument bo zapisan le z oznako, medtem ko bo pri
protiargumentu oznaki sledila še oznaka argumenta, ki ga ta proti-argument spodbija. Če je drugi argument
neobstoječ, je to irrelevanten argument in ga lahko ignorirate. Primer vhodne datoteke:
6
T1
O1,T1
TNep
O2
T3,O2
OPomozni,T3
V datoteki imamo 6 argumentov. Prvi je tožilčev neposredni argument T1, potem sledi odvetnikov
protiargument O1, ki spodbija T1. Nato sledi tožilčev argument TNep, sledi neposredni argument odvetnika O2,
ki ga tožilec spodbije s T3, a odvetnik nato spodbije T3 z argumentom OPomozni.
Argument je sprejet, če nima sprejetega protiargumenta. Argument, ki nima protiargumentov, je vedno
sprejet.
Obtoženec je kriv, če
a
b
ne obstaja sprejet neposreden odvetnikov argument in
če obstaja vsaj en sprejet neposreden tožilčev argument.
Vaša naloga je, da v drevesni obliki izpišete argumentacijo, kjer mora biti vsak protiargument za en presledek
zamaknjen v desno. Argumenti morajo biti znotraj posameznega vozlišča izpisani v istem vrstnem redu, kot so
se pojavili v vhodni datoteki. Poleg imena argumenta boste ob vsakem argumentu še zapisali, če je argument
sprejet (S) ali ni sprejet (NS). Na koncu, ko je celotno drevo izpisano, izpišite še, ali je bil obsojenec spoznan za
krivega (K) ali nedolžnega (N).
Implementirajte razred Sodisce:
public class Sodisce {
public static void main(String[] args) {
String vhodnaDatoteka = args[0];
String izhodnaDatoteka = args[1];
...
}
...
}
V argumentih programa (args[0] in args[1]) bosta poti do vhodne in izhodne datoteke. Potem preberite vhodno
datoteko, ki vsebuje zapis argumentov, in izpišite ustrezno drevo s končno odločitvijo v izhodno datoteko.
Pravilna izhodna datoteka za našo argumentacijo je:
T1,NS
O1,S
TNep,S
O2,S
T3,NS
OPomozni,S
N
Dva dodatna primera
Vhodna datoteka
6
O1
T1,O1
O2,T1
T2,O2
O3,T2
T3,O4
9
T1
T2
O1,T2
O2
T3,O2
O3,T3
T4,O3
O4,T3
T5,O4
Izhodna datoteka
O1,S
T1,NS
O2,S
T2,NS
O3,S
N
T1,S
T2,NS
O1,S
O2,NS
T3,S
O3,NS
T4,S
O4,NS
T5,S
K
Naloga 8
V vhodni datoteki je podano zaporedje števil, ki ustreza vmesnem (inorder) izpisu elementov nekega binarnega
drevesa. Za to drevo vemo, da je delno urejeno - za vsako poddrevo velja, da je v korenu največji element tega
poddrevesa. Vemo tudi to, da drevo ni nujno poravnano niti delno poravnano.
Implementirajte razred Rekonstrukcija, ki vsebuje metodo main. Metoda v argumentih prejme poti do vhodne
in izhodne datoteke (args[0] in args[1]), prebere vhodne podatke, rekonstruira drevo (rešitev je enolično
določena) in v izhodno datoteko zapiše elemente drevesa po nivojih.
Na primer, če je vsebina vhodne datoteke
7,5,10,3,2,17,1,12,14
je rekonstruirano drevo oblike
zato bo v izhodni datoteki zapisano
17,10,14,7,3,12,5,2,1
Izhodišče
public class Rekonstrukcija {
public static void main(String[] args) {
String vhodnaDatoteka = args[0];
String izhodnaDatoteka = args[1];
...
}
...
}
Naloga 9
V nekem mestu ima javni prevoz N linij. Po mestu je razporejenih M postajališč, ki so označena s celimi števili.
Potek proge posamezne linije je podan s seznamom oznak postajališč. Vsaka linija obratuje v obeh smereh.
Vhodna datoteka v prvi vrstici vsebuje število linij javnega prevoza. Nato so po vrsticah podana zaporedja
postajališč, ki določajo potek posameznih linij (ena linija v eni vrstici). Oznake postajališč so ločene z vejicami.
V zadnji vrstici vhodne datoteke sta celi števili Vstop in Izstop (ločeni z vejico), ki predstavljata oznaki vstopnega
in izstopnega postajališča
Implementirajte razred Prevoz, ki vsebuje metodo main. Metoda prejme poti do vhodne in izhodne datoteke
(args[0] in args[1]), prebere vhodne podatke o linijah javnega prevoza in nato v izhodno datoteko zapiše dve
vrednosti, vsako v svoji vrstici.
V prvi vrstici naj bo zapisano minimalno število prestopanj, ki ga potrebujemo za pot od vstopnega postajališča
Vstop do izstopnega postajališča Izstop (pri tem nas ne zanima dejanska dolžina poti oziroma število prevoženih
postaj). Če sta obe postajališči na isti progi, je število prestopanj enako 0. Če z uporabo linij javnega prevoza ni
možno priti iz enega postajališča do drugega, je število prestopanj enako -1.
V drugi vrstici naj bo zapisano število prevoženih postaj na najkrajši vožnji med vstopnim postajališčem Vstop in
izstopnim postajališčem Izstop (pri tem nas ne zanima število prestopanj na tej poti). Če sta postajališči sosednji
na isti liniji, je dolžina najkrajše poti enaka 1. Če z uporabo linij javnega prevoza ni možno priti iz enega
postajališča do drugega, je dolžina najkrajše poti enaka -1.
Na primer, če je vsebina vhodne datoteke:
4
1,2,3,4,5
6,7
8,7,4
2,6
1,7
bo v izhodni datoteki zapisano:
1
3
saj je za pot med postajališči 1 in 7 dovolj samo eno prestopanje (v postajališču 4 prestopimo s prve na tretjo
linijo), najkrajša pot pa zahteva 3 postaje (1 → 2 s prvo linijo, 2 → 6 s četrto linijo, 6 → 7 s tretjo linijo).
Izhodišče
public class Prevoz {
public static void main(String[] args) {
String vhodnaDatoteka = args[0];
String izhodnaDatoteka = args[1];
...
}
...
}
Naloga 10
V občini skrbijo za zadovoljstvo svojih občanov. Zato so sklenili, da bodo brezplačno podelili usmerjevalnike.
Zaradi finančne krize so se odločili, da bodo pripravili program za izračun najmanjšega števila potrebnih
usmerjevalnikov.
V prvi vrstici vhodne datoteke je zapisan maksimalni domet usmerjevalnikov.
V drugi vrstici je položaj centrale (x in y koordinati, ločeni z vejico), v kateri je nastavljen prvi usmerjevalnik.
V naslednjih vrsticah so opisani občani (vsak v svoji vrstici). Občan je opisan z imenom, položajem (x in y
koordinati) in seznamom prijateljev (imena soobčanov). Vsi podatki so ločeni z vejicami. Koordinate so tipa
double. Lahko predpostavite, da bodo v vhodni datoteki prijateljstva med občani vedno obojestranska. Seznam
prijateljev je lahko tudi prazen.
Vsak občan se lahko poveže s centralo ter s tistimi soobčani, s katerimi je v prijateljskem odnosu. Drugi pogoj za
vzpostavitev povezave med dvema točkama je njuna (evklidska) razdalja, ki mora biti manjša ali enaka
maksimalnemu dometu usmerjevalnika. Usmerjevalniki nimajo omejitev glede števila povezav.
Program naj izračuna in v izhodno datoteko izpiše minimalno število usmerjevalnikov, ki jih občina potrebuje,
da bi povezali vse občane. Če ni možno povezati vseh občanov, naj bo v izhodni datoteki zapisana vrednost -1.
Na primer, če je vsebina vhodne datoteke:
5.2
A,2.0,4.0,B,D,C
B,4.0,4.0,A,C,E
C,4.0,2.0,A,B,D
D,9.0,1.0,A,C,E
E,13.0,1.0,B,D
bo v izhodni datoteki zapisano:
3
saj je potrebno postaviti usmerjevalnike pri občanih A, C in D.
Implementirajte razred Obcina po vzorcu spodaj. Metoda main prejme poti do vhodne in izhodne datoteke
(args[0] in args[1]), prebere vhodne podatke in zapiše rezultat v izhodno datoteko.
public class Obcina {
public static void main(String[] args) {
String vhodnaDatoteka = args[0];
String izhodnaDatoteka = args[1];
...
}
...
}