Tehnike sa listama

Liste i modul random

U random modulu postoje neke lepe funkcije za rad sa listama.

Funkcija

Opis

choice(L)

Vraća slučajan podatak iz liste L

sample(L,n)

Vraća grupu od n slučajnih podataka iz L

shuffle(L)

Promeša (napravi slučajan redosled) podatke iz L

Napomena

Funkcija shuffle modifikuje originalnu listu, tako da ako ne želite da menjate listu, morate sačuvati njenu kopiju.

Primer 1

Možemo iskoristiti choice funkciju da izaberemo jedno od imena iz liste imena.

from random import choice
names = ['Joe', 'Bob', 'Sue', 'Sally']
current_player = choice(names)

Primer 2

Funkcija sample je slična funkciji choice. I dok choice vraća jedan podataka iz liste, sample može da vrati više podataka.

from random import sample
names = ['Joe', 'Bob', 'Sue', 'Sally']
team = sample(names, 2)

Primer 3

Funkcija choice takođe radi i sa stringovima, tako što vraća jedan znak (character) iz stringa. Evo jednog primera korišćenja choice funkcije da se popuni ekran sa gomilom slučajnih znakova.

from random import choice
s='abcdefghijklmnopqrstuvwxyz1234567890!@#$%^&*()'
for i in range(10000):
    print(choice(s), end='')

Primer 4

Evo lepe upotrebe shuffle funkcije da se izmeša redolsed igrača u nekoj igri.

from random import shuffle
players = ['Joe', 'Bob', 'Sue', 'Sally']
shuffle(players)
for p in players:
    print(p, 'it is your turn.')
    # code to play the game goes here...

Primer 5

Ovde koristimo shuffle da podelimo grupu ljudi u timove od dva čoveka. Pretpostavka je da nam je unapred data lista imena pod imenom names.

shuffle(names)
teams = []
for i in range(0,len(names),2):
    teams.append([names[i], names[i+1]])

Svaki podatak u varijabli teams je lista od dva imena. Način na koji kod radi je da smo najpre pomešali imena tako da budu u slučajnom redosledu. Prva dva imena iz pomešanog redosleda postaju prvi tim, sledeća dva drugi tim itd. Zapazite da u funkciji range koristimo i treći argument da preskačemo po dva podatka u listi.

split

Metod split (kako smo ranije videli) vraća listu reči u stringu. Metod pretpostavlja da su reći razdoveje blanko znacima. Evo primera:

s = 'Hi! This is a test.'
print(s.split())

['Hi!', 'This', 'is', 'a', 'test.']

Kao što vidimo, pošto split razbija string na blanko znacima, znaci intepunkcije ostaju kao deo reči. Postoji modul pod nazivom string koji, između ostalog, ima string varijablu punctuation koja sadrži uobičajene znake intepunkcije. Možemo izbrisati interpunkciju iz stringa s na sledeći način:

from string import punctuation
for c in punctuation:
    s = s.replace(c, '')

Primer

Evo programa koji prebrojava kolko se puta neka reč pojavljuje u stringu.

from string import punctuation

s = input('Unesite string: ')
for c in punctuation:
    s = s.replace(c, '')
s = s.lower()
L = s.split()

rec = input('Unesite reč: ')
print(rec, 'se pojavljuje', L.count(rec), 'puta.')

Opcioni argument u split metodi

Metod split ima jedan opcioni argument kojim se omogućava da se razbijanje stringa vrši na nekom drugom mestu a ne na blanko znacima. Evo primera:

s = '1-800-271-8281'
print(s.split('-'))
['1', '800', '271', '8281']

Metod join

Metod join je na neki način suprotan metodu split. To je string metod koji uzima listu stringova i spaja je u jedan string. Evo nekoliko primera korišćenjm liste L = [‘A’, ‘B’, ‘C’]

Operacija

Rezultat

‘ ‘.join(L)

A B C

‘’.join(L)

ABC

‘, ‘.join(L)

A, B, C

‘xxx’.join(L)

AxxxBxxxC

Primer upotrebe join metode

