Python - Kineski astrološki kalendar


Primjena osnovnih struktura podataka, stringova, lista i n-torki, prikazaće se na primjerima realizacije programa za upotrebu uprošćenog kineskog astrološkog kalendara i pronalaženje liste prostih brojeva manjih od nekog zadanog broja (tzv. Eratostenovo sito).



Kineski astrološki kalendar

Kineski astrološki kalendar ima ciklus od 12 godina, koje su nazvane po životinjama, akterima jedne legende, kao što je prikazano na sljedećoj slici:



Algoritam programa je jednostavan: na osnovu godine rođenja osobe, određuje se njen astrološki znak prema indeksu, koji se računa na osnovu godine rođenja kao ostatak od deljenja (godina-1900)|12. Zatim se, prema indeksu iz tabele, biraju znak i lične karakteristike osobe, kao što je prikazano u sljedećoj tabeli:

1 Pacov Iskren, vrijedan, osjetljiv, intelektualac, druželjubiv
2 Vo Pouzdan, metodičan, skroman, rođeni vođa, strpljiv
3 Tigar Nepredvidljiv, buntovan, strastven, smio, impulsivan
4 Zec Dobar drug, dobar, tih, oprezan, umjetnički
5 Zmaj Jak, samouvjeren, ponosan, odlučan, odan
6 Zmija Dubokouman, kreativan, odgovoran, miran, usmjeren
7 Konj Veseo, dovitljiv, perceptivan, pričljiv, otvoren
8 Koza Iskren, simpatičan, stidljiv, velikodušan, pažljiv
9 Majmun Motivator, radoznao, fleksibilan, inovativan, rješava probleme
10 Petao Organizovan, samouvjeren, odlučan, perfekcionista, revnostan
11 Pas Pošten, nepretenciozan, idealista, moralista, ležeran
12 Svinja Miroljubiv, vrijedan, povjerljiv, pun razumevanja, zamišljen

Za prikaz podataka iz tabele u programu koriste se dvije n-torke i dvanaest imenovanih konstanti s tekstom ličnih osobina pojedinih znakova. Jedna n-torka stringova je spisak naziva životinja, a druga spisak imenovanih konstanti s opisom osobina znakova zodijaka.

import datetime

# Inicijalizacija struktura podataka
astroloske_zivotinje = ('pacov', 'vo', 'tigar', 'zec', 'zmaj', 'zmija', 'konj',
                        'koza', 'majmun', 'petao', 'pas', 'svinja')

pacov = 'Iskren, vrijedan, osjetljiv, intelektualac, druželjubiv'
vo = 'Pouzdan, metodičan, skroman, rođeni vođa, strpljiv'
tigar = 'Nepredvidljiv, buntovan, strastven, smio, impulsivan'
zec = 'Dobar drug, dobar, tih, oprezan, umjetnički'
zmaj = 'Jak, samouvjeren, ponosan, odlučan, odan'
zmija = 'Dubokouman, kreativan, odgovoran, miran, usmjeren'
konj = 'Veseo, dovitljiv, perceptivan, pričljiv, otvoren'
koza = 'Iskren, simpatičan, stidljiv, velikodušan, pažljiv'
majmun= 'Motivator, radoznao, fleksibilan, inovativan, rješava probleme'
petao = 'Organizovan, samouvjeren, odlučan, perfekcionista, revnostan'
pas = 'Pošten, nepretenciozan, idealista, moralista, ležeran'
svinja = 'Miroljubiv, vrijedan, povjerljiv, pun razumevanja, zamišljen'

osobine = (pacov, vo, tigar, zec, zmaj, zmija, konj, koza, majmun,petao, pas, svinja)
# Određivanje znaka i ispis rezultata
# Pozdravna poruka

print('Program na osnovu godine rođenja pronalazi znak osobe', 
      'iz kineskog horoskopa i prikazuje njene lične sobine\n')

# Pronalaženje tekuće godine
tekuca_godina = datetime.date.today().year

kraj = False
while not kraj:

# Unos datuma rođenja
    godina_rodjenja = 0
    while godina_rodjenja < 1900 or \
        godina_rodjenja > tekuca_godina:
        godina_rodjenja = \
                int(input('Unesite datum rođenja osobe (samo godinu): '))

    # Prikaz rezultata
    broj_ciklusa = (godina_rodjenja - 1900) % 12
    print('Vaš znak u kineskom horoskopu je',\
        astroloske_zivotinje[broj_ciklusa],'\n')
    print('Vaše lične osobine su ...')
    print(osobine [broj_ciklusa])

    # Uslovni kraj programa
    odgovor = \
        input('\nDa li želite znak još neke osobe? (d/n): ')
    if odgovor == 'n':
        kraj = True

Prikaz koda iz gornjeg primjera izgledaće ovako:

