1. Določanje spola

Zanima nas torej, ali je trimestno število, ki se začne pri deveti števki, večje ali enako 500. To število sicer res dobimo z int(emso[9:12]), pa vendar gre še enostavneje. Spomniti se moramo le, da se trimestna števila, ki so večja ali enaka 500, vobče začenjajo s števko, ki je večja ali enaka 5, torej je rešitev prve naloge huronsko preprosta.

def jeZenska(emso): return emso[9] >= '5'

2. Srečni gostje

Naloga ni zahtevna, le precej pogojev je v rešitvi. Motita nas dve stvari.

  1. Ker je miza okrogla, moramo zadnjega gosta obravnavati posebej. Naj bo n število gostov (torej n = len(razpored). Potem bi morali najbrž pisati zanko for i in range(n-1) (pazite, n-1, gremo torej samo do vključno predzadnjega gosta, tistega z indeksom n-2) in potem ugotavljamo srečo i-tega gosta tako, da ga primerjamo z gostoma i-1 in i+1. Zadnjega gosta obravnavamo posebej - gosta n-1 primerjamo z gostom n-2 in gostom 0.

    Trik, ki ga lahko uporabimo, da se temu izognemo, je preprost: gosta i primerjamo z gostoma i-1 in (i+1)%n. Dokler je i manjši od n-1, je (i+1)%n isto kot i+1. Pri nerodnem zadnjem gostu, ko je i enak n-1, pa je (i+1)%n enako n%n torej 0!

  2. Pogoji so malo zoprni: če je i-ti ženska, morata biti soseda moška. Če je i-ti moški, morata biti sosedi ženski. Vendar se da to povedati veliko preprostje: spol i-tega mora biti drugačen od spola sosedov. Torej: funkcija jeŽenska, ki smo jo napisali v prejšnji nalogi, mora vračati drugačno vrednost za soseda.

def stevilo_srecnezev(razpored): srecnih = 0 n = len(razpored) for i in range(n): srecnih += jeZenska(razpored[i-1]) != jeZenska(razpored(i)) != jeZenska(razpored[(i+1)%n]) return srecnih

C'est tout! Če se trikov ne domislimo, je rešitev nekoliko daljša, a v osnovi nič težja.

3. Razporedi

Trik je povedal vse: najprej naredimo seznam žensk in seznam moških. Potem jih izmenično dodajamo v seznam, na koncu pa oddamo še nepoparjene.

def razporedi(gostje): zenske = [] moski = [] for gost in gostje: if jeZenska(gost): zenske.append(gost) else: moski.append(gost) parov = min(len(zenske), len(moski)) razpored = [] for i in range(parov): razpored.append(moski[i]) razpored.append(zenske[i]) razpored += moski[parov:] + zenske[parov:] return razpored

V gornjem programu smo si privoščili le en mali trik, predzadnjo vrstico: eden od seznamov, ki ju prištevamo, moski[parov:] ali pa zenske[parov:] je v resnici prazen.

Nalogo rešimo še malo elegantneje.

def razporedi(gostje): zenske = [gost for gost in gostje if jeZenska(gost)] moski = [gost for gost in gostje if not jeZenska(gost)] razpored = [] for par in zip(moski, zenske): razpored += par parov = len(razpored)/2 razpored += moski[parov:] + zenske[parov:] return razpored

Gre seveda tudi krajše, celo v eni vrstici, a tale rešitev je še povsem elegantna in vsaj eno študentko sem videl pisati nekaj v tem slogu.

Sicer pa ta naloga nudi še nekaj lepih možnih rešitev. Spodnji bi naredil veliko krivico, če je ne bi objavil:

def razporedi(gostje): zenske = [gost for gost in gostje if jeZenska(gost)] moski = [gost for gost in gostje if not jeZenska(gost)] razpored = [] while zenske or moski: for x in zenske, moski: if x: razpored.append(x.pop()) return razpored

4. Enaka razporeda

Dva razporeda sta enaka, če enega lahko "preobrnemo" v drugega, tako, da postavimo vse goste od i-tega naprej na začetek. To nam da skoraj pravilno rešitev naloge:

def enaka_razporeda(razpored1, razpored2): for i in range(len(razpored2)): if razpored2 == razpored1[i:]+razpored1[:i]: return True return False

Težave imamo le še, če sta obe mizi prazni. V tem primeru sta namreč enaki, vendar ne uspemo priti do return True, saj se zanka nikoli ne izvede. To lahko rešimo tako, da na začetek funkcije, damo if not razpored1 and not razpored2: return True. Če hočemo krajši program, pa to zrinemo v return: četudi znotraj zanke nismo vrnili True, je pravilni odgovor še vedno True, če sta oba seznama prazna.

def enaka_razporeda(razpored1, razpored2): for i in range(len(razpored2)): if razpored2 == razpored1[i:]+razpored1[:i]: return True return not razpored1 and not razpored2

Nekoliko daljša, a hitrejša rešitev ne uporablja zanke (vsaj ne v Pythonu), ker ugane, koliko je treba zavrteti mizo:

def enaka_razporeda(razpored1, razpored2): if not razpored1: return not razpored2 prvi = razpored1[0] if not prvi in razpored2: return False kjePrvi = razpored2.index(prvi) return razpored1 == razpored2[kjePrvi:]+razpored2[:kjePrvi]

5. Hosts

Program ni vreden komentarja.

def read_hosts(): d = {} for line in file("hosts"): if "#" in line: line = line[:line.find("#")] line = line.strip() if line: name, ip = line.split() d[name] = ip return d

6. Iskanje URLjev

Tudi ta ne.

import re def find_URLs(s): return re.findall(r"\bhttps?://\S*", s)

Tudi, če ste izpustili \b na začetku (o tem se res nismo pogovarjali), ne bom hud. Nekateri ste nalogo rešili brez regularnih izrazov. Tudi prav.

마지막 수정됨: 수요일, 10 8월 2011, 10:21 AM