Napišite program koji kreira jedan anagram od zadate reči. Da podsetimo anagram neke reči je sastavljen od istih slova ali u drugom redosledu. Na primer, dva anagrama reči there su three i ether. Neka vas ne brine da li je anagram stvarna reč ili ne, to nije važno.

Ovo liči kao da možemo iskoristiti funkciju shuffle , ali nažalost funkcija shuffle radi samo sa listama. Zato moramo najpre konvertovani string u listu, upotrebiti shuffle na toj listi, a zatim konvertovati listu nazad u string. Za konvertovanje string-a u listu možemo koristiti funkciju list(s). Da vratimo listu nazad u string koristimo join.

from random import shuffle
rec = input('Unesite reč: ')

lista_slova = list(rec)
shuffle(lista_slova)
anagram = '';.join(lista_slova)

print(anagram)

Sastavljanje liste (comprehension)

Sastavljanje (comprehension) liste je jedan moćan način za kreiranje liste. Evo jednog jednostavnog primera:

L = [i for i in range(5)] Ovime se kreira lista [0,1,2,3,4]. Uočite da je sintaksa veoma slična načinu koji se koristi u matematici. Evo još nekoliko primera za sastavljanje liste. U ovim primerima pretpostavićemo da je:

string = 'Hello'
L = [1,14,5,9,12]
M = ['one', 'two', 'three', 'four', 'five', 'six']

Naredba za sastavljanje

Rezultirajuća lista

[0 for i in range(10)]

[0,0,0,0,0,0,0,0,0,0]

[i**2 for i in range(1,8)]

[1,4,9,16,25,36,49]

[i*10 for i in L]

[10,140,50,90,120]

[c*2 for c in string]

[‘HH’, ‘ee’, ‘ll’, ‘ll’, ‘oo’]

[m[0] for m in M]

[‘o’, ‘t’, ‘t’, ‘f’, ‘f’, ‘s’]

[i for i in L if i<10]

[1,5,9]

[m[0] for m in M if len(m)==3]

[‘o’, ‘t’, ‘s’]

Kao što vidimo u poslednja dva primera, možemo da dodajemo if naredbu pri sastavljanju liste. Uporedite poslednji primer sa dužim načinom za sastavljanje iste liste:

L = []
for m in M:
    if len(m)==3:
        L.append(m)

Višestruke for naredbe pri sastavljanju liste

Može se koristiti više for naredbi pri sastavljanju liste, kao u primeru:

L = [[i,j] for i in range(2) for j in range(2)]
[[0, 0], [0, 1], [1, 0], [1, 1]]

Ovo je ekvivalentno sledećem kodu:

L = []
for i in range(2):
    for j in range(2):
        L.append([i,j])

Evo još jedan primer:

[[i,j] for i in range(4) for j in range(i)]
[[1, 0], [2, 0], [2, 1], [3, 0], [3, 1], [3, 2]]

Korišćenje sastavljanja liste

Da demonstriramo snagu ovoga načina sastavljanja liste uradićemo neke ranije primere korišćenjem ovog metoda.

Primer 1

Napišite program koji generiše listu L od 50 slučajnih brojeva između 1 i 100.

L = [randint(1,100) for i in range(50)]

Primer 2

Zamenite svaki član liste L sa njegovim kvadratom.

L = [i**2 for i in L]

Primer 3

Prebrojte koliko u listi L ima podataka većih od 50.

len([i for i in L if i>50])

Primer 4

Data je lista koja sadrži brojeve između 1 i 100, kreirajte novu listu čiji je prvi član broj jedinica, drugi član broj dvojaka itd. u listi L.

frekvencije = [L.count(i) for i in range(1,101)]

Još jedan primer

Metod join često se može iskoristiti za brzu izgradnju stringova. Evo kako se može kreirati string koji sadrži 1000 slova.

from random import choice
alfabet = 'abcdefghijklmnopqrstuvwxyz'
s = '';.join([choice(alfabet) for i in range(1000)])

I još jedan primer

Pretposatvimo da imamo listu čiji su elementi liste dužine 2, kao ova dole:

L = [[1,2], [3,4], [5,6]]