Program na osnovu godine rođenja pronalazi znak osobe iz
kineskog horoskopa i prikazuje njene lične sobine

Unesite datum rođenja osobe (samo godinu): 1991
Vaš znak u kineskom horoskopu je koza 

Vaše lične osobine su ...
Iskren, simpatičan, stidljiv, velikodušan, pažljiv

Da li želite znak još neke osobe? (d/n): d
Unesite datum rođenja osobe (samo godinu): 1992
Vaš znak u kineskom horoskopu je majmun 

Vaše lične osobine su ...
Motivator, radoznao, fleksibilan, inovativan, rješava probleme

Da li želite znak još neke osobe? (d/n): n
PS C:\Users\PC\OneDrive\Desktop>

Program provjerava unesenu godinu rođenja, koja mora biti između 1900. godine i tekuće godine, koju program pronalazi pomoću funkcije today() iz modula datetime.



Eratostenovo sito

Složeni brojevi se mogu predstaviti kao proizvod drugih brojeva, kao što je npr. broj 12=2∙2∙3, dok su prosti brojevi djeljivi samo s njima samima i brojem 1. Proste brojeve su poznavali i proučavali još antički matematičari, npr. Euklid je dokazao da je broj prostih brojeva beskonačan. Značaj prostih brojeva naglo je porastao u savremeno doba, jer se na njima zasnivaju važne računarske aplikacije, kao npr. kriptografski algoritmi, koji omogućavaju zaštitu informacija u javnoj računarskoj mreži.

Problem je što ne postoji jednostavan obrazac ili pravilo otkrivanja sljedećeg prostog broja, već se koristi neki metod sistematskog pronalaženja prostih brojeva u intervalu od interesa. Metod poznat još od antičkih vremena naziva se Eratostenovo sito (Sieve of Eratosthenes). Pronalaženje svih prostih brojeva manjih od nekog broja može se izvršiti provjerom djeljivosti svakog od brojeva iz intervala, ali bi to bilo veoma neefikasno. Eratostenovo sito jedan je od efikasnijih algoritama, a njegov osnovni oblik je:

  1. Napravi se lista svih brojeva od 2 do n.
  2. Počev od od prvog broja u listi (broj dva) označe se svi brojevi djeljivi sa dva, dok dva ostaje kao prost broj. Postupak se ponavlja sa sljedećim neoznačenim brojem, npr. m, označe se svi brojevi deljivi sa m, a on ostaje kao prost broj.
  3. Lista prostih brojeva je skup svih neoznačenih brojeva.

Ilustracija primjene Eratostenovog metoda u pronalaženja prva tri prosta broja prikazana je na slici u nastavku. Vidi se da algoritam počinje od spiska prirodnih brojeva (a) i prvog prostog broja 2 (b), čije sve množenike u spisku pronalazi i uklanja. Nakon toga prelazi na broj 3, sljedeći koji nije uklonjen i ponavlja isti postupak (c), zatim prelazi na broj 5 (d), itd. sve dok ne ostanu neoznačeni samo prosti brojevi.




Metod je realizovan programom u jeziku Python, koji koristi strukturu liste za predstavljanje niza brojeva u zadanom intervalu:

from math import sqrt, ceil

def sito(n):
    # Vraća listu svih prostih brojeva manjih od n
    brojevi = [False, False]+[i for i in range(2,n)]
    for k in range(2, ceil(sqrt(n))):
        if brojevi[k] is not False:
            prosej(k, brojevi)
    return samo_prosti(brojevi)

def prosej(k, lista):
    # Uklanja iz liste brojeve djeljive s k
    for i in range(2*k, len(lista), k):
        lista [i] = False

def samo_prosti(lista):
    # Izdvaja listu prostih brojeva
    prosti = []
    for i in lista:
        if i is not False:
            prosti.append(i)
    return prosti

print("Spisak svih prostih brojeva manjih od n")
n = int(input("Unesite n: "))
print("Prosti brojevi manji od", n,"su:\n",sito(n))

Inicijalno su u listi brojeva prikazani svi brojevi od 2 do zadanog broja kao potencijalni prosti brojevi. Označavanje ostalih brojeva koji nisu prosti brojevi vrši se na isti način, tako što se broj u listi zamjeni logičkom vrijednošću False. Da bi indeksi liste bili jednaki samim brojevima, prikazani su i brojevi 0 i 1, ali su odmah označeni vrijednošću False, tako da se ne smatraju prostim. Označavanje složenih brojeva, proizvoda tekućeg prostog broja, vrši se funkcijom prosej(), a izdvajanje konačne liste neoznačenih prostih brojeva vrši pomoću funkcije samo_prosti().


Primjer izvršavanja programa za pronalaženje prostih brojeva manjih od 50 je:

Spisak svih prostih brojeva manjih od n
Unesite broj n: 50
Prosti brojevi manji od 50 su:
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]