Ako želimo da obrnemo redosled u listama to možemo da uradimo ovako:

M = [[y,x] for x,y in L]

[[2, 1], [4, 3], [6, 5]]

Napomena

Vi nararavno možete da prođete i bez korišćenja navedene metode kreiranja lista, ali jednom kada se na nju naviknete, bićete u stanju da brzo pišete i lakše čiatate nego kada koristite duže varijante kreiranja liste.

Dvodimenzione liste

Postoji mnogo stvari koje se mogu predstaviti dvodimenzionim listama, kao što su Tic-tac-toe tabla ili pikslovi kompjuterskog ekrana. U Python-u, jedan od načina za kreiranje dvodimenzionih lista je da se kreira lista čiji su elementi takođe liste. Evo primera:

L = [[1,2,3],
     [4,5,6],
     [7,8,9]]

Indeksiranje

Koristimo dva indeksa da pristupimo pojedinačnim elementima dvodimezionalne liste. Da dobijemo podatak iz reda r, i kolone c, koristimo sledeći način:

L[r][c]

Štampanje dvodimenzione

Da štampate dvodimenzionu listu možete koristiti ugnježdene for petlje. Sledeći primer štampa listu veličine 10 × 5 ( deset redova i pet kolona):

for r in range(10):
    for c in range(5):
        print(L[r][c], end=" ")
    print()

Druga mogućnost je da koristite pprint iz pprint modula. Ova se funkcija koristi za takozvani “pretty-print” ( „lepu štampu“ ). Evo primera za štampanje liste L:

from pprint import pprint
pprint(L)

Funkcija pprint se može koristiti i za štampanje običnih lista i drugih objekata u Python-u.

Rad sa dvodimenzionalnim listama

Ugnježdene for petlje, kao ona korišćena za štampanje dvodimenzionih lista, mogu biti korišćene i za procesiranje elemenata dvodimenzionih lista. Evo primera koji prebrojava koliko ima parnih brojeva u jednoj 10 × 5 listi.

count = 0
for r in range(10):
    for c in range(5):
        if L[r][c]%2==0:
            count = count + 1

Ovo može biti takođe urađeno i list-comprehension metodom:

broj_parnih = sum([1 for r in range(10) for c in range(5) if L[r][c]%2==0])

Kreiranje velikih dvodimezionalnih lista

Da kreirate veće liste, možete koristiti list-comprehension ovako:

L = [[0]*50 for i in range(100)]

Ovime se kreira lista nula sa 100 redova i 50 kolona.

Dobijanje redova i kolona

Da dobijete ceo r-ti red liste L, koristite

L[r]

Da dobijete c-tu kolonu liste L, koristite list-comprehension:

[L[i][c] for i in range(len(L))]

Poravnjavanje (flattening) liste

Da poravnate dvodimenzionu listu, to jest da dobijete jednodimenzionu listu svih elemenata, koristite sledeće:

[j for M in L for j in M]

Na primer, pretpostavimo da imamo listu:

L = [[1,2,3],
     [4,5,6],
     [7,8,9]]

Poravnata lista će biti

[1, 2, 3, 4, 5, 6, 7, 8, 9]

Liste sa više dimezija

Kreiranje liste sa 3 i više dimenzija je slično već prikazanom. Evo kako se kreira jedna 5 × 5× 5 lista

L = [[[0]*5 for i in range(5)] for j in range(5)]

To je lista čiji su elementi liste lista. Prvi element liste je

L[0][0][0]

Vežbe

8.1 Napišite program koji traži od korisnika da unese naki engleski tekst, a zatim prebrojava koliko ima članova u tom tekstu. Članovi su reči ‘a’, ‘an’, i ‘the’.

8.2 Napišite program koji omogućava korisniku da unese pet brojeva (pročitanih kao string). Kreirajte string koji se sastoji od unetih brojeva sa „+“ znakom kao separatorom. Na primer, ako korisnik unese 2, 5, 11, 33, and 55, onda će string biti ‘2+5+11+33+55’.

8.3 Tražite od korisnika da unese jednu rečenicu pa štampajte svaku treću reč iz te rečenice.

8.4 Napišite program koji traži od korisnika da unese jednu rečenicu pa na slučajan način razmestite reči te rečenice. Ne morate voditi računa o znacima interpunkcije i velikom slovu na početku rečenice.

8.5 Uradite kao u predhodnom zadatku, ali sada vodite računa da rečenica počinje velikim slovom, te da originalna prva reč ne treba da počne velikim slovom ako se nađe negde u sredini rečenice, a takođe i tačka treba da bude na pravom mestu.

8.6 Napišite jednostavan program za „Izjavu dana“. Program treba da sadrži listu izjava, pa kada se izvrši štampa jednu slučajno izabranu izjavu.

8.7 Napišite jednostavan program za izvlačenje brojeva u igri LOTO. Izvlačenje se sastoji od šest slučajno izabranih brojeva između 1 i 48.

8.8 Napišite program kojim se procenjuje prosečan broj izvlačenja potrebnih da korisnički tiket od šest brojeva ostavri dobitak u igri loto u kojoj se biraju brojevi od 1 do 10. Da to uradite izvršite 1000 puta petlju u kojoj se generiše korisnički tiket i simulira izvlačenje sve dok korisnički tiket nije izvučen. Izračunajte prosečan broj izvlačenja koja su bila potrebna u 1000 izvršenih simulacija.

8.9 Napišite program kojim se simulira izvlačenje imena iz šešira. U ovom izvlačenju svaka osoba može imati više pojavljivanja u šeširu. Omogućite korisniku da unese listu imena i listu brojeva pojavljivanja imena u šeširu, a zatim štampajte pobednika.

8.10 Napišite jednostavnu kviz igru koja ima listu od 10 pitanja i listu odgovora na ta pitanja. U igri korisnik dobija 4 slučajno odabrana pitanja. Program postavlja pitanja jedno po jedno i odmah saopštava korisniku da li je odgovor tačan ili pogrešan. Na kraju program štampa koliko je bilo tačnih odgovora.

8.11 Napišite program za cenzurisanje teksta. Omogućite korisniku da unese neki tekst pa vaš program štampa tekst sa zvezdicama umesto slova u zabranjenim rečima. Za testiranje programa koristite sledeće reči kao one koje treba cenzurisati: darn, dang, freakin, heck, i shoot, kao što je prikazano u primeru

Enter some text: Oh shoot, I thought I had the dang problem
figured out. Darn it. Oh well, it was a heck of a freakin
try.

Oh *****, I thought I had the **** problem figured out.
**** it. Oh well, it was a **** of a ****** try.

8.12 Napišite program koji koristi choice metod za kreiranje slučajnog anagrama učitanog stringa.

8.13 Napišite program koji preuzima od korisnika string koji je potencijalno telefonski broj. Program treba da štampa Ispravan ako odluči da je string predtsvlja stvaran telefonski broj, a Neispravan ako string ne odgovara stvarnom telefonskom broju. Telefonski broj će se smatrati ispravnima ako ima oblik abc-def-hijk ili 1-abc-def-hijk. Crtice moraju biti uključene, telefonski broj može sadržati samo cifre i crtice, a broj cifara u svakoj grupi mora biti korektan. Testirajte program sa sledećim podacima

Unesite telefonski broj: 1-301-447-5820
Ispravan
Unesite telefonski broj: 301-447-5820
Ispravan
Unesite telefonski broj: 301-4477-5820
Nesipravan
Unesite telefonski broj: 3X1-447-5820
Nesipravan
Unesite telefonski broj 3014475820
Nesipravan

8.14 Neka je L lista stringova. Napišite naredbu za sastavljanje liste (list-comprehensions) koja kreira novu listu od liste L na sledeće načine:

  • Listu koja sadrži stringove s iz L sa uklonjenim prvim slovom

  • Listu koja sadrži dužine stringova iz L

  • Listu koja se sastoji od onih stringova iz L koji su dugački najmanje 3 znaka

8.15 Iskoristite list-comprehensions da napravite listu koja se sastoji od svih palindromskih brojeva izmđu 100 i 1000.

8.16 Iskoristite list-comprehensions da napravite donju listu, koja se sastoji od jedinica razdvojenih rastućim brojem nula. Poslednje dve jedinice treba da budu razdvojene sa deset nula:

[1,1,0,1,0,0,1,0,0,0,1,0,0,0,0,1,....]

8.17 Neka je L=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47]. Korišćenjem list-comprehension metode napravite listu razlika među uzastopnim brojevima iz L. Zatim nađite maksimalnu razliku kao i procenat slučajeva kada je razlika 2.

8.18 Napišite program koji nalazi srednju vrednost svih elemenata u nekoj 4 × 4 listi celih brojeva.

8.19 Napišite program koji kreira listu od 10 × 10 slučajnih brojeva između 1 i 100. Zatim uradite sledeće:

  • Štampajte listu.

  • Nađite najveću vrednost u trećem redu.

  • Nađite najmanju vrednost u šestoj koloni.

8.20 Napišite program koji kreira i štampa listu dimenzija 8 × 8 čiji su elementi alternacija između 1 i 2 , počev od 1 u gornjem levom uglu.

8.21 Napišite program koji proverava da li je lista dimenzija 4 × 4 list magičan kvadrat. Kod magičnog kvadrata svaki red, svaka kolona kao i dve dijagonale imaju istu vrednost sume svojih elemenata.

8.22 Napišite program koji traži od korisnika da unese neku dužinu. Program treba da pita u kojim je jedinicama data dužina i u koje jedinice je treba konvertovati. Moguće jedinice su inči, jarde,milje,milimetri,santimetri, metri i kilometri. Iako se ovo može uraditi sa 25 if naredbi, mnogo je kraće i lakše ako se koristi dvodimenziona lista konverzije, pa zato iskoroitite listu za rešenje ovog zadatka.

8.23 Sledeći program je koristan kao deo igre „Podmornice“. Pretpostavimo da imate listu dimenzija 5 × 5 koja sadrži nule i jedinice. Tražite od korisnika da unese red i kolonu. Ako je podatak u tom redu i koloni liste jednak jedan program treba da štampa Pogodak, u suprotnom štampa Promašaj.

8.24 Ova vežba može da posluži za igru „Memorija“. Slučajno generišite listu dimenzija 6 × 6 koja sadrži tekstualne znakove tako da se svaki pojavljuje tačno dva puta. Jedan primer je prikazan dole

@ 5 # A A !
5 0 b @ $ z
$ N x ! N z
0 - + # b :
- : + c c x

8.25 Ovo može biti korisno za implementaciju igrača u raznim kompjuterskim igrama. Napišite program koji kreira jednu 5 × 5 listu koja se sastoji od nula i jedinica. Vaš program treba da slučajno izabere jednu od pozicija u listi koja sadrži nulu i da je promeni u jedinicu. Ako su svi podaci u listi jedinica, program treba to da sopšti. [Pomoć: jedan način da se ovo uradi je da se kreira nova lista čiji će elementi biti koordinate svih jedinica u listi, pa korišćenjem choice metoda slučajno bira jedna od njih. Možete koristiti listu sa dva elementa da predtsvite koordinate.]

8.26 Ovde se radi o jednom staroj zagonetki koja se može rešiti kompjuterskim programom. Postoji samo jedan petocifreni broj n takav da svaki od sledećih brojeva ima samo jednu cifru koja je sa njim zajednička na istoj poziciji. Pronađite broj n.

01265, 12171, 23257, 34548, 45970, 56236, 67324, 78084, 89872, 99414

8.27 Obično se elementi dvodimenzione liste adresiraju pomoću redova i kolona, kao što je dole prikazano u levom delu. Drugi način bi bio onaj prikazan u desnom delu:

(0,0) (0,1) (0,2)    0  1  2
(1,0) (1,1) (1,2)    3  4  5
(2,0) (2,1) (2,2)    6  7  8
  • Napišite kod koji prevodi iz leve u desnu prezentaciju. Operacije // i % su korisne za ovu transformaciju. Proverite da li vaš kod radi za bilo koje dimenzije liste.

  • Napišite kod koji prevodi iz desne u levu prezentaciju.