[ a1234567 @ 09.12.2019. 02:58 ] @
Za ambiciozne pyhtoniste početnike materijala na engleskom koliko hoćeš, ali na srpskom slabo. Pa evo da ja kao isti takav početnik nešto doprinesem po tom pitanju, dok se ovi iskusniji ne reše da stvar preuzmu u svoje ruke.

U tu svrhu sam rešio da postavljam ovde zadatke iz knjige po kojoj radim, pa možda još nekom bude od koristi. Dakle, to je knjiga Al Sweigart: Automate The Boring Stuff With Python - Practical Programming For Total Beginners (No Starch Press, 2019). Da bi bilo zanimljivije, zamislio sam da postavim prvo output na ekranu koji treba da proizvede program. Na osnovu njega bi trebalo napisati kod. Naravno, u početku su to (za mnoge ovde) jednostavne stvari, ali kasnije će siguran sam naići i prave poslastice, da ne kažem korisne komplikacije :)

Koga bude zanimalo, nek postavi ovde svoje rešenje. A ja ću posle nekoliko dana postaviti i rešenje iz knjige, pa da uporedimo. Vidim da često pominju kako je isti zadatak moguće u pythonu rešiti na više načina, pa da vidimo koliko takvih rešenja ima. To je verujem odlična lekcija za proširivanje programerskih vidika :)

Eto zabave za sve prave i wannabe pythoniste. Uživajte!
[ a1234567 @ 09.12.2019. 03:04 ] @
Dobro, posle akademskog uvoda, evo i konkretnog zadatka za danas.

Zadatak broj 1: Pogađanje zamišljenog broja

Ispis ekrana je sledeći. Koji je kod?

Zamislio sam jedan broj između 1 i 20.
Šta misliš koji je?

Unesi neki broj: 4
Tvoj broj je suviše mali.

Unesi neki broj: 17
Tvoj broj je suviše mali.

Unesi neki broj: 20
Tvoj broj je suviše velik.

Unesi neki broj: 18
Tvoj broj je suviše mali.

Unesi neki broj: 19
Bravo majstore! Pogodio si moj broj u 5 pokušaja!
[ a1234567 @ 09.12.2019. 03:13 ] @
Da bi posao bio lakši, evo početnih redova koda:

# Ovo je igra pogađanja brojeva.
import random
tajniBroj = random.randint(1, 20)
print('Zamislio sam jedan broj između 1 i 20.')

E sad je pesma :)
[ mjanjic @ 09.12.2019. 23:46 ] @
To možeš i u JS u nekoliko linija koda, Python je interesantan za nešto ozbiljnije, tipa programčić koji će da predvidi koji ćeš broj uneti ako te pita da uneseš broj između 1 i 20 :)
[ a1234567 @ 10.12.2019. 00:57 ] @
E dobro, pošto nas je Janjić ohrabrio (hvala mu!), možemo da krenemo dalje.

Ovde sam postavio rešenje zadatka broj 1.
[ a1234567 @ 10.12.2019. 01:44 ] @
I da ne dangubimo, evo odmah i zadatka broj 2, koji se tiče korišćenja funkcija.

Reč je o nizu brojeva nazvanom "3x+1 problem" ili "Collatzov niz" (nazvan po nemačkom matematičaru Lotharu Collatzu, 1910-1990). Ja kad sam prvi put pročitao zadatak, nije mi baš bilo jasno, jer sam još od osnovne škole alergičan na matematiku :))), ali na drugo čitanje se malo razbistrilo. A zadatak je sledeći:

Napiši funkciju u nazovi je collatz(). Ona ima jedan parametar nazvan broj. Funkcija radi tako što za neki zadati broj, ako je paran, računa broj // 2 vrednost. Ako je uneti broj neparan, tada collatz() izračunava 3 * broj + 1 vrednost.

Kad si napravio tu funkciju, napiši program koji ti omogućuje da uneseš bilo koji pozitivan integer i potom stalno poziva funkciju collatz() na taj broj, sve dok funkcija ne dobije na kraju vrednost 1.

Neverovatno ili ne, ovo radi za svaki integer, jer pre ili kasnije, koristeći ovaj metod stižemo do 1! Čak ni matematičari nemaju pojma zašto je to tako. Zato se Collatzov niz naziva i "najjednostavniji nerešivi matematički problem".

Ne zaboravi da vrednost unetu na input() kovertuješ u integer pomoću int() funkcije. Inače će ostati string vrednost.

Hint: Integer broj je paran ako broj % 2 == 0, a neparan je ako broj % 2 == 1.

I na kraju, ispis programa na ekranu je nešto ovako:

Unesi broj:
3
10
5
16
8
4
2
1


Ajd sad, srećna radnja pythonisti.

PS. Janjić može ovo da rešava i u JS (al na drugom topiku), pa da uporedimo.

[ Branimir Maksimovic @ 10.12.2019. 14:42 ] @
U matematici se konvergiranje ka nekom broju stalno koristi. Recimo najpoznatija je newton rafson metoda konvergencije tangente ka 0 zato
sto se koristi za izracunavanje deljenja preko mnozenja i sabiranja u svrhu optimizacije na Intel procesorima. Imas neki moj uradak na podforumu
programiranje u asembleru.
[ a1234567 @ 11.12.2019. 01:03 ] @
Hvala, Branimire, na poruci.
Imaš li rešenje za postavljeni zadatak?
[ Branimir Maksimovic @ 11.12.2019. 06:51 ] @
Ja rezignirano odbijam da pisem python, eto ti Rust:

Code:

fn main()->Result<(),String> {
    let args:Vec<_> = std::env::args().collect();
    let collatz = |n:i64|->i64 {
        if n & 1 == 1 {
            3*n+1
        } else {
            n/2
        }
    };
    let mut n = args[1].parse::<i64>().unwrap();
    while n != 1 { 
        println!("{}",n);
        n = collatz(n); 
    }
    Ok(())
}


Code:

~/examples >>> ./collatz 3                                                                                                                                                                                      
3
10
5
16
8
4
2

[ bojan_bozovic @ 11.12.2019. 07:21 ] @
Evo, u Adi.

Code:

with Ada.Text_IO;
with Ada.Integer_Text_IO;

use Ada.Text_IO;
use Ada.Integer_Text_IO;

procedure Collatztest is
   procedure Collatz (Arg : in out Integer) is
   begin
      if (Arg mod 2) = 0 then
         Arg := Arg / 2;
      else
         Arg := 3 * Arg + 1;
      end if;
      Ada.Integer_Text_IO.Put (Arg);
   end Collatz;
   Argument : Integer;
begin
   Ada.Text_IO.Put_Line ("Unesi celobrojnu vrednost:");
   Ada.Integer_Text_IO.Get (Argument);
   while Argument /= 1 loop
      Collatz (Argument);
   end loop;
   Ada.Text_IO.New_Line;
end Collatztest;



Moze i kao taj Rust kod da radi, malo drugaciji bi kod bio, uz Ada.Command_Line


[Ovu poruku je menjao bojan_bozovic dana 11.12.2019. u 09:14 GMT+1]
[ a1234567 @ 11.12.2019. 08:22 ] @
Citat:
Ja rezignirano odbijam da pisem python, eto ti Rust:

Branimire, ko/šta te tako rezigniralo!?
Python je baš lep jezik :)


Citat:
Evo, u Adi.

Hvala, Bojane na trudu. Nisam probao, ali verujem da radi.

Jedino se pythonisti ne oglašavaju :)
Ali dobro, dok pripale mašinu, pa dok krenu... mi već na zadatku broj 5! :))
[ Branimir Maksimovic @ 11.12.2019. 10:50 ] @
"Branimire, ko/šta te tako rezigniralo!?"

Brzina Pythona. Ako hoces nesto ozbiljno da uradis
sve moras da radis preko nekog drugog jezika.
Python koristis samo kao lepak poziva f-ja drugog jezika.
[ a1234567 @ 11.12.2019. 14:21 ] @
Dobro je, ja sam onda bezbedan. Dok ne stignem dotle, (ako ikada?) ima još dosta vode mutnim Dunavom da proteče. :)
[ Branimir Maksimovic @ 11.12.2019. 20:01 ] @
a vidi haskell tek sto je lep ;)

Code:

import System.Environment

main = do
    (n:[]) <- getArgs
    let callatz n = if n `mod` 2 == 0 then n `div` 2 else n * 3 + 1
        go n | n /= 1 = do
                   print n
                   go $ callatz n
             | otherwise = return n
    go $ read n


E sad napisi ti u pitonu...
[ a1234567 @ 12.12.2019. 03:13 ] @
Pre svega je kratko, a ja volim minimalizam :)

Mada nisam siguran da je baš po standardu pisanje te petlje if - then u jednom redu. Zbog čitljivosti koda. Barem koliko sam shvatio to ne preporučuje python "pravopis".

Moje rešenje za zadatak br. 2 dajem u posebnom postu...
[ a1234567 @ 12.12.2019. 03:14 ] @
Moje rešenje za zadatak br. 2: Collatzov niz možete pronaći
na ovom linku

Ima li još koje?
[ Branimir Maksimovic @ 12.12.2019. 05:17 ] @
Kad vec nitpikujes za if, ne ide ti print u collatz, to treba da bude f-ja koja obracunava vrednosti i ne radi nista vise
osim toga to radis redundantno.

[ a1234567 @ 12.12.2019. 06:19 ] @
Hvala na komentaru. Početničke greške. Kao što i dolikuje jednom pravom početniku

Bože, kako je lepo biti početnik! Rasterećen si opsesije da moraš biti savršen.
To valjda dođe kasnije
[ a1234567 @ 12.12.2019. 06:44 ] @
Evo probao da izvadim print funkciju izvan if...else statement, ali ne radi, jer naravno više ne prepoznaje promenljivu "rezultat"
Daj primer na šta konkretno misliš. Da nešto naučimo.
[ a1234567 @ 12.12.2019. 07:44 ] @
Evo stiže i zadatak broj 3: Nabrajanje!
Sasvim je jednostavan.
Unesemo četiri artikla i program ih na kraju izlista. S tim što iza svakog ubaci zarez, a pre poslednjeg artikla stavi veznik "i", kao što je i red.

Evo ispis ekrana. Boldom je označen unos, a plavim konačni ispis.

Unesi četiri artikla
prvi: so
drugi: biber
treći: hleb
cetvrti: voda
so, biber, hleb i voda


Naravno, ovo u Rustu ne mož da uradiš ni u ludilu, a o Adi i Haskellu ne vredi ni govoriti :D


[ Panta_ @ 12.12.2019. 08:19 ] @
Citat:
Evo probao da izvadim print funkciju izvan if...else statement, ali ne radi, jer naravno više ne prepoznaje promenljivu "rezultat"
Daj primer na šta konkretno misliš. Da nešto naučimo.


Dovoljno je:
Code:
if nekiBroj % 2 == 0:
    return nekiBroj // 2
else: 
    return nekiBroj * 3 + 1

ili 

nekiBroj // 2 if nekiBroj % 2 == 0 else nekiBroj * 3 + 1

Malo drugaciji primer:
Code:
from typing import Iterator

def collatz(number: int) -> Iterator[int]:
    while number != 1:
        number = number // 2 if number % 2 == 0 else number * 3 + 1
        yield number

try:
    user_input = int(input('Enter some number: '))
    for num in collatz(user_input):
        print(num)
except ValueError as err:
    print(f'Value must be an integer.\n{err}')
[ a1234567 @ 12.12.2019. 09:09 ] @
Ja napravio program sa 12 redova, Panta ga slupao u jednom!!!
Šta reći do -- genije!

PANTU ZA PREDSEDNIKA

[ djoka_l @ 13.12.2019. 11:36 ] @
Ja sam imao sličnu ideju kao Panta, a pošto sam manijak za testiranje, program je morao da radi ispravno bez obzira na argument. Pošto je trebalo naći sekvencu, meni je bilo logično da vratim listu...
Code:
def colatz(n):

  lista = [n]
  try:
    if (n != int(n) or n<1):
      raise ValueError
  except ValueError:
    lista.append("Error: positive integer expected")
    return lista

  while (n>1):
    if(n%2==0):
      n=int(n/2)
    else:
      n=int(3*n+1)
    lista.append(n)
  return lista

print(colatz(1))
print(colatz(2))
print(colatz(10))
print(colatz(1.5))
print(colatz("a"))
print(colatz(-1))


Citat:
[1]
[2, 1]
[10, 5, 16, 8, 4, 2, 1]
[1.5, 'Error: positive integer expected']
['a', 'Error: positive integer expected']
[-1, 'Error: positive integer expected']
[ a1234567 @ 13.12.2019. 12:11 ] @
Apdejtovana Pantina verzija, sad neko može da unese i frižider, a ne negativan broj, neće zabagovati!
Svaka čast, mastore.

Ubacio i tvoje i Pantino rešenje u github

Nego da ja ovde stavim i rešenje za zadatak broj 3.
To je lako, al čisto da se nađe.



[Ovu poruku je menjao a1234567 dana 13.12.2019. u 13:58 GMT+1]
[ a1234567 @ 13.12.2019. 12:19 ] @
Vreme leti, a mi korak po korak, stigosmo i do četvrtog zadatka.
Za ove što vole kockarnice, prava poslastica. I to besplatna. Ne moraš posle da se vadiš :)

Daklem:

Zadatak 4: Pismo/glava

Za ovu vežbu ćemo pokušati da uradimo jedan eksperiment. Ako baciš novčić 100 puta i upišeš jedno P za „pismo“ i jedno G za „glavu“, napravićeš niz koji će izgledati otprilike ovako: “PPPPGGGGPP”. Ako pitaš drugara da napiše jedan takav niz, bez bacanja novčića, verovatno će krenuti da naizmenično stavlja „glave“ i „pisma“, nešto slično ovome: “PGPGPPGPGG”, što se ljudskom oku čini kao jedan nasumičan niz. Ali on nije matematički nasumičan. Tako čovek verovatno nikada neće napisati šest „glava“ ili šest „pisama“ u nizu, iako je vrlo verovatno da se to dogodi kada zaista bacamo novčić. Mi ljudi smo predvidljivo loši u proceni kada je u pitanju nasumičnost.

E kad ovo sve znamo, tvoj je zadatak da napišeš program koji će umesto nas utvrditi koliko puta se šest „glava“ ili šest „pisama“ zaista javlja u jednom nizu od većeg broja bacanja novčića. Tvoj program će tako ovaj eksperiment podeliti u dva dela: u prvom delu generiše listu nasumično dobijenih „pisama“ i „glava“, a u drugom delu proverava ima li i koliko nizova u njemu. Sav taj kod stavi u petlju koja će ovaj eksperiment ponoviti 10.000 puta, tako da utvrdimo koji procenat bačenih novčića sadrži niz od šest „pisama“ ili „glava“. Kao hint, napomenuću da će funkcija random.randint(0, 1) dati vrednost 0 u 50% odsto slučajeva, a vrednost 1 u ostalih 50% slučajeva.

Možeš krenuti od ovog obrasca:

Code:
import random
brojNizova = 0
for brojEksperimenata in range(10000):
    # Kod koji pravi listu od 100 glava/pismo vrednosti.

    # Kod koji proverava postoji li niz od 6 „pisama-glava“.
print('Šanse za niz: %s%%' % (brojNizova / 100))

Naravno, ovo je samo procena, ali 10.000 pokušaja je solidan uzorak.
Ukoliko znaš matematiku, mogao bi da izračunaš procente i uštediš sebi muku pisanja programa. Ali opšte je poznato da su programeri vrlo loši matematičari.
[ djoka_l @ 13.12.2019. 23:16 ] @
Programeri MORAJU da znaju verovatnoću i još neke grane matematike (na primer algebru, logiku i teoriju skupova).
Pošto su bacanja novčića međusobno nezavisni događaj, svako bacanje ima verovatnoću od 1/2 da padne pismo ili glava.

U prvom bacanju u nekom nizu verovatnoća je 1 da će pasti pismo ili glava (siguran događaj), u svakom sledećem bacanju vefrovatnoća da će pasti ista strana kau u prvom je 1/2, pa je verovatnoća da će pasti 6 puta za redom ista strana 1/32 (32=2**5), odnosno u 100 bacanja očekuje se približno tri niza od po šest pisama ili glava (100/32 = 3.125)

Moj profesor programiranja sa faksa je imao običaj da kaže: "Čuvaj se Monte Karla, kako grada, tako i metode".

Ako te zanima verovatnoća, evo jednog malo težeg zadatka sa https://projecteuler.net/ (zadatak 205)
Aca ima 9 četvorostranih kockica za igru (tetraedara) na čijim su stranicama brojevi 1,2,3 i 4
Boban ima 6 šestostranih (normalnih) kockica sa brojevima 1-6 na stranama.

Aca i Boban bacaju istovremeno kockice i pobednik je onaj koji dobije veći zbir.
Koja je verovatnoća da će Aca da pobedi? Dati verovatnoću na 7 decimala.

rešenje je 0.5731441

Zadatak je rangiran sa težinom 15% (zadaci imaju težinu od 5-100% u koracima po 5)
[ a1234567 @ 14.12.2019. 02:23 ] @
Ne znam šta moraju, ali eto Sweigart kaže da slabo znaju :)
A završio je i sam computer science.
Inače, deluje mi kao jedna baš zanimljiva personality
pre svega zato što je toliko stvari postavio na svom sajtu besplatno

Zanimljiv ti je taj sajt sa problemima koji si linkovao. Vidim prvi problem rešilo skoro milion ljudi. Međutim, kako dalje, rapidno opada broj.

Inače, bacao novčić po 100 puta i evo rezultata iz tri serije:

1 glava u nizu - 12
1 pismo u nizu - 5
2 glave u nizu - 7
2 pisma u nizu - 12
3 glave u nizu - 4
3 pisma u nizu - 6
4 glave u nizu - 1
5 pisama u nizu - 1
6 pisama u nizu - 1
----------------------
1 glava u nizu - 17
1 pismo u nizu - 14
2 glave u nizu - 5
2 pisma u nizu - 11
3 glave u nizu - 3
3 pisma u nizu - 1
4 glave u nizu - 1
5 pisama u nizu - 1
8 glava u nizu - 1
8 pisama u nizu - 1
-----------------------
1 glava u nizu - 13
1 pismo u nizu - 10
2 glave u nizu - 6
2 pisma u nizu - 8
3 glave u nizu - 2
3 pisma u nizu - 5
4 glave u nizu - 3
4 pisma u nizu - 1
5 pisama u nizu - 1
7 glava u nizu - 1
[ a1234567 @ 15.12.2019. 03:41 ] @
Dok čekamo odgovore ambicioznih pythonista, imam jedno pitanje.
Danas na Sololearn challenge jedno od pitanja je bilo sledeće:

x = [[0], [1]]
print(len('a'.join(list(map(str, x)))))

rešenje je 7

Međutim, meni nikako nije jasno kakva je to magija u pitanju.
Jel može neko da razjasni misteriju?

Pre svega mi ovo "map" zadaje problem, jer ne razumem šta ovde radi. Gledao nek primere i objašnjenje, ali nije mnogo pomoglo u ovom slučaju.
[ tuxserbia @ 15.12.2019. 11:32 ] @
Možda te zbunjuju duple, namerno stavljene uglaste zagrade?

Probaj primer bez njih

Code:

x = [0, 1]


Ako te zbunjuje kompletna linija, uvek možeš da razdvojiš funkcije koje pozivaš

Code:


x = [[0], [1]]
print(len('a'.join(list(map(str, x)))))


x = [[0], [1]]
print('a'.join(list(map(str, x))))


x = [[0], [1]]
print(list(map(str, x)))

[ Panta_ @ 15.12.2019. 11:41 ] @
Citat:
Pre svega mi ovo "map" zadaje problem, jer ne razumem šta ovde radi.

Izvršava str za svaku stavku iz liste x, npr. str(x[0]), str(x[1]).

Code:

def add(x, y):
    return x + y

list(map(add, [1, 2, 3], [4, 5, 6]))
[5, 7, 9]

list(map(lambda x, y: x+y, [1, 2, 3], [4, 5, 6]))
[5, 7, 9]
[ Branimir Maksimovic @ 15.12.2019. 11:55 ] @
Koliko je python pozajmio iz funkcionalnog ptogramiranja:

Code:

{- x = [[0], [1]]
print(len('a'.join(list(map(str, x))))) -}
main = do
  let x = [[0],[1]]
  print $ concat $ "a":map show x

[ Branimir Maksimovic @ 15.12.2019. 12:20 ] @
Samo sto Haskell to moze na vise nacina:
Code:

main = do
  let x = [[0],[1]]
  (print.length.concat) $ "a":map show x


ili ovako:

Code:

main = do
  let x = [[0],[1]]
  (print.length) $ 'a':(concat $ map show x)


[ a1234567 @ 15.12.2019. 16:41 ] @
Citat:
tuxserbia:
Možda te zbunjuju duple, namerno stavljene uglaste zagrade?

Probaj primer bez njih
x = [0, 1]

Razumeo sam da se radi o listi koja u sebi ima dve liste od jednog člana.
Ako uklonim zagrade, onda je to jedna lista [0, 1] i rezultat je drugačiji:

0a1
len = 3

Citat:

Ako te zbunjuje kompletna linija, uvek možeš da razdvojiš funkcije koje pozivaš

Odlična ideja. Hvala!

Code:

x = [[0], [1]]
print(list(map(str, x)))

>>> ['[0]', '[1]']


Code:

print('a'.join(list(map(str, x))))

>>> [0]a[1]


i na kraju:

Code:

print(len('a'.join(list(map(str, x)))))

>>>7


Pa jel moguće da ga na kraju čita kao string '[0]a[1]' koji ima 7 karaktera!?




[ sneguljko @ 15.12.2019. 19:05 ] @
Gledam ovo pa me sramota koliko malo znam. Tri dana sam učio payton, dobio online sertifikat.... i MISLIO SAM da nešto znam. Bruka. Moram još da bistrim vodu. Sad ću jednu fuka vruću pa da se bacim na video tutorijale ili pdf na srpskom, videću. :) :(
[ a1234567 @ 16.12.2019. 01:51 ] @
Ako ti je za utehu, nisi jedini.
Ali dan po dan, naučićemo i nas dvojica nešto. :)

Evo vežbe radi jedan ne suviše težak zadatak:

Napravi program u kojem korisnik prvo unese tri integera, a potom ih program ispiše sortirane po veličini (od najmanjeg do najvećeg). Koristi min i max funkciju da nađeš najmanji i najveći broj. Srednju vrednost ćeš utvrditi računajući zbir sve tri vrednosti i onda od njega oduzeti najmanju i najveću.

Eto, probaj pa da vidimo kakva ćemo rešenja pronaći.

Ako zapne, a neće, ja sam moje rešenje stavio ovde:

[Ovu poruku je menjao a1234567 dana 16.12.2019. u 03:27 GMT+1]
[ Branimir Maksimovic @ 16.12.2019. 07:30 ] @
Hm malo mi je to glupo da prvo racunas zbir 3 vrednosti a onda da oduzimas dve. Zar srednja vrednost nije sum(niz)/len niz?
[ a1234567 @ 16.12.2019. 08:09 ] @
Koliko ja razumem, tvojim metodom ćemo dobiti srednju vrednost

4 + 7 + 8 = 19 / 3 = 6.3333

a nama treba srednji broj po veličini, dakle 7
[ Branimir Maksimovic @ 16.12.2019. 08:21 ] @
ako znas najmanji i najveci preostali je srednji, ne treba ti tu nikakva matematika...
[ sneguljko @ 16.12.2019. 08:39 ] @
brano malo si zabrazdio, to je aritmetička sredina a ne traženi broj.
[ sneguljko @ 16.12.2019. 08:59 ] @
Rešio sam problem na identičan način :) Idemo nešto teže.
[ Branimir Maksimovic @ 16.12.2019. 09:31 ] @
Citat:
sneguljko:
brano malo si zabrazdio, to je aritmetička sredina a ne traženi broj.


Ma sad vidim ne znas koji je od a, b, c pa moras da racunas ;)
[ Branimir Maksimovic @ 16.12.2019. 09:32 ] @
Aj sad na ovu temu od n unetih brojeva naci max min i srednji ;)
To je malo teze ;)
[ sneguljko @ 16.12.2019. 09:47 ] @
0.o

uuuu al teškooooooo...
[ a1234567 @ 16.12.2019. 10:10 ] @
Code:
Sneguljko:
Rešio sam problem na identičan način :) Idemo nešto teže. 




Idemo

Štampanje tabele


Napiši funkciju printTabela() koja uzima listu lista stringova i prikazuje je na ekranu, tako da je svaka kolona pravilno poravnata udesno. Pretpostavićemo da svaka od unutrašnjih lista ima isti broj stringova. Na primer, vrednosti mogu ovako da izgledaju:

podaciTabela = [[‘Panta’, ‘Branimir’, ‘Sneguljko’, ‘a1234567’]
[‘python’, ‘haskell’, ‘turbo pascal’, ‘cbasic’]
[‘profi nivo’, ‘srednji nivo’, ‘osnovni nivo’, ‘nema nivo’]


Tvoja printTabela funkcija treba da isprinta sledeće:



Hint: Tvoj kod treba prvo da nađe koji je najduži string u svakoj od unutrašnjih lista, tako da bi kolona bila dovoljno široka da taj string stane u nju. Tu maksimalnu širinu svake kolone možeš da sačuvaš kao listu integera. printTabela() funkcija može da počne sa kolShir = [0] * len(podaciTabela), što će napraviti listu koja sadrži isti broj 0 vrednosti koliko ima i unutrašnjih lista u podaciTabela. Na taj način kolShir može da širinu najdužeg stringa smesti u podaciTabela[1] i tako dalje. Potom možeš da nađeš najveću vrednost u kolShir listi, kako bi utvrdio koji integer za širinu treba da proslediš rjust() string metodu.

Ajd sad...
[ Branimir Maksimovic @ 16.12.2019. 11:00 ] @
Evo u haskell-u, jer moze krace u pythonu ;)?

Code:

import qualified Data.Text as T
import Data.List 

main = do
    let podaciTabela = [["Panta", "Branimir", "Sneguljko", "a1234567"],
                    ["python", "haskell", "turbo pascal", "cbasic"],
                    ["profi nivo", "srednji nivo", "osnovni nivo", "nema nivo"]]
    let maxlen :: Int 
        maxlen = foldl (\m x->max m $ maximum $ map length x) 0 podaciTabela
    mapM_ (\x -> do mapM_ (\x->putStr $ (T.unpack $ T.justifyRight maxlen ' ' $ T.pack x) ++ " ") x
                    putStrLn "") $ transpose podaciTabela


Code:

~/examples/haskell >>> ./tabela                                                                                                                                                                                              
       Panta       python   profi nivo 
    Branimir      haskell srednji nivo 
   Sneguljko turbo pascal osnovni nivo 
    a1234567       cbasic    nema nivo 
[ a1234567 @ 16.12.2019. 11:05 ] @
Ne može. Nema šanse.
Prebacićemo te na profi nivo
[ sneguljko @ 16.12.2019. 14:35 ] @
teško. Ja sad vidim da je python suva matematika, a ja sam hteo da pravim prozore i nešto da mi skačka u okviru.
[ a1234567 @ 16.12.2019. 14:51 ] @
Nema u ovom zadatku matematike, samo slova, abeceda, a može i azbuka :)
[ Branimir Maksimovic @ 16.12.2019. 15:04 ] @
Citat:
sneguljko:
teško. Ja sad vidim da je python suva matematika, a ja sam hteo da pravim prozore i nešto da mi skačka u okviru.


pogledaj https://github.com/Nicotine-Plus/nicotine-plus
to je jedina python GUI aplikacija koju koristim...
[ djoka_l @ 16.12.2019. 20:03 ] @
Ako nekoga interesuje kako da se reši moj zadatak (euler.net zaadatak 205), postaviću ovde jedno moguće rešenje.
Ko još uvek želi da pokuša da ga reši, neeka preskoči ovaj post

Code:

#frequency of posible sums for 4 and 6 dices games
dice4sum = 36*[0]
dice6sum = 36*[0]

for d1 in range (1,5):
  for d2 in range (1,5):
    for d3 in range (1,5):
      for d4 in range (1,5):
        for d5 in range (1,5):
          for d6 in range (1,5):
            for d7 in range (1,5):
              for d8 in range (1,5):
                for d9 in range (1,5):
                  s = d1+d2+d3+d4+d5+d6+d7+d8+d9
                  dice4sum[s-1] += 1

for d1 in range (1,7):
  for d2 in range (1,7):
    for d3 in range (1,7):
      for d4 in range (1,7):
        for d5 in range (1,7):
          for d6 in range (1,7):
            s = d1+d2+d3+d4+d5+d6
            dice6sum[s-1] += 1

partsum = 0

#win probability for 4 dices player is:
#frequency of outcome n when 6 dices player has outcome lese then n
#divided by product of both total outcomes
for i in range (1,36):
  #calculate running sum of 6 dices games
  dice6sum[i] += dice6sum[i-1]
  #number of outcomes when player with 4 dices wins
  partsum += dice4sum[i]*dice6sum[i-1]

#print(dice4sum)
#print(dice6sum)
#print(partsum)

print(round(partsum/(4**9*6**6),7))
[ Panta_ @ 16.12.2019. 20:27 ] @
Citat:
Branimir Maksimovic:
Evo u haskell-u, jer moze krace u pythonu ;)?

Code:

import qualified Data.Text as T
import Data.List 

main = do
    let podaciTabela = [["Panta", "Branimir", "Sneguljko", "a1234567"],
                    ["python", "haskell", "turbo pascal", "cbasic"],
                    ["profi nivo", "srednji nivo", "osnovni nivo", "nema nivo"]]
    let maxlen :: Int 
        maxlen = foldl (\m x->max m $ maximum $ map length x) 0 podaciTabela
    mapM_ (\x -> do mapM_ (\x->putStr $ (T.unpack $ T.justifyRight maxlen ' ' $ T.pack x) ++ " ") x
                    putStrLn "") $ transpose podaciTabela


Code:

~/examples/haskell >>> ./tabela                                                                                                                                                                                              
       Panta       python   profi nivo 
    Branimir      haskell srednji nivo 
   Sneguljko turbo pascal osnovni nivo 
    a1234567       cbasic    nema nivo 


Ajde da probam sa dve linije Python koda:
Code:
for row in zip(*podaciTabela):
    print(' '.join(s.rjust(len(max(map(lambda x: x[1], podaciTabela)))) for s in row))
     
       Panta       python   profi nivo
    Branimir      haskell srednji nivo
   Sneguljko turbo pascal osnovni nivo
    a1234567       cbasic    nema nivo
[ Branimir Maksimovic @ 17.12.2019. 02:46 ] @
Samo sto ne odredjuje maksimalnu duzinu svih, nego samo duzinu jedne kolone...
[ a1234567 @ 17.12.2019. 02:54 ] @
Panto, hajde objasni taj kod. Sve si smućkao u jedan red, ko palačinku kad zaviješ. Protresi to malo

Sad gledam, lambda je no-name privremena funkcija, ali šta ti je ovo [1] pored x, koji deo podaciTabela to obuhvata? Liči mi na index kod liste, ali zašto baš 1? Ovako mi izgleda kao da mapira samo drugi član u svakoj listi. Jel to zato što odokativno vidiš da je "turbo pascal" najduži string, pa ne proveravaš ostale članove liste?

Ostalo ovako razumem:
map mu kaže da funkciju primeni na svaki član liste podaciTabela. I funkcija ide kroz drugi član svake liste.
max vraća najveću vrednost u iteratoru (ako mu je to pravi srpski prevod?), dakle, najduži string.
len daje broj karaktera tog najdužeg stringa.
rjust poravnava udesno za toliko koliko je dužina + onaj jedan spejs ' ' na početku. Ali šta ti je ovaj s? Verovatno frljoka varijabla, koja se pojavljuje i na kraju i preko row povezuje ime funkcije u prvom redu sa njenim statement u drugom.
join valjda dodaje taj jedan spejs svakom članu iteratora, tj. svakom članu tabele.

zip pravi tuple spajajući prve, druge, treće itd. članove različitih iteratora.

Ovako kad razložim mi je ponešto i jasno. Ali nema šanse da to ovako sklopim



[ Branimir Maksimovic @ 17.12.2019. 03:21 ] @
"ali zašto baš 1?"

Zato sto je u toj koloni najveca duzina, sto nije resenje zadatka. Trazi se maksimalna duzina svih ne samo jedne kolone.
[ a1234567 @ 17.12.2019. 03:37 ] @
Ma fušerira Panta. Odmah sam ga provalio :)
[ sneguljko @ 17.12.2019. 07:57 ] @
vi ste krejzi, meni mozak ne radi tako napredno. Mora da ste napredni.

------------------

Jel može sad neko da kaže, šta mi treba da se program hello world izvrši u prozoru a ne u terminalu. Jel komplikovano?

[Ovu poruku je menjao sneguljko dana 17.12.2019. u 09:59 GMT+1]
[ a1234567 @ 17.12.2019. 09:27 ] @
Kakvom terminalu?
Pa koristiš neki interpreter, ne terminal. Jednostavno je.

Sa instalacijom pythona valjda ide i IDLE interpreter ili shell. U njemu kucaš komande i u njemu se i izvršavaju.




Naravno kad je više linija, lakše je ukucati sve u običnom text fajlu. Za to ideš u IDLE meniju gore File > New (ili ctrl + N)
i otvoriš prazan fajl, kucaš (ako znaš šta) i u meniju Run > Run Module (ili F5) pokreneš program u IDLE i vidiš koju ti grešku javlja

Možeš i da instaliraš neki drugi interpreter. Vrlo je jednostavan ovaj
Mož da probaš online ili gore link za Download, pa instaliraš. I onda... pesma

Srećno!




[ sneguljko @ 17.12.2019. 09:56 ] @
ja sam na linuxu, sve ide preko terminala. Mislio sam eto da nacrtam jedan krug :) Kako ćeš tu kad je loša rezolucija.

---

vidi ovoooo :)

Code:

import turtle

t = turtle.Turtle()
t.circle(50)
[ a1234567 @ 17.12.2019. 10:03 ] @
Onda će morati linux majstori da te remontuju.
Ja sam prozordžija.
[ sneguljko @ 17.12.2019. 10:07 ] @
Od početka sam znao da ti nešto fali
[ Deunan @ 17.12.2019. 14:08 ] @
Citat:
sneguljko:
vi ste krejzi, meni mozak ne radi tako napredno. Mora da ste napredni.

------------------

Jel može sad neko da kaže, šta mi treba da se program hello world izvrši u prozoru a ne u terminalu. Jel komplikovano?

Treba ti neki compiler. Ja volim pyinstaller. Pyinstaller koristim na windowsu, nisam isprobavao na linuxu, ali bi trebalo da radi potpuno isto. Na kojem ga sistemu kompajliras, na tom ce da radi.

Ako koristis python 3.8, pyinstaller iz pip repo-a ima neki bug, skini ga ovako:
Code:
pip install https://github.com/pyinstaller/pyinstaller/archive/develop.tar.gz

Posle toga:
Code:
pyinstaller myapp.py --onefile

Pyinstaller ce sve da spakuje u jedan fajl u "dist" folderu (kreirace sam). U tom fajlu ti je ceo program i sve python skripte za izvrsenje. Ne moras da instaliras python na drugom sistemu da bi pokrenuo program. Kreirace i fajl "myapp.spec" gde mozes da podesavas: ikonu programa, fajlove koje da includuje...

Da bi imao graficke elemente (dugmice, input, select...), treba ti neka GUI biblioteka. Ja volim PyQt, imas jos Tkinter, Kiwi, ... (moraces sam da odlucis koja ti odgovara. Kao da nekog pitas sta je bolje: react.js, vue.js, angular...). Posto je Tkinter vec deo python-a, najbolje pocni malo sa njim. Recimo, kreiraj fajl myapp.py i kopiraj kod:
Code:
from tkinter import *

window = Tk()

window.title("Elitesecurity.org")
window.geometry('350x200')

lbl = Label(window, text="Hello")
lbl.grid(column=0, row=0)

def clicked():
    lbl.configure(text="Button was clicked !!")

btn = Button(window, text="Click Me", command=clicked)
btn.grid(column=1, row=0)

window.mainloop()

I pokreni. Kod je prilicno jednostavan, ali ako si ikad radio neki front end (javascript, android sdk, swift, kotlin...) vrlo lako bi trebalo da razumes kako funkcionise. Kad budes zavrsio, zapakuj ga:
Code:
pyinstaller myapp.py --onefile

[ gglavni @ 17.12.2019. 16:13 ] @
@Deunan



Izvinjavam se, promenio sam nik jer sam imao problem, zaboravio sam mail, ja sam sneguljko.
[ Deunan @ 17.12.2019. 16:48 ] @
Kad hoces da instaliras python pakete ne ulazis u python shell. Samo otvoris cmd ili powershell i kucas.
"pip" je packet manager, kao composer za php, ili npm za js.
Vrati se jos malo na pocetne stvari, ne vredi preskakati osnove, samo ces da se pogubis. Znam da nekad zelis samo da "krenes da radis", ali cesto to oduzima vise vremena nego da se uci redom. Sve je to jednostavno.

Tkinter mozes da koristis bez instaliranja ako te interesuju desktop aplikacije. Prekopiraj gornju skriptu i pokreni program kao i do sad sto si radio.
[ gglavni @ 17.12.2019. 17:02 ] @
Hvala. Nisam dodao putanju u PATH, pip mi je već bio instaliran, ali ko što kažem problem je bio path do njega.

Sad ću da probam program.

---

radi ovaj prozorčić. Ali me nervira pyinstaller ovaj, trebao bi hello world da convertuje u exe valjda... Neće. a i "auto py to exe" neće da se instalira, izgleda da je problem verzija 3.8 pythona, pa još nisu sredili, možda sam trebao da instaliram stariju verziju pythona.

[Ovu poruku je menjao gglavni dana 17.12.2019. u 18:16 GMT+1]
[ gglavni @ 17.12.2019. 19:22 ] @
I šta je sad ovo??? Ne može običan hello world da kompajlira...

evo slike, gde grešim, pomagajte.

[ Deunan @ 17.12.2019. 20:54 ] @
Zasto koristis python 2.7?
To je skoro drugi jezik i bukvalno se "penzionise" za 14 dana . Debagovati to nema nikakvog smisla.

[ gglavni @ 17.12.2019. 21:12 ] @
na 3.8 mi još gore radi. Probaću ponovo 3.8 ali izlaze mi silne crvene greške kad nešto kompajliram.
---
nisam zabeležio koje, ali probao sam ovako, instalirao sam pyinstaller i to je dobro prošlo, a onda 'pyinstaller helloworld.py' iz komandne linije i krene da kompajlira i silne greške, probaću sutra za danas je dosta.
[ Deunan @ 17.12.2019. 21:44 ] @
Kako si instalirao pyinstaller?
Ako si instalirao standardno "pip install pyinstaller", ima neki bug.
Moraces da uninstaliras "pip uninstall pyinstaller" pa da instaliras ovako:
Code:
pip install https://github.com/pyinstaller/pyinstaller/archive/develop.tar.gz


P.S. Uostalom, sto ne vrati na python 3.7, gde nadje 2.7. Ima 10 godina.

[Ovu poruku je menjao Deunan dana 17.12.2019. u 22:57 GMT+1]
[ gglavni @ 17.12.2019. 21:55 ] @
Evo sad probam tako kao što si rekao. Javljam za koji minut.
----

RADI !!!

kad udjem u dist folder onda radi. To je izgleda ceo program a ne samo jedan fajl. Probao sam da ga prebacim van foldera, onda ne radi. Ukapirao sam suštinu.



p.s. Deunan imaš piće od mene. A svakako će koristiti svima, po jedan dinar svako. :)

p.s.2 Hebi ga vratih na 2.7 kao prosto program manje zahtevan, a ono karambol. Valjda će da isprave grešku na default instaliranom pyinstalleru, inače mora svako da gituje.
[ Deunan @ 17.12.2019. 22:02 ] @
Ako hoces jedan fajl moras da uneses --onefile:
Code:
pyinstaller myapp.py --onefile

[ gglavni @ 17.12.2019. 22:09 ] @
E strava. Čovek si nema dalje.
[ a1234567 @ 19.12.2019. 08:48 ] @
Pošto je sve instalirano što se instalirati može, da se vratimo na zadatak 4, koji je još uvek pending

Zadatak 4: Pismo/glava

Za ovu vežbu ćemo pokušati da uradimo jedan eksperiment. Ako baciš novčić 100 puta i upišeš jedno P za „pismo“ i jedno G za „glavu“, napravićeš niz koji će izgledati otprilike ovako: “PPPPGGGGPP”. Ako pitaš drugara da napiše jedan takav niz, bez bacanja novčića, verovatno će krenuti da naizmenično stavlja „glave“ i „pisma“, nešto slično ovome: “PGPGPPGPGG”, što se ljudskom oku čini kao jedan nasumičan niz. Ali on nije matematički nasumičan. Tako čovek verovatno nikada neće napisati šest „glava“ ili šest „pisama“ u nizu, iako je vrlo verovatno da se to dogodi kada zaista bacamo novčić. Mi ljudi smo predvidljivo loši u proceni kada je u pitanju nasumičnost.

E kad ovo sve znamo, tvoj je zadatak da napišeš program koji će umesto nas utvrditi koliko puta se šest „glava“ ili šest „pisama“ zaista javlja u jednom nizu od većeg broja bacanja novčića. Tvoj program će tako ovaj eksperiment podeliti u dva dela: u prvom delu generiše listu nasumično dobijenih „pisama“ i „glava“, a u drugom delu proverava ima li i koliko nizova u njemu. Sav taj kod stavi u petlju koja će ovaj eksperiment ponoviti 10.000 puta, tako da utvrdimo koji procenat bačenih novčića sadrži niz od šest „pisama“ ili „glava“. Kao hint, napomenuću da će funkcija random.randint(0, 1) dati vrednost 0 u 50% odsto slučajeva, a vrednost 1 u ostalih 50% slučajeva.

Ja sam sa ovo malo znanja uspeo da napravim prvi korak, to jest da izlistam prvih 100 bacanja:

Code:
import random

print('Koliko puta da bacim novčić?')
while True:
    odgovor = input()
    if odgovor.isdecimal():
        brojBacanja = int(odgovor)
        break
for i in range (1, brojBacanja):
    if random.randint(0, 1) == 0:
        baci = '1glava'
    else:
        baci = '0pismo'
    print(baci[0], end='')


i dobijem ovaj ispis na ekranu:

Koliko puta da bacim novčić?
100
011011011111111010011101101011011111000000001000110111011110010010010110100101111101110001101001000


E sad kako dalje? Kako da u ovom nizu od 100 bacanja izbrojim nizove od 6 ponavljanja!?
[ gglavni @ 19.12.2019. 11:53 ] @
lako je tebi da čitaš zadatke iz knjiga koji imaju rešenja i onda nas ovde tovariš. Ja još nisam ni junior ja sam jaje, a dal sam mućak ili plodonosno, videćemo za koji mesec kad malo proučim još knjige. Zeza me to što nemam strpljenje pa učim i C++ istovremeno.
[ tuxserbia @ 19.12.2019. 12:47 ] @
Code:

print (string.count(‘000000’))
print (string.count(‘111111’))



Sad ti reši gde je string.
[ a1234567 @ 19.12.2019. 16:39 ] @
Hvala tuxserbia na hintu.
Rešio.

Code:
import random

print('Koliko puta da bacim novčić?')
while True:
    odgovor = input()
    if odgovor.isdecimal():
        brojBacanja = int(odgovor)
        break

with open('pismo_glava.txt', 'a+') as file:
    for i in range (1, brojBacanja):
        if random.randint(0, 1) == 0:
            baci = '1'
            file.write(baci)
        else:
            baci = '0'
            file.write(baci)
file.close()

with open('pismo_glava.txt', 'r') as file:
    data = file.read()

print('Broj glava je:', data.count('000000'))
print('Broj pisama je:', data.count('111111'))


Na ekranu dobijem ovaj ispis:

Koliko puta da bacim novčić?
100000
Broj glava je: 800
Broj pisama je: 796


Ovaj kod bi sigurno mogao u tri reda da se spakuje.
Ali meni apsolutnom početniku srce puno i ovako kad sam ga rešio :)))
[ Deunan @ 19.12.2019. 18:26 ] @
Nema potrebe da kod pakujes u 2, 3... reda. Mnogo je vaznije da je razumljiv i efikasan.
Ti si verovatno zapisivao u fajl zato sto si to prethodno naucio :) Sto neko rece, "ako jedino znas da koristis cekic, svaki problem ti izgleda ko ekser".
Evo jedno resenje koje ce da razume i neko ko ne poznaje python, a koristi samo jednu "for" petlju:
Code:
import random

brojNizova = 0          # broj nizova od 6 istih
trenutniStatus = 0      # prethodni bacen status, pismo ili glava (0 ili 1)
brojPonavljanja = 0

for i in range(10000):
    rand = random.randint(0, 1)
    if trenutniStatus == rand:
        brojPonavljanja += 1
    else:
        trenutniStatus = rand
        brojPonavljanja = 1

    if brojPonavljanja == 6:
        brojNizova += 1
        brojPonavljanja = 0

print(f"Broj nizova: {brojNizova}")

[ a1234567 @ 20.12.2019. 01:33 ] @
Hvala na komentaru.

Zapisivao sam u fajl zato što nisam znao kako da posle te petnje dobijeni niz nula i jedinica stavim u neku varijablu,
pa da prebrojavam nizove sa count.
Bogami sam se i oko tog zapisivanja namučio dok nisam prokljuvio, ali sam tako valjda nešto i naučio.

Ono što mene buni kod tvog koda je da mi se čini da on broji samo niz od 6 ponavljanja, ili nula ili jedinica,
a ne pravi razliku koliko jednih koliko drugih.

Druga stvar o kojoj sam počeo da razmišljam kad sam napravio ovaj moj kod je kako da ga apdejujem :))
Naime, ako imam string
0011101011110000000101011111000111111111110000011
kako da pronađem koliko u njemu ima nizova od recimo 2, 3, 4, 5 i 6 istih karaktera?

Naravno, mogao bih sa
print('Broj glava je:', data.count('00'))
print('Broj glava je:', data.count('000'))
print('Broj glava je:', data.count('0000'))
print('Broj glava je:', data.count('00000'))

pa isto za jedinice, ali mora da ima neke elegantnije rešenje.
[ a1234567 @ 20.12.2019. 08:03 ] @
Moram da se podelim događaj

Danas naiđem na rečenicu

“MAN IS A ROPE
STRETCHED
BETWEEN THE
ANIMAL AND
THE SUPERMAN –
A ROPE OVER
AN ABYSS.”
Friedrich Nietzsche, Thus Spoke Zarathustra

koja mi treba, ali napisana redovno, a ne velikim slovima.
Ništa, šta ću, otvorim dokument i krenem da je prekucam. Posle prve reči zastanem i "programer" u glavi mi kaže... alo, prijatelju, šta to radiš!? pa jesmo već zaboravili na x.lower()!

I konvertujem je programski. Niko srećniji od mene, kez od uveta do uveta.

Posle pogledam, ima i funkcija capitalize. Sad sam i nju naučio.
Svakog dana u svakom pogledu...
[ Panta_ @ 20.12.2019. 09:51 ] @
Citat:
Naime, ako imam string
0011101011110000000101011111000111111111110000011
kako da pronađem koliko u njemu ima nizova od recimo 2, 3, 4, 5 i 6 istih karaktera?

Code:
for i in range(2, 7):
    print(f"{'0' * i} = {'0011101011110000000101011111000111111111110000011'.count('0' * i)}")

00 = 7
000 = 4
0000 = 2
00000 = 2
000000 = 1
[ a1234567 @ 20.12.2019. 14:51 ] @
Panto, samo ću reći - magija

Inače, postavio sam rešenja zadatka broj 4 ovde.
[ a1234567 @ 20.12.2019. 16:04 ] @
Ova tema, od kada sam je otvorio pre deset dana ima skoro 2500 pregleda.
Izgleda ima dosta onih koji gledaju sa strane, ali se ne hvataju tastature
Ne stidite se, slobodno se uključite, od mene sigurno više znate. Ja učim python eto cele dve nedelje

I zato evo nova šansa i novi zadatak za ove što vole da šifriraju i hakerišu!

Zadatak broj 5: Cezarova šifra

Jedan od prvih poznatih primera šifriranja koristio je Julije Cezar. Slao je pisana naređenja svojim generalima, ali nije želeo da ona padnu u neprijateljske ruke. Zato je razvio sistem koji će kasnije biti nazvan Cezarova šifra. A ideja je bila sasvim jednostavna (i zato je ovako kodiran tekst lako dešifrovati savremenim tehnikama), a sastojala se u tome da se svako slovo u originalnoj poruci pomeri za tri mesta u abecedi. Tako A postaje D, B postaje E, C postaje F itd. Poslednja tri slova abecede se tako pomeraju na početak, pa X postaje A, Y postaje B, a Z postaje C. Znakovi interpunkcije su ostajali nepromenjeni. Naravno, mi ćemo koristiti našu latinicu:

abcčćddžđefghijklljmnnjoprsštuvzž

Napiši program koji rešava Cezarovu šifru. Korisnik unosi poruku i broj slova za koliko će biti pomeranje kod šifriranja. Program zatim ispisuje šifriranu poruku. Vodi računa da program šifrira i velika i mala slova. Tvoj program bi takođe trebalo da podržava pomeranje za negativan broj, tako da može i da kodira i da dekodira poruke.

Ajde sad. Lako je )

[Ovu poruku je menjao a1234567 dana 20.12.2019. u 18:14 GMT+1]
[ BogOtac @ 20.12.2019. 16:22 ] @
Mene zanima (da vi mene kažete) zašto, kad kompajliram program u .exe jako sporo se pokreće.
[ a1234567 @ 20.12.2019. 16:39 ] @
Imam i ja jedno pitanje za tebe.

Što ne otvoriš posebnu temu, pa pitaš, ko što je red?
Ova je za zadatke, kao što piše na ulazu :)
[ BogOtac @ 20.12.2019. 16:45 ] @
Pa zgodno mi je ovde, pre će da vide ljudi. :)
[ a1234567 @ 21.12.2019. 16:25 ] @
Evo izborih se nekako sa ovim zadatkom, doduše polovično.


Code:
# Cezarova šifra
poruka = input('Unesi poruku: ')
pomeranje = input('Za koliko mesta pomeriti slova? ')

abc = ['a', 'b', 'c', 'č', 'ć', 'd', 'dž',
       'đ', 'e', 'f', 'g', 'h', 'i', 'j',
       'k', 'l', 'lj', 'm', 'n', 'nj', 'o',
       'p', 'r', 's', 'š', 't', 'u', 'v', 'z', 'ž']

for i in poruka:
    if i in abc:
        ind = abc.index(i)
        ind2 = ind + int(pomeranje)
        if ind2 > 26:
            ind2 = ind2 - 30
        else:
            ind2 = ind2
        slovo = abc[ind2]
        print(slovo, end='')

    else:
         i == i
         slovo = i
         print(slovo, end='')

Ispis na ekranu:


>>> Unesi poruku: Ovo je poruka.
>>> Za koliko mesta pomeriti slova? 4
Obš mi tšuanć.

>>> Unesi poruku: Obš mi tšuanć.
>>> Za koliko mesta pomeriti slova? -4
Ovo je poruka.


Radi i šifrovanje i dešifrovanje.
Ali postoji problem sa našim slovima koja imaju dva znaka: lj, nj, dž.
Jer petlja ide slovo po slovo, pa ih tretira odvojeno kod dešifrovanja.
Jedino da se dopisujemo na engleskom :=))
[ djoka_l @ 22.12.2019. 14:48 ] @
Ovaj tvoj program je loš po toliko mnogo osnova, da će objašnjenje šta je loše biti mnogo duže od samog programa.
Nemoj ovo da shvatiš kao napad na tvoju ličnost, nadam se da ćeš iz ovoga nešto da naučiš

Da krenem redom:

Code:
ind2 = ind + int(pomeranje)


je bezveze, jer u svakom prolazu kroz petlju ponovo radiš konvertovanje u int. Umesto toga, dovoljno je da to uradiš jednom, pre petlje

Code:
pomeranje = int(input('Za koliko mesta pomeriti slova? '))

Code:
else:
  ind2 = ind2

je besmisleno, uopšte ti ne treba taj else. if može da bude i bez else dela

Code:
        ind = abc.index(i)
        ind2 = ind + int(pomeranje)
        if ind2 > 26:
            ind2 = ind2 - 30
        else:
            ind2 = ind2
        slovo = abc[ind2]
        print(slovo, end='')


je višestruko loše. Bezveze koristiš varijable ind, ind2 slovo. Koristiš ono što se zove "magični brojevi". Imaš 26 i 30, a na oba mesta treba da bude 30. Python oprašta greške i dozvoljava negativne vrednoste indeksa, ali samo pukim slučajem program radi.

Code:
    else:
         i == i
         slovo = i
         print(slovo, end='')


Uh, "i==i" - ZAŠTO TO PIŠEŠ??? čak i da si hteo da napišeš i=i to ti ne treba. Zar nije jednostavnije da samo staviš print(i, end='')

Evo tvog programa, bez ulaženja u ispravku logike, koji radi isto što i tvoj kod, samo malo ispravnije:

Code:

# Cezarova šifra
poruka = input('Unesi poruku: ')
pomeranje = int(input('Za koliko mesta pomeriti slova? '))

abc = 'abcčćdđefghijklmnoprsštuvzž'
n=len(abc)

for i in poruka:
    if i in abc:
        print(abc[(abc.index(i)+pomeranje) % n], end='')
    else:
         print(i, end='')


Problem sa slovima lj, nj i dž je REŠEN. Tretiraju se kao dva slova.
Uzmi reči nadživeti, konjunkcija, injekcija. Ovo su slučajevi kada znaci dž i nj predstavljaju DVA slova. Ne mogu da se setim primera da je nekada i lj dva slova.

Sada još samo da rešiš problem velikih slova, pa si rešio zadatak...
[ djoka_l @ 22.12.2019. 15:21 ] @
Evo ti varijanta programa koja zna da radi i sa velikim slovima.

Code:
# Cezarova šifra
poruka = input('Unesi poruku: ')
pomeranje = int(input('Za koliko mesta pomeriti slova? '))

abc = 'abcčćdđefghijklmnoprsštuvzž'
n=len(abc)

for i in poruka:
    c=i.lower()
    up=i.isupper()
    if c in abc:
        s=abc[(abc.index(c)+pomeranje) % n]
        print(s.upper() if up else s, end='')
    else:
        print(i, end='')
[ a1234567 @ 22.12.2019. 16:13 ] @
Pozdrav Đoko,
Veliko hvala na trudu. Upravo mi to treba, povratna informacija i komentar za moj program, kako bih nešto naučio i ispravio greške.
Jer ja u stvari još ništa ne znam. Više nagađam i guglujem, nego što sam siguran kako treba. Ali valjda je to tako uvek u početku.

Dakle, uopšte ne shvatam tvoje komentare kao napad na ličnost, već sam zahvalan što si se uopšte potrudio da pogledaš šta sam uradio.
To mu dođe kao kad nastavnik ispravi domaći zadatak crvenom olovkom, pa iz grešaka učenik nešto nauči. :)

Proučiću pažljivo prvo tvoje komentare, a onda i rešenje koje si ponudio.
Ako budem imao dodatnih pitanja, šaljem i njih.

HVALA JOŠ JEDNOM ZA TRUD!
[ a1234567 @ 22.12.2019. 17:29 ] @
Proučio sam primedbe. Uglavnom su mi jasne i vidim gde sam grešio.
Suviše mnogo koraka tamo gde je moguće pojednostaviti.

Nisam se setio da za oduzimanje iskoristim modulo.
Valjda zato što mi je ostalo u glavi da je on za deljenje.

Novost je za mene i da if ne mora da ima else.
Zato sam i pisao to što sam pisao, da nešto bude i u else :))
I naravno to je višak.

Najviše mi se od svega sviđa abc string bez lj, nj, i dž.
Odlična ideja. Ja sam video problem tamo gde ga nema.

Stavio sam i moju (apdejtovanu) i tvoju verziju programa ovde, ako nekom zatreba.

[ mjanjic @ 22.12.2019. 17:52 ] @
Sledeći korak: napraviti rešenje koje koristi chr() i ord() funkcije, a radi i za naša slova - za engleski alfabet može da se realizuje jednom linijom koda :)
[ Branimir Maksimovic @ 23.12.2019. 05:02 ] @
Bolje uradi rot13 to se bar koristi.
[ a1234567 @ 23.12.2019. 16:48 ] @
Idemo dalje.
Za opuštanje jedan sasvim lak zadatak, čak i meni :)

Zadatak broj 6

Treba zvezdicama iscrtati pravougaonik.
Jedan način je naravno ovako, ali je tada veličina fiksirana.
Code:
print('************')
print('*          *')
print('*          *')
print('*          *')
print('************')

Napravi programčić gde korisnik može da unese željenu širinu i visinu budućeg pravougaonika/kvadrata.

Ja sam svoje rešenje sačuvao ovde.
[ mjanjic @ 23.12.2019. 23:56 ] @
Else blok može u jednoj liniji (doduše, manje jasno, ali zanimljivo za razmišljanje):
Code:
    for i in range (y):
        print('*' + ('*' * (x-2) if (i == 0 or i == y-1) else ' ' * (x-2)) + '*')
[ a1234567 @ 24.12.2019. 01:51 ] @
ja sam ovo tvoje ('*' + ('*' * (x-2) malo pojednostavio
Code:
for i in range (y):
        print('*' * x) if (i == 0 or i == y-1) else print('*' + ' ' * (y+2) + '*')


E sad mi je bilo zanimljivo da sam morao da stavim print i posle else, inače ne radi program kako treba.
[ djoka_l @ 24.12.2019. 08:30 ] @
Citat:
E sad mi je bilo zanimljivo da sam morao da stavim print i posle else, inače ne radi program kako treba.


Obrati pažnju na zagrade!!

mjanjic je napisao izraz

print ( NEŠTO if USLOV else NEŠTODRUGO )

ti si napisao

print ( NEŠTO ) if USLOV else print ( NEŠTODRUGO )

[ a1234567 @ 24.12.2019. 08:47 ] @
Aha, dobro.
Sad i moja verzija radi bez drugog print,
kad sam uklonio višak zagrada

Code:
x = 10
y = 6

for i in range (y):
        print('*' * x if i == 0 or i == y-1 else '*' + ' ' * (y+2) + '*')
[ djoka_l @ 24.12.2019. 09:02 ] @
To što si ti napisao nije greška.

U tom primeru, if-else konstrukcija je TERNARNI operator, odnosno operator koji računa sa tri izraza.
Kao što je "+" BINARNI operator i <izraz> + <izraz> je BINARNA operacija koja kao rezultat vraća <izraz>, tako i

<izraz> if <logicki_izraz> else <izraz>

ternarna operacija koja vraća vrednost.
Ti sada možeš da koristiš povratnu vrednost za nešto drugo, recimo za print:

print( <izraz> if <logicki_izraz> else <izraz> )

a može i sam izraz da bude print() ili neka druga funkcija.

Dakle ispravno je i
print( <izraz> if <logicki_izraz> else <izraz> )
i
print( <izraz> ) if <logicki_izraz> else print( <izraz> )

Samo treba da znaš zašto se to dešava.
A da je i print() funkcija, vidi se jasno jer sve funkcije se pozivaju kao ime_funkcije( argumenti ) (bitno je da stoji zagrada posle imena). Tako je, bar u pythonu 3.
Da je print funkcija, koja vraća neku vrednost, možeš i sam da proveriš sa:

print( print ('x') )
[ mjanjic @ 24.12.2019. 09:19 ] @
Ja sam hteo još "komplikovanije" da napravim koristeći product() ili neki drugi način da izbegnem petlje, nego da na neki drugi način realizujem iscrtavanje karaktera u formi pravougaonika, ali sam odustao. Moglo bi kao dvostruki niz pa da posle odštampa samo elemente niza, ali da bi se taj niz formirao treba poprilično koda.

Drugi problem, koji mi je bio interesantniji, jeste da se detektuje rezolucija ekrana i/ili broj karaktera koji može da se ispiše horizontalno i vertikalno pa da se zvezdice odštampaju samo uz ivicu, međutim tu je potrebna dodatna biblioteka, čija primena se dodatno komplikuje ako je uključeno skaliranje (obično kod 2k displeja sa malim ekranima i većine 4k displeja), ali nigde nisam našao mogućnost da se detektuju dimenzije "output" box-a (npr. kod onlih online interpretera), tj. moramo ih znati unapred.
[ Branimir Maksimovic @ 24.12.2019. 09:45 ] @
Na Linux-u imas environment variable LINES i COLUMNS...
[ a1234567 @ 24.12.2019. 10:24 ] @
Citat:
mjanjic:
Ja sam hteo još "komplikovanije" da napravim koristeći product()...

Janjiću samo bez komplikovanja... ovo je kindergarten. Ne obeshrabruj poletarce
[ a1234567 @ 24.12.2019. 10:36 ] @
Citat:
djoka_l:
Dakle ispravno je i
print( <izraz> if <logicki_izraz> else <izraz> )
i
print( <izraz> ) if <logicki_izraz> else print( <izraz> )


Ali je zanimljivo da ovo ne radi

Code:
print('*' * x if i == 0 or i == y-1) else ('*' + ' ' * (y+2) + '*')


Po meni bi i ovo imalo logike jer je if uslov za prvi izraz bude štampan, dakle ide uz njega, a else mu dođe obaška, kao alternativa.
[ djoka_l @ 24.12.2019. 11:10 ] @
Nije logično.

Po istom principu, trebalo bi da bude ispravno i

print( a + b )
i
print( a + ) b

A ovo drugo sigurno nije ispravno.

Tebi je if ostalo u prvoj zagradi (od print) a else si stavio van zagrade, a one je deo istog izraza sa if.
Dakle, treba

( if ... else )
a ne
( if ... ) else
[ a1234567 @ 24.12.2019. 15:39 ] @
OK, shvatam, if... else su par i ne može taraba između njih.
I to mi ima logike :))
[ a1234567 @ 24.12.2019. 16:23 ] @
E dobro, logiku smo pretresli do u sitna crevca.
Vreme je za relaksaciju, to jest kartanje

Zadatak broj 7: Mešanje karata

Standarni špil karata sadrži 52 karte. Svaka karta ima jednu od četiri boje: pik (♠), herc (), karo () i tref (♣). Karte su po hijerarhiji poređane: 2, 3, 4, 5, 6, 7, 8, 9, 10, J (Jack), Q (Queen), K (King), A (Ace).

Svaka karta može se predstaviti sa dva karaktera. Prvi karakter je vrednost karte, gde su vrednosti od 2 do 9 direktno predstavljene. Karakteri “T”, “J”, “Q”, “K” i “A” se koriste da predstave 10, Jack, Queen, King i Ace. Drugi karakter se koristi da predstavi boju karte. To je obično malo slovo: „p“ (pik), „h“ (herc), „k“ (karo) i „t“ (tref). Evo nekoliko primera kako su karte predstavljene sa dva karaktera:


Jack pik = Jp
dva tref = 2t
deset karo = Tk
Ace herc = Ah
devet pik = 9p

Počni tako što ćeš napisati funkciju napraviShpil. Ona će koristiti petlju da napravi ceo špil sortirajući dvoslovne oznake za sve 52 karte u listu. Return listu karata kao jedini rezultat te funkcije. Tvoja funkcija ne zahteva nikakve parametre.

Napiši drugu funkciju i nazovi je meshanje, koja randomizuje redosled karata u listi. Jedna tehnika za ovakvo mešanje karata je da prođeš svaki elemenat u listi i zameniš mu mesto sa nekim drugim, nasumično odabranim elementom liste. Moraš napisati sopstvenu petlju za mešanje karata. Ne možeš koristiti pythonovu izvornu shuffle funkciju

Sada iskoristi obe funkcije da napraviš glavni program koji prikaže ceo špil pre i posle mešanja.

Ajmo da krenemo. Ko meša?

[ mjanjic @ 24.12.2019. 21:01 ] @
A baš mora "prosta" petlja za kreiranje špila, ja bih da koristim product() da naučimo i nešto novo, obične petlje smo valjda savladali?

Evo funkcije za kreiranje špila pomoću product():

Code:
from itertools import product

def createDeck():
    cardList = product(['2','3','4','5','6','7','8','9','T','J','Q','K','A'], ['p','t','k','h'])
    cards = []
    for card in cardList:
        cards.append(''.join(card))
    return cards
[ Branimir Maksimovic @ 24.12.2019. 21:57 ] @
haskell:
Code:

   let cards = [(face,sign)|face<-['2','3','4','5','6','7','8','9','T','J','Q','K','A'],
                  sign <- ['p','t','k','h']]
[ a1234567 @ 25.12.2019. 04:32 ] @
Evo i mog rešenja na ovom linku.

Ispis na ekranu je ovakav:

Početni špil:
['2p', '3p', '4p', '5p', '6p', '7p', '8p', '9p', 'Tp', 'Jp', 'Qp', 'Kp', 'Ap', '2h', '3h', '4h', '5h', '6h', '7h', '8h', '9h', 'Th', 'Jh', 'Qh', 'Kh', 'Ah', '2k', '3k', '4k', '5k', '6k', '7k', '8k', '9k', 'Tk', 'Jk', 'Qk', 'Kk', 'Ak', '2t', '3t', '4t', '5t', '6t', '7t', '8t', '9t', 'Tt', 'Jt', 'Qt', 'Kt', 'At']

Promešane karte:
['Kt', 'Kp', '3p', 'Jt', '9t', 'Tt', '2t', 'Jp', '6p', 'Kk', '7k', '5k', '4k', '8p', '9k', 'Ah', '6k', 'Ak', '8t', '5t', '5p', '3h', '7p', 'Qp', 'Jk', '7h', '7t', 'Qk', 'Kh', 'Ap', '2p', '8h', '6h', '6t', 'At', '3k', '8k', '9p', 'Qh', '2h', '2k', '3t', '5h', 'Th', 'Tk', 'Tp', '9h', '4t', 'Jh', '4p', '4h', 'Qt']
[ djoka_l @ 25.12.2019. 09:38 ] @
Da li ti sam smišljaš ove zadatke?
Pitam zato što je ovo loš način da se predstavi špil karata. Koristiš dvoslovne oznake, a to je pogrešno.

Tako ti je, na primer, sedmica pik predstavljena kao string '7p'. Zar ti nije logičnije da bude predstavljena kao ['7', 'pik']?
Ovo je greška koju često vidim kod početnika - prave nekakve "samogovoreće" šifre za predstavljanje entiteta iz modela.

Špil karata može i da se predstavi i kao niz cifara od 0 - 51, tako da je za kartu n vrednost v=n % 13 a boja b=n // 4
Posebno držiš niz oznaka za karte 0-12, posebno boje za vrednosti 0-3.

Zamisli, recimo, da je ovo mešanje samo uvod u neki program za igranje bridža. Tada ti odjednom zatreba da karatama dodeliš honor poene, (A=4, K=3, Q=2, J=1), a boje treba poređati u redosledu tref, karo, herc, pik.
Zato je bolje kartu predstaviti kao neki objekat ili strukturu podataka, tako da modifikacija bude jednostavna.
[ a1234567 @ 25.12.2019. 10:44 ] @
Ne smišljam ja, nisam tako talentovan, već kad naiđem na neki zadatak koji mi je zanimljiv, postavim ga ovde.
A ovaj mi je bio zanimljiv po ovom random premeštanju elemenata skupa, koje se može primeniti u različitim igrama.

No, u pravu si, ovo je samo bio uvod. Ima i nastavak zadatka

Zadatak broj 8

Sad kad smo promešali karte, najprirodniji sledeći potez je da ih i podelimo.
Dakle, treba napisati novu funkciju, koja se nadovezuje na prethodne dve i radi sledeće:

* podeli po 6 karata četvorici igrača,
* ispiše koje karte ko od njih ima i
* naravno, ukloni te karte iz preostalog špila.
* pa onda i njega izlista, čisto da proverimo da nije neka od karata u opticaju ostala u njemu.

Ko deli?
[ a1234567 @ 25.12.2019. 14:35 ] @
Dok ne vidimo ko deli, imam jedno praktično pitanje:

lista = ['12', '17', '28', '93', '4', '6', '24', '19', '32', '9', '54', '63', '6', '24',]

imali li random modul neki metod koji bi vraćao nasumični element niza, ali unutar određenog raspona njegovih indeksa, recimo [4:10]?
U slučaju ove liste, to bi značilo da metod vraća ili jedan od ovih elemenata: '4', '6', '24', '19', '32', '9' ili njegov index.

[ Panta_ @ 25.12.2019. 15:02 ] @
Ima, random.choice.
[ a1234567 @ 25.12.2019. 15:57 ] @
Panto, gledao sam i njega.
Ali koliko sam razumeo on vraća bilo koji član liste, ne vidim da može da se suzi izbor.

Dokumentacija kaže:

random.choice(seq)
Return a random element from the non-empty sequence seq. If seq is empty, raises IndexError.
[ Panta_ @ 25.12.2019. 16:11 ] @
Code:
random.choice(['12', '17', '28', '93', '4', '6', '24', '19', '32', '9', '54', '63', '6', '24',][4:10])
'19'
[ a1234567 @ 25.12.2019. 16:23 ] @
Bravo majstore!
Pa piši im da dopune dokumentaciju, to uopšte tamo ne piše :)
[ Branimir Maksimovic @ 25.12.2019. 18:05 ] @
evo haskell-a:

Code:

import Data.Random.Source.DevRandom
import Data.Random.RVar
import Data.Random.Extras
import Data.Maybe
dealCard :: [(a,b)] -> RVar ([(a,b)],(a,b))
dealCard l = do
    fromJust $ choiceExtract l
main = do
    let cards = [(face,sign)|face<-['2','3','4','5','6','7','8','9','T','J','Q','K','A'],
                  sign <- ['p','t','k','h']]
        dealHand :: [(a,b)] -> IO ([(a,b)],[(a,b)])
        dealHand cards =  do
          (l',card1) <- runRVar (dealCard cards) DevRandom
          (l'',card2) <- runRVar (dealCard l') DevRandom
          (l''',card3) <- runRVar (dealCard l'') DevRandom
          (l'''',card4) <- runRVar (dealCard l''') DevRandom
          (l''''',card5) <- runRVar (dealCard l'''') DevRandom
          (ret,card6) <- runRVar (dealCard l''''') DevRandom
          return (ret,card1:card2:card3:card4:card5:card6:[])

    (l',hand1) <- dealHand cards
    (l'',hand2) <- dealHand l'
    (l''',hand3) <- dealHand l''
    (l'''',hand4) <- dealHand l'''
    print hand1
    print hand2
    print hand3
    print hand4
    print l''''


i izlaz:
Code:

~/examples/haskell >>> ./cards                                                                              
[('4','p'),('J','k'),('K','k'),('8','p'),('T','p'),('4','k')]
[('Q','p'),('3','h'),('7','h'),('A','p'),('Q','k'),('8','t')]
[('7','k'),('3','p'),('2','t'),('4','t'),('9','k'),('5','k')]
[('K','p'),('8','h'),('Q','t'),('A','k'),('2','h'),('5','t')]
[('2','p'),('2','k'),('3','t'),('3','k'),('4','h'),('5','p'),('5','h'),('6','p'),('6','t'),('6','k'),('6','h'),('7','p'),('7','t'),('8','k'),('9','p'),('9','t'),('9','h'),('T','t'),('T','k'),('T','h'),('J','p'),('J','t'),('J','h'),('Q','h'),('K','t'),('K','h'),('A','t'),('A','h')]
[ a1234567 @ 26.12.2019. 07:16 ] @
Citat:
djoka_l:
Da li ti sam smišljaš ove zadatke?
Pitam zato što je ovo loš način da se predstavi špil karata. Koristiš dvoslovne oznake, a to je pogrešno.

Tako ti je, na primer, sedmica pik predstavljena kao string '7p'. Zar ti nije logičnije da bude predstavljena kao ['7', 'pik']?
Ovo je greška koju često vidim kod početnika - prave nekakve "samogovoreće" šifre za predstavljanje entiteta iz modela.

Špil karata može i da se predstavi i kao niz cifara od 0 - 51, tako da je za kartu n vrednost v=n % 13 a boja b=n // 4
Posebno držiš niz oznaka za karte 0-12, posebno boje za vrednosti 0-3.

Zamisli, recimo, da je ovo mešanje samo uvod u neki program za igranje bridža. Tada ti odjednom zatreba da karatama dodeliš honor poene, (A=4, K=3, Q=2, J=1), a boje treba poređati u redosledu tref, karo, herc, pik.
Zato je bolje kartu predstaviti kao neki objekat ili strukturu podataka, tako da modifikacija bude jednostavna.

Đoko, pokušao sam da napravim ovo što si predložio i izgleda da mi je uspelo.
A najviše mi se dopada što sam pojednostavio staru for petlju.

Code:
boja = ['p', 'h', 'k', 't']
vrednost = ['2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A']

print('Početni špil je:')
for x in range(0, 13):
    karte = [(i, j) for i in vrednost[x] for j in boja]
    print(karte)

ali sam napravio jednu drugu for petlju da bude lepši ispis karata

Početni špil je:
[('2', 'p'), ('2', 'h'), ('2', 'k'), ('2', 't')]
[('3', 'p'), ('3', 'h'), ('3', 'k'), ('3', 't')]
[('4', 'p'), ('4', 'h'), ('4', 'k'), ('4', 't')]
[('5', 'p'), ('5', 'h'), ('5', 'k'), ('5', 't')]
[('6', 'p'), ('6', 'h'), ('6', 'k'), ('6', 't')]
[('7', 'p'), ('7', 'h'), ('7', 'k'), ('7', 't')]
[('8', 'p'), ('8', 'h'), ('8', 'k'), ('8', 't')]
[('9', 'p'), ('9', 'h'), ('9', 'k'), ('9', 't')]
[('T', 'p'), ('T', 'h'), ('T', 'k'), ('T', 't')]
[('J', 'p'), ('J', 'h'), ('J', 'k'), ('J', 't')]
[('Q', 'p'), ('Q', 'h'), ('Q', 'k'), ('Q', 't')]
[('K', 'p'), ('K', 'h'), ('K', 'k'), ('K', 't')]
[('A', 'p'), ('A', 'h'), ('A', 'k'), ('A', 't')]


[ Panta_ @ 26.12.2019. 09:17 ] @
Code (python):

from random import sample
cards = [value+color for value in "23456789TJQKA" for color in "ptkh"]
for player in range(1,5):
    hand = sample(cards, k=6)
    print(f"Player {player}: {hand}")
    for i in hand:
        cards.remove(i)
print(f"Remaining cards: {cards}")

Player 1: ['5h', '3t', '9k', '8p', '5p', '5t']
Player 2: ['4k', '6t', 'Ah', '9p', '6h', '6k']
Player 3: ['Ap', '7k', '2p', 'Qh', '9t', '2k']
Player 4: ['Jt', 'Tp', 'Jh', 'Tt', 'Jp', '7p']
Remaining cards: ['2t', '2h', '3p', '3k', '3h', '4p', '4t', '4h', '5k', '6p', '7t', '7h', '8t', '8k', '8h', '9h', 'Tk', 'Th', 'Jk', 'Qp', 'Qt', 'Qk', 'Kp', 'Kt', 'Kk', 'Kh', 'At', 'Ak']
 
[ a1234567 @ 27.12.2019. 02:05 ] @
Panta ga slupao u tri reda!
Ali si vidim jednu stvar zaboravio i to vrlo važnu!
Posle mešanja karata, a pre deljenja, moraju karte da se precepe, naravno.
Zato sam pitao za random.choice.

Panto ako ne znaš kako da precepiš karte, nije problem,
pogledaj moj kod ovde

Eto, rešismo još jedan zadatak.
Uskoro postavljam novi. Stay tuned
[ a1234567 @ 27.12.2019. 04:48 ] @
Evo jedan lak

Zadatak broj 9:
Ubedi python da odštampa nešto ovako:

1
2 2
3 3 3
4 4 4 4
5 5 5 5 5


[ a1234567 @ 28.12.2019. 00:56 ] @
Evo i rešenja:

Code:

for i in range(6):
      for x in range(i):
          print (i, end=" ")
      print("\n")
[ Panta_ @ 28.12.2019. 06:35 ] @
Imas novu liniju posle svakog for loopa, zameni print("\n") sa print(). Evo malo jednostavnijeg resenja:

Code:
for i in range(6):
    print((str(i) + ' ') * i)


2 2 
3 3 3 
4 4 4 4 
5 5 5 5 5
[ a1234567 @ 28.12.2019. 12:23 ] @
Evo Panto ja još skratio

Code:
for i in range(6):
          print(str(i) * i)


Ti si izgleda veliki ljubitelj kratkih formi, samo skraćuješ.
Evo ti onda jedne super kratke priče velikog Danila Harmsa, pa uživaj:

Bio jedan riđi čovek

Bio jednom jedan riđi čovek. Taj nije imao ni oči ni uši. Ni kosu nije imao, tako da su ga riđim zvali tek uslovno. Ni da govori nije mogao, jer taj ni usta nije imao. Nije imao ni nos. Nije imao čak ni ruke ni noge. Ni stomak nije imao, ni leđa nije imao, ni kičmu nije imao, ni unutrašnje organe. Ništa taj nije imao. Tako da se ni ne zna o kome se radi. Bolje onda da o njemu više i ne govorimo.
[ Branimir Maksimovic @ 28.12.2019. 13:26 ] @
evo pascalov trougao:

Code:

~/examples/haskell >>> cat pascal.hs                                                                                                                                                                                     
fac :: (Num a,Enum a) =>a->a
fac = product . enumFromTo 1

binCoef :: Integer->Integer->Integer
binCoef n k = (fac n) `div` ((fac k) * (fac $ n - k))
 
pascal :: Integer -> [[Integer]]
pascal n = map (\x -> map (binCoef $ x - 1) [0..x-1]) [1..n]
 
main = do
    line <- getLine
    let n = read line
    putStrLn $ unlines $ map (unwords.map (show)) $ pascal n


Code:

~/examples/haskell >>> ./pascal                                                                                                                                                                                          
10
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1

[ a1234567 @ 28.12.2019. 14:37 ] @
Lepo, lepo.

Evo onda za tebe jedne Paskalove misli:
Lepa reč ne košta mnogo. A ipak postiže mnogo.

[ a1234567 @ 28.12.2019. 14:39 ] @
A odmah zatim da postavim kratki i jubilarni

Zadatak broj 10

Napiši funkciju koja određuje da li je lista brojeva koje je uneo korisnik sortirana (po rastućem ili opadajućem nizu, svejedno) ili je nasumična. Funkcija treba da dâ rezultat True ukoliko je lista već sortirana pri unosu, a u suprotnom False.

Napiši glavni program u kojem korisnik unese recimo 5 brojeva i onda iskoristi svoju funkciju da napraviš izveštaj je li lista sortirana ili nije.
[ Panta_ @ 28.12.2019. 15:31 ] @
Citat:
a1234567:
Evo Panto ja još skratio :D

Code:
for i in range(6):
          print(str(i) * i)


Nemas razmak izmedju brojeva. Zar ne treba 5 5 5 5 5?
[ a1234567 @ 28.12.2019. 15:37 ] @
Pa kad smo već krenuli u minimalizam, ja reko da zakinem što je moguće više


Inače za ovaj deseti zadatak kao privremeno rešenje dok ne nađem bolje,
dajem takozvano "brute force" rešenje

Code:

lista = [6, 15, 23, 31, 52]

def provera():
    if lista[0] <= lista[1] and lista[1] <= lista[2] and lista[2] <= lista[3] and lista[3] <= lista[4]:
        return True
    elif lista[0] >= lista[1] and lista[1] >= lista[2] and lista[2] >= lista[3] and lista[3] >= lista[4]:
        return True
    else:
        return False

print(provera())

proverio, radi!
[ a1234567 @ 28.12.2019. 15:52 ] @
Malo elegantnije rešenje zadataka 10 postavio sam na mestu za rešenja, ako nekom zatreba.
[ Panta_ @ 28.12.2019. 16:04 ] @
Code:
True if lista == sorted(lista) or lista == sorted(lista)[::-1] else False
[ Branimir Maksimovic @ 28.12.2019. 16:14 ] @
samo lista == sorted ne treba True ili False.
[ Panta_ @ 29.12.2019. 06:47 ] @
True, zato što operator vraća boolean vrednost (True ili False), ali mi je sa if else za ovaj primer delovalo čitkije.
[ a1234567 @ 29.12.2019. 11:32 ] @
E nešto sam razmišljao o ovim trouglovima od brojeva što smo pravili.
Geometrija je čudo. Pa mi pade na pamet, kako napraviti ovako nešto!?

1
2 2
3 3 3
4 4 4 4
5 5 5 5 5
6 6 6 6 6 6
5 5 5 5 5
4 4 4 4
3 3 3
2 2
1
[ a1234567 @ 29.12.2019. 11:34 ] @
Jedino što sam uspeo da smislim je da stavim dve petlje

Code:
for i in range(6):
      for x in range(i):
          print (i, end=" ")
      print()
for i in range(6, 0, -1):
      for x in range(i):
          print (i, end=" ")
      print()


Sad će Panta da zvizne one liner
[ Panta_ @ 29.12.2019. 14:19 ] @
Chain them up:

Code:
from itertools import chain
for x in chain(range(1,6), range(6, 0, -1)):
    print((str(x) + ' ') * x)
     

2 2 
3 3 3 
4 4 4 4 
5 5 5 5 5 
6 6 6 6 6 6 
5 5 5 5 5 
4 4 4 4 
3 3 3 
2 2 
1


[Ovu poruku je menjao Panta_ dana 29.12.2019. u 15:54 GMT+1]

[Ovu poruku je menjao Panta_ dana 29.12.2019. u 16:08 GMT+1]
[ a1234567 @ 29.12.2019. 14:25 ] @
E to, majstore, svaki dan nešto novo naučim :)

The chain() function takes several iterators as arguments and returns a single iterator that produces the contents of all of them as though they came from a single sequence.

Code:
from itertools import *

for i in chain([1, 2, 3], ['a', 'b', 'c']):
    print i

$ python itertools_chain.py

1
2
3
a
b
c

[ a1234567 @ 30.12.2019. 13:46 ] @
Zadatak 11. Pronađi proste brojeve

Prvo, da se podsetimo šta je prost broj? Svaki pozitivan broj od 1 do n, koji je deljiv jedino brojem 1 i samim sobom.
E sad treba u nizu od 1 do nekog zadatog broja izlistati sve proste brojeve.
Recimo u nizu od 1 do 50, to su brojevi: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47.

Napiši funkciju, čiji je opis sledeći:

Code:
Napravi listu sa svim brojevima od 0 do n.
izbaci 0 i 1, jer nisu prosti brojevi.

Postavi p jednako 2 i odatle krećeš
Dok je p manje od n radi ovo:
    Izbaci iz liste sve brojeve koji su proizvod broj p tako što ćeš im dati vrednost 0 (ali ne izbacuj samo p).
    Postavi da je p jednako narednom broju u listi, a koji već nije pretvoren u vrednost 0 

Isprintaj kao proste sve brojeve koji nisu postali 0.


[ mjanjic @ 30.12.2019. 20:59 ] @
Zar nije logičnije napraviti novi niz pa vrednosti prostih brojeva upisivati u njega?
Za ovo kako si ti opisao je pogodna neka vrsta heš tabele, ali je besmisleno jer nas zanimaju samo brojevi koji su prosti. Na kraju, logično je imati niz koji sadrži samo proste brojeve do broja n, a ne da većina članova niza budu 0, pa pri štampanju treba opet da proveravamo za svaki element niza da li je različit od nule.

Od ovakvih zadačića se prosečnom početniku smuči programiranje, jer ne vidi poentu rešavanja zadataka koji se u takvom obliku nikad neće pojaviti u praksi.

Uzmi npr. one jednostavnije zadačiće iz knjiga tipa "Coding interviews".
[ a1234567 @ 31.12.2019. 04:17 ] @
Takav je zadatak na koji sam naišao. Ne mogu ja autoru da krojim kapu :)
Evo i rešenja za zadatak 11.

Nije problem, ako imaš i ti neki zadatak za početnike, postavi ga ovde, pa da se zabavljamo :)

E da, najvažnije!

SVIMA VAM ŽELIM SVE NAJBOLJE U NOVOJ GODINI
i još mnogo programerskih "zadačića" da rešimo :D
[ Branimir Maksimovic @ 31.12.2019. 04:42 ] @
To je eratostenovo sito:
https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes

Srecna nova unapred :P
[ djoka_l @ 31.12.2019. 07:39 ] @
Kada praviš Eratostenovo sito, ne treba petlja da ide do "limit", nego do sqrt(limit)

Tako, na primer, ako želiš da nađeš proste brojeve do 100, petlja se vrti samo do 10. Kada izbaciš sve brojeve deljive sa 2, 3, 5 i 7, sve što ostane je prost broj.
Ako broj nije prost, tada može da se napiš kao proizvod dva broja k=m*n.
m i n su veći od 1 (ne moraju da budu prosti) i neka je m<=n
Tada je maksimalna vrednost za m u slučaju da je m=n, pa m ne može biti veće od sqrt(k)
[ Branimir Maksimovic @ 31.12.2019. 08:34 ] @
Ene de nisam se udubio u resenje ;)
Imam ja nesto komplikovaniju stvar koju sam koristtio za resavanja ojlera 512, al ajde :P
[ a1234567 @ 08.01.2020. 17:56 ] @
Stiže i Zadatak 12: Pretraga rečnika

Napravi funkciju i nazovi je pretragaRecnika. Ona će potom imati rečnik i vrednost za pretragu kao svoje jedine parametre.

Napravi i glavni program koji pokazuje da pretragaRecnika funkcioniše kao deo rešenja za ovu vežbu. Tvoj program treba da kreira rečnik i onda da pokaže da funcija ispravno radi kada za rezultat ima više ključeva, jedan ili nijedan ključ.

Eto. Kratko i valjda je jasno.
[ anon70939 @ 08.01.2020. 20:15 ] @
Kupio sam na Udemy za oko 9$ neki kurs za ucenje pajtona u obliku zadataka. Svideo mi se ali sam prosao samo 30% jer sam posle otisao na neku drugu stranu.
Ovaj kurs
https://www.udemy.com/course/python-video-workbook/

Pored toga sam na tel instalirao i SoloLearn pa u kojekakvim redovima dok sam cekao zabavljao sam se s tim.

Evo i nestp gde kao kodiras igricu i tako ucis
https://www.codingame.com/start

[Ovu poruku je menjao CoyoteKG dana 08.01.2020. u 21:35 GMT+1]
[ anon70939 @ 08.01.2020. 21:21 ] @
^ greska
Promasio temu. Molim moderatora da obrise.
[ Branimir Maksimovic @ 09.01.2020. 04:41 ] @
"Eto. Kratko i valjda je jasno. "

Nije jasno, recnik nije definisan.
[ a1234567 @ 09.01.2020. 10:31 ] @
Ako nije definisan, verovatno je zadavač mislio da ga sami definišemo.
Ali evo ovde imaš jedan za nuždu.
[ Branimir Maksimovic @ 09.01.2020. 16:10 ] @
znaci mapiranje 1-1? To je onda lako. Da li piton ima map-u, asocijativni niz ili dictionary data strukturu?
Ako ima onda eje ovo trivijalno.
[ a1234567 @ 09.01.2020. 17:09 ] @
Ima dictionary, naravno.



[ anon70939 @ 09.01.2020. 18:03 ] @
pa kako drugacije da se pretrazuje recnik osm sa "dictionary"
[ a1234567 @ 10.01.2020. 15:32 ] @
Pa može... list po list
[ a1234567 @ 10.01.2020. 16:22 ] @
Evo i rešenja za zadatak broj 12.

Ovo sa rečnikom mi se baš dopada. Mogao bi i pravi rečnik da se napravi sa ovom funkcijom.
Jel može neko da kaže, koji se program uz python koristi za pravljenje interfejsa?
[ B3R1 @ 10.01.2020. 19:50 ] @
Da li je ovo tvoje resenje ili je to prepisano iz knjige? Zadatak je postavljen prilicno nejasno. Da li se trazi englesko-srpski recnik ili obrnuto? Recnik koji si postavio online podrazumeva da su reci s leve strane srpske, s desne engleske, a onda autor resenja pravi recnik (odnosno 'dict' strukturu) u kome su stvari postavljene obrnuto - kljucevi su engleske reci, a vrednosti srpske. Da bi na kraju program za zadate srpske reci vracao engleske ... prilicno konfuzno, ako mene pitas.

Ako ti vec treba srpsko-engleski recnik, zar nije prirodnije definisati dict u stilu:
srEn = { 'a' : 'but, and', 'abonos' : 'ebony', 'avaj' : 'oh', 'avgust' : 'August', 'avet' : 'ghost, phantom', 'avetinja' : 'ghost, phantom', 'avlija' : 'court, court-yard' ... }

u kom slucaju funkcija pretraga postaje krajnje jednostavna:
def pretraga (data, key):
if (key in data):
return data[key]
else:
return ''

Ova funkcija gore podrazumeva da je recnik konstruisan u strogom 1:1 maniru. Medjutim, ovaj tvoj nije. Ima slucajeva kada se iste engleske reci mapiraju u vise srpskih reci i obrnuto:
'agent' : 'agent'
'agent' : 'commercial-traveller'
'bakarna' : 'copper'
'bakarno' : 'copper'

Ta cinjenica ti delimicno pravi program neupotrebljivim, jer ako definises recnik od te 4 odrednice dobices (mozes da testiras u python shellu):
$ python
>>> srEn = { 'agent' : 'agent', 'agent' : 'commercial-traveller', 'bakarna' : 'copper', 'bakarno' : 'copper' }
>>> srEn
{'bakarna': 'copper', 'bakarno': 'copper', 'agent': 'commercial-traveller'}

Kao sto vidis, druga definicija reci 'agent' je zamenila ovu prvu.

Tu dolazimo do problema ucitavanja recnika. Python dict od nekih 20-30 key:value parova, ako se ne menjaju tokom vremena, mozes da 'hard-kodujes' u samom programu, kao sto si to i uradio. Medjutim, ako dict sadrzi nekih 10000 key:value parova sigurno je bolje ucitati to iz nekog fajla, sto je u pythonu trivijalno:
srEn = {}
for line in open('recnik.txt', 'r'):
key, value = line.strip().split(':')
srEn[key] = value

Ovo ti je osnovni kod koji ilustruje princip. Metod split(delimiter) razdvaja string u niz (listu) stringova koristeci znak 'delimiter' kao razdvajac - npr.
string='The;Big;Brown;Fox'
words = string.split(';')

vraca niz 'words' koji ce u sebi imati 4 elementa: [ 'The', 'Big', 'Brown', 'Fox' ].

Ali to je sve daleko od resenja, jer recnik koji si postavio sadrzi nekoliko zackoljica koje moras da razresis.

Prvi problem je ovo sto je vec opisano gore. Najjednostavniji nacin je da prevode razmaknes znakom ';', kao sto se to radi u pravim recnicima. Kod onda postaje:
srEn = {}
for line in open('recnik.txt', 'r'):
key, value = line.strip().split(':')
if (key not in srEn):
srEn[key] = value
else:
srEn[key] += '; ' + value

Drugi nacin, koji lici na ovo tvoje resenje, je da ti prevodi uvek budu nizovi, odnosno liste, pa da dobijes recnik tipa:
srEn = { 'agent' : [ 'agent', 'commercial-traveller'], 'bakarna' : ['copper'], 'bakarno' : ['copper'] }

Takvu strukturu mozes da napunis iz fajla na sledeci nacin:
srEn = {}
for line in open('recnik.txt', 'r'):
key, value = line.strip().split(':')
if (key not in srEn)
srEn[key] = [ value ]
else:
srEn[key].append(value)

Verovatno primecujes da sam na pocetku u oba slucaja stavio:
srEn = {}

Mada Python ne zahteva da promenljive deklarises kao u C/C++ na primer, svaka promenljiva koju koristis mora da bude definisana pre prvog koriscenja:
b = a + 1

ce vratiti gresku ako 'a' nigde nije definisano. Ispravno je:
a = 0 # ili neka druga vrednost
b = a + 1

Slicno je i sa listama i recnicima - njih takodje moras da inicijalizujes pre koriscenja:
recnik = {}
lista = []
recnik['nova rec'] = 'nesto novo'
lista.append('novi clan')


Drugi problem je sto ces, ako napravis fajl identican ovom zadatom recniku, u kome su reci s leve i s desne strane oivicene navodnicima, prilikom citanja fajla parametri 'key' i 'value' ce dobiti dvostruke navodnike i jos poneki razmak izmedju:
>>> line="'bakarno' : 'copper'"
>>> line.split(':')
["'bakarno' ", " 'copper'"]

A to nije ono sto si hteo. Znaci, prilikom ucitavanja recnika moraces da skines navodnike (odnosno apostrofe), kao i da se resis razmaka. Za brisanje razmaka s leve i desne strane stringa (a.k.a. "trimovanje") koristis funkciju (odnosno metod) strip():
key, value = line.split(':')
key = key.strip()
value = value.strip()

Ostaje jos da skines navodnike na pocetku i kraju izraza, sto je najelegantnije da uradis ovako:
key = key[1:-1]  # Izdvaja rec od drugog do pretposlenjeg znaka
value = value[1:-1]

A sada - tutti ... odnosno sve to spojeno u jedno:
srEn = {}
for line in open('recnik.txt', 'r'):
key = line.split(':')[0].strip()[1:-1]
value = line.split(':')[1].strip()[1:-1]
if (key not in srEn)
srEn[key] = [ value ]
else:
srEn[key].append(value)

Potom, neke linije u tvom recniku sadrze samo znak '$'. Njih bi najbolje bilo da preskocis, odnosno da preskocis sve linije koje ne sadrze dvotacku kao separator:
for line in open('recnik.txt', 'r'):
if (':' not in line):
continue
key = ...

Ovde bih stao za sada. Mada, pricu mozemo da sirimo i dalje. Sta raditi kada ti taj fajl s recnikom od 10000 elemenata ukucava neko ko bas nije mnogo pedantan, pa dobijes:
'"agent' : 'agent"
' agent : commercial-traveller'
bakarna :copper
'bakarno' : 'copper'

Ali to je vec zadatak za lekciju o regularnim izrazima u Pythonu.
[ djoka_l @ 10.01.2020. 22:49 ] @
Beri je ovo jako lepo objasnio.

Moram da ti ukažem na jednu tvoju veliku grešku u ratmišljanju:
Citat:
Ovo sa rečnikom mi se baš dopada. Mogao bi i pravi rečnik da se napravi sa ovom funkcijom.


Ti si trenutno u poziciji koja je opisana u literaturi o "situational leadership" (vidi, na primer https://www.atlassian.com/blog...hip-styles-for-every-situation) koja se naziva "enthusiastic beginner" ili D1.
Svi smo mi bili u tom položaju, bilo kada smo pokušavali da naučimo programiranje, ili skijanje, ili da vozimo kola, ili da sviramo gitaru (nastavi niz)...
Imaš jaku želju da naučiš programiranje, imaš motivaciju, ali vrlo malo iskustva i znanja. Ne znaš šta ne znaš. Ono što je problematično je to što ova pozicija (D1) zahteva vođstvo koje se zove S1 - tutorstvo.
Ljudima u ovoj poziciji jako je potrebno da imaju nekoga koji im TAČNO kaže šta dalje da rade.

I to je veliki problem sa svima koji hoće da nauče neku veštinu, a nemaju instruktora, nego idu sa nekim Internet "samoučenjem".
A problem je to što je sledeća faza u procesu napredavanja faza D2 koja se zove "disilusioned lerner". U toj fazi nastupa razočaranost, dolaziš do shvatanja koliko zapravo malo znaš i to je faza, u kojoj bez dobrog vođstva, napuštaš to što si počeo da radiš.

Sada si oduševljen python distionary strukturom podataka. A ne znaš, na primer, da je dictionary u pythonu realizovan kao hash tabela. Ne znaš šta je hash tabela. Ne znaš da pretraživanje hash tabele ima linernu kompleksnost i da se ta linearna kompleksnost obeležava kao O(n), Ne znaš ni šta je to O notacija. Ne znaš da efikasni algoritmi pretraživanja, kao na primer B-stablo imaju kompleksnost od O(log n). Ne znaš ni šta je to B-stablo, pa ni obično stablo.

I sada bi ti pravio grafičku aplikaciju za rečnik, koristeći neefikasnu strukturu podataka i bez najbliže predstave koliko to može da bude komplikovano.

Nemam nameeru da ti dam savet kako da napraviš takvu aplikaciju, jer bi to samo povećalo broj pitanja za koje ni ne znaš da postoje, niti znaš odgovore na njih.
Svi tvoji dosadašnji python programi imaju po desetak linija koda. Onda kada budeš u stanju da napišeš python program od 1000 linija koda (koji RADI), počni da razmišljaš o sebi kao o junior programeru.

Do tada, rešavaj ove fizz buzz probleme, a pokušaj i da nađeš nekog predavača ili da odeš na neki kurs python programiranja.
[ a1234567 @ 11.01.2020. 01:47 ] @
Đoko, prijatelju, još jednom hvala na dobronamernim savetima.

Sve sam te razumeo i sve si u pravu. Imam želju, imam motivaciju i radim svaki dan pomalo, pa dokle stignem.
Nažalost, ovo što si na kraju savetovao, nije ostvarimo. U situaciji u kojoj sam, ne mogu da nađem ni (živog) predavača, niti da se upišem na kurs. Možda jednog dana. Zato pokušavam da nešto naučim koristeći ono što mi je na raspolaganju, a to su net i knjige. Ako hoćeš da se prihvatiš uloge onlajn instruktora, primljen si na posao odmah

Druga alatka mi je upravo to što si naveo, motivacija. A kako je održavam? Pa tako što pokušavam da nađem problem KOJI ME ZANIMA. I otuda ideja o rečniku, jer mi se to čini kao zanimljiv projekat. Već sam pisao, najviše me zapravo zanima rad sa tekstom, a ne kojekakvi matematički problemi.

Dakle, skočim u vodu i probam da plivam. Nailazim na probleme usput i rešavam kako u tom trenutku znam i umem, bez pritiska rokova ili toga da uopšte moram nešto da postignem. Niti ja pravim neki poizvod za nekoga, pa da mora biti savršeno, niti mi egzistencija od toga zavisi, već je to za sada za mene hobi. Dakle, baš kao skijanje koje si naveo. Spustim se niz BLAGU padinu, pa ako i padnem koji put, nije smak sveta. Ali to što usput naučim ne bih naučio ako ostanem na vrh staze i nastavim da proveravam vezove, nameštam kapu i rukavice ili skakućem okolo sa jednom skijom na nozi.

Sve u svemu, pokušavam da sebi pronađem izazov, koji će mi održavati motivaciju i vući dalje. Ako imaš bolji konkretan predlog, biće mi neobično drago da ga saslušam. I još jednom, zaista sam ti zahvalan na svakom savetu.

E da, juče čačkam po netu i naiđem na ovaj, meni zanimljiv problem, koji je zapravo zadatak broj 13:

Kako da sabiraš ili oduzimaš ovakve stringove?
'1plus2plus3plus4'
rezultat = 10

ili:
'1plus2plus3minus4'
rezultat = 2
[ Branimir Maksimovic @ 11.01.2020. 06:53 ] @
Djoka:"Ne znaš da pretraživanje hash tabele ima linernu kompleksnost"

Djoko, mislim da si umoran ;)
[ Panta_ @ 11.01.2020. 07:50 ] @
Citat:
a1234567:
Ako nije definisan, verovatno je zadavač mislio da ga sami definišemo.
Ali evo ovde imaš jedan za nuždu.

Nije ti dobro definisan taj rečnik, npr. imaš 'glava me boli, my head aches' kao i '$'.

Inače, Python dictionary ima get funkciju koja vraća vrednost ključa ako je ključ u rečniku ili porazumevanu None.
Code:
mydict = eval(open("recnik.txt").read())  # kreira recnik iz fajla "recnik.txt"

mydict.get('aps', 'Unknown')                                                                                                                                                          
'gaol, prison, lock-up'

mydict.get('abc', 'Unknown')                                                                                                                                                          
'Unknown'


Citat:
E da, juče čačkam po netu i naiđem na ovaj, meni zanimljiv problem, koji je zapravo zadatak broj 13:

Kako da sabiraš ili oduzimaš ovakve stringove?
'1plus2plus3plus4'
rezultat = 10

ili:
'1plus2plus3minus4'
rezultat = 2


Code:
eval('1plus2plus3plus4'.replace('plus', '+'))                                                                                                                                         
10

eval('1plus2plus3minus4'.replace('plus', '+').replace('minus', '-'))                                                                                                                  
2


https://docs.python.org/3/library/functions.html#eval

[ Zurg @ 11.01.2020. 08:11 ] @
Izgleda da je Đoki pun heš i da zato ima veliki broj kolizija i nije baš O(k).
[ Panta_ @ 11.01.2020. 12:08 ] @
Citat:
Jel može neko da kaže, koji se program uz python koristi za pravljenje interfejsa?

Tkinter dolazi podrazumevano, a ima i dosta drugih npr. PyQT, WxPython, PySide, Kivy, PyGUI, itd.

https://wiki.python.org/moin/GuiProgramming

[ Zurg @ 11.01.2020. 16:04 ] @
Program ili biblioteka? Ovo nabrojano su biblioteke i frejmvorci. Na primer QtCreator je program koji sadrži UI builder.
[ a1234567 @ 11.01.2020. 16:30 ] @
Citat:
B3R1:
Da li je ovo tvoje resenje ili je to prepisano iz knjige? Zadatak je postavljen prilicno nejasno. Da li se trazi englesko-srpski recnik ili obrnuto? Recnik koji si postavio online podrazumeva da su reci s leve strane srpske, s desne engleske, a onda autor resenja pravi recnik (odnosno 'dict' strukturu) u kome su stvari postavljene obrnuto - kljucevi su engleske reci, a vrednosti srpske. Da bi na kraju program za zadate srpske reci vracao engleske ... prilicno konfuzno, ako mene pitas.

Ako ti vec treba srpsko-engleski recnik, zar nije prirodnije definisati dict u stilu:
srEn = { 'a' : 'but, and', 'abonos' : 'ebony', 'avaj' : 'oh', 'avgust' : 'August', 'avet' : 'ghost, phantom', 'avetinja' : 'ghost, phantom', 'avlija' : 'court, court-yard' ... }

u kom slucaju funkcija pretraga postaje krajnje jednostavna:
def pretraga (data, key):
if (key in data):
return data[key]
else:
return ''

Ova funkcija gore podrazumeva da je recnik konstruisan u strogom 1:1 maniru. Medjutim, ovaj tvoj nije. Ima slucajeva kada se iste engleske reci mapiraju u vise srpskih reci i obrnuto...

Ako je rešenje za prethodni zadatak konfuzno, to je zaštitni znak da je moje

Svaka čast, Berislave, baš si se potrudio da mi objasniš i veliko hvala.

Kao prvo, meni je u glavi pre englesko-srpski, nego srpsko-engleski rečnik. Mada kad napraviš jedan, nije pretpostavljam nepremostiv problem napraviti i obrnuto.
Dosta si napisao i treba mi vremena da to u glavi raspetljam. Ono što sam shvatio je da nije dobar ovaj sistem 1:1 sa više reči u keys

'gaol, prison, lock-up' : 'aps'

jer vidim da ako u polje za pretragu ukucam samo 'court' neće pronaći prevod u rečniku. Stvari dodatno komplikuje ako ima više reči i u keys i u values. Npr.:

'gaol, prison, lock-up' : 'aps, zatvor'

Da li onda da svako značenje izdvojim u poseban par?
gaol : aps, gaol : zatvor, prison : aps, prison : zatvor, gaol : aps, gaol : zatvor

ali onda gubim neke odrednice, kao što si ti pokazao u primeru.

$ python
>>> srEn = { 'agent' : 'agent', 'agent' : 'commercial-traveller', 'bakarna' : 'copper', 'bakarno' : 'copper' }
>>> srEn
{'bakarna': 'copper', 'bakarno': 'copper', 'agent': 'commercial-traveller'}

Kao sto vidis, druga definicija reci 'agent' je zamenila ovu prvu.


Kako izbeći da se jedna definicija ne izgubi?

Naravno, ovaj deo o učitavanju rečnika iz fajla nije problem. Svakako da definicije neće biti deo programa, već u eksternom fajlu, jer će ih biti na hiljade.




[ Zurg @ 11.01.2020. 16:52 ] @
Ključevi moraju biti jedinstveni. Ne možeš imati dva unosa sa istim ključem. Kao što ti je Đoka već rekao Dictionary je u stvari heš tabela. Pogledaj prvo šta je heš tabela, npr. https://en.wikipedia.org/wiki/Hash_table ili https://www.youtube.com/watch?v=MfhjkfocRR0

Mogao bi pod ključem agent da čuvaš niz.

Code:
srEn = { 'agent' : ['agent', 'commercial-traveller'] }


[ a1234567 @ 11.01.2020. 16:58 ] @
Citat:
Panta_:
Citat:
a1234567:
Ako nije definisan, verovatno je zadavač mislio da ga sami definišemo.
Ali evo ovde imaš jedan za nuždu.

Nije ti dobro definisan taj rečnik, npr. imaš 'glava me boli, my head aches' kao i '$'.

Inače, Python dictionary ima get funkciju koja vraća vrednost ključa ako je ključ u rečniku ili porazumevanu None.
Code:
mydict = eval(open("recnik.txt").read())  # kreira recnik iz fajla "recnik.txt"

mydict.get('aps', 'Unknown')                                                                                                                                                          
'gaol, prison, lock-up'

mydict.get('abc', 'Unknown')                                                                                                                                                          
'Unknown'



Panto ovaj tvoj mydic.get metod ne rešava problem koji imamo kad je više istih ključeva:

>>> mydic = {'agency' : 'agencija', 'court' : 'avlija', 'court' : 'dvorište'}
>>>mydyc.get('court')
dvorište


nema 'avlije'

Inače, položio si kolokvijum sa zadatkom broj dvanaest. Čestitam! :)
I tvoje i moje rešenje su ovde.
[ a1234567 @ 11.01.2020. 17:03 ] @
Citat:
Panta_:
Citat:
Jel može neko da kaže, koji se program uz python koristi za pravljenje interfejsa?

Tkinter dolazi podrazumevano, a ima i dosta drugih npr. PyQT, WxPython, PySide, Kivy, PyGUI, itd.

https://wiki.python.org/moin/GuiProgramming



Ništa od interfejsa za sada. Stavljamo ga na ler.
Iskrsni problemi neviđeni oko heš tabele, ne mož raspetljati ni pod razno
Kao što je Đoka i predviđao. Zna čovek gde su nagazne mine.

Odoh da vidim šta su te heš tabele, pa ćemo onda na kanal da budžimo

I naravno, hvala za apdejtovani rečnik. Mada je to tek test verzija, sad je čista ko suza!

[Ovu poruku je menjao a1234567 dana 11.01.2020. u 18:25 GMT+1]
[ Panta_ @ 11.01.2020. 17:44 ] @
Citat:
Panto ovaj tvoj mydic.get metod ne rešava problem koji imamo kad je više istih ključeva:

>>> mydic = {'agency' : 'agencija', 'court' : 'avlija', 'court' : 'dvorište'}
>>>mydyc.get('court')
dvorište

nema 'avlije'

Nema zato što je nemaš ni u rečniku. Ne možeš da imaš dva istoimena ključa.

Code:
mydic = {'agency' : 'agencija', 'court' : ['avlija', 'dvorište']}
mydic.get('court')
['avlija', 'dvorište']
[ a1234567 @ 11.01.2020. 17:45 ] @
Citat:
Zurg:
Ključevi moraju biti jedinstveni. Ne možeš imati dva unosa sa istim ključem. Kao što ti je Đoka već rekao Dictionary je u stvari heš tabela. Pogledaj prvo šta je heš tabela, npr. https://en.wikipedia.org/wiki/Hash_table ili https://www.youtube.com/watch?v=MfhjkfocRR0

Mogao bi pod ključem agent da čuvaš niz.

Code:
srEn = { 'agent' : ['agent', 'commercial-traveller'] }




Hvala za link. Ovo sa Wiki je pisano za vanzemaljce. Ništa ne razumem.
Pa sam našao na Stackoverflow nešto svarljivije. Možda će još nekom trebati, pa prenosim ovde.
Naravno, ostaje pitanje, kako sve to tehnički implementirati, ali bar mi je malo jasniji princip rada. Koliko shvatam, to mu dođe nešto kao bar-kod.

Here's an explanation in layman's terms.

Let's assume you want to fill up a library with books and not just stuff them in there, but you want to be able to easily find them again when you need them.

So, you decide that if the person that wants to read a book knows the title of the book and the exact title to boot, then that's all it should take. With the title, the person, with the aid of the librarian, should be able to find the book easily and quickly.

So, how can you do that? Well, obviously you can keep some kind of list of where you put each book, but then you have the same problem as searching the library, you need to search the list. Granted, the list would be smaller and easier to search, but still you don't want to search sequentially from one end of the library (or list) to the other.

You want something that, with the title of the book, can give you the right spot at once, so all you have to do is just stroll over to the right shelf, and pick up the book.

But how can that be done? Well, with a bit of forethought when you fill up the library and a lot of work when you fill up the library.

Instead of just starting to fill up the library from one end to the other, you devise a clever little method. You take the title of the book, run it through a small computer program, which spits out a shelf number and a slot number on that shelf. This is where you place the book.

The beauty of this program is that later on, when a person comes back in to read the book, you feed the title through the program once more, and get back the same shelf number and slot number that you were originally given, and this is where the book is located.

The program, as others have already mentioned, is called a hash algorithm or hash computation and usually works by taking the data fed into it (the title of the book in this case) and calculates a number from it.

For simplicity, let's say that it just converts each letter and symbol into a number and sums them all up. In reality, it's a lot more complicated than that, but let's leave it at that for now.

The beauty of such an algorithm is that if you feed the same input into it again and again, it will keep spitting out the same number each time.

Ok, so that's basically how a hash table works.

Technical stuff follows.

First, there's the size of the number. Usually, the output of such a hash algorithm is inside a range of some large number, typically much larger than the space you have in your table. For instance, let's say that we have room for exactly one million books in the library. The output of the hash calculation could be in the range of 0 to one billion which is a lot higher.

So, what do we do? We use something called modulus calculation, which basically says that if you counted to the number you wanted (i.e. the one billion number) but wanted to stay inside a much smaller range, each time you hit the limit of that smaller range you started back at 0, but you have to keep track of how far in the big sequence you've come.

Say that the output of the hash algorithm is in the range of 0 to 20 and you get the value 17 from a particular title. If the size of the library is only 7 books, you count 1, 2, 3, 4, 5, 6, and when you get to 7, you start back at 0. Since we need to count 17 times, we have 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, and the final number is 3.

Of course modulus calculation isn't done like that, it's done with division and a remainder. The remainder of dividing 17 by 7 is 3 (7 goes 2 times into 17 at 14 and the difference between 17 and 14 is 3).

Thus, you put the book in slot number 3.

This leads to the next problem. Collisions. Since the algorithm has no way to space out the books so that they fill the library exactly (or the hash table if you will), it will invariably end up calculating a number that has been used before. In the library sense, when you get to the shelf and the slot number you wish to put a book in, there's already a book there.

Various collision handling methods exist, including running the data into yet another calculation to get another spot in the table (double hashing), or simply to find a space close to the one you were given (i.e. right next to the previous book assuming the slot was available also known as linear probing). This would mean that you have some digging to do when you try to find the book later, but it's still better than simply starting at one end of the library.

Finally, at some point, you might want to put more books into the library than the library allows. In other words, you need to build a bigger library. Since the exact spot in the library was calculated using the exact and current size of the library, it goes to follow that if you resize the library you might end up having to find new spots for all the books since the calculation done to find their spots has changed.

I hope this explanation was a bit more down to earth than buckets and functions :)

[ B3R1 @ 11.01.2020. 18:06 ] @
Citat:
a1234567:
Već sam pisao, najviše me zapravo zanima rad sa tekstom, a ne kojekakvi matematički problemi.

Sada si me podsetio na one dve legendarne scene iz filma Karate Kid - prve, kao i one kasnije u filmu, druge ... gde ucitelj objasnjava klincu kako je sve u zivotu Kung Fu. A sto rece profesor Edsger Dijkstra: "Programiranje je jedna od najtezih oblasti primenjene matematike. Losim matematicarima bi bilo najbolje da se drze ciste matematike".

Matematicki problemi u pocetnickim zbirkama iz programiranja su vojnicki dril za buduceg programera. Svrha tih zadataka je da te nauce da razmisljas kao programer, sto tebi u ovom trenutku prilicno nedostaje i to se recimo videlo na onom zadatku s bacanjem novcica. Lepo si iskoristio funkciju random.randint(0,1) da dobijes uniformno raspodeljene slucajne ishode nule ili jedinice, a onda si napisao:
    if random.randint(0, 1) == 0:
baci = '1glava'
else:
baci = '0pismo'
print(baci[0], end='')

Znaci, ako ti je rezultat 0 ti to tumacis kao '1glava', a ako ti je rezultat 1 tebi je to '0pismo', da bi kasnije 'pismo' i 'glavu' odsekao i ispisao samo 0 i 1. Nazivi 'glava' i 'pismo' su cist visak. Takodje, nema potrebe da obrces rezultat funkcije randint(), ako imas u vidu da je verovatnoca ishoda 0 i 1 fifty-fifty, zar ne? Prema tome, zasto ne odmah:
    print (random.randint(0,1), end='')

Slicno si uradio i sa ovim recnikom - napravio si strukturu u kojoj su ti kljucevi engleske reci, a vrednosti srpske, da bi onda vrsio obrnuto prevodjenje.

Nemoj da me shvatis pogresno, ovo sto radis je sjajna stvar. Ucis! I to je super! Zapravo, trenutno samo opipavas teren, ali sada je vec vreme da malcice naucis neke temelje struke, kako bi ti se kockice slozile na pravi nacin. Recimo, na netu ces naci gomilu kurseva posveceih uvodu u programiranje i strukturama podataka. Moj favorit je ovaj uvodni Python kurs sa MIT - pokriva sve aspekte Pythona, veoma lep, akademski, metodican, imas video snimke profesora koji pricaju, mozes da skines slajdove da ih listas dok slusas predavanja, sve besplatno dostupno, mozes sve i da downloadujes. I nije namenjen samo buducim programerima, vec studentima svih inzenjerskih disciplina koje se tamo izucavaju, jer je na MIT Python neka vrsta programerskog bukvara za sve studente ... kasnije oni koji rade number crunching uce SciPy/SymPy, a programeri napredne algoritme itd. Mislim da bi ti ovaj kurs pomogao da popunis rupe u znanju. Oni imaju i zadatke za vezbu itd. A mozes i paralelno da nastavis da eksperimentises, naravno. Jednom kada odslusas kurs videces kako ovi zadaci koje postujes ovde pocinju da ti imaju vise smisla.

Na kraju, da se nadovezem na ovo sto je Djole lepo rekao:
Citat:
Onda kada budeš u stanju da napišeš python program od 1000 linija koda (koji RADI), počni da razmišljaš o sebi kao o junior programeru.

A onda kada budes shvatio da je tocak i vatru vec izmislio neko drugi ... i da je vecinu standardnih programerskih zadataka neko vec resio i napravio i Python modul za to ... i da je tvoje samo da proucis dokumentaciju za taj modul, vidis koje su ti funkcije potrebne i opalis jedan 'import modul_taj_i_taj' na pocetku programa (prethodno ces morati da radis 'pip install', doduse ...) - videces da se mnogi problemi resavaju i sa 10 linija, umesto 10000 linija koda. E tada postajes vec medior programer, koji uspesno koristi ono sto vec postoji i ne izmislja toplu vodu svaki put iznova i iznova. A senior ces postati onda kada i sam budes uspeo da napises svoje module. Otprilike tako.

P.S. Ja nisam programer, niti mi je softverski inzenjering ikada bio core business. Kodiranje mi je sporedna stvar u poslu. Bavim se mrezama (IP/MPLS), a Python koristim samo za scripting / network automation ... za sta sam do sada koristio Perl, ponekad bash/awk ...
[ Zurg @ 11.01.2020. 18:27 ] @
Koncept heš tabele je jednostavan. Da bi razumeo heš tabelu, odnosno Dictionary potrebno je prvo da razumeš nizove. Elementima niza pristupaš na osnovu indeksa. Takav pristup je direktan (brz) i vreme pristupa je konstantno. Na primer:

Code:

niz = ["nula", "jedan", "dva"]
print(niz[0]) # 0 je indeks

#print prikazuje vrednost "nula"


Ako imaš gomilu podataka kojima treba da pristupiš na osnovu ključa, a želiš da vreme pristupa ne zavisi od broja elemenata, onda koristiš heš tabelu. Heš tabela ima funkciju koja za svaki ključ generiše indeks i pod tim indeksom čuva vrednost u nizu. Ako ovo razumeš i ne planiraš da implementiraš svoju heš funkciju/tabelu mislim da za sada tu možeš da se zaustaviš i nastaviš da koristiš Dictionary.

(Stvari su malo komplikovanije od onoga što sam napisao. Kada bi imali beskonačno memorije radilo bi odlično, međutim pošto je to nemoguće, onda su neophodni neki kompromisi i zato je bitno pametno osmisliti strategiju heširanja i smeštanja podataka u slučaju da heš funkcija generiše isti indeks za različite ključeve...)

Mali test, da li je Dictionary (heš tabela) dobar izbor ako želimo da u okviru for petlje prođemo kroz sve unose i zašto?


[ Branimir Maksimovic @ 12.01.2020. 00:01 ] @
Beri:"E tada postajes vec medior programer, koji uspesno koristi ono sto vec postoji i ne izmislja toplu vodu svaki put iznova i iznova. "

Ima i kategorija koja se zove skript kidi :P
[ djoka_l @ 12.01.2020. 00:23 ] @
Citat:
Zurg:
Ključevi moraju biti jedinstveni. Ne možeš imati dva unosa sa istim ključem. Kao što ti je Đoka već rekao Dictionary je u stvari heš tabela. Pogledaj prvo šta je heš tabela, npr. https://en.wikipedia.org/wiki/Hash_table ili https://www.youtube.com/watch?v=MfhjkfocRR0

Mogao bi pod ključem agent da čuvaš niz.

Code:
srEn = { 'agent' : ['agent', 'commercial-traveller'] }




Zurg, prvo hvala na konstruktivnom doprinosom u ovoj temi. Drugo, nisam pogrešio kada sam rekao da je kompleksnost pretrage hash tabele O(n). Pogledaj i sam link na wiki koji si ostavio
Doduše, ta kompleksnost je "worst case" scenario, ali ga je vrlo lako isprogramirati izborom lošeg hash algoritma i "štimovanjem" podataka da postigneš worst case.

Drugo, postavljaču teme predlažem da pokuša da piše FUNKCIONALNE SPECIFIKACIJE.
Ne zato da ga obeshrabrim, nego da ga usmerim na pravi put.

Funkcionalnu specifikaciju možeš da posmatraš, sa jedne strane, kao niz obećanja klijentu šta ćeš da uradiš, a sa druge strane, kada programiraš za svoju dušu, podsetnik šta treba da se uradi. To je okvirni plan rada. Kaže se: plan nije ništa, planiranje je sve. Kako drugačije da proceniš da li napreduješ, ako nisi zacrtao ciljeve koje želiš da postigneš?
Ja uvek imam običaj da pravim funkcionalnu specifikaciju za svaki program za koji mi je potrebno više od jednog dana da ga napišem.

Kako bi izgledala funkcionalna specifikacija za rečnik:

1. pretraga rečnika, za reč iz jezika J1 naći reči u jeziku J2.
2. obezbediti pretragu rečnika iz komandne linije
3. obezbediti grafički interfejs za pretragu rečnika (ovo može i kasnije)
4. unos nove odrednice
5. unos novog pevoda
6. postojanje više od dva jezika u rečniku (ako nije suviše teško)
7. snimanje izmena rečnika u fajl
8. korišćenje baze podataka za smeštanje reči

itd.

Onda kreneš da planiraš da uradiš one delove koji su ti lakši da prvo isprogramiraš, a one teže ostaviš za kraj.

U nekom trenutku, uporediš svoju funkcionalnu specifikaciju, ako treba izmeniš ili dodaš novu funkcionalnost i napraviš plan kako da tu funkcionalnost da uradiš.

Recimo, želim grafički interfejs, da li da interfejs napravim kao desktop aplikaciju, ili kao web aplikaciju? Podsetnik: proveri koje grafičke biblioteke mogu da iskoristim za desktop aplikaciju, a koje za web? Ako idem na web, šta mi je od dodatnog softvera potrebno da instaliram? Koliko vremena mi je potrebno da naučim da napravim jednostavnu desktop aplikaciju? Recimo da odredim dve nedelje, pa ako procenim posle nedelju dana da nije dovoljno, menjam plan...


[Ovu poruku je menjao djoka_l dana 12.01.2020. u 01:43 GMT+1]
[ djoka_l @ 12.01.2020. 00:39 ] @
Još neke napomene uz projekat rečnik:

Šta raditi u slučaju, recimo gramatičkih oblika koje imaju isti koren?
Na primer, play može biti imenica igra ili glagol u infinitivu igrati.
Ali play kao glagol može da se pojavi i u oblicima plays kada se koristi uz imenicu ili zamenicu trećeg lice jednine, ili u obliku playing.
Takođe, odrednice u srpskom mogu da budu i igram, igraš, igra, igramo, igrate igraju, igrajući, igrao, igralii i slično.

Šta raditi sa imenicama? Da li treba čuvati imenicu samo u nominativu jednine ili u svim padežima?
Da li treba čuvati rod imenice? U engleskom je to jednostavno, ali u srpskom i nemačkom nema strogog pravila...
Šta raditi sa rečima koje se isto pišu ortografski, ali imaju različito značenje. Na primer "da" može biti afirmacija "yes" ili predlog "to"
Da li ima smisla označavati neke reči kao sinonime ili antonime drugih reči (dakle veza između reči može biti između reči u istom jeziku, a ne samo između reči u različitim jezicima).

Dakle, ti si samo zagrebao vrh teme, a da nisi ozbiljno razmislio...
[ Branimir Maksimovic @ 12.01.2020. 00:40 ] @
"Drugo, nisam pogrešio kada sam rekao da je kompleksnost pretrage hash tabele O(n)."

Jesi. Nemo sad da se vadis ;)

"Doduše, ta kompleksnost je "worst case" scenario,"

worst case svakako, ali to ti je i worst case za stablo.

Kako i stablo biva balanasirano, tako i hash funkcija ne mapira sve kljuceve na jedan broj,
tako da je to teorijski moguce, prakticno nemoguce.
[ djoka_l @ 12.01.2020. 00:56 ] @
Recimo, da je hash tabela realizovana kao niz od k ulaza a svaki ulaz je lista parova key value za key koji daje istu hash vrednost.
Tada je prosečna dužina liste za svaku hash vrednost n/k a prosečno vreme pretrage n/2k, što daje kompleksnost od O(n). Ne treba da se posebno trudiš da postigneš worst case.
Mogu da se naprave i bolji algoritmi za razrešenje kolizije, ali sve je to linearna ili nešto malo bolja kompleksnost...
[ Branimir Maksimovic @ 12.01.2020. 01:00 ] @
Tacno, sa time da hash tabela raste kako se dodaju novi elementi tako da to n/k tezi jedinici. To je poenta hash tabele.
[ a1234567 @ 12.01.2020. 03:32 ] @
Evo prema Đokinom odličnom predlogu, pribeležih ono što mi je palo na pamet u vezi sa projektom rečnik.
Sigurno sam nešto zaboravio, pa dodajte ako imate ideju.

Englesko-srpski rečnik - specifikacija

A. Softver:
1. pretraživanje značenja prema unetoj reči (ili prvim slovima reči u desktop verziji - dropdaun lista)
2.1. preko konzole
2.1. kasnije napraviti desktop aplikaciju
2.2. još kasnije napraviti onlajn izdanje, gde bi korisnici mogli i sami da predlažu nove reči ili njihova značenja (crowdsourcing)
3. mogućnost unošenja novih reči za oba jezika i snimanje izmena
4. mogućnost popravljanja već unetih reči za oba jezika i snimanje izmena
5. mogućnost brisanja već unetih reči za oba jezika i snimanje izmena
6. veličina: do 100.000 reči u svakom od jezika.
7. operativni sistem: windows

B: Sadržaj:
1. Svaka engleska reč ima oznaku za vrstu (n = noun, v = verb, adj = adjective, pre = preposition itd.)
2. Na taj način se pravi razlika između onih koje imaju isti oblik:
play n. = 1. igra, zabava; 2. drama, pozorišna predstava
play v. = 1. igrati (se); 2. svirati; 3. glumiti
3. Različita polja značenja iste reči se odvajaju arapskim brojevima (vidi gornji primer).
4. Fraze u kojima se javlja neka reč idu na kraj značenja te reči i iza kose crte (/). Tako za play:
play v. = 1. igrati (se); 2. svirati; 3. glumiti / to bring into play = staviti u pogon, pokrenuti
5. Oblik imenica je uvek u prvom licu jednine (play, a ne plays)
6. Oblik glagola je uvek u infinitivu bez "to" (work, a ne working ili worked, sem naravno u frazama)
[ Zurg @ 12.01.2020. 06:37 ] @
Đoko, priznaj lepo da nisi u pravu da ne smetamo čoveku dok uči.
[ Branimir Maksimovic @ 12.01.2020. 08:36 ] @
Nego da ti odgovorim na ovo:
"Mali test, da li je Dictionary (heš tabela) dobar izbor ako želimo da u okviru for petlje prođemo kroz sve unose i zašto?"

Ukoliko zelimo sortiran prolaz nije, zato sto hash tabela za razliku od stabla nije sortirana. No u svakom drugom slucaju je hash tabela bolja od stabla.
Znaci uzmi najprostije recimo brojanje reci u nekom vecem tekstu i svako ce videti razliku O(1) hash tabela vs O(log n) stablo.

[ a1234567 @ 12.01.2020. 16:16 ] @
Evo ovde je dobro objašnjena ideja hash tabele.

To ko bibli uoteci knjige i katalog, pa ne tražiš knjigu redom na polici, već u katalogu vidiš njenu signaturu, tj, mesto u magacinu.
E sad vidim ima kao neke kolizije. To kao kad staviš knjigu na pogrešno mesto, pa kad na to isto mesto hoćeš posle da staviš pravu, cvrc, ne može. :)
[ Branimir Maksimovic @ 12.01.2020. 23:26 ] @
"E sad vidim ima kao neke kolizije"

Kolizija je kada dva razlicita kljuca gadjaju isti slot u tabeli. To je ili zato sto hash funkcija nije savrsena ili zato sto ima vise kljuceva nego sto moze da stane.
U slucaju da je ovo drugo onda se poveca velicina i uradi rehashing posle nekog tresholda.
Inace hash tabela je obicno implementirana kao niz listi gde u liste idu kolizije.
[ a1234567 @ 15.01.2020. 12:44 ] @
Počeli smo da mešamo babe i žabe, pa ću napraviti novu temu za englesko-srpski rečnik, a ovde nastaviti da postavljam samo zadatke za ambiciozne početnike.

Evo ga novi, zadatak broj 14:

Napiši program koji će uporediti tri varijable: x, y, z
i ispisati najveći neparni broj među njima. Ako nijedna od varijabli nije
neparan broj, trebalo bi da ispiše odgovarajuću poruku.

Za pravljenje funkcije moguće koristiti jedino dve alatke:
1. if-elif-else petlju i
2. modulo, za proveru je li broj neparan.

Uživajte! :)
[ B3R1 @ 17.01.2020. 10:36 ] @
Zasto samo tri broja? Hajde da malo napravimo zadatak tezim. Neka to bude matrica N x M i da nadjes najveci neparan broj, ali da uz to ispises i koordinate (vrstu i kolonu) gde se taj broj nalazi.
[ a1234567 @ 17.01.2020. 12:03 ] @
Zašto samo tri broja?
Pa jer smo tako u mogućnosti u ovom trenutku :)

Elem, izborih se ja nekako sa 14. zadatkom i svoje rešenje sam postavio ovde.


E sad kad smo ovu preponu preskočili, da vidimo šta predlaže Berislav.

Dakle, treba da bude matrica.
Ali čekaj, pa još nisam radio sa matricama!?

Pa šta čekaš!? :)

I to što kažeš. Dobro, misliš nešto ovako?

brojevi = [[8, 29, 22, 17]
[14, 38, 21, 18]
[15, 52, 40, 39]
[31, 20, 26, 41]]


Jesi ti siguran da se ovo može rešiti samo sa if... else?

Dobro, ako idem ovim metodom kojim sam rešio zadatak četrnaest, red po red, naći ću najveći neparan broj u svakom redu.
Onda od ta četiri broja opet nađem najveći.
Ali mi nije baš jasno kako ću odrediti njegovo mesto.
Jedino za svaki broj da bude promenljiva po nekom nizu, recimo
[a1, a2, a3, a4
b1, b2, b3, b4...]

pa da u odnosu na to koja bude najveća određujem poziciju. Gore bi to bila c2, dakle treći red, druga kolona.
Ili ima neka prečica?
[ B3R1 @ 17.01.2020. 13:31 ] @
Citat:
a1234567: Jesi ti siguran da se ovo može rešiti samo sa if... else?

Ocigledno ne, treba ti i petlja ... 'for' petlja. :-) Mislim, ako resavas opsti slucaj (dimenzija M x N).
Citat:
Ali mi nije baš jasno kako ću odrediti njegovo mesto. Jedino za svaki broj da bude promenljiva po nekom nizu, recimo

Zato sam ti i savetovao da prodjes onaj kurs sa MIT. Tamo lepo objasnjavaju strukture podataka, pocev od skalarnih tipova (str, int, float ...) do vektorskih (list, dict ...). Kada imas listu:
a = [ 10, 20, 50, 100, 200 ]

Elemente liste mozes da dobijes sa:
>>> a[0]
10
>>> a[2]
50

Prvi element liste s leve strane ima indeks 0, slede 1, 2 itd. Slicno tome, u matrici iz tvog primera (zaboravio si zareze na kraju vrsta).
brojevi = [[8, 29, 22, 17],  [14, 38, 21, 18], [15, 52, 40, 39], [31, 20, 26, 41]]

vrednost pojedinih elemenata dobijas sa:
>>> brojevi[0][0]
8
>>> brojevi[0][1]
29
>>> brojevi[2][3]
39

U opstem slucaju brojevi[x][y], gde je x vrsta (0-3), a y kolona (0-3). Znaci, za svaki element liste, odnosno 'liste lista' (matrice) mozes lako da dobijes indeks elementa.

Kako mozes da odstampas / analiziras elemente liste, jedan iza drugog? Koriscenjem 'for' petlje. Imas dva nacina - iterativno, element po element:
lista = [ 10, 11, 12, 13, 14]
for element in lista:
print element

Ili pristupajuci klasicno, indeks po indeks:
for id in range(len(lista)):   # len(lista) = 5 u gornjem primeru:
print lista[id]


A sada nesto sto mozda nisi znao: za razliku od nekih drugih programskih jezika u Pythonu su liste dinamicke, implementirane kao ulancane liste s pointerima. Ako napravis praznu listu:
lista = []

Ona nece imati nijedan element, a ako pokusas da pristupis ili da direktno dodelis vrednost desetog elementa u listi, dobices:
>>> lista[9] = 12
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range

Listu mozes da definises ili direktno (lista = [1, 3, 5, 7, 11]) ili metodom element po element, koriscenjem append() metode:
>>> lista.append(51234)
>>> lista.append(51)
>>> lista.append(3)
>>> lista
[51234, 51, 3]
>>> lista[1]
51

Elemente liste mozes i da brises (pop() / remove()), da umeces elemente usred postojece liste (insert()) itd. Osnovne operacije sa listama mozes da vidis ovde

Medjutim, ponekad ti moze zatrebati prazna lista koja sadrzi svuda nule, a gde mozes proizvoljno da pristupis bilo kom elementu i dodelis mu vrednost. To je narocito pogodno kada prevodis prastare programe koje su neke fortrandzije pisale pre 40 godina, tamo su nizovi staticki definisani i automatski popunjeni nulama. Ili neki Perl skript, u Perlu su sve promenljive kada ih prvi put pozoves uvek nule (osim ako ne koristis 'use strict').

Praznu listu od 10 nula kreiras sa:
lista = [0]*10
>>> lista
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> lista[5]=111
>>> lista
[0, 0, 0, 0, 0, 111, 0, 0, 0, 0]

Slicno tome, matricu 3 x 3 popunjenu nulama mozes da dobijes sa:
>>> matrica = [[0, 0, 0]]*3

ili:
>>> matrica = [[0]*3]*3

U oba slucaja rezultat je isti:
>>> matrica
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]

Takozvanu jedinicnu matricu:
1 0 0
0 1 0
0 0 1

dobijas ovako:
Code:
e = [] # Kreira praznu listu
for i in range(3):
    e.append([]) # Dodaje praznu vrstu matrice
    for j in range(3):
        if (i==j):
           e[i].append(1)
       else:
           e[i].append(0)

U gornjem izrazu 'i==j' je izraz tipa boolean, ciji je rezultat True ili False. Boolean se moze konvertovati u integer funkcijom int() (int(False) = 0, int(True) = 1). Samim tim, ovo gore mozes da skratis:
Code:
e = [] # Kreira praznu listu
for i in range(3):
    e.append([]) # Dodaje praznu vrstu matrice
    for j in range(3):
        e[i].append(int(i==j))  # Daje 0 ako je i!=j, a 1 ako je i==j

Moze li jos krace? Moze! U Pythonu imas lepu stvar koja se zove comprehension, koja ti omogucava da gornji kod skratis na jednu liniju (verovatno si video ovaj trik u Pantinim kodovima, na linku koji sam ti dao imas vise o tome):
Code:
e = [ [ int(i==j) for i in range(3) ] for j in range (3) ]


Mislim da ti sada nece biti tesko da uradis zadatak.


[Ovu poruku je menjao B3R1 dana 17.01.2020. u 15:40 GMT+1]
[ B3R1 @ 17.01.2020. 14:46 ] @
Citat:
a1234567:
Dobro, ako idem ovim metodom kojim sam rešio zadatak četrnaest, red po red, naći ću najveći neparan broj u svakom redu.

Zamisli da stojis pred ljudima (oba pola, imuskarci i zene) postrojenim u vrstu. Ljudi nisu sortirani po visini. U ruci drzis kanap i lenjir. Kako ces odrediti visinu najvise zene u vrsti?

Ako znas odgovor na to pitanje znas da resis i ovaj problem. Misilm da sam ti dovoljno pomogao.
[ Panta_ @ 18.01.2020. 06:43 ] @
Citat:
Dobro, ako idem ovim metodom kojim sam rešio zadatak četrnaest, red po red, naći ću najveći neparan broj u svakom redu.
Onda od ta četiri broja opet nađem najveći.
Ali mi nije baš jasno kako ću odrediti njegovo mesto.

Python lista ima index() funkciju koja vraća poziciju tj. indeks elementa u listi, npr.
Code:
[31, 20, 26, 41].index(41)
3


Sad samo prođi kroz listu i proveri da li je broj neparni i da li je veći od prethodnih, i ako je True, zabeleži ga, kao i njegovu poziciju.
[ B3R1 @ 18.01.2020. 12:31 ] @
Zaboravio sam da pomenem i enumerate(). Kada prolazis kroz listu u for-petlji, listajuci element po element:
for elem in [11, 13, 14, 17, 21]:
print elem

Dobices spisak elemenata liste, jedan ispod drugog. Ali ako zelis da uz to vodis racuna i o njihovim indeksima, mozes da koristis enumerate():
for i, elem in enumerate([11, 13, 14, 17, 21]):
print "%d\t%d" % (i, elem)

U slucaju matrice to je:
matrix = =[[1,3,5], [2, 4, 8], [3, 5, 3]]
for j, row in enumerate(matrix):
for k, cell in enumerate(row):
print "Matrica (%d,%d):\t%d" % (j, k, cell)
# Rezultat:
Matrica (0,0): 1
Matrica (0,1): 3
Matrica (0,2): 5
Matrica (1,0): 2
Matrica (1,1): 4
Matrica (1,2): 8
Matrica (2,0): 3
Matrica (2,1): 5
Matrica (2,2): 3

Inace, ovo je jedan od prvih algoritama koji se obradjuje na svakom pocetnom kursu programiranja - nalazenje minimuma i maksimuma niza. Analogija sa kanapom i strojem ljudi je bas potpuna. Prosta pravolinijska procedura. Ostavljam tebi da sam dodjes do tacnog postupka, nije tesko. A uz enumerate() funkciju diskusija o listama je recimo kompletna.
[ a1234567 @ 18.01.2020. 12:50 ] @
Prošao sam taj deo sa listama, indexima i ostalim.
Lupao glavu danas i evo došao do nekog rešenja kad je obična lista u pitanju:

Code:
niz = [23, 33, 44, 55, 11]
niz_deo = len(niz) - 1
max = [niz[0]]
for i in niz[1:niz_deo]:
    if i%2 != 0 and i > niz[0]:
        max.append(i)
        max1 = max.pop(0)
kolona = niz.index(max[0]) + 1
print('Najveći neparni broj je u koloni: ', kolona)


rezultat:

Najveći neparni broj je u koloni: 4

Onda sam krenuo na listu lista, tj matricu i jasno mi je da treba da imam dve petlje

niz = [[23, 33, 44, 55, 11],
[13, 39, 74, 85, 61],
[67, 49, 94, 37, 10],
[42, 66, 44, 83, 27]]

Code:
max = niz[0][0]

for i in niz:
    for j in i:
        if j%2 != 0 and j > max:


ali imam problem sa upoređivanjem veličine dva broja.
Ovako u prvom prolazu upoređujem j sa prvim brojem u matrici,
ali ne vidim kako da taj max broj posle zamenjujem brojem iz prethodnog prolaza kako prolazim kroz petlju.
[ B3R1 @ 18.01.2020. 14:13 ] @
Mislim da tebi ozbiljno nedostaje algoritamski nacin razmisljanja. Nisam pomenuo uzaludno onu analogiju sa kanapom i vrstom ljudi. Recimo da treba da nadjes najviseg coveka, sta ces uraditi? Imas kanap i lenjir. Znaci, uzmes kanap, stanes ispred prvog coveka, izmeris ga od pete do glave i tacku na kanapu koja dodiruje vrh njegove glave uhvatis prstima (ili vezes cvor, obelezis flomasterom ... sta god ...). Stanes ispred sledeceg, izmeris ga ... pa ako je polozaj prstiju/cvora/fleke na kanapu iznad njegove glave, znaci on je nizi od prethodnog, tako da ides dalje ne menjajuci polozaj prsta ... kada nadjes nekog viseg, pomeras prst navise (ili vezes novi cvor). Na kraju, kada prodjes celu vrstu ljudi, uzmes lenjir i izmeris duzinu kanapa od pocetka do pozicije na kojoj se finalno nalazi prst (odnosno vezao cvor ili sta vec ...) Znaci:
Code:
ljudi = [ 165, 190, 185, 172, 168, 173, 189, 188 ]   # Visine ljudi u vrsti
kanap = ljudi[0]   # Stajem ispred prvog coveka i izmerim ga
covek = 0            # Njegova pozicija je 0
for id, h in enumerate(ljudi):
    if h > kanap:      # Ako je glava coveka iznad kanapa - nasli smo viseg!
        kanap = h      # Pomeramo prst na njegovu visinu
        covek = id      # Upisujemo njegovu poziciju
print 'Najvisi covek u stroju je # ' + str(covek) + ', njegova visina izmerena kanapom je: ' + str(kanap)

Gornje resenje radi dobro, osim za specijalan slucaj kada rekord u visini deli vise ljudi. Onda bi verovatno trebalo da pamtis negde pozicije tih rekordera. Nije tesko izmeniti program da to postigne:
Code:
ljudi = [ 165, 191, 185, 172, 168, 190, 190, 188 ]   # Visine ljudi u vrsti
kanap = ljudi[0]         # Stajem ispred prvog coveka i izmerim ga
covek = [ 0 ]            # Upisujem ga u listu visinskih rekordera
for id, h in enumerate(ljudi):
    if h > kanap:        # Ako je glava coveka iznad kanapa - nasli smo viseg!
        kanap = h        # Pomeramo prst na njegovu visinu
        covek = [ id ]   # Ispraznimo listu i zapamtimo njegovu poziciju 
    elif h == kanap and id > 0:  # Naisao si na coveka iste visine kao trenutno najviseg, ali koji nije prvi sleva
        kanap = h
        covek.append(id) # Dodaj poziciju na listu
if len(covek)>1:
    print 'Najvisi ljudi u stroju su na pozicijama # ' + str(covek) + ', njihovavisina izmerena kanapom je: ' + str(kanap)
else:
    print 'Najvisi covek u stroju je na poziciji # ' + str(covek[0]) + ', njegova visina izmerena kanapom je: ' + str(kanap)


Ovo je zaista bukvar programiranja i prvi zadatak koji se uci na prvim casovima, danas cak i u osnovnoj skoli. Tebi je potrebna dobra knjiga koja se bavi algoritmima i strukturama podataka. Programiranje ne moze da se uci bez sustinskog razumevanja nacina rada, odnonso algoritma programa.
[ Branimir Maksimovic @ 18.01.2020. 14:56 ] @
Cek ti pamtis sve duplikate bez obzira da li je max visina ili nije? Zar ne bi trebalo prvo da odradis maksimum pa onda skupis sve ljude sa datom visinom?

recimo:
Code:

import Data.List
collect l = (foldl (\m (i,h) -> if h == max_h then (i:m) else m) [] $ zip [0..] l , max_h)
    where max_h = maximum l
main = do
    let ljudi = [ 165, 191, 185, 172, 191, 168, 190, 190, 188 ]
    print $ collect ljudi


Code:

~/examples/haskell >>> ./maxheight                                                                                                                                                                                       
([4,1],191)


[ B3R1 @ 18.01.2020. 15:35 ] @
Citat:
Branimir Maksimovic: Cek ti pamtis sve duplikate bez obzira da li je max visina ili nije? Zar ne bi trebalo prvo da odradis maksimum pa onda skupis sve ljude sa datom visinom?
Samo ako su ti ljudi isti kao i trenutni maksimum. U suprotnom, kada se pojavi novi maksimum lista se brise. Recimo, ako je niz [ 180 190 190 195 194 195 193 ], tada pamtim pozicije 1 i 2 (gde su ovi od 190), ali kada naidje ovaj 195 na poziciji 3, niz [1, 2] se brise i dobija vrednost [3]. Na kraju liste bice [3, 5]. Ovo mi je prvo palo na pamet i zahteva samo jedan prolaz kroz listu. Ova tvoja ideja zahteva dva prolaza, ako se ne varam? Ne poznajem haskell uopste. Sigurno ima i boljih resenja, ovo je bio sam brzinski demo ...
[ a1234567 @ 18.01.2020. 15:43 ] @
Citat:
B3R1:
Mislim da tebi ozbiljno nedostaje algoritamski nacin razmisljanja. Nisam pomenuo uzaludno onu analogiju sa kanapom i vrstom ljudi.

Ovo je zaista bukvar programiranja i prvi zadatak koji se uci na prvim casovima, danas cak i u osnovnoj skoli. Tebi je potrebna dobra knjiga koja se bavi algoritmima i strukturama podataka. Programiranje ne moze da se uci bez sustinskog razumevanja nacina rada, odnonso algoritma programa.


Hvala na vrlo plastičnom i jasnom primeru. Pomogao je.
Počeo sam inače da idem kroz Guttagovu knjigu koju si preporučio. Doduše ide polako, ali važno je da napredujem.

Analizirajući tvoj primer, rešio sam i nalaženje najvećeg broja za matrix.

niz = [[23, 33, 44, 55, 11],
[13, 39, 74, 85, 61],
[67, 149, 94, 37, 10],
[42, 66, 44, 83, 27]]

max = niz[0][0]
for i in niz:
for j in i:
if j%2 != 0 and j > max:
max = j
print('Najveći broj je', str(max))

Da bih našao njegovu poziciju, da li i u matrixu mogu da nađem index sa nečim sličnim kao niz.index(max), kao što to radi u običnoj listi?

brojevi = [23, 54, 65, 3, 4, 5, 6, 16, 33, 44]

brojevi.index(65)
2
[ Branimir Maksimovic @ 18.01.2020. 15:49 ] @
Ber:"U suprotnom, kada se pojavi novi maksimum lista se brise."

ah, da, taj detalj sam propustio.
[ Panta_ @ 18.01.2020. 15:59 ] @
Citat:
ali imam problem sa upoređivanjem veličine dva broja.
Ovako u prvom prolazu upoređujem j sa prvim brojem u matrici,
ali ne vidim kako da taj max broj posle zamenjujem brojem iz prethodnog prolaza kako prolazim kroz petlju.

Napisao sam ti u gornjem postu. Na primer:

Code:
for i in niz:
    for j in i:
        if j%2 != 0 and j > m:
            m = j
            p = i.index(j)         
print(m, p)
85 3

Ili sa enumerate:

for i in niz:
    for index, j in enumerate(i):
        if j%2 != 0 and j > m:
            m = j
            p = index

Sa range i len:

for i in niz:
    for index in range(len(i)):
        if i[index] % 2 != 0 and i[index] > m:
            m = i[index]
            p = index

Bez pomoćnih funkcija:

for i in niz:
    c = 0
    for j in i:
        if j % 2 != 0 and j > m:
            m = j
            p = c
       c+=1


Kao što možeš da vidiš iz navedenih primera, Python ima dosta ugrađenih (built-in) funkcija, pored pomenutih, za tvoj zadatak možeš da iskoristiš npr. max() za najveći broj ili filter() da filtriraš neparne brojeve. Na primer:

Code:
max(filter(lambda n: n[1] % 2 == 1, [(index, row) for sub in niz for index ,row in enumerate(sub)]), key=lambda i: i[1])

(3, 85)


https://docs.python.org/3/library/functions.html
[ a1234567 @ 18.01.2020. 16:09 ] @
Bogami, ima dosta načina. Pribeležiću ih.
A ja ni da ubodem makar jedan :))

Za max() sam znao, ali zadatak je bio da se uradi sa for petljom, pa nisam hteo da sabotiram.
[ B3R1 @ 18.01.2020. 16:52 ] @
Citat:
a1234567:
Analizirajući tvoj primer, rešio sam i nalaženje najvećeg broja za matrix.

Ok, odlican pocetak! Ali ja sam ti nasao jedan bag ... ako je niz[0][0] paran broj veci od svih ostalih (npr. 1000), a ostatak matrice ima i neparne brojeve manje od 1000 najveci neparan broj ce biti pogresno ispisan da bude niz[0][0].

Analogija s kanapom: ako su vrsti ljudi stoje samo muskarci, a tebi je zadatak da nadjes najvisu zenu, ako podjes redosledom da meris prvog coveka bez obzira na pol - tu si pogresio. Znaci, moraces da kanap drzis smotan dok ne naidjes na prvu zenu u vrsti. Ako ne naidjes - rezultat je da medju ljudima nema nikoga zenskog pola.

Imas dva resenja: ako se zadatak ogranici samo na skup prirodnih brojeva, tada je ispravka jednostavna i svodi se na zamen linije:
max = niz[0][0]

alternativnom linijom:
max = -1

Takodje, print na kraju programa mora da postane:
if max < 0:
print 'Matrica ne sadrzi neparne brojeve'
else:
print('Najveći broj je', str(max))

Ako program mora da radi nad skupom celih brojeva, tada ces morati da primenis ovu analogiju s kanapom, pa program postaje nesto slozeniji (ali ne preterano):
Code:
m = niz[0][0]                      # Najveci neparan broj
xm = -1                            # Vrsta sa max neparnim brojem
ym = -1                            # Kolona sa max neparnim brojem

for x, i in enumerate(niz):
    for y, j in enumerate(i):

#  Ako je broj paran, vrti dalje
        if j%2 == 0:
            continue

#  Ako jos nismo nasli prvi neparan broj ILI ga vec imamo, ali ovaj neparan broj je veci ...
        if (xm < 0) or (xm >=0 and j > m): 
            m = j
            xm = x
            ym = y

# Ispis
if (xm < 0):
    print 'Matrica nema neparne brojeve'
else:
    print 'Maksimum %d se nalazi na poziciji: [%d,%d]' % ( m, xm, ym)


U svakom slucaju, napredujes odlicno, svaka cast!
[ a1234567 @ 19.01.2020. 01:50 ] @
U ovom drugom primeru mi nije jasno šta ti radi prva polovina ove linija:
if (xm < 0) or (xm >=0 and j > m):

Kad je skratim samo na
if j > m:

Program i dalje radi kako treba.
[ a1234567 @ 19.01.2020. 05:19 ] @
Posle napornog rada, evo nešto malo za opuštanje :)

[ Branimir Maksimovic @ 19.01.2020. 06:10 ] @
Citat:
a1234567:
U ovom drugom primeru mi nije jasno šta ti radi prva polovina ove linija:
if (xm < 0) or (xm >=0 and j > m):

Kad je skratim samo na
if j > m:

Program i dalje radi kako treba.


Dobro si to uocio. Za sve vrednosti xm ovo prolazi tako da xm ne utice na uslov.

[ B3R1 @ 19.01.2020. 10:44 ] @
Evo novog zadatka, ovog puta jedan od klasicnih algoritama. Ostajemo u svetu nizova i matrica.

Dat je veoma dugacak niz prirodnih brojeva, sortiranih u rastucem redosledu - niz = [ 3, 7, 11, 21, 25, 38, 41 ... ], kao i prirodni broj n (npr. n=123). Ubaciti broj n u niz, na odgovarajuce mesto, tako da niz ostane sortiran. Program treba da radi optimalno i za ekstremno velike nizove.

Na prvi pogled, zadatak je jednostavan: prodjes kroz niz od prvog do poslednjeg elementa, pa kada vidis zgodno mesto tu broj zasadis. To je tzv. linearni algoritam i njegova slozenost je O(n), jer je vreme izvrsavanja programa u opstem slucaju proporcionalno velicini niza. Moze li bolje i efikasnije?

Prednog u odgovoru ima postavljac teme, ostali neka se za sada uzdrze ...
[ a1234567 @ 19.01.2020. 11:40 ] @
Evo, javlja se postavljač :)

Ja sam došao do ovakvog rešenja

Code:
niz = [3, 7, 11, 21, 25, 38, 41, 95, 118, 129, 144, 153]
n = 138

for i in niz:
    if i > n:
        ind = niz.index(i)
        niz.insert(ind, n)
        print(niz)
        break


[3, 7, 11, 21, 25, 38, 41, 95, 118, 129, 138, 144, 153]
[ Branimir Maksimovic @ 19.01.2020. 12:04 ] @
Koja je kompleksnost index f-je? Pretpostavljam da je O(n), pa je to ukupno kvadratna slozenost... sto je gore od predlozenog resenja.

edit:
nije kvadratna nego 2n :P

[Ovu poruku je menjao Branimir Maksimovic dana 19.01.2020. u 13:21 GMT+1]
[ B3R1 @ 19.01.2020. 12:30 ] @
U redu, to je sasvim lepo, skolsko resenje. Ali da li ce program optimalno raditi i za 100,000,000 elemenata, ako prodjes kroz ceo niz da bi ustanovio da broj treba ubaciti negde pred sam kraj niza? Imas li neki bolji predlog?

Edit: uzgred, ne radi ti program kada je n > niz[-1] (npr. n=153), kao i kada se n poklapa sa nekim postojecim elementom u nizu.

[Ovu poruku je menjao B3R1 dana 19.01.2020. u 14:50 GMT+1]
[ Branimir Maksimovic @ 19.01.2020. 14:49 ] @
Nego niz nije bas najsrecnija struktura za insertovanje elemenata pogotovo kad je veliki. Lista takodje nije ali dvostruko ulancana lista jeste.
No pitanje je koja je struktura podataka optimalna za ovaj zadatak? Necu reci ali to moze dati ideju kako resiti za niz :P
[ a1234567 @ 19.01.2020. 15:07 ] @
Citat:
B3R1:
U redu, to je sasvim lepo, skolsko resenje. Ali da li ce program optimalno raditi i za 100,000,000 elemenata, ako prodjes kroz ceo niz da bi ustanovio da broj treba ubaciti negde pred sam kraj niza? Imas li neki bolji predlog?

Edit: uzgred, ne radi ti program kada je n > niz[-1] (npr. n=153), kao i kada se n poklapa sa nekim postojecim elementom u nizu.

[Ovu poruku je menjao B3R1 dana 19.01.2020. u 14:50 GMT+1]


Ne znam hoće li raditi, moram da ga testiram :D
Samo da mi ne zariba komp.

Nego, imam drugu ideju.

Šta ako prvo odredim sredinu niza i uporedim broj na sredini sa mojim.
Ako je veći idem desno, ako je manji, idem levo i uštedeo sam očas 50.000.000 prolaza.
Šta misliš? Mada još nemam ideju kakako to praktično da izvedem, ali kao koncept misli da može da prođe :)

Možda sa len(lista), pa podelim na pola i dobijem indeks broja u sredini... i onda uporedim.
Ako tako seckam na pola, doći ću i do liste od recimo 20 brojeva, a onda mogu da odradim kao ovo rešenje koje sam dao.
[ a1234567 @ 19.01.2020. 15:14 ] @
E da, da se pohvalim :)
Išao dalje po onoj tvojoj knjizi, pa došao do zadatka:

za string
s = '1.23, 2.4, 3.123'
izračunaj zbir brojeva.

Code:
s = '1.23, 2.4, 3.123'
q = s.split(', ')
total = 0
for i in q:
    total = total + float(i)
print(total)

i radi!

6.753
[ B3R1 @ 19.01.2020. 17:44 ] @
Citat:
a1234567:
Šta ako prvo odredim sredinu niza i uporedim broj na sredini sa mojim. Ako je veći idem desno, ako je manji, idem levo i uštedeo sam očas 50.000.000 prolaza.
...
Ako tako seckam na pola, doći ću i do liste od recimo 20 brojeva, a onda mogu da odradim kao ovo rešenje koje sam dao.

Tacno tako! Uporedis broj na sredini sa zadatim. Ako je zadati broj veci, pomeris donju granicu niza na sredinu. Ako je broj maji pomeras gornju granicu na sredinu. Sada tu polovinu u kojoj se nalazi broj opet delis na pola. Ako je broj manji, gornju granicu pomeras na tu novu sredinu; ako je veci pomeras donju itd. Onda tu cetvrtinu delis na pola itd. dok ne dodjes do liste od dva broja.

Pokusaj da implementiras, nije tesko. Vidis kako ti lepo ide ...
[ a1234567 @ 20.01.2020. 02:22 ] @
Ništa nije teško, kad rešiš :)

Ali zato dok ne rešiš, muke Isusove.
Mislim, ideja za rešenje mi je bila jasna relativno brzo,
ali sam celo popodne lupao glavu oko implementacije.
No, mislim da sam došao do rešenja:

Code:
niz = [3, 7, 11, 21, 25, 38, 41, 95, 118, 129, 144, 153, 174]
niz_2 = niz.copy()
broj = 138

while len(niz) != 1:
    mid = int(len(niz)/2)
    if broj > niz[mid]:
        niz = niz[mid:]
    else:
        niz = niz[:mid]

br_niz = niz.pop(0)
indx = niz_2.index(br_niz)

if broj > br_niz:
    niz_2.insert(indx + 1, broj)
elif broj < br_niz:
    niz_2.insert(indx - 1, broj)
else:
    niz_2.insert(indx - 1, broj) #ovo u slučaju da je zadati broj isti kao i  neki u nizu

print(niz_2)


Dosta sam vremena izgubio oko while funkcije, jer sam prvo stavio
while len(niz) == 1:
misleći da će se izvršavati, dok len ne postane 1. Ali, naravno, ništa se nije dešavalo.
Posle n pokušaja i očajanja :) uzmem knjigu i pročitam o while funkciji, a tamo lepo piše da se izvršava
sve dok uslov nije ispunjen. I onda mi sine šta treba da menjam.

Imao sam takođe muku kad na kraju dobijem listu od jednog člana, recimo niz = [129], kako da vrednost
tog člana pretvorim u integer, da bih mogao da dobijem njegov index. I onda natrčim na niz.pop funkciju. Zlata vredi! :)

Eto tako. Ovo je rudarski posao. Korak po korak, kao da kopam tunel i pipam u mraku.
Ali zato kad ga prokopaš i na kraju te obasja svetlo rešenja! :))) Ništa lepše!
[ Branimir Maksimovic @ 20.01.2020. 06:59 ] @
E sad insert u niz je O(n)...
Koja struktura podataka je idealna za ovaj zadatak?
[ a1234567 @ 20.01.2020. 07:10 ] @
Šta ti je O(n)?

Koja vrsta?
Pa valjda lista.
[ Branimir Maksimovic @ 20.01.2020. 07:19 ] @
To znaci n operacija (linearno). Znaci kada umeces element u niz, onda moras sve elemente sa desne strane da pomeris za jedno mesto sto je O(n).
[ a1234567 @ 20.01.2020. 07:30 ] @
Aha, pa dobro, pomerio sam ih, naravno. Ne možeš drugačije da ubaciš.
A što je to bitno? I dalje ne razumem smisao pitanja. Što i nije čudo, kad se bolje razmisli :)
[ a1234567 @ 20.01.2020. 07:33 ] @
A evo i novog zadatka iz Guttagove knjige:

Napiši program koji traži od korisnika da unese neki integer,
a potom štampa dva druga integera, root i pwr, tako da 0 < pwr < 6,
a root**pwr je jednako integeru koji je uneo korisnik.
Ako takav par inetegera ne postoji, program ispisuje odgovarajuću poruku.
[ Branimir Maksimovic @ 20.01.2020. 11:43 ] @
Citat:
a1234567:
Aha, pa dobro, pomerio sam ih, naravno. Ne možeš drugačije da ubaciš.
A što je to bitno? I dalje ne razumem smisao pitanja. Što i nije čudo, kad se bolje razmisli :)


Pitanje je koja je struktura podataka idealna za ovaj zadatak ;)?
[ B3R1 @ 20.01.2020. 12:07 ] @
Citat:
a1234567:
Aha, pa dobro, pomerio sam ih, naravno. Ne možeš drugačije da ubaciš.
A što je to bitno? I dalje ne razumem smisao pitanja. Što i nije čudo, kad se bolje razmisli :)

Branimir je mislio da te natera da pogledas kako su liste u Pythonu implementirane interno ... bas kao sto je onomad bila diskusija o tome kako su implementirani dict-ovi, pa si naucio da je to hash tabela, sto te je nateralo da naucis malo vise o hashevima ... Nije tesko pronaci i ovo o listama, dovoljno je da odes na Gugl i otkucas: python lists implementation ... i izaci ce ti gomila clanaka na tu temu. Tu ces videti tacno kako radi insert(), pop() itd.

U tim clancima su ponedge ponudjene i alternative. Ali mislim da si u ovom trenutku suvise daleko od tih alternativa. To je neki intermediate nivo ...
[ Branimir Maksimovic @ 20.01.2020. 12:15 ] @
Mislio sam na binarno stablo al ajde ;)
Nego, jel u pythonu ispod lista ili niz? U haskell-u je lista, pa je pristup preko index-a O(n) a insert jedino moguc na pocetak...
il opet O(n).
Znaci bilo lista bilo niz insert ce da uzme O(n), tako da sam mislio da implementira binarno stablo :P
Binarno stablo pretrazivanja je 1) sortirano 2) insert uzima O(log n)
Idealno za niz od 100_000_000 elemenata.
[ B3R1 @ 20.01.2020. 12:27 ] @
Citat:
Branimir Maksimovic:
Nego, jel u pythonu ispod lista ili niz? U haskell-u je lista, pa je pristup preko index-a O(n) a insert jedino moguc na pocetak...

https://www.laurentluce.com/posts/python-list-implementation/
Insert je O(n).
Citat:
Znaci bilo lista bilo niz insert ce da uzme O(n), tako da sam mislio da implementira binarno stablo :P

Linkovane liste, dvostruko ulinkovane liste, binarna stabla ... su vec napredniji kurs, a covek je tek na pocetku pocetaka. :-)

Inace za sve te strukture postoje moduli.
[ a1234567 @ 20.01.2020. 12:57 ] @
Ja tek seo na bicikl, a Branimir bi već da me posadi u bolid.
Polako čoveče, trebal negde da se skrljam!? :)))

Binarna i druga listopadna stabla... doći će i to na red jednog dana.
Sad smo još kod zimzelenih stringova, lista, rečnika i tupli. Zimski period :)
[ a1234567 @ 20.01.2020. 13:02 ] @
Berislave, jesi pogledao rešenje za tvoj zadatak koje sam dao?
Ima li neki bag ili da ga štrikliram?
[ B3R1 @ 20.01.2020. 14:03 ] @
Citat:
a1234567: Berislave, jesi pogledao rešenje za tvoj zadatak koje sam dao?
Ima li neki bag ili da ga štrikliram?

Ako si ga dobro testirao i ako radi nema razloga da ti ne verujemo. :-) Testiranje bi trebalo da obuhvati broj manji od niz[0], broj veci od niz[-1] i neki broj u sredini. Potom da vidis kako ce program reagovati za niz tipa [ 5, 5, 5, 5, 5 ] a da je zadata vrednost 4, 5 ili 6. Potom da testiras za niz [ 5 ] i niz [ 5, 5 ] i [ 5, 6 ]. Ako za sve te slucajeve radi, resio si problem. Izmisli jos slucajeva. Testiranje softvera je nauka za sebe, inace ...

Moja jedina zamerka bi bila da su ti dva niza visak. Motivacija za to ti je verovatno bila da sacuvas prvobitni niz kako bi ga kasnije modifikovao, a da nad originalnim nizom radis svu "hirurgiju". Nema nikakve potrebe za hirurgijom, imajuci u vidu da ti vec rukujes indeksima. Niz menjas tek na kraju. Evo alternativnog resenja:
Code:
niz = [3, 7, 11, 21, 25, 38, 41, 95, 118, 129, 144, 153, 174]
broj = 138

if broj < niz[0]:
    niz.insert(0, broj)
elif broj > niz[-1]:
    niz.append(broj)
else:
    levo = 0
    desno = len(niz)

    while desno-levo > 1:
        mid = (levo + desno) / 2
        if broj >= niz[mid]:
            levo = mid
        else:
            desno = mid
    niz.insert(desno, broj)
print niz
[ Branimir Maksimovic @ 21.01.2020. 01:37 ] @
Mislim da generalno da radis binary search tako sto ces da slajsujes, a onda pozoves index nad elementom nije nesto sto ima intellectual merit :P
[ a1234567 @ 22.01.2020. 17:16 ] @
Novi, zanimljiv zadatak broj 15:

Napiši program koji će dešifrovati poruku pisanu Morzeovom azbukom?

U slučaju da možda, eventualno, ipak ne znate znakove ove azbuke, ovde su:

morse = {"A" : ".-", "B" : "-...", "C" : "-.-.", "D" : "-..", "E" : ".", "F" : "..-.", "G" : "--.", "H" : "....", "I" : "..", "J" : ".---", "K" : "-.-", "L" : ".-..", "M" : "--", "N" : "-.", "O" : "---", "P" : ".--.", "Q" : "--.-", "R" : ".-.", "S" : "...", "T" : "-", "U" : "..-", "V" : "...-", "W" : ".--", "X" : "-..-", "Y" : "-.--", "Z" : "--..", "0" : "-----", "1" : ".----", "2" : "..---", "3" : "...--", "4" : "....-", "5" : ".....", "6" : "-....", "7" : "--...", "8" : "---..", "9" : "----."}

Poruka koju treba dešifrovati je:

".... . .-.. .-.. --- .-- --- .-. .-.. -.."

Ja sam svoje rešenje sačuvao ovde.

Naravno, kad napravimp ovaj program, naredni zadatak može biti njegova nadogradnja, da prevodi u ova smera.
Ali polako, korak po korak :)
[ a1234567 @ 23.01.2020. 06:08 ] @
Evo, noćas mi se javilo i kako doraditi program da prevodi u oba smera :)

Prepravio rešenje od juče i postavio
na isto mesto
[ Panta_ @ 23.01.2020. 06:56 ] @
Code (python):
print(' '.join({v:k for k, v in morse.items()}.get(l) for l in ".... . .-.. .-.. --- .-- --- .-. .-.. -..".split(' ')))
H E L L O W O R L D

print(' '.join(morse.get(l, ' ') for l in "HELLO WORLD"))
.... . .-.. .-.. ---   .-- --- .-. .-.. -..
 


Malo potpuniji rečnik:

Code (python):
{'A': '.-',
 'B': '-...',
 'C': '-.-.',
 'Č': '-..-',
 'Ć': '--.-',
 'D': '-..',
 'DŽ': '-.--',
 'Đ': '..-..',
 'E': '.',
 'F': '..-.',
 'G': '--.',
 'H': '....',
 'I': '..',
 'J': '.---',
 'K': '-.-',
 'L': '.-..',
 'M': '--',
 'N': '-.',
 'O': '---',
 'P': '.--.',
 'Q': '--.-',
 'R': '.-.',
 'S': '...',
 'Š': '----',
 'T': '-',
 'U': '..-',
 'V': '...-',
 'W': '.--',
 'X': '-..-',
 'Y': '-.--',
 'Z': '--..',
 'Ž': '.--',
 '1': '.----',
 '2': '..---',
 '3': '...--',
 '4': '....-',
 '5': '.....',
 '6': '-....',
 '7': '--...',
 '8': '---..',
 '9': '----.',
 '0': '-----',
 '.': '.-.-.-',
 ',': '--..--',
 ':': '---...',
 ';': '-.-.-.',
 '?': '..--..',
 '!': '-.-.--',
 '-': '-....-',
 '/': '-..-.',
 '()': '..-.'}
[ a1234567 @ 23.01.2020. 07:13 ] @
Odlično, Panto, apdejtovao sam kod!
[ B3R1 @ 24.01.2020. 14:11 ] @
Hmmm ... i dalje ne kapiras kako radi Python dict:
Code:
for i in poruka2:
    for key, value in morse.items(): 
       if i == key: 
            print(value, ' ', end='')

Cemu ovo? morse[key] ti daje direktnu vrednost 'value', prema tome dovoljno je reci:
Code:
for i in poruka2:
    if (i in morse):
        print(morse[i], ' ', end='')

Nesto tezi slucaj je ovaj inverzni, kada sa Morzeovog koda prevodis u alfabet. Tu vec ima smisla ova "for key, value ..." petlja, mada moze i elegantnije: tako sto ces uvesti poseban dict gde su kljucevi Morzeovi kodovi, a vrednosti slova alfabeta. Ali svakako da ne moras da rucno pravis taj drugi dict - njega pravis na pocetku programa na osnovu 'morse':
Code:
alphabet = {}
for key, value in morse:
    alphabet[value] = key

ili skraceno:
Code:
alphabet = dict((v, k) for k, v in morse.iteritems())

Time se program uproscava:
Code:

for i in poruka1:
    if (i in alphabet):
        print(alphabet[i], ' ', end='')
for i in poruka2:
    if (i in morse):
        print(morse[i], ' ', end='')



[ a1234567 @ 24.01.2020. 15:05 ] @
To rešenje za poruka2 sam samo prepisao od poruka1 i zamenio šta je trebalo zameniti :)
I pošto radi, ništa više ne pipam!
[ a1234567 @ 24.01.2020. 15:13 ] @
E a sada da mi krenemo na zadatak broj 16.

Ovoga puta je vrlo kratak, treba zadati broj ispisati slovima.

Unesi pozitivan broj od 1 do 1000: 529
petsto dvadeset devet


Svoje rešenje sam sačuvao ovde.
[ a1234567 @ 25.01.2020. 07:49 ] @
Evo jedan, što bi pravi programeri rekli, trivijalan zadatak i to broj 17

Napravi program koji će prebrojati i potom ispisati sva unikatna slova i znakove u zadatom tekstu.

Svoje rešenje sam sačuvao ovde.
[ Panta_ @ 25.01.2020. 11:45 ] @
Imaš jedno if viška, zameni ga sa and.
[ a1234567 @ 25.01.2020. 13:50 ] @
bilo je sa and, al ne radi kako treba
pa sam zato stavio u drugi red.
[ a1234567 @ 25.01.2020. 17:52 ] @
Zadatak broj 18

Treba napraviti računaljku za onu igru Scrabble, gde slažeš kockice sa slovima, kao u ukrštenim rečima,
Svako slovo nosi određeni broj bodova, tako da kad sastaviš reč, dobijaš zbir tih bodova.

Nije neki problem, sve dok nisam došao do sabiranja naših slova od dva znaka: LJ, NJ, DŽ
jer ih petlja razloži, pa računa svako slovo posebno.

Dakle, stigao sam dovde:

Code:
bodovi = {'A' : 1, 'E' : 1, 'I' : 1, 'L' : 3, 'N' : 2, 'O' : 1,
          'R' : 2, 'S' : 2, 'T' : 2, 'U' : 1, 'D' : 2, 'G' : 2,
          'B' : 3, 'C' : 5, 'M' : 3, 'P' : 3, 'F' : 4, 'H' : 4,
          'V' : 3, 'K' : 3, 'J' : 3, 'DŽ' : 10, 'LJ' : 10, 'NJ' : 10,
          'Č' : 8, 'Ć' : 8, 'Š' : 5, 'Ž' : 8, 'Đ' : 10, 'Z' : 5}

rec = 'DANAS'

zbir = 0

for i in rec:
    zbir += bodovi[i]

print('Zbir za ovu reč je:', zbir)


Ali kako obračunati kad je reč recimo 'LJUDI'?

Trebalo bi valjda sa nekim find prvo ustanoviti ima li ta tri slova u zadatoj reči i ako ima za svako dodati 10 bodova. Onda izbaciti iz reči to slovo i obračunati za ostala kao što je gore dato.
[ Panta_ @ 26.01.2020. 06:18 ] @
Recimo, jednostavno da kreiraš promenljivu npr. t i da bude t=i svaki put osim kada je t+i u recniku.

"bilo je sa and, al ne radi kako treba"

if i not in slova and i != ' '
[ Branimir Maksimovic @ 26.01.2020. 06:59 ] @
Kako je 'LJ' slovo od dva znaka, jednostavno tako treba i uneti.
[ a1234567 @ 26.01.2020. 07:05 ] @
Da, i onda ga računa
L = 3
J = 3
dakle ukupno 6,
a LJ je u stvari 10 bodova!?
[ djoka_l @ 27.01.2020. 18:38 ] @
Inženjeru koji ima samo čekić, svaki problem izgleda kao ekser.
Nemoj samo šablonski da razmišljaš...

Code:
bodovi = {'A' : 1, 'E' : 1, 'I' : 1, 'L' : 3, 'N' : 2, 'O' : 1,
          'R' : 2, 'S' : 2, 'T' : 2, 'U' : 1, 'D' : 2, 'G' : 2,
          'B' : 3, 'C' : 5, 'M' : 3, 'P' : 3, 'F' : 4, 'H' : 4,
          'V' : 3, 'K' : 3, 'J' : 3, 'DŽ' : 10, 'LJ' : 10, 'NJ' : 10,
          'Č' : 8, 'Ć' : 8, 'Š' : 5, 'Ž' : 8, 'Đ' : 10, 'Z' : 5}

rec = 'LJUDI'

zbir = 0
i = 0

while i<len(rec):
    spec = rec[i:i+2]
    if spec == 'LJ' or spec == 'NJ' or spec == 'DŽ':
       zbir+=10
       i+=2
    else:
       zbir += bodovi[rec[i]]
       i+=1

print('Zbir za ovu reč je:', zbir)


Inače, programi za parsiranje regularnih izraza koriste "look ahead" odnosno "look behind" tehnike za uparivanje. Ovo je jedna implementacija look ahead tehnike. Nije dovoljno sam na osnovu tekućeg slova da se odredi vrednost, nego je, ponekad, potrebno i sledeće slovo...
[ djoka_l @ 27.01.2020. 18:51 ] @
Drugim rečima, ako ti trebaju dva slova, ima da uzmeš dva slova...

[ Panta_ @ 27.01.2020. 20:13 ] @
Naveo sam gore primer za pomenuti problem, a evo i da ga implementiram, na primer:

Code (python):
rec = 'LJUDI'
zbir = 0
t = ''

for i in rec:
    if t != '' and bodovi.get(t+i):
        zbir += bodovi[t+i]
        zbir-=bodovi[t]
    else:
        zbir += bodovi[i]
        t=i        

print('Zbir za ovu reč je:', zbir)
Zbir za ovu reč je: 14


Radi i kada nije vrednost za sva tri slova 10.
[ djoka_l @ 27.01.2020. 20:28 ] @
Uradi si praktično isto što i ja, možda malo elegantnije.
Moja ideja je samo bila da pokažem da nije hash lista jedini alat (čekić) u torbi sa alatom, nego da može i na drugačiji način da se radi.
[ a1234567 @ 28.01.2020. 03:17 ] @
E super ste obojica, hvala na rešenju!

Ali:
Đokino rešenje mi je sasvim jasno,
a tvoje Panto uopšte ne kapiram šta radi taj t = ''
Kako on dobije vrednost drugačiju od praznog niza?

Daj neki komentar, ne škrtari :)
[ Panta_ @ 28.01.2020. 07:51 ] @
Prilično jednostavno. Osnovno, ukoliko uslov (if) nije ispunjen tj. ako t+i nije u rečniku, izvršava se else, tj. t=i, zatim, pri narednom prolasku petlje (for), t je L a i je J, kako je 'L' + 'J' u rečniku, izvršava se if, itd.

Možeš ovde da vidiš kako se navedeno izvršava, unesi kod i klikni na Visualize Execution dugme, zatim postepeno klikni na Next dugme.
[ a1234567 @ 28.01.2020. 12:22 ] @
Sad sam uklavirio. Kad sam video da oduzimaš t u slučaju da je [t+i]. Toga se ne bih nikad setio.
Lepo sam ja rekao još onomad, Panta mađioničar :)

E pa dobro, ovo je bilo korisno, jer sam naučio novu stvar koju je Đoka pomenuo: look ahead.
Moram to malo pogledati na netu. Nego mi pada na pamet da smo tom tehnikom mogli izbrojati one nizove jedinica i nula kad smo računali pismo i glava.

00011100001111010100111100
[ a1234567 @ 05.02.2020. 15:58 ] @
Evo stiže i zadatak broj 19.
Još malo pa jubilej!

E ovoga puta je stvar malo drugačija. Do sada sam kucao tekst u IDLE, pa F5 i program se izvrši. Sada menjamo taktiku.
Dakle, treba napisati program, sačuvati ga na disku, pa ga pokrenuti preko komandne linije.

Pri pokretanju programa dodajemo i jedan argument, a to je ime tekstualnog fajla.
Nešto ovako:

>>> python moj_program.py text.txt

Naš programčić treba da učita taj tekstualni fajl, proveri da li je dat argument. Ako nije, ispiše odgovarajuću poruku.
Ako jeste dat, onda ispiše poslednjih deset redova teksta iz učitanog fajla..

Kažu da u unix sistemima postoji isti ovakav program, koji se zove tail. Ajd da im verujemo :)



[Ovu poruku je menjao a1234567 dana 06.02.2020. u 02:55 GMT+1]

[Ovu poruku je menjao a1234567 dana 06.02.2020. u 02:56 GMT+1]
[ Branimir Maksimovic @ 05.02.2020. 16:23 ] @
Nije isti, moze mnogo vise.
[ a1234567 @ 06.02.2020. 01:54 ] @
Pa šta smo mi windowsaši šugavi, pa je taj program samo za unix!?
E napravićemo još bolji i još stariji
[ a1234567 @ 06.02.2020. 02:00 ] @
Rešenje zadatka broj 19
postavio sam ovde.

[Ovu poruku je menjao a1234567 dana 06.02.2020. u 05:21 GMT+1]
[ Branimir Maksimovic @ 06.02.2020. 02:17 ] @
Citat:
a1234567:
Pa šta smo mi windowsaši šugavi, pa je taj program samo za unix!?
E napravićemo još bolji i još stariji :D


tail koristim za pracenje log-ova, i da vidim zadnje linije izlaza neke komande.
recimo tail -f logfile ili : komanda | tail -n 10

znaci, u prvom slucaju -f opcija da se prati fajl kako raste a u drugom cita sa stdin-a
pa -n prikazuje zadnjih toliko linija izlaza.
Napravi tako na Win-u :P
[ a1234567 @ 06.02.2020. 04:22 ] @
Napravio sam da se vidi poslednjih deset lniija.
Nisam još probao, ali pretpostavljam da mogu da ga prepravim da vidi poslednjih n linija, a da -n bude argument.
[ Panta_ @ 06.02.2020. 11:28 ] @
"Napravio sam da se vidi poslednjih deset lniija."

Dobro je to ako imaš mali fajl, npr. par MB ili malo više, a ša ako recimo imaš fajl od par GB ili više. Na primer:
Code:
du -h log.txt 
1.6G    log.txt

# Komanda tail
$ time tail log.txt
tail log.txt  0.00s user 0.00s system 85% cpu 0.002 total

# Tvoj tail program
$ time ./tail.py
./tail.py  8.74s user 0.40s system 99% cpu 9.139 total


Problem je što tvoj kod prolazi kroz ceo fajl da bi prikazao poslednjih 10 linija, zar nije bolje da krene od poslednje linije u fajlu.

Da definišeš poziciju, pogledaj seek funkciju:
Citat:
seek(target, whence=0, /) method of _io.BufferedReader instance
Change stream position.

Change the stream position to the given byte offset. The offset is
interpreted relative to the position indicated by whence. Values
for whence are:

* 0 -- start of stream (the default); offset should be zero or positive
* 1 -- current stream position; offset may be negative
* 2 -- end of stream; offset is usually negative

Return the new absolute position.

Na primer:

Code:
# Krece od poslednje linije
position = fh.seek(0, 2)
# ....

$ time ./tail.py
./tail.py  0.02s user 0.00s system 97% cpu 0.025 total


Mnogo bolje zar ne? Sad ti samo ostaje da implementiraš ostatak koda.
[ a1234567 @ 06.02.2020. 11:45 ] @
"97% cpu"
Ovo mi se najviše dopada. Al sam ga nagazio, do daske! :D
Pa nek radi. Bolje nego da se hvata na njega prašina :)

Dobro, veliki fajl. Ja sam krenuo sa txt fajlom od 50 redova, sitno,
a ti Panto bi odmah u veleprodaju. Lagano, dok se uhoda radnja.

Za seek znam. E to sam se patio dok nisam prokljuvio, zašto neće da čita fajl opet ispočetka, već došao do kraja i na print samo mi kaže "".
Ni makac!

Da bolje je otići na kraj fajla, pa krenuti odnazad.
A jel ima neka komanda reverse, ko u listi [-1], pa pretumba redove i čita poslednje od početka?
[ Panta_ @ 06.02.2020. 12:04 ] @
Tvom programu treba 9 sekundi da se izvši dok se tail komanda izvršava za 0.002.
[ djoka_l @ 06.02.2020. 12:14 ] @
To 97% ne znači to što ti misliš.

To samo znači da je 97% realnog vremena (vremena između momenta od kada si lupio enter dok se nije komanda završila) procesor radio nad tvojim programom u poređenju sa vremenom koje je tvoj program stvarno potrošio.

Drugim rečima, računar nije radio ništa pametno, osim što je izvršavao python program.
Da je bilo nešto drugo da se radi, ne bi ti bio dodeljeno 97% procesorskog vremena. Idealno, želeo bi da dobiješ iznad 98% , ali to je malo teže na sistemu koji ima šta pametno da radi, a ne da vrti školske python programe.
[ Panta_ @ 06.02.2020. 12:23 ] @
"A jel ima neka komanda reverse, ko u listi [-1], pa pretumba redove i čita poslednje od početka?"

Ima reversed ili readlines()[::-1].
[ Branimir Maksimovic @ 06.02.2020. 15:56 ] @
Inace ovo se najbrze radi tako sto se fajl mapira u memoriju pa se cita od pozadi. E sad ne verujem da je to izvodljivo u Pythonu osim preko C biblioteke, a verujem da to mora
da ima.
[ a1234567 @ 06.02.2020. 16:46 ] @
Naišao sam na ovo zanimljivo rešenje

Code:
with open('logfile.txt', 'rb') as f:
    f.seek(-2, 2)
    while f.read(1) != b'\n':
        f.seek(-2, 1) 
    print(f.readline().decode())


Vrati ga do kraja fajla i onda ide redom unazad po dva bajta dok ne naiđe na kraj reda.
Ali tako otprinta samo poslednji red fajla.
E sad kako da to uradi recimo 5 puta.

Stavio ga u petlju, ali mi printa pet puta poslednju rečenicu :)

Kako ga ubediti da nastavi unazad od prvog kraja reda?

[ Panta_ @ 06.02.2020. 19:52 ] @
Zapamti poziciju pre f.readline(). readline() resetuje poziciju na kraj linije, pa petlja ponovo vrti istu liniju. Na primer:
Code (python):
with open('logfile.txt', 'rb') as f:
    f.seek(-2, 2)
    counter = 0
    while counter < 5:
        while f.read(1) != b'\n':
            f.seek(-2, 1)
        pos = f.tell()
        print(f.readline().decode())
        f.seek(pos - 2)
        counter += 1
[ a1234567 @ 07.02.2020. 01:59 ] @
Tako sam i ja zamišljao da mu sa fajl.tell() zabeležim poziciju,
ali nisam znao kako da nastavim.

No, ovo tvoje rešenje štampa redove unazad, 5, 4, 3, 2, 1.

Ja sam još malo doradio i sad printa redovnim redosledom 1, 2, 3, 4, 5

Code:
redovi = []
with open('new1.txt', 'rb') as f:
    f.seek(-2, 2)
    counter = 0
    while counter < 5:
        while f.read(1) != b'\n':
            f.seek(-2, 1)
        pos = f.tell()
        redovi.append(f.readline().decode())
        f.seek(pos - 2)
        counter += 1
print(*redovi[::-1], sep='\n')
[ Panta_ @ 07.02.2020. 05:25 ] @
Nije to moje rešeje već tvoje, samo sam ti napisao kao da pređe na novu liniju, da ne vrti uvek istu. Ima tu još nedostataka, šta ako recimo fajl ima samo 3 linije, tj. manje od onoga što je navedeno u counter. Linuksova tail komanda radi iako je podrazumevano 10.
[ djoka_l @ 07.02.2020. 11:19 ] @
Citat:
Branimir Maksimovic:
Nije isti, moze mnogo vise.


Kao što reče Branimir, radi mnoooogo više.
AKo te interesuje kako izgleda "pravi" program za tail, može lako da se nađe izvorni kod:
https://github.com/coreutils/coreutils/blob/master/src/tail.c

Nije naročito veliki program, samo 2537 linija C koda, mogu da se nauče lepe stvari...
[ a1234567 @ 07.02.2020. 15:25 ] @
Citat:
Panta_:
Nije to moje rešeje već tvoje, samo sam ti napisao kao da pređe na novu liniju, da ne vrti uvek istu. Ima tu još nedostataka, šta ako recimo fajl ima samo 3 linije, tj. manje od onoga što je navedeno u counter. Linuksova tail komanda radi iako je podrazumevano 10.


Hm. Pa zato smo tražili ovo rešenje, jer su pretpostavljeni fajlovi mnooogo veći od 3 reda.
Mada, ok, mogao bi prvo program da prebroji redove u fajlu i onda limitira broj traženih redova za izlistavanje.

Ali onda smo opet na početku. Kako prebrojati redove, a da program ne prođe kroz ceo fajl?
Što smo hteli da izbegnemo :)
[ a1234567 @ 07.02.2020. 15:35 ] @
Citat:
djoka_l:

Kao što reče Branimir, radi mnoooogo više.
AKo te interesuje kako izgleda "pravi" program za tail, može lako da se nađe izvorni kod:
https://github.com/coreutils/coreutils/blob/master/src/tail.c

Nije naročito veliki program, samo 2537 linija C koda, mogu da se nauče lepe stvari...


Pogledao, lepo izgleda, samo što ne razumem mnogo.
No, blizu sam. Još svega 2530 redova :))

Nego, kod ovog pozivanja programa preko komandne linije,
kako dajem mogućnost za dodatne parametre?
Recimo, ako hoću da zadam broj linija koje treba da izlista.

> python tail.py new1.txt 5

[ Panta_ @ 07.02.2020. 21:02 ] @
Citat:
Hm. Pa zato smo tražili ovo rešenje, jer su pretpostavljeni fajlovi mnooogo veći od 3 reda.
Mada, ok, mogao bi prvo program da prebroji redove u fajlu i onda limitira broj traženih redova za izlistavanje.

A možeš samo da proveriš poziciju, tj. ako je f.tell() == 0 (početak fajla), onda prekineš dalje izvršavanje (break) i ispišeš linije.
[ a1234567 @ 08.02.2020. 02:00 ] @
Ne razumem ideju.

Posle open svakako je pozicija na početku fajla, koliko god da ima redova taj fajl.
U čemu je poenta sa proveravanjem pozicije?
[ djoka_l @ 08.02.2020. 02:11 ] @
Ideja koju ti je Panta dao je da kreneš UNAZAD (seek metoda) od kraja fajla i da brojiš redove.
Kada izbrojiš 10 redova ILI kada si u pretrazi došao do početka (tell daje 0), onda izlaziš iz petlje i ispisuješ redove.
[ a1234567 @ 08.02.2020. 07:09 ] @
E sad sam skapirao. Polako to ide, ali eto, mrda :)

Dakle, plan:

zadaš broj redova, recimo 5
otvoriš fajl
pomeriš kursor na kraj-2

while petlja 1:
ideš unazad po dva bajta dok ne dođeš do kraja prethodnog reda, \n

ona je unutar while petlje 2
koja broji redove do 5

a sve to je u if... else

if fajl.tell() != 0:
vrti petlju
else:
print('nema toliko redova')

E ovo je loš plan, jer sam probao i kod kratkog fajla od tri reda, ne stigne do 5, već javi grešku.

Dakle, trebalo bi verovatno ovu drugu petlju napraviti if...else, da zaustavi brojanje,
pa ako dođe do 0, da ne vrti dalje. Moram i to probati, samo još da vidim kako.
[ Branimir Maksimovic @ 08.02.2020. 07:15 ] @
To je znaci samo za Windows resenje. Na OSX \r i na Linux-u \n su samo jedan bajt.
[ Panta_ @ 08.02.2020. 07:20 ] @
Citat:
tail koristim za pracenje log-ova, i da vidim zadnje linije izlaza neke komande.
recimo tail -f logfile ili : komanda | tail -n 10

Da li si siguran da ti radi taj primer? Komanda tail -f konstantno čita iz log fajla, tj. nikad se ne završava, kako onda da prosledi izlaz drugoj tail komandi?
[ Branimir Maksimovic @ 08.02.2020. 07:25 ] @
Ne ne, to su dva primera, ne jedan. Znaci jedna je da pratis log, druga da prikazes zadnjih 10 linija neke komande.
[ Panta_ @ 08.02.2020. 07:39 ] @
Ja sam zbog | znaka mislio da je jedna.

"Dakle, trebalo bi verovatno ovu drugu petlju napraviti if...else, da zaustavi brojanje"

Ili da ukloniš jednu petlju, dovoljna je jedna, ova što broji linije. Zatim proveriš poziciju, ako nije nula, onda proveriš znak, ako je \n, pročitaš liniju i uvećaš brojač, itd.
[ a1234567 @ 08.02.2020. 09:56 ] @
Nešto sam ovako nabo, ali na žalost ne radi kad je u fajlu manje linija od zadatih.
Što je još gore, ne vidim zašto.

Code:
redovi = []
red = 0
with open('new1.txt', 'rb') as f:
    f.seek(-2, 2)
    while red < 5:
        while f.read(1) != b'\n':
            f.seek(-2, 1)
            if f.tell() == 0:
                print('kratak fajl')
                break
        pos = f.tell()
        redovi.append(f.readline().decode())
        f.seek(pos - 2)
        red += 1

print(*redovi[::-1], sep='\n')
[ Panta_ @ 08.02.2020. 11:06 ] @
Na pogrešnom mestu ti je if. Prvo proveriš sa f.tell() da li je početak fajla, pa onda pomeriš poziciju sa f.seek(). Takođe, pošto imaš jednu petlju viška, moraš i njeno izvršavanje da prekineš, inače ona i dalje nastavlja izvršavanje. Na primer:

Code (python):
redovi = []
red = 0
done=False
with open('new1.txt', 'rb') as f:
    f.seek(-2, 2)
    while red < 5:
        while f.read(1) != b'\n':
            if f.tell() <= 1:
                f.seek(0)
                redovi.append(f.readline().decode())
                done=True
                # break
            else:
                f.seek(-2, 1)
        if done:
            break
        pos = f.tell()
        redovi.append(f.readline().decode())
        f.seek(pos - 2)
        red += 1
    print(*redovi[::-1], sep='')

Malo je komplikovano, zato sam i naveo jednostavniji primer sa jednom petljom.
[ a1234567 @ 08.02.2020. 12:21 ] @
Vala mene i jeste komplikovano.
Ovo done mi je novost. Što si tu stavio done = True, a ne obično break?
[ Branimir Maksimovic @ 08.02.2020. 12:36 ] @
Zato sto python nema goto? Ili break label.
[ Panta_ @ 08.02.2020. 13:21 ] @
"Što si tu stavio done = True, a ne obično break?"

Zato što isti neće da prekine izvršavanje prve petlje.

https://www.python.org/dev/peps/pep-3136/
[ a1234567 @ 09.02.2020. 08:23 ] @
"The break statement allows the programmer to terminate a loop early, and the continue statement allows the programmer to move to the next iteration of a loop early. In Python currently, break and continue can apply only to the innermost enclosing loop."

Zanimljivo.
[ B3R1 @ 09.02.2020. 08:32 ] @
Citat:
a1234567: In Python currently, break and continue can apply only to the innermost enclosing loop."

Nije to samo u Pythonu. Identicna filozofija je i u PHP, Perlu i mnogim drugim jezicima. Zapravo, sve vuce korene iz C, gde je to tako reseno.
[ Branimir Maksimovic @ 09.02.2020. 09:04 ] @
Noviji jezici imaju rust, nim, golang. to je zato sto je koriscenje goto tu prirodno, a kao sto znamo goto je evil :P
[ a1234567 @ 09.02.2020. 09:17 ] @
Eto Rosum pretabačio C i pravi se toša :D

A što je goto evil?
Pa bilo bi lepo da njime možeš da zakočiš jednu petlji i skočiš drugu.
[ Branimir Maksimovic @ 09.02.2020. 09:28 ] @
Ma goto je evil od ranijih dana kada nije postojalo struktuirano programiranje pa je skakanje sa linije na
liniju pravilo spageti kod. No sada, kada imas while for case koriscenje i nije neophodno osim eto
kada ne mozes da izadjes iz unutrasnje petlje ili kada treba da skocis na obradu greske.
[ djoka_l @ 09.02.2020. 11:35 ] @
Samo što svi ti nabrojani jezici imaju i goto, kada baš zatreba.
A i C, koji nema exception konstrukciju, ima longjump
[ a1234567 @ 09.02.2020. 15:29 ] @
Došao je na red i jubilarni 20. zadatak.

Vidim da ovaj čovek traži Python program za OCR-ovanje, pa umalo da to postavim kao zadatak. :)
Ali se bojim da bi malo potrajalo, a čoveku se sigurno žuri...
Zato ipak idemo na nešto drugo, a možda i to nekom zatreba.

Ovoga puta treba spojiti dva fajla u treći i to iz komandne linije.
Nešto ovako:

> python spoji.py fajl1.txt fajl2.txt fajl3.txt

Malo sam eksperimentisao i nije tako teško kao što mi se u prvi trenutak učinilo.
Pa sam svoje rešenje postavio ovde.
[ a1234567 @ 09.02.2020. 15:43 ] @
E sad pitanje.

Jel moguća varijanta da se ne zada broj fajlova unapred?
I kako?

[ djoka_l @ 09.02.2020. 16:33 ] @
Probaj da napišeš i izvršiš program
Code:
import sys
print( sys.argv )


sa desetak parametara, pa će ti sve biti jasno...

Code:
py argv.py 1 2 3 4 5 6 7 8 9 10
['argv.py', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
[ a1234567 @ 10.02.2020. 13:51 ] @
Pa šta, jel fora da koliko god mu zadaš argumenata u komandnoj liniji, sys modul to upiše u argv?
[ djoka_l @ 10.02.2020. 14:45 ] @
Naravno, zar si mislio da računar telepatijom pogađa koliko ti argumenata treba, pa ti onda toliko šalje, ili da šalje sve što si napisao u komandnoj liniji?

Naravno, na normalnim operativnim sistemima (Linux), shell radi ekspanziju naziva fajlova, dok glupavi Windows to ne ume da radi.
Na linuxu bi

py argv.py *.txt velikifajl.txt

Umesto *.txt stavio sve fajlove koji u direktorijumu iz kog si pozvao fajl imaju ekstenziju txt, dok Win šalje tačno ono što je napisano, pa onda ti traži fajlove koji odgovoraju imenu sa džoker znacima.
[ a1234567 @ 10.02.2020. 15:09 ] @
Nisam mislio baš na telepatiju, ali jesam da mu možda u kodu definišeš broj argumenata, pa modul odatle to čita.
[ a1234567 @ 10.02.2020. 16:46 ] @
Zadatak 21

Napravi program koji čita tekst iz fajla, dodaje redni broj ispred svakog reda
i tako numerisan tekst snima u novi fajl.
Naziv oba fajla će biti dat iz komandne linije.
Svaki red u novom fajlu počinje rednim brojem, dvotačkom i razmakom.

Samo toliko za ovaj put.
[ Panta_ @ 11.02.2020. 08:30 ] @
Citat:
Na linuxu bi

py argv.py *.txt velikifajl.txt

Umesto *.txt stavio sve fajlove koji u direktorijumu iz kog si pozvao fajl imaju ekstenziju txt, dok Win šalje tačno ono što je napisano, pa onda ti traži fajlove koji odgovoraju imenu sa džoker znacima.

Ima Python glob modul kome može da se prosledi argument, na primer:
Code:
import glob
import sys

for files in glob.glob(sys.argv[1]):
    print(files)

Ili:

from pathlib import Path

p = Path('.')

for files in p.glob(sys.argv[1]):
    print(files)


https://docs.python.org/3/library/glob.html

https://docs.python.org/3/library/pathlib.html
[ a1234567 @ 13.02.2020. 11:43 ] @
Evo i rešenja za zadatak 21
postavljenog ovde.

Ako neko ima neku drugačiju ideju, nek iskomentariše.
[ Panta_ @ 13.02.2020. 13:55 ] @
Code (python):
import fileinput
import sys

with open(sys.argv[2], 'w') as fh:
    for line in fileinput.input(files=sys.argv[1]):
        fh.write(f'{fileinput.lineno()}: {line}')


Zadatak je sličan Linuksovoj nl komandi, ili više cat -n komandi koja takođe numeriše prazne linije. Obe komande imaju opcije da numerišu ili preskoče prazne linije, takođe mogu da procesuiraju više od jednog fajla. Na primer:

Code (bash):

# Komand `cat -n` slično tvom programu numeriše prazne linije
# što u nekim slučajevima i inije baš najbolje rešenje

cat -n 1.txt 2.txt
1 one
2 two
3 three
4 four
5    
6 five
7 six

# Za razliku od pomenute, komanda `nl` podrazumevano preskače prazne linije

nl 1.txt 2.txt
1 one
2 two
3 three
4 four
       
5 five
6 six


Probaj da implementiraš nešto slično u tvom programu.
[ a1234567 @ 13.02.2020. 16:53 ] @
Pa evo ova petlja preskače prazne redove:

Code:
import sys

novi = open('novi.txt', 'w', encoding='utf-8')

broj = 1
with open('stari.txt', 'r') as f:
    for line in f:
        if len(line) == 1:
            novi.writelines(line)
        else:
            novi.writelines(str(broj) + '  ' + line)
            broj += 1

novi.close()

Ispis:
1 First Part.

2 By whom missioned falls the mind shot to its mark?
3 By whom yoked moved the first life-breath forward on its paths?
4 By whom impelled is this word that men speak?
5 What god set eye and ear to their workings?

6 That which is hearing of our
7 The wise are released beyond
8 There sight not, nor speech, nor the

[ Panta_ @ 14.02.2020. 05:08 ] @
Dobro, sad napiši da radi sa više fajlova, recimo da spojiš 4 u jedan fajl, slično kao gore pomenuta nl komanda, stim što tvoj program upisuje u fajl. Na primer:

tvoj_program.py file1.txt file2.txt file3.txt file4.txt file.txt
[ a1234567 @ 14.02.2020. 08:24 ] @
tu je, spaja 4 fajla i numeriše svaki red, sem praznih:

Code:
if len(sys.argv) != 6:
    print("Unesi ime 4 ulazna i 1 izlaznog fajla u komandnoj liniji.")
    quit()

broj = 1
novi = open(sys.argv[5], "w")
try:
    for i in range(1, 4)
        with open(sys.argv[i], 'r') as f:
            for line in f:
                if len(line) == 1:
                    novi.writelines(line)
                else:
                    novi.writelines(str(broj) + '  ' + line)
                    broj += 1

except:
    print("Dogodila se greška pri učitavanju fajla.")
    quit()

Nego, kad mu dajem linijsku komandu

> python 152b-b.py new1.txt new2.txt new3.txt new4.txt novi.txt

kako da mu zadam i opcije, da recimo u jednoj varijanti numeriše sve redove (-ns), a u drugoj da preskoči prazne redobe (-nt)?
I kako onda da mu napravim help fajl da pokaže šta koja opcija znači (-h)?

> python 152b-b.py new1.txt new2.txt new3.txt new4.txt novi.txt -ns

> python 152b-b.py new1.txt new2.txt new3.txt new4.txt novi.txt -nt

> python 152b-b.py -h

[ Panta_ @ 14.02.2020. 09:05 ] @
Pogledaj getopt i argparse module.
[ a1234567 @ 14.02.2020. 15:22 ] @
Hvala, pogledaću.

Nego, taman se ja izborio sam ovim tail programčićem, kad danas natrčim na ovo

Code:
from collections import deque

def tail(filename, n=10):
    with open(filename) as f:
        return deque(f, n)
    

print(tail('new2.txt'))


Da sam video ranije, nisam se morao mučiti
[ a1234567 @ 15.02.2020. 14:30 ] @
Pogledao argparse i nije mi jasno kad jednom postavim argumente,
kako napravim skretnicu da jedan argument usmerava ka petlji koja numeriše sve redove,
a drugi kao petlji koja preskače prazne redove.

Trebalo bi u jednoj negde da udenem agparse.numesve,
a kod druge agparse.neprazne, ali ne znam kako :)


Code:
import sys
import argparse

parser = argparse.ArgumentParser(description='Numeriši redove u tekstu.')
parser.add_argument('--numsve', type=str, help='numeriši sve redove')
parser.add_argument("--neprazne", type=str, help='preskoči prazne redove')

args = parser.parse_args()


# Provera da su dati svi argumenti.
if len(sys.argv) != 4:
    print("Unesi naziv 2 ulazna i 1 izlaznog fajla u komandnoj liniji.")
    quit()

broj = 1
novi = open(sys.argv[3], 'w')

try:
    for i in range(1, 3):
        with open(sys.argv[i], 'r') as f:
            for i, line in enumerate(f, start=1):
                novi.writelines(('{}: {}'.format(i, line)))

except:
    print("Dogodila se greška pri učitavanju fajla.")
    quit()


try:
    for i in range(1, 3):
        with open(sys.argv[i], 'r') as f:
            for line in f:
                if len(line) == 1:
                    novi.writelines(line)
                else:
                    novi.writelines(str(broj) + '  ' + line)
                    broj += 1

except:
    print("Dogodila se greška pri učitavanju fajla.")
    quit()


[ Panta_ @ 15.02.2020. 20:18 ] @
Nisu ti potrebna dva argumenta, dovoljan je jedan. Ne znam šta te buni, jednostavno "if args.numsve: petlja 1 else: petlja 2" ili elif ako imaš više argumenata. Kako argument ne zahteva neku vrednost, zameni type=str sa action="store_true".
[ a1234567 @ 16.02.2020. 05:07 ] @
Uradio, ali javlja grešku. Ne prepoznaje poslednja 2 argumenta.

C:\FAJLOVI\Python_School\> python 152b-c.py --numsve new1.txt new2.txt novi.txt
usage: 152b-c.py [-h] [--numsve NUMSVE]
152b-c.py: error: unrecognized arguments: new2.txt novi.txt


Code:
import sys
import argparse

parser = argparse.ArgumentParser(description='Numeriši redove u tekstu.')
parser.add_argument('--numsve', action='store_true', help='numeriši sve redove')

args = parser.parse_args()


# Provera da su dati svi argumenti.
if len(sys.argv) != 4:
    print("Unesi naziv 2 ulazna i 1 izlaznog fajla u komandnoj liniji.")
    quit()

broj = 1
novi = open(sys.argv[3], 'w')

if args.numsve:
    try:
        for i in range(1, 3):
            with open(sys.argv[i], 'r') as f:
                for i, line in enumerate(f, start=1):
                    novi.writelines(('{}: {}'.format(i, line)))

    except:
        print("Dogodila se greška pri učitavanju fajla.")
        quit()

else:
    try:
        for i in range(1, 3):
            with open(sys.argv[i], 'r') as f:
                for line in f:
                    if len(line) == 1:
                        novi.writelines(line)
                    else:
                        novi.writelines(str(broj) + '  ' + line)
                        broj += 1

    except:
        print("Dogodila se greška pri učitavanju fajla.")
        quit()
[ Panta_ @ 16.02.2020. 08:23 ] @
Dodaj ih u parser, na primer:
Code:
parser.add_argument("files", nargs=argparse.REMAINDER)

ili

args, files = parser.parse_known_args()

print(args)
Namespace(files=['new1.txt', 'new2.txt', 'novi.txt'], numsve=True)

args.files[0]
'new1.txt'
args.files[1]
'new2.txt'
args.files[2]
'novi.txt'

len(args.files)
3


Zatim izmeni kod u nalik na sledeće:
Code (python):
# Provera da su dati svi argumenti.
if len(args.files) != 3:
    print("Unesi naziv 2 ulazna i 1 izlaznog fajla u komandnoj liniji.")
    quit()

broj = 1
novi = open(args.files[2], 'w')

if args.numsve:
    try:
        for i in range(len(args.files) - 1):
            with open(args.files[i], 'r') as f:
                for i, line in enumerate(f, start=1):
                    novi.writelines(('{}: {}'.format(i, line)))

    except:
        print("Dogodila se greška pri učitavanju fajla.")
        quit()

else:
    try:
        for i in range(len(args.files) - 1):
            with open(args.files[i], 'r') as f:
                for line in f:
                    if len(line) == 1:
                        novi.writelines(line)
                    else:
                        novi.writelines(str(broj) + '  ' + line)
                        broj += 1

    except:
        print("Dogodila se greška pri učitavanju fajla.")
        quit()


Inače, ova linija "for i, line in enumerate(f, start=1)" počinje ponovo od broja 1 prilikom narednog prolaska prethodne for petlje, pa imaš ponovo numerisanje od 1, 2, 3, itd.
[ Panta_ @ 16.02.2020. 09:11 ] @
Evo malo jednostavnijeg rešenja bez duplih try i for:

Code (python):
import sys
import argparse
import fileinput

parser = argparse.ArgumentParser(description='Numeriši redove u tekstu.')
parser.add_argument('--numsve', action='store_true', help='numeriši sve redove')
parser.add_argument("files", nargs=argparse.REMAINDER)

args = parser.parse_args()

# Provera da su dati svi argumenti.
if len(args.files) != 3:
    print("Unesi naziv 2 ulazna i 1 izlaznog fajla u komandnoj liniji.")
    parser.print_help()
    sys.exit()

broj = 1
novi = open(args.files[2], 'w')

try:
    for line in fileinput.input(files=args.files[:2]):
        if args.numsve:
            if line.strip() == '':
                novi.write(line)
            else:
                novi.write(f'{broj}: {line}')
                broj+=1
        else:
            novi.write(f'{broj}: {line}')
            broj+=1
except FileNotFoundError as err:
    print(f'No such file: {err.filename}')
    parser.print_help()
finally:
    novi.close()

[ a1234567 @ 17.02.2020. 10:57 ] @
Da, ja sam samo kopirao obe petlje, a naravno da mogu obe da se stave u jednu.
Hvala Panto na lekciji!
[ a1234567 @ 17.02.2020. 11:10 ] @
Sledi naravno zadatak broj 22

Napiši program koji nalazi najdužu reč/reči u tekstu. Prvo uklanja
svu interpunkciju, a na kraju ispisuje odgovarajuću poruku,
koja uključuje broj slova najduže reči, zajedno sa svim rečima
te dužine koje se nalaze u tekstu.

Ja sam svoje rešenje sačuvao ovde.
[ a1234567 @ 18.02.2020. 16:45 ] @
Nema nikakvih komentara za rešenje zadatka broj 22,
što jedino mogu da protumačim tako da je bez mana

Zato idemo na zadatak broj 23:

# Jedna od tehnika koje se koriste pri razbijanju neke jednostavnije forme enkripcije je utvrđivanje
# koja slova se u nekom tekstu najčešće pojavljuju. Zatim se ona mapiraju najučestalijim
# slovima iz datog jezika. Ne znam koja su najučestalija slova u srpskom, ali uz ovaj program možemo to utvrditi,
# ako uzmemo dovoljno velik uzorak. Ovaj program broji koliko se svako slovo teksta puta ponavlja i ispisuje
# odgovarajuću tabelu: "slovo = broj ponavljanja". Korisnik prilikom pokretanja programa navodi ime fajla za analizu.
# Program ga upozorava ako to nije učinio ili ako nije u stanju da otvori traženi fajl.

Rešenje sam postavio ovde.
[ djoka_l @ 18.02.2020. 18:37 ] @
Zašto brojiš samo slova, a pri tom praviš razliku između malih i velikih slova?
Budi dosledan, ili prebroj SVE znake, uključujući interpunkciju i razmake, ili broj samo slova, ali onda nemoj da praviš razliku mala/velika slova.
[ a1234567 @ 19.02.2020. 02:49 ] @
Takav je zadatak. Naći koje slovo je najčešće.

Ali u pravu si, nema potrebe da razdvajam velika i mala slova.
Zato sam dodao jedan
tekst.lower()
i sve u redu

Sada je ispis slova sortiran po abecedi. Bilo bi zanimljivo da postoji i
opcija da se ispis sortira po učestalosti. Od najvećeg do najmanjeg broja.
I kao šlag na tortu, da program sabere sve te brojeve i ispiše koliko je
ukupno slova u tekstu.

Moram još to da provalim, pre nego što rešenje pošaljem guglu
[ a1234567 @ 19.02.2020. 04:46 ] @
Dobro, verzija 2.0 programa urađena.

Sada ispisuje sortirano i po slovima i po broju ponavljanja,
u zavisnosti šta mušterija odabere. :)

Kao bonus, dobija na kraju i ukupan broj slova.
Ma sve servirano ko na tacni :))

Ostala je još jedna začkoljica.
Kad ispisuje prema broju ponavljanja, ide od najmanjeg ka najvećem:

15019 = l
15341 = d
15365 = p
17206 = m
19288 = k
19598 = v
19610 = u
21376 = t
23857 = j
27513 = s
34764 = n
43633 = e
47215 = o
52152 = i
53968 = a

Ne znam kako da ga sortiram u opadajućem nizu.
[ Branimir Maksimovic @ 19.02.2020. 05:54 ] @
A evo i nesto u rustu:
Code:

use std::fs::File;
use std::io::prelude::*;
use std::collections::*;

fn main()-> Result<(),String> {
    let args:Vec<_> = std::env::args().collect();
    if args.len() != 2 {
        return Err(format!("expected: {} file_name",args[0]));
    }
    let mut f = File::open(args[1].clone()).unwrap();
    let mut contents = String::new();
    let _ = f.read_to_string(&mut contents);
    let filtered = contents.chars().filter(|c|c.is_alphabetic()).collect::<String>().to_lowercase();
    let mut hm:HashMap<char,i32>=HashMap::new();
    for l in filtered.chars() {
        let r = hm.entry(l).or_insert(0);
        *r += 1;
    }
    let mut sorted:Vec<(i32,char)> = Vec::new();
    for (k,v) in hm {
        sorted.push((v,k));
    }
    sorted.sort();
    for (k,v) in sorted.iter().rev() {
        println!("{} = {}",k,v);
    }
    println!("chars {}", sorted.iter().fold(0,|s,(num,_)|s+num));
    Ok(())
}


za poredjenje izmenjeni python:
Code:

import sys
import re
import string
import operator

# Provera da su dati svi argumenti.
if len(sys.argv) != 2:
    print("Unesi ime fajla za slovnu analizu. Npr. >> 154.py fajl.txt")
    quit()

sva_slova = {}

# uklanjanje interpunkcije
try:
    with open(sys.argv[1], 'r', encoding='utf-8') as f:
        tekst = f.read()
        tekst1 = tekst.lower()
        samo_reci = re.sub('['+string.punctuation+', 0-9, r\n, ' ']', '', tekst1)
        sorta = ''.join(sorted(samo_reci))

        for slovo in sorta:
            if slovo in sva_slova:
                sva_slova[slovo] += 1
            else:
                sva_slova[slovo] = 1

except:
    print("Dogodila se greška pri učitavanju fajla.")
    quit()

# pravljenje liste sa tuplama, kako bi se dobio ispis
lista = [(k, v) for k, v in sva_slova.items()]

print()
print('Ovo je učestalost po broju ponavljanja:')
lista.sort(key = operator.itemgetter(1))
for item in lista:
        print(str(item[1]) + str(' = ') + str(item[0]))

# izračunavanje ukupnog broja slova u tekst
zbir = 0
lista.reverse()
for char in lista:
    zbir += char[1]
print('Ukupno u tekstu {} slova'.format(zbir))
/code]
A sad vreme izvrsavanja:
rust:
Code:

~/examples/rust >>> time ./letter_count bible.txt                                                                                                                                                                        
437385 = e
323802 = t
292940 = h
291659 = a
253611 = o
236506 = n
214156 = s
209062 = i
179738 = r
160755 = d
140235 = l
91170 = u
90659 = m
83210 = f
66586 = w
61424 = c
59411 = y
58877 = g
52207 = b
46827 = p
32426 = v
26908 = k
13753 = j
4810 = z
2662 = x
953 = q
chars 3431732
./letter_count bible.txt  0.16s user 0.00s system 99% cpu 0.168 total

python:
Code:

/examples/rust >>> time python letter_count.py bible.txt                                                                                                                                                                

Ovo je učestalost po broju ponavljanja:
953 = q
2662 = x
4810 = z
13753 = j
26908 = k
31102 =     
32426 = v
46827 = p
52207 = b
58877 = g
59411 = y
61424 = c
66586 = w
83210 = f
90659 = m
91170 = u
140235 = l
160755 = d
209062 = i
214156 = s
236506 = n
253611 = o
291659 = a
292940 = h
323802 = t
437385 = e
Ukupno u tekstu 3283096 slova
python letter_count.py bible.txt  1.02s user 0.08s system 99% cpu 1.097 total


Kao sto vidis rust je vise nego 5 puta brzi :)
[ Branimir Maksimovic @ 19.02.2020. 05:56 ] @
Zeznuo sam se u pythonu samo koju listu d uradim reverse :)
Drugo, python broji i space-ove ....
[ Panta_ @ 19.02.2020. 05:58 ] @
"Ne znam kako da ga sortiram u opadajućem nizu."

Dodaj reverse=True sort funkciji: lista.sort(key = operator.itemgetter(1), reverse=True)
[ a1234567 @ 19.02.2020. 06:22 ] @
Citat:
Branimir Maksimovic:
Zeznuo sam se u pythonu samo koju listu d uradim reverse :)
Drugo, python broji i space-ove ....


Kako koju listu? Pa ovu sa brojevima napred.
Da vidimo koje je najčešće slovo.
Šta će nam reverse sa slovima od z do a? :))

Pošto sam radio na tekstu od skoro 500.000 slova,
ispada da je "a" stvarno najčešće slovo u srpskom.
Iznenadilo me da su n,s,j,t pre vokala u.

Inače, rust je malo zarđao. Moraš ga podmazati :)))

Python je majka. Prelazi što pre dok nije kasno :D
[ a1234567 @ 19.02.2020. 06:29 ] @
Citat:
Panta_:
"Ne znam kako da ga sortiram u opadajućem nizu."

Dodaj reverse=True sort funkciji: lista.sort(key = operator.itemgetter(1), reverse=True)

Radi!

Eto, ko će drugi nego Panta.
Pa čoveče ima li pitanja na koje ti ne znaš odgovor!? :)

Nego, sad kad je program pod konac, da šaljem guglu?
Ili da pokrećem startap? :D
[ Panta_ @ 19.02.2020. 07:53 ] @
Malo brža Python verzija:
Code (python):
import sys
import re
import string
import operator
from collections import Counter

# Provera da su dati svi argumenti.
if len(sys.argv) != 2:
    print("Unesi ime fajla za slovnu analizu. Npr. >> 154.py fajl.txt")
    quit()

#sva_slova = {}

# uklanjanje interpunkcije
try:
    with open(sys.argv[1], 'r', encoding='utf-8') as f:
        tekst = f.read()
        #tekst1 = tekst.lower()
        #samo_reci = re.sub('['+string.punctuation+', 0-9, r\n, ' ']', '', tekst1)
        #sorta = ''.join(sorted(samo_reci))
        sorta = ''.join(i for i in sorted(re.findall('[a-zA-Z]+', tekst.lower())))

        # for slovo in sorta:
        #     if slovo in sva_slova:
        #         sva_slova[slovo] += 1
        #     else:
        #         sva_slova[slovo] = 1
        sva_slova = Counter(sorta)

except:
    print("Dogodila se greška pri učitavanju fajla.")
    quit()

# pravljenje liste sa tuplama, kako bi se dobio ispis
#lista = [(k, v) for k, v in sva_slova.items()]

print()
print('Ovo je učestalost po broju ponavljanja:')
#lista.sort(key = operator.itemgetter(1))
lista = sorted(sva_slova.items(), key=operator.itemgetter(1), reverse=True)
for item in lista:
        print(str(item[1]) + str(' = ') + str(item[0]))

# izračunavanje ukupnog broja slova u tekst
#zbir = 0
#lista.reverse()
#for char in lista:
#    zbir += char[1]

zbir = sum(i[1] for i in lista)
print('Ukupno u tekstu {} slova'.format(zbir))
 


Python:

Code:
time python3 letter_count.py pg10.txt 

Ovo je učestalost po broju ponavljanja:
412265 = e
317765 = t
282690 = h
275735 = a
243208 = o
225065 = n
193974 = i
190038 = s
170339 = r
158103 = d
129947 = l
83550 = f
83476 = u
79945 = m
65496 = w
58578 = y
55307 = g
55070 = c
48880 = b
43260 = p
30368 = v
22295 = k
8890 = j
2972 = z
1479 = x
964 = q
Ukupno u tekstu 3239659 slova
real    0m 1.25s
user    0m 1.18s
sys    0m 0.07s


Rust:

Code:
time ./letter_count pg10.txt 
412265 = e
317765 = t
282690 = h
275735 = a
243208 = o
225065 = n
193974 = i
190038 = s
170339 = r
158103 = d
129947 = l
83550 = f
83476 = u
79945 = m
65496 = w
58578 = y
55307 = g
55070 = c
48880 = b
43260 = p
30368 = v
22295 = k
8890 = j
2972 = z
1479 = x
964 = q
chars 3239659
real    0m 2.82s
user    0m 2.81s
sys    0m 0.01s


Python više nego duplo brži. ;)

Fajl input: http://www.gutenberg.org/cache/epub/10/pg10.txt
[ Panta_ @ 19.02.2020. 08:01 ] @
Gledam nešto ovaj Rust Docker image mnogo veliki? rust alpine 753MB
[ Branimir Maksimovic @ 19.02.2020. 08:01 ] @
Kako si useo da ti Rust radi tako sporo? ;)
Code:

~/examples/rust >>> time ./letter_count bible.txt                                                                                                                                                                        
437385 = e
323802 = t
292940 = h
291659 = a
253611 = o
236506 = n
214156 = s
209062 = i
179738 = r
160755 = d
140235 = l
91170 = u
90659 = m
83210 = f
66586 = w
61424 = c
59411 = y
58877 = g
52207 = b
46827 = p
32426 = v
26908 = k
13753 = j
4810 = z
2662 = x
953 = q
chars 3431732
./letter_count bible.txt  0.16s user 0.01s system 99% cpu 0.174 total
~/examples/rust >>> time python letter_count.py bible.txt                                                                                                                                                                

Ovo je učestalost po broju ponavljanja:
437385 = e
323802 = t
292940 = h
291659 = a
253611 = o
236506 = n
214156 = s
209062 = i
179738 = r
160755 = d
140235 = l
91170 = u
90659 = m
83210 = f
66586 = w
61424 = c
59411 = y
58877 = g
52207 = b
46827 = p
32426 = v
26908 = k
13753 = j
4810 = z
2662 = x
953 = q
Ukupno u tekstu 3431732 slova
python letter_count.py bible.txt  0.63s user 0.06s system 99% cpu 0.703 total

rust vise nego 4 puta brzi ;)

probaj da ukljucis optimizacije:
Code:

rustc -O -C target-cpu=native letter_count.rs

[ Panta_ @ 19.02.2020. 08:11 ] @
"probaj da ukljucis optimizacije:"

Tako radi dosta brže.

real 0m 0.20s
user 0m 0.20s
sys 0m 0.00s
[ Panta_ @ 19.02.2020. 10:48 ] @
Sad tek vidim da Python dvaput sortira, dovoljno je "sorta = ''.join(i for i in re.findall('[a-z]+', tekst.lower()))". Onda je "samo" 3 puta sporiji. :)
[ Branimir Maksimovic @ 19.02.2020. 11:08 ] @
I ako izbacis regex ubrzaces jos vise ;)
[ a1234567 @ 19.02.2020. 11:25 ] @
A kad izbaciš učitavanje fajla, biće ko munja :D
[ Panta_ @ 19.02.2020. 12:17 ] @
"I ako izbacis regex ubrzaces jos vise ;)"

Neće, čak je i sporije.
[ Branimir Maksimovic @ 19.02.2020. 13:34 ] @
Pa da, regex implementacija u C-u ;)
[ Panta_ @ 19.02.2020. 14:32 ] @
Fora je što regex + čita koliko god može karaktera u opsegu od a-z dok ne naiđe na neki ne a-z karakter i vrati match, tzv. greedy quantifier, dok bi recimo bez + za svaki a-z karakter vratio match.

Code:
%timeit ''.join(i for i in tekst.lower() if i.isalpha())
1 loop, best of 5: 368 ms per loop

%timeit ''.join(filter(lambda i: i.isalpha(), tekst))
1 loop, best of 5: 508 ms per loop

%timeit ''.join(re.findall('[a-z]+', tekst.lower()))
1 loop, best of 5: 276 ms per loop
[ djoka_l @ 20.02.2020. 17:31 ] @
Citat:
Panta_:
Gledam nešto ovaj Rust Docker image mnogo veliki? rust alpine 753MB


Gde samo nađe Rust kontejner od 753MB?

https://hub.docker.com/_/rust?tab=tags

Najveći je 450MB. A ide od 125MB pa na gore. Java HelloWorld ne može da se spakuje na manje od 1GB...
[ Branimir Maksimovic @ 21.02.2020. 01:29 ] @
Citat:
Panta_:
Fora je što regex + čita koliko god može karaktera u opsegu od a-z dok ne naiđe na neki ne a-z karakter i vrati match, tzv. greedy quantifier, dok bi recimo bez + za svaki a-z karakter vratio match.

Code:
%timeit ''.join(i for i in tekst.lower() if i.isalpha())
1 loop, best of 5: 368 ms per loop

%timeit ''.join(filter(lambda i: i.isalpha(), tekst))
1 loop, best of 5: 508 ms per loop

%timeit ''.join(re.findall('[a-z]+', tekst.lower()))
1 loop, best of 5: 276 ms per loop


Ma ne, pazi ova petlja gde ide samo prolaz i provera, u kompajliranom jeziku, nema teorije da bi bila
sporija od regex-a. Zato kad radis u Pythonu, napravis heavy workload u C-u, a onda samo pozivas
f-je.
[ djoka_l @ 21.02.2020. 09:12 ] @
Citat:
Panta_:
Fora je što regex + čita koliko god može karaktera u opsegu od a-z dok ne naiđe na neki ne a-z karakter i vrati match, tzv. greedy quantifier, dok bi recimo bez + za svaki a-z karakter vratio match.

Code:
%timeit ''.join(i for i in tekst.lower() if i.isalpha())
1 loop, best of 5: 368 ms per loop

%timeit ''.join(filter(lambda i: i.isalpha(), tekst))
1 loop, best of 5: 508 ms per loop

%timeit ''.join(re.findall('[a-z]+', tekst.lower()))
1 loop, best of 5: 276 ms per loop


isalpha i regex [a-z]+ nisu isto. regex neće da radi za UTF-8
[ Panta_ @ 21.02.2020. 10:02 ] @
"Ma ne, pazi ova petlja gde ide samo prolaz i provera, u kompajliranom jeziku, nema teorije da bi bila
sporija od regex-a."

Mislio sam na regex [a-z]+ vs [a-z]: "regex + čita koliko god može karaktera u opsegu od a-z dok ne naiđe na neki ne a-z karakter i vrati match, tzv. greedy quantifier, dok bi recimo bez + za svaki a-z karakter vratio match

Manje ima backtrackinga sa +.

Evo nekih primera:

Code:
%timeit ''.join(re.findall(r'[a-z]', 'hello, 123 abc 456, world!'))
3.95 µs per loop

%timeit ''.join(re.findall(r'[a-z]+', 'hello, 123 abc 456, world!'))
2.59 µs per loop

# Kada se prethodno regex kompajlira
pattern = re.compile(r'[a-z]+')
%timeit ''.join(pattern.findall('hello, 123 abc 456, world!'))
1.35 µs per loop

%timeit ''.join(i for i in 'hello, 123 abc 456, world!' if i.isalpha())
2.6 µs per loop

%timeit ''.join(filter(str.isalpha, 'hello, 123 abc 456, world!'))
2.36 µs per loop
[ Panta_ @ 21.02.2020. 10:27 ] @
"isalpha i regex [a-z]+ nisu isto. regex neće da radi za UTF-8"

Neće, ali nisam u primeru imao takva slova pa sam upotrebio taj jednostavan regex. Python re modul ne podržava POSIX character class ili unicode properties, pa ne može jednostavno [:alpha:] ili \p{L}, već recimo [^\W\d_].
[ Panta_ @ 21.02.2020. 10:42 ] @
"Gde samo nađe Rust kontejner od 753MB?
https://hub.docker.com/_/rust?tab=tags
Najveći je 450MB. A ide od 125MB pa na gore."

To je compressed size, kada se raspakuje onda je znatno više.
[ a1234567 @ 28.02.2020. 06:30 ] @
Stiže zadatak broj 25.

Napiši program koji će prikazati 5 reči koje se najčešće pojavljuju u datom tekstu. Posle učitavanja teksta,
program će prvo ukloniti sve znakove interpuncije, a prilikom brojanja reči zanemariti mala i velika slova.

Svoje polurešenje sa okačio ovde.
Njime dobijem ovakvu listu iz rečnika:

that 3
which 1
is 6
hearing 1
of 7
our 6
hearing, 1
mind 1
speech 2
too 1
life 1
life-breath 1
and 3
sight 2


Ali nisam još otkrio kako da sortiram po opadajućem nizu ponavljanja reči.
I kako da ispis ograničim na prvih 5 reči.

Radim na fazi 2 :)
[ Branimir Maksimovic @ 28.02.2020. 06:54 ] @
Stavis u listu parova (broj_ponavljanja,rec) pa sortiras reverse ili sortiras pa obrnes ili ides iteraciju reverse.
Da li python ima `take` iz iteracije kao Haskell ili Rust? Ako nema onda ides petlju po brojacu.
[ djoka_l @ 28.02.2020. 07:06 ] @
Ovo je prilično neobičan engleski tekst, kada "the" nije najčešća reč.
Osim toga, pojavljuje se haering dva puta:

hearing 1
hearing, 1

Očigledno, ne radi ti baš dobro uklanjanje interpunkcije.
A i pitanje je šta da se radi sa "life-breath"? Da li je to jedna ili dve reči...
[ Panta_ @ 28.02.2020. 13:45 ] @
Citat:
Ali nisam još otkrio kako da sortiram po opadajućem nizu ponavljanja reči.
I kako da ispis ograničim na prvih 5 reči.

Radim na fazi 2 :)

Importovao si re i collections module ali ih nigde nisi upotrebio. Moga si da vidiš kako sam ih ja upotrebio u prethodnom zadatku. Na primer za ovaj zadatak:

Code:
import re
import collections

text = open('textfile.txt').read()
words = re.findall('\w+', text)

collections.Counter(words).most_common(5)
[('and', 24), ('more', 21), ('which', 18), ('for', 18), ('to', 16)]


Citat:
most_common(self, n=None)
List the n most common elements and their counts from the most
common to the least. If n is None, then list all element counts.

>>> Counter('abcdeabcdabcaba').most_common(3)
[('a', 5), ('b', 4), ('c', 3)]
[ a1234567 @ 28.02.2020. 13:58 ] @
import collection je ostalo od nekog prethodnog polurešenja.

No sad sam sve skockao, vidi ovde

Ispis je sledeći, limitiran na 5 najčešćih reči

the = 36
a = 31
of = 23
to = 20
and = 14


I da, promenio sam uzorak teksta i sada je stvarno 'the' najčešća reč :)
[ Panta_ @ 28.02.2020. 14:36 ] @
Evo malo drugačijeg rešenja:

Code:
import string

text = open('textfile.txt').read()

words = text.translate(str.maketrans('', '', string.punctuation)).split()

sorted([(word, words.count(word)) for word in set(words)], key=lambda x: x[1], reverse=True)[:5]
[('and', 24), ('more', 21), ('which', 18), ('for', 18), ('to', 16)]

[ a1234567 @ 28.02.2020. 14:49 ] @
Zanimalo me i za srpski tekst kako stoje stvari.
Proverio sam Crnjanskog, prva knjiga Seoba.
Generalno je ova situacija, ubedljivo vode uglavnom veznici i predlozi
što je za očekivati. Jedino je ime glavnog junaka ušlo u prvih 40:

i = 3517
je = 2485
da = 2122
se = 1983
u = 1846
na = 919
su = 738
kao = 690
sa = 650
mu = 590
što = 575
od = 467
ne = 442
za = 440
ga = 400
koji = 351
nije = 349
sve = 347
po = 346
tako = 326
a = 294
on = 290
beše = 283
ni = 273
to = 259
kad = 247
bio = 242
ih = 241
iz = 239
isakovič = 231
će = 230
ona = 225
pred = 221
bi = 216
pod = 213
joj = 211
više = 204
još = 190
pri = 184
koje = 181


[ a1234567 @ 28.02.2020. 15:05 ] @
Citat:
Panta_:
Evo malo drugačijeg rešenja:

Code:
import string

text = open('textfile.txt').read()

words = text.translate(str.maketrans('', '', string.punctuation)).split()

sorted([(word, words.count(word)) for word in set(words)], key=lambda x: x[1], reverse=True)[:5]
[('and', 24), ('more', 21), ('which', 18), ('for', 18), ('to', 16)]



Au Panto, al si ga skvizovao!
A ja tri dana ulupao da nažem rešenje.
Mogao nive Seobe da napišem za to vreme :D

Zanimljivi ti je taj string modul. Moram to malo bolje proučiti.
Ako s nečim radim u ovoj fazi, onda su to stringovi.

Ovo sa translate baš ne kapiram :(
[ Panta_ @ 28.02.2020. 15:28 ] @
Pogledaj https://docs.python.org/3/library/stdtypes.html#str.translate

A evo i jednostavan primer:

Code:
'hello world'.translate(str.maketrans('hw', 'HW'))
'Hello World'

str.maketrans('hw', 'HW')
{104: 72, 119: 87}

'hello world'.translate({104: 72, 119: 87})
'Hello World'
[ djoka_l @ 28.02.2020. 15:57 ] @
Ovo sam ja izvukao iz jedne knjige (top 15):
Code:
JE    2696
I    1857
DA    1789
SE    1587
U    1303
NA    870
SU    595
ON    560
ZA    513
TO    496
SA    477
A    457
ONA    414
NE    390
ALI    351
[ a1234567 @ 28.02.2020. 17:15 ] @
Citat:
Panta_:
Pogledaj https://docs.python.org/3/library/stdtypes.html#str.translate

A evo i jednostavan primer:

Code:
'hello world'.translate(str.maketrans('hw', 'HW'))
'Hello World'

str.maketrans('hw', 'HW')
{104: 72, 119: 87}

'hello world'.translate({104: 72, 119: 87})
'Hello World'


Što meni neće da radi maketrans!?

>>> import string

i onda probam, ali se buni interpreter

>>> trantab = maketrans(intab, outtab)
Traceback (most recent call last):
File "<pyshell#68>", line 1, in <module>
trantab = maketrans(intab, outtab)
NameError: name 'maketrans' is not defined
[ a1234567 @ 28.02.2020. 17:23 ] @
Citat:
djoka_l:
Ovo sam ja izvukao iz jedne knjige (top 15):
Code:
JE    2696
I    1857
DA    1789
SE    1587
U    1303
NA    870
SU    595
ON    560
ZA    513
TO    496
SA    477
A    457
ONA    414
NE    390
ALI    351

Da, to su sve reči od 2-3 slova.
Nije baš nešto informativno.

Ja sam eksperimentisao sa zadavanjem dužine reči koje lista.
Kad mu stavim da ispiše reči duže od 5 slova, dobijem kod Crnjanskog ovo kao najčešće:

isakovič = 231
svojim = 149
kojima = 93
aranđel = 84
sasvim = 79
nekoliko = 79
jednom = 65
toliko = 65
kolima = 52
činilo = 49
isakoviča = 48
njegove = 46
svojih = 45
naročito = 43
najposle = 43
međutim = 42
vojnika = 41
jednog = 40
berenklau = 40
njegova = 38
činjaše = 37
gospoža = 36
velikim = 35
potpuno = 34
vojnici = 34
rukama = 33
dafina = 33
osećao = 32
njegovog = 31
varoši = 31
iznenada = 31


Ovo sad uraditi analizu više pisaca, pa upoređivati, taman za magistarski :)
[ djoka_l @ 28.02.2020. 17:28 ] @
U toj knjizi, pojavljuje se oko 17500 reči, ali samo 4300 reči se pojavljuje 2 i više puta. Ostale samo po jednom...

Citat:
>>> import string

i onda probam, ali se buni interpreter

>>> trantab = maketrans(intab, outtab)
Traceback (most recent call last):
File "<pyshell#68>", line 1, in <module>
trantab = maketrans(intab, outtab)
NameError: name 'maketrans' is not defined


maketrans je metoda klase string.
Ne može tako da se poziva, nego
'nesto'.maketrans
ili
string.maketrans
ili
stringvarijabla.maketrans

[ a1234567 @ 28.02.2020. 17:33 ] @
A ja našao ovaj primer i probao da ga odradim kod mene na računaru



from string import maketrans # Required to call maketrans function.

intab = "aeiou"
outtab = "12345"
trantab = maketrans(intab, outtab)

str = "this is string example....wow!!!";
print str.translate(trantab)

When we run above program, it produces following result −

th3s 3s str3ng 2x1mpl2....w4w!!!
[ djoka_l @ 28.02.2020. 17:41 ] @
Citat:
Ovo sad uraditi analizu više pisaca, pa upoređivati, taman za magistarski :)

Ovo je pre za neki seminarski rad, nije čak ni za diplomski.

Klasična metoda analize prirodnog jezika (jedna od) je da se rečenica posmatra kao "bag of words". Dakle ne analiziraš gramatiku, stil itd, nego izdvojiš reči, pa onda odbaciš iz tog skupa reči 100 (500, 1000, koliko god najčešćih) jer one ne nose mnogo značenja, a ono što ti ostane su ključne reči.

"U gužvi koja je tada nastala, Mitrović je skočio najviše i plasirao loptu u mrežu!"

Kada izbaciš u, koja, je, tada, i
ostane ti gužvi, nastala, Mitrović, skočio, najviše, plasirao, loptu, gol.
Onda vrlo lako možeš da shvatiš kontekst...
Dakle, to su reči koje zaista nose informaciju, ostale samo čine da bude rečenica gramatički ispravna.
[ a1234567 @ 28.02.2020. 18:10 ] @
Ja sam mislio više na stilsku analizu vokabulara koji pisac koristi.

Iz ovo malo reči kod Crnjanskog, možeš povaditi
aranđel
najposle
berenklau
činjaše
gospoža

dakle arhaizme, strane reči ili glagolske oblike koji nisu deo savremenog govora
i raspredati o njegovom stilu.
Pa onda te zaključke uporediti sa istim takvim zaključcima kod nekih drugih pisaca
koji pripadaju možda različitim umetničkim pravcima ili epohama itd.
Mogućnosti su velike.
[ Panta_ @ 28.02.2020. 19:38 ] @
Citat:
A ja našao ovaj primer i probao da ga odradim kod mene na računaru

from string import maketrans # Required to call maketrans function.

intab = "aeiou"
outtab = "12345"
trantab = maketrans(intab, outtab)

str = "this is string example....wow!!!";
print str.translate(trantab)

When we run above program, it produces following result −

th3s 3s str3ng 2x1mpl2....w4w!!!


Koju verziju Pythona koristiš? U Pythonu 3 string modul nema maketrans i translate funkcije, zamenjene su sa str.maketrans i str.translate metodama str klase, help(str). Tako da maketrans(intab, outtab) zameni sa str.maketrans(intab, outtab). Takođe, print str.translate(trantab) sa print(str.translate(trantab)).

Inace maketrans ima i treći argument koji je string, koji sam ja u primeru iskoristio da uklonim znakove interpuncije.

Code:
import string

string.punctuation
'!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'

my_string = 'hello, world!'

my_string.translate(my_string.maketrans('hw', 'HW', string.punctuation))
'Hello World'


Citat:
maketrans(x, y=None, z=None, /)
| Return a translation table usable for str.translate().
|
| If there is only one argument, it must be a dictionary mapping Unicode
| ordinals (integers) or characters to Unicode ordinals, strings or None.
| Character keys will be then converted to ordinals.
| If there are two arguments, they must be strings of equal length, and
| in the resulting dictionary, each character in x will be mapped to the
| character at the same position in y. If there is a third argument, it
| must be a string, whose characters will be mapped to None in the result.
[ a1234567 @ 29.02.2020. 02:14 ] @
A to je kvaka, koristim Python 3.8.
Što ti ne pređeš na noviju verziju?

Da, to sam video sa tri argumenta, da si koristio. Vrlo korisno, jer uklanja iz stringa sve što je u tom trećem arg.
Pa još kad se kombinuje sa .punctuation.
Sa string.maketrans praviš translacionu tabelu
a sa str.translate ga odradi.

A čemu služi maketrans sa jednim argumentom.
Vidim da u rečniku pretvara slovo u unikod broj.
Kad mi to treba?
[ Panta_ @ 29.02.2020. 05:17 ] @
Kao što piše u gore citiranom, ako je samo jedan argument, on mora da bude dictionary. Na primer, prvi i drugi argument moraju da budu iste dužine, tj. da imaju isti broj karaktera, recimo da hoćeš slovo h da zameniš sa XYZ:

Code:
'hello, world!'.translate(str.maketrans('h', 'XYZ'))
ValueError: the first two maketrans arguments must have equal length

'hello, world!'.translate(str.maketrans({'h': 'XYZ'}))
'XYZello, world!'


Ili na primer, kao u zadatku da ukloniš znakove interpuncije, umesto da koristiš kao treći argument string.punctuation, možeš da ih definišeš u rečniku, npr.:

Code:
'hello, world!'.translate(str.maketrans({'h': 'XYZ', ',': '', '!': ''}))
'XYZello world'
[ a1234567 @ 29.02.2020. 06:13 ] @
Ma video sam da kod jednog argumenta mora d abude rečnik, ali mi to nije mnogo pomoglo.
Ali sad vidim da je to u stvari skoro pa isto.
Ili imaš dva argumenta, pa drugi menja prvi, ili imaš jedan, tj. rečnik, koji se takođe sastoji od para - key: value
pa mu opet dođe kao da imaš dva argumenta :)

Jedina je razlika u dužini. I ovo mi se sviđa što value menja key bez obzira na dužinu jednog i drugog.

Hvala na jasnim objašnjenjima, sad mi je jasno šta i kako radi.
[ Panta_ @ 29.02.2020. 06:23 ] @
"Jedina je razlika u dužini. I ovo mi se sviđa što value menja key bez obzira na dužinu jednog i drugog."

Dužina ključa mora da bude 1, npr. recimo da hoćeš he da zameniš sa XYZ:

Code:
'hello, world!'.translate(str.maketrans({'he': 'XYZ',}))
ValueError: string keys in translate table must be of length 1

'hello, world!'.translate(str.maketrans({'h': 'XYZ', 'e': ''}))
'XYZllo, world!'
[ a1234567 @ 29.02.2020. 06:24 ] @
I da ne bi mnogo dangubili, evo i naredni zadatak broj 26.

Napravi program koji računa zbir brojeva koje unese korisnik,
a ignoriše unos koji nije ceo ili decimalni broj. Program treba da
ispiše tekući zbir posle svakog unetog broja. Takođe, ispisuje
poruku posle svakog ne-brojčanog unosa i potom nastavlja
da sabira ako je naredni unos ispravan. Izlazak iz programa je
sa praznim unosom, tj. enterom.

Svoje rešenje sam postavio ovde.


Testirajući program sa unosom decimalnih brojeva imam često ovakvu situaciju:

Unesi neki broj. Enter za izlaz: 2
Zbir je: 2.0
Unesi neki broj. Enter za izlaz: 6
Zbir je: 8.0
Unesi neki broj. Enter za izlaz: 5
Zbir je: 13.0
Unesi neki broj. Enter za izlaz: 3
Zbir je: 16.0
Unesi neki broj. Enter za izlaz: 2.6
Zbir je: 18.6
Unesi neki broj. Enter za izlaz: 5.1
Zbir je: 23.700000000000003


Pa jel to python ima problem sa sabiranjem decimalnih brojeva!?
Gvido alert! Možeš ti to i bolje.
[ Branimir Maksimovic @ 29.02.2020. 06:34 ] @
Nepreciznost floating point aritmetike.... nije to do Pythona.
[ a1234567 @ 29.02.2020. 06:35 ] @
Citat:
Panta_:
"Jedina je razlika u dužini. I ovo mi se sviđa što value menja key bez obzira na dužinu jednog i drugog."

Dužina ključa mora da bude 1, npr. recimo da hoćeš he da zameniš sa XYZ:

Code:
'hello, world!'.translate(str.maketrans({'he': 'XYZ',}))
ValueError: string keys in translate table must be of length 1

'hello, world!'.translate(str.maketrans({'h': 'XYZ', 'e': ''}))
'XYZllo, world!'


aaa to je caka. Šta sve Švaba neće smisliti da nam zagorča život :D

Pa dobro, onda mora zamena one by one.
[ Branimir Maksimovic @ 29.02.2020. 06:37 ] @
Aj ti napravi da moze da duzina kljuca bude vise od 1 :)
[ Panta_ @ 29.02.2020. 06:40 ] @
"Pa jel to python ima problem sa sabiranjem decimalnih brojeva!?"

Code:
round(23.700000000000003, 2)
23.7

round(float(18.6 + 5.1), 2)
23.7

float(f'{23.700000000000003:.2f}')
23.7

float(f'{18.6+5.1:.2f}')
23.7


https://docs.python.org/3/tutorial/floatingpoint.html
[ a1234567 @ 29.02.2020. 07:14 ] @
Citat:
Branimir Maksimovic:
Aj ti napravi da moze da duzina kljuca bude vise od 1 :)


jel to kao ice bucket challenge!? :D
[ a1234567 @ 29.02.2020. 07:27 ] @
Citat:
Panta_:
"Pa jel to python ima problem sa sabiranjem decimalnih brojeva!?"

Code:
round(23.700000000000003, 2)
23.7

round(float(18.6 + 5.1), 2)
23.7

float(f'{23.700000000000003:.2f}')
23.7

float(f'{18.6+5.1:.2f}')
23.7


https://docs.python.org/3/tutorial/floatingpoint.html


Dobro, sad sam i to regulisao.
Ono sa milion decimala izgleda stvarno ružno.

stavio sam
round(zbir,2)

Jedino u tvojim primerima index 2, a zaokruži na 1 decimalu!?
[ Branimir Maksimovic @ 29.02.2020. 07:40 ] @
Probaj sa 2 decimale gde zadnja nije 0. od 23.70 valjda odbaci 0.
[ Panta_ @ 29.02.2020. 08:21 ] @
Code:
round(23.70000, 2)
23.7

f'{23.70000:.2f}'
'23.70'
[ a1234567 @ 03.03.2020. 07:31 ] @
Evo nama zadatak broj 27:

Piton koristi # znak da obeleži početak komentara. Komentar se nastavlja od tog znaka do kraja reda.
Napravi program koji uklanja sve komentare iz python izvornog koda. Sačuvaj modifikovani fajl pod novim imenom.
Imena ulaznog i izlaznog fajla treba da unese korisnik u komandnoj liniji. Obezbedi da program prijavi grešku
ukoliko ima problem da pristupi jednom od fajlova.

Stigao sam dovde i sve lepo radi:

Code:
with open('fajl1.txt', 'r') as f:
    redovi = f.readlines()

with open('fajl2.txt', 'w') as g:
    for red in redovi:
        red = red.split('#')   
        obrishi = red[0].rstrip()
        g.writelines(obrishi)
        g.writelines('\n')


Ali kad sam pokušao da to apgrejdujem do pune verzije kakva se traži u zadatku,
nešto ne radi. A ne vidim razlog.

Code:
import sys

# Provera da su dati svi argumenti.
if len(sys.argv) != 3:
    print("Unesi ime fajla čije komentare brišeš i ime za novi fajl. Npr. >> 27.py komentari.py bez.txt")
quit()

try:
    with open(sys.argv[1], 'r') as f:
        redovi = f.readlines()
        
    with open(sys.argv[2], 'w') as g:
        for red in redovi:
            red = red.split('#')   
            obrishi = red[0].rstrip()
            g.writelines(obrishi)
            g.writelines('\n')
except:
    print("Greška pri učitavanju fajla.")
quit()
[ djoka_l @ 03.03.2020. 08:24 ] @
quit() mora da bude indentovano isto kao print, inače svaki put izlalziš iz programa posle if-a
[ B3R1 @ 03.03.2020. 09:10 ] @
Ovo uopste nije lak zadatak. Tvoje resenje recimo da radi, ali ne bas za sve slucajeve. Pogledaj sta tvoj program radi za ovakve linije koda:
Code:
print "# je nekom taraba, a nekom povisilica (F#==Fis)"   # A ovo je komentar
linija = re.sub('#.*$', '', linija)   # Jos jedan nacin da se ovo uradi, ali opet ne radi bas ono sto hocemo
print 'Za stanje na racunu otkucajte "*101#" ...'     # Ako imamo '#' u liniji (# je separator komentara u Pythonu, ali ne u C#, tamo se koristi //)
print "*106*" + telefon + "#123#" + '#'    # Ako imamo '#' u liniji (# je separator komentara u Pythonu, ali ne u C#, tamo se koristi //)

Evo, smislio sam ti bas primere da se pomucis ...
[ djoka_l @ 03.03.2020. 10:07 ] @
Beri, malo ti je sintaksa zastarela, ovo ne prolazi u Pythonu 3
Mislim da bi bio "overkill" da ga nateramo da koriti paket tokenize ili da sam pravi leksički analizator.
[ a1234567 @ 03.03.2020. 10:24 ] @
Citat:
djoka_l:
quit() mora da bude indentovano isto kao print, inače svaki put izlalziš iz programa posle if-a


Bravo Đoko
Pa da, ovako nije ni išao kroz petlju,
a ja se čudim što ne radi :)


[ a1234567 @ 03.03.2020. 10:31 ] @
Citat:
B3R1:
Ovo uopste nije lak zadatak. Tvoje resenje recimo da radi, ali ne bas za sve slucajeve. Pogledaj sta tvoj program radi za ovakve linije koda:
Code:
print "# je nekom taraba, a nekom povisilica (F#==Fis)"   # A ovo je komentar
linija = re.sub('#.*$', '', linija)   # Jos jedan nacin da se ovo uradi, ali opet ne radi bas ono sto hocemo
print 'Za stanje na racunu otkucajte "*101#" ...'     # Ako imamo '#' u liniji (# je separator komentara u Pythonu, ali ne u C#, tamo se koristi //)
print "*106*" + telefon + "#123#" + '#'    # Ako imamo '#' u liniji (# je separator komentara u Pythonu, ali ne u C#, tamo se koristi //)

Evo, smislio sam ti bas primere da se pomucis ...


pa ništa, dodao tri spejsa pre # i oljušti ga od komentara ko kuvarica mlad krompir :D

Code:
import sys

# Provera da su dati svi argumenti.
if len(sys.argv) != 3:
    print("Unesi ime fajla čije komentare brišeš i ime za novi fajl. Npr. >> 27.py komentari.py bez.txt")
    quit()

try:
    with open(sys.argv[1], 'r') as f:
        redovi = f.readlines()
        
    with open(sys.argv[2], 'w') as g:
        for red in redovi:
            red = red.split('   #')   
            obrishi = red[0].rstrip()
            g.writelines(obrishi)
            g.writelines('\n')
except:
    print("Greška pri učitavanju fajla.")
    quit()


[ Panta_ @ 03.03.2020. 11:43 ] @
Sada ti ne radi ako linija počinje sa # ili ako ima dva ili manje razmaka ispred. ;)
[ B3R1 @ 03.03.2020. 11:56 ] @
Citat:
a1234567:
pa ništa, dodao tri spejsa pre # i oljušti ga od komentara ko kuvarica mlad krompir :D

Code:
>>> print "String se zavrsava sa #"#A odavde pocinje komentar, koji moze imati i "#hashtag" ili "nesto drugo@"
String se zavrsava sa #

Naravoucenije: razmaci su nebitni.
[ a1234567 @ 03.03.2020. 11:56 ] @
Panto, zadatak je odrađen.
A ti sad zakeraj koliko hoćeš
[ B3R1 @ 03.03.2020. 12:38 ] @
Citat:
a1234567: Panto, zadatak je odrađen.
A ti sad zakeraj koliko hoćeš :D

Pa i nije bas ... vidi gornji primer koji ne radi. Da bi ga resio moraces da analiziras karakter po karakter i da pamtis stanje. Kriticni karakteri koje treba da pamtis su ti apostrof, navodnici ili taraba.

* Ako navodnik naidje prvi (pre tarabe) - tada smatras da si u string-modu, pa tarabe i apostrofe smatras delom stringa sve dok ne naidje zavrsni navodnik (kada zatvaras string)
* Ako apostrof naidje prvi (pre tarabe) - tada smatras da si u string-modu, pa tarabe i navodnike smatras delom stringa sve dok ne naidje zavrsni apostrof (kada zatvaras string).
* Ako naidje taraba, a nisi u string-modu - to je prelomni znak od koga treba da "ljustis" sve zdesna.

Eto, sada napisi kod ... Eh da, ima i dva posebna slucaja - znaci \' i \" koji se, ako se nadju unutar stringa, smatraju delom stringa:
Code:
print "Ovaj # je deo stringa, kao i \"ovaj #\", a mozda i # isto tako"# Ali ovaj nije

Ali hajde, preskoci taj slucaj za pocetak, to mozes da odradis i kasnije ... mada nije tesko.
[ djoka_l @ 03.03.2020. 12:40 ] @
U pythonu, za razliku od nekih drugih jezika, znak "#" ne može da bude deo identifikatora (imena varijable ili rezervisana reč).
Dakle, "#" može da se pojavi ISKLJUČIVO u dva konteksta - ili kao početak komentara, ili kao deo stringa.

Utoliko je onda lakše da se uradi analiza teksta i izbace komentari.

String literal može da počne i da se završi jednostrukim znakom navoda, dvostrukim znakom navoda, ili da se (multilinijski string literal) započne i završi sa tri jednostruka znaka navoda ili 3 dvostruka znaka naloga.
Onda parser treba da zna da pronađe početak i kraj string literala (treba paziti na to da se unutar string može nalaziti \' ili \" kako bi se uneo znak navoda u string), a sve što nije "quoted" tekst da se čita do prve pojave "#" i da se onda od tog znaka do kraja reda ignoriše ostatak linije.

[Ovu poruku je menjao djoka_l dana 03.03.2020. u 14:45 GMT+1]
[ a1234567 @ 04.03.2020. 08:42 ] @
Evo verzije 2.0 rešenja zadatka 27,
koja sada uklanja komentare i u redovima koji imaju više #.

Idem slovo po slovo od kraja reda i tražim #, tu podelim red i odsečem desni deo.
Nije jako komplikovano.

Code:
with open('fajl1.txt', 'r') as f:
    redovi = f.readlines()

with open('fajl2.txt', 'w') as g:
    for red in redovi:
        if len(red.strip()) == 0:  # sačuvaj prazne linije
            g.writelines(red)
        elif red[0] == '#':        # ukloni ceo red ako počinje sa #
            g.writelines('\n')
        elif '#' not in red:       # prekopiraj red ako nema #
            g.writelines(red)
        else:                      # briši deo red desno od poslednjeg #
            for i in range(len(red) -1, -1, -1):
                if red[i] == '#':
                    red1 = red.split(red[i])   
                    obrishi = red1[0].rstrip()
                    g.writelines(obrishi)
                    g.writelines('\n')


Ostale egzibicije ostavljam iskusnim programerima
[ Branimir Maksimovic @ 04.03.2020. 08:47 ] @
a kamo ako je # u okviru string literala?
[ a1234567 @ 04.03.2020. 08:58 ] @
Nema veze, komentar je na kraju reda, tako da prvi desni # označava komentar
svi ostali, pa i ti u stringu, su levo od njega.
[ B3R1 @ 04.03.2020. 10:31 ] @
Citat:
a1234567: Nema veze, komentar je na kraju reda, tako da prvi desni # označava komentar
svi ostali, pa i ti u stringu, su levo od njega.

Pa i nije bas:
Code:

    print "Primer koda"  # Komentar pocinje ovde, # a ne ovde

Evo resenja koje obuhvata sve slucajeve, s objasnjenjem sta se tu tacno radi ... napominjem da je ovo bas osnovacko resenje, ali korisno da uvidis neke stvari koje se koriste u slicnim problemima (eksperti bi to odradili drugacije, ali o tom potom):
Code:

#!/usr/bin/python

import sys

for line in open(sys.argv[1], 'r').readlines():
    line = line.rstrip()
    q_single = False        # Apostrof (')
    q_double = False        # Navodnik (")
    escape = False          # Backslash (\)
    prev_char = ''          # Pamti prethodni znak u redu
    for pos,ch in enumerate(line):
        if (q_single or q_double) and escape:
            escape = not escape
            continue
        elif (q_single or q_double) and (ch == "\\"):
            escape = not escape
            continue
        elif (ch == '"' and prev_char != "\\" and not q_single and not escape):
            q_double = not q_double
        elif (ch == "'" and prev_char != "\\" and not q_double and not escape):
            q_single = not q_single
        elif (ch == '#' and not q_single and not q_double):
            line = line[:pos]
            break
        prev_char = ch
    print line

Kao sto sam vec pomenuo, u ovom problemu moras da ispitas da li se taraba nalazi unutar string literala ("Ova # je unutar literala") ili ne ("Ovo je literal" # A ovo komentar). I kao sto sam ti vec predlozio gore, moras da skeniras znak po znak u svakoj liniji i da donosis odluku da li ti je trenutna pozicija "skenera" unutar ili van literala. U gornjem primeru smo definisali tri logicke promenljive, cije vrednosti menjamo u toku programa koristeci logiku:
Code:

var = False
...
var = not var

Ova klik-klak tehnika u programiranju, poput prekidaca, se inace naziva 'toggle'. Kad god prodjes kroz liniju 'var = not var', promenljiva var naizmenicno menja vrednost od True ka False i obrnuto. U ovom kontekstu toggle smo koristili kao indikator STANJA, odnosno moda. Kada naidjemo na navodnik ("), prolazimo kroz toggle (q_double = not q_double), cime menjamo stanje literala - ako smo bili van literala sada smo unutar i obrnuto. Znaci - kada naidjes na prvi navodnik, program smatra da je string literal zapocet, a kada ponovo naidjes na isti tip navodnika literal je zavrsen. Slicno vazi i za apostrof, za literale koji su oiviceni apostrofima koristimo toggle q_single. Ali recimo, navodnik (") unutar literala oivicenog apostrofima (npr. 'Ovaj znak " je unutra') ili obrnuto ("Ovaj znak ' je unutra") ne sme da se broji ni kao pocetak, ni kao kraj literala, vec kao njegov deo. Osnovni program bi znaci bio:
Code:

...
if (ch == '"' and not q_single):        # Naisao je ", ali ne unutar literala oivicenog sa '
    q_double = not q_double
elif (ch == "'" and not q_double):     # Naisao je ', ali ne unutar literala oivicenog sa "
    q_single = not q_single
...

Ostaje da resimo slucaj \" i \'. To su escape znaci, koriste se kada unutar literala koristis isti znak kojim se definisu granice literala - npr. "Rec \"google\" oznacava inace ...". Tu u igru vec ulazi pamcenje prethodnog znaka, za sta se koristi prev_char. Na kraju, najtezi slucaj je kada se pojavi \\ unutar literala, sto se u Pythonu koristi za sam backslash. Tu uvodimo i ovaj toggle escape kojim se taj slucaj resava.

Gornji primer je prost, ali resava konkretan deo sintakse Pythona (parsiranje komentara). Profesionalci koji pisu kompajlere ne rade to tako pesice. Parsiranje sintakse teskta je nauka za sebe, ali i nije neka visa matematika i fizika ... :-). Kao sto se vidi cak i u gornjem primeru, kljucni pojam je STANJE (namerno napisano velikim slovima) - biti unutar i van literala je primer stanja. Biti unutar for() ili while() petlje ili if() strukture je takodje primer stanja. Znaci, treba nam algoritam koji pamti stanje sistema i u zavisnosti koji karakter/slovo/rec/sta god ... dodje dok si u stanju X, sistem prelazi u stanje Y ili Z. Ta problematika je stara vec solidnih 60 godina, time su se bavili i Turing, kao i Moore i Mealy i naziva se teorija konacnih automata. (Finite State Machines - FSM). Na ovom blog postu lik je zaista lepo objasnio kako se FSM moze implementirati u Pythonu.

Medjutim, FSM je samo temelj price. Svakako da profesionalci ne prave FSM bas uvek od nule. Postoje gotovi alati za parsiranje sintakse - lex, yacc, bison, flex ... o njima mozes da procitas ovde ako te zanima, ali to ti je vec masterclass nivo.

Ali ima i nesto sto mozes da savladas cak i na ovom nivou. Programeri ne prave kompajlere svaki dan ... osim ako se ne zovu Guido van Rossum :-). Obicnim smrtnicima - IT-sljakerima je mnogo potrebnije da parsiraju dokumente formatirane u nekom markup jeziku - HTML, SGML, XML ... Recimo, s nekog servera ti stize HTML tabela, sa sve onim <TD></TD> tagovima, a zelis da izdvojis podatke iz te tabele. Ili neki XML fajl, tipa: <TEMPERATURA>27</TEMPERATURA><PRITISAK>1000</PRITISAK> ... naravno, i to moze da se radi alatima opisanim gore, ali ljudi vise vole gotovanska prosta resenja. Srecom, ima tako nesto, zove se BeautlfulSoup, koji ti omogucava da neki HTML ili XML dokument parsiras lako ... bs4 moze da koristi i apsolutni pocetnik. Eto ti ideje za neki naredni zadatak ...

[Ovu poruku je menjao B3R1 dana 04.03.2020. u 11:48 GMT+1]
[ Panta_ @ 04.03.2020. 19:41 ] @
Evo sličnog rešenja, osim što prolazi znak po znak samo linije koje sadrže # znak:

Code (python):
lines = open('python_file.py').readlines()

for line in lines:
    line = line.rstrip()
    if '#' in line:
        in_str=False
        pos=0
        for char in line:
            if char == '"' or char == "'":
                if not in_str:
                    in_str=True
                    quote=char
                else:
                    if char == quote and prev_char != '\\':
                        in_str=False
            elif char == '#' and not in_str:
                line = line[:pos]
                break
            prev_char = char
            pos+=1
    print(line)
[ a1234567 @ 05.03.2020. 08:20 ] @
Baš ste se obojica potrudili da mi objasnite. Hvala vam.
Potrudio sam se i ja da razumem, ali slabo ja to kapiram. :(
Biće da još nisam na tom nivou.
[ a1234567 @ 05.03.2020. 10:00 ] @
Sigurno bi pomoglo ako bi se stvar pojednostavila, da bude samo jedan slučaj.
Recimo, da u stringu uklonim deo iza # ako nije unutar duplih navoda, a ako jeste da ostane.
Recimo ovakav slučaj:

line = 'They are designed "to whet your #appetite", not fill you up.'

Ali ja za sada umem da ga uklonim u svakom slučaju:

Code:
for pos, ch in enumerate(line):
    if ch == '#': 
        line = line[:pos]
        print(line)

i dobijem 'They are designed "to whet your'

Teorijski mi je jasno, naravno, da "skener" idući slovo po slovo kad naiđe na prvi navodnik uključi stanje False
i ako u tom stanju naiđe na # ne briše ga.
Kad naiđe na drugi navodnik, prebaci na stanje True i posle toga ako naiđe na # briše nastavak reda.
Ali nažalost ni pored primera ne kapiram baš kako to prevesti u kod.
[ Panta_ @ 05.03.2020. 14:44 ] @
"Sigurno bi pomoglo ako bi se stvar pojednostavila, da bude samo jedan slučaj."

Evo malo pojednostavljen slučaj sa samo jednom vrstom navodnika i bez escape (\) znaka:

Code (python):

linija = """ 'Ovo je # znak unutar stringa' # Ove je # znak izvan stringa """.strip()

da_li_sam_u_stringu = 'Nisam'

for pozicija, znak in enumerate(linija):
    if znak == "'":
        print(f'{pozicija}. {znak} Našao sam znak {znak}. Proveravam da li sam unutar stringa...')
        if da_li_sam_u_stringu == 'Nisam':
            da_li_sam_u_stringu = 'Jesam'
            print(f'Da li sam u stringu? {da_li_sam_u_stringu}')
        else:
            da_li_sam_u_stringu = 'Nisam'
            print(f'Da li sam u stringu? {da_li_sam_u_stringu}')
    elif znak == '#':
        print(f'{pozicija}. {znak} Našao sam znak {znak}. Proveravam da li sam u stringu...')
        if da_li_sam_u_stringu == 'Nisam':
            print(f'Nisam u stringu. Ispisujem liniju do pozicije {znak} znaka i prekidam izvršavanje:\n')
            print(linija[:pozicija])
            break
        else:
            print(f'Još uvek sam u stringu. Nsatavljam.')
    else:
        print(f'{pozicija}. {znak}')



Izlaz:

0. ' Našao sam znak '. Proveravam da li sam unutar stringa...
Da li sam u stringu? Jesam
1. O
2. v
3. o
4.  
5. j
6. e
7.  
8. # Našao sam znak #. Proveravam da li sam u stringu...
Još uvek sam u stringu. Nsatavljam.
9.  
10. z
11. n
12. a
13. k
14.  
15. u
16. n
17. u
18. t
19. a
20. r
21.  
22. s
23. t
24. r
25. i
26. n
27. g
28. a
29. ' Našao sam znak '. Proveravam da li sam unutar stringa...
Da li sam u stringu? Nisam
30.  
31. # Našao sam znak #. Proveravam da li sam u stringu...
Nisam u stringu. Ispisujem liniju do pozicije # znaka i prekidam izvršavanje:

'Ovo je # znak unutar stringa'
[ B3R1 @ 05.03.2020. 15:07 ] @
Python dopusta koriscenje apostrofa (') i navodnika (") kao oznake granice niza znakova (string), s tim da se za pocetak i kraj stringa moraju da koriste isti znaci. Znaci:
Code:

'ili ovo'
"ili ovo"
'NE MOZE OVAKO"   # OVO JE NEPRAVILNO!
"NITI OVAKO'          # I OVO JE GRESKA!
"Ispred slova 'I' pocinje, a iza tacke se zavrsava."
'Ispred slova "I" pocinje, a iza tacke se zavrsava.'

U kodu iz primera koji si naveo, ispred prve reci (They) nalazi se APOSTROF ('), dok se ispred "to" nalazi NAVODNIK ("). To su dva razlicita karaktera ...

Python dopusta i jednu i drugu varijantu ravnopravno, ali moras da budes dosledan - kako pocinjes string, tako ga i zavrsavas, ne mozes da mesas babe i zabe.

Inace, u nekim drugim programskim jezicima postoji znacajna, ali bitna razlika izmedju stringova oivicenih navodnicima ("blabla") ili apostrofima ('blabla'). Recimo, PHP i Perl kada napises:
Code:

$ dan = "Ponedeljak";
print "Danas je $dan\n";   # U PHP: echo umesto print
print 'Danas je $dan\n';    # U PHP: echo umesto print

Dobijes kao rezultat:
Code:

Danas je ponedeljak
Danas je $dan\n

U prvom slucaju (navodnici) Perl i PHP zamenjuju $dan vrednoscu promenljive $dan unutar stringa oivicenog navodnicima ("). Ako se string oivici apostrofima (') string se prikazuje as-is, odnosno nema zamene promenljivih, niti tumacenja escape sekvenci (\n, \r itd.).
[ a1234567 @ 06.03.2020. 10:18 ] @
Citat:
Panta_:
"Sigurno bi pomoglo ako bi se stvar pojednostavila, da bude samo jedan slučaj."

Evo malo pojednostavljen slučaj sa samo jednom vrstom navodnika i bez escape (\) znaka:

Panto, svaka čast za pedagoški pristup :)
Treba da objaviš negde tutorial za ovo.

Da, sad mi je slika mnogo bistrija, jer je i primer jednostavniji.
Dakle ovo sad sasvim lepo radi

Code:
linija = """ 'Ovo je # znak unutar stringa' # Ove je # znak izvan stringa """.strip()

stanje = False

for index, char in enumerate(linija):
    if  char == "'":
        if stanje == False:
            stanje = True  
        else:
            stanje = False
    elif char == "#":
        if stanje == False:
            print(linija[:index])
            break




[ a1234567 @ 06.03.2020. 10:30 ] @
Citat:
B3R1:
Python dopusta koriscenje apostrofa (') i navodnika (") kao oznake granice niza znakova (string), s tim da se za pocetak i kraj stringa moraju da koriste isti znaci. Znaci:
Code:

'ili ovo'
"ili ovo"
'NE MOZE OVAKO"   # OVO JE NEPRAVILNO!
"NITI OVAKO'          # I OVO JE GRESKA!
"Ispred slova 'I' pocinje, a iza tacke se zavrsava."
'Ispred slova "I" pocinje, a iza tacke se zavrsava.'

U kodu iz primera koji si naveo, ispred prve reci (They) nalazi se APOSTROF ('), dok se ispred "to" nalazi NAVODNIK ("). To su dva razlicita karaktera ...


Berislave, znam za pravilo da nema mešanja navodnika. Što je sasvim razumljivo. To su različiti karakteri.
Kod mene su dupli navodnici unutar stringa koji počinje i završava jednostrukim navodnicima.
Tako da mislim da nije greška.
Evo napravio sam ovu kombinaciju:

Code:
linija = 'They are designed "to whet your appetite" # not fill you up.'
lin = linija.strip()

stanje = False

for index, char in enumerate(lin):
    if  char == '"':
        if stanje == False:
            stanje = True
        else:
            stanje = False
    elif char == "#":
        if stanje == False:
            print(lin[:index])
            break

i rezultat je

They are designed "to whet your appetite"
[ a1234567 @ 07.03.2020. 11:45 ] @
Zadatak broj 28

Napiši program koji čita fajl sa listom reči, zatim nasumično bira dve ili tri od njih i spaja, kako bi napravio
novu lozinku. Kada pravi lozinku, njena dužina ne treba da bude manja od 10 slova, a da reči koje se koriste nisu
kraće od tri slova. Neka početna slova tih reči budu velika, tako da korisnik lako vidi gde se završava jedna i gde
počinje sledeća reč. Na kraju, program ispisuje novu lozinku za korisnika.

Moje rešenje je ovde.
[ Panta_ @ 08.03.2020. 06:47 ] @
"Kada pravi lozinku, njena dužina ne treba da bude manja od 10 slova, a da reči koje se koriste nisu kraće od tri slova"

Tvoje rešenje koristi i reči kraće od tri slova. Treba u random.choice() da filtriraš reči duže od dva slova.
[ a1234567 @ 08.03.2020. 11:03 ] @
Ja sam to elegantno rešio tako što sam u početni fajl words.txt stavio samo reči koje imaju 3 i više slova

Ali dobro, sad sam ubacio još jednu petlju da selektujem takve reči, ako u fajlu ima kraćih

Code:
import random

lozinka = ''
redovi3 = ''
with open('words.txt', 'r') as fajl:
    redovi2 = fajl.readlines()

for i in redovi2:
    if len(i) >= 4:
        redovi3 += i.capitalize()

while len(lozinka) <= 12:
    lozinka += random.choice(redovi3.split()).rstrip()
print('Tvoja nova lozinka je:\n\n', lozinka) 
[ B3R1 @ 08.03.2020. 15:02 ] @
"Kada pravi lozinku, njena dužina ne treba da bude manja od 10 slova, a da reči koje se koriste nisu kraće od tri slova"

Mislim da nisi dobro procitao zadatak. U matematici, "A nije manje od B" znaci "A >= B", a "A nije vece od B" znaci "A <= B". Ako duzina lozinke nije manja od 10 slova, znaci da mora da bude veca ili jednaka od 10. U tvom programu vidim 12 (?!). Slicno tome, zadatak kaze da reci nisu krace od 3 slova, a ti poredis duzinu reci sa 4. Po meni bi trebalo:
Code:

import random

lozinka = ''
redovi3 = ''
with open('words.txt', 'r') as fajl:
    redovi2 = fajl.readlines()

for i in redovi2:
    if len(i) >= 3:
        redovi3 += i.capitalize()

while len(lozinka) < 10:
    lozinka += random.choice(redovi3.split()).rstrip()
print('Tvoja nova lozinka je:\n\n', lozinka) 

Takodje, zasto filtriranje duzine ne radis odmah prilikom citanja iz fajla? Ne vidim razlog zasto bi prolazio kroz petlju dva puta. A ako to vec radis, zasto ti je redovi3 string, a ne lista? Elemente liste redovi2 ti nadovezujes u string redovi3, da bi kasnije koristio redovi3.split() (sto je opet treci prolazak kroz petlju, istina ovaj put "ispod haube" Pythona). Pokusaj da to malo optimizujes, nije tesko.
[ a1234567 @ 08.03.2020. 17:32 ] @
Ovo je originalni zadatak iz knjige Ben Stephenson: The Python Workbook (2019)

Exercise 159: Two Word Random Password

While generating a password by selecting random characters usually creates one that
is relatively secure, it also generally gives a password that is difficult to memorize.
As an alternative, some systems construct a password by taking two English words
and concatenating them. While this password may not be as secure, it is normally
much easier to memorize.

Write a program that reads a file containing a list of words, randomly selects two
of them, and concatenates them to produce a new password. When producing the
password ensure that the total length is between 8 and 10 characters, and that each
word used is at least three letters long. Capitalize each word in the password so that
the user can easily see where one word ends and the next one begins. Finally, your
program should display the password for the user.

Ja sam stavio u kodu dužinu lozinke na 12 slova, što je sigurno sigurno :))

Što se tiče dužine pojedinačnih reči, prvo sam stavio len >= 3
ali mi je program u lozinku ubacivao i reči od dva slova!?
I tu mi ništa nije bilo jasno, jel neki bag u pythonu ili šta je!? :)))
Prošlo je tu vremena dok mi u jednom trenutku nije sinulo da originalni fajl sa rečima izgleda ovako

Both
no
Check
Ensure
is
Python
Save
accessing
all
and
appropriate
character
...


i da program broji kao karakter i kraj reda \n.
Onda sam povećao na 4.

A ovo za optimizaciju, moram razmotriti, pa javljam rezultat :)
Stavio sam redovi3 prvo da bude lista, da ne moram posle da splitujem,
ali sad se više ne sećam gde je zapinjalo, pa sam prebacio na string.
[ B3R1 @ 08.03.2020. 18:25 ] @
Citat:
Što se tiče dužine pojedinačnih reči, prvo sam stavio len >= 3 ali mi je program u lozinku ubacivao i reči od dva slova!?
I tu mi ništa nije bilo jasno, jel neki bag u pythonu ili šta je!? :)))

Nije bag. Kompjuteri ne rade ono sto ti zelis, vec ono sto im zadas. A ti si rekao:
Code:

with open('words.txt', 'r') as fajl:
    redovi2 = fajl.readlines()

for i in redovi2:
    if len(i) >= 3:

Tekstualni fajlovi na kraju svake linije imaju tebi nevidljiv (ali kompjuteru itekako vidljiv) separator linije - tzv. newline. To je ono sto ti nesvesno u programima pises kao '\n' (to je inace karakter s ASCII kodom 10). Funkcija readlines() cita liniju po liniju i smesta je u listu, ali ako u python shellu otkucas prve 2 linije svog programa i onda kazes samo "redovi2", videces: [ 'Both\n', 'no\n', 'secure\n' ... ]. Bas zato ti je svaka rec realno 1 karakter duza. Tu imas dva resenja - ili da koristis 4 umesto 3 (sto si ti i uradio) ili da stripujes '\n' tokom ucitavanja fajla. Ako radis to drugo, onda mozes lepo da istovremeno upucs dve muve istim udarcem:
Code:

redovi = []
lozinka = ''
for red in open('words.txt', 'r'):
    red = red.strip()
    if (line(red)>=3):
        redovi.append(red)
while (len(lozinka)<10):
    lozinka += random.choice(redovi)
print('Tvoja nova lozinka je:\n\n', lozinka) 

Inace, mala zanimljivost. Newline separator varira od jednog do drugog operativnog sistema, ali danas su u upotrebi dve varijante. Unix i njegovi derivati (medju njima i Linux) koriste '\n' (linefeed ili LF - ASCII kod 10 (dec)). DOS i njegovi naslednici (Windows), kao i stari Digitalovi sistemi, koriste '\r\n' (carriage return + line feed - CR+LF, ASCII kodovi 13+10). Medjutim, Linux (i GNU) softver preveden na Windows takodje koristi Unix-ovski '\n'. U ovo poslednje spada i Python.
[ a1234567 @ 09.03.2020. 02:06 ] @
Kod tvog koda mi je otkriće da posle otvaranja ne moram da koristim readline,
već mogu odmah da pređem na operacije sa stringom.

Ja sam stalno išao na ovo

Code:
with open('words.txt', 'r') as fajl:
    redovi2 = fajl.readlines()


U kojim se onda slučajevima koristi readline?

Inače dodao sam kod tebe .capitalize()

i imao si
if (line(red)>=3):
umesto
if (len(red)>=3):

Vidim da stavljaš zagrade pre len i na kraju.
Jel to tako bilo u python 2.x?
U trojci može i bez zagrada.

Sad je kod sledeći:

Code:
import random
redovi = []
lozinka = ''
for red in open('words.txt', 'r'):
    red = red.strip().capitalize()
    if len(red) >= 3:
        redovi.append(red)
while len(lozinka) < 10:
    lozinka += random.choice(redovi)
print('Tvoja nova lozinka je:\n\n', lozinka)
[ Panta_ @ 09.03.2020. 11:58 ] @
"U kojim se onda slučajevima koristi readline?"

readline čita jednu liniju do znaka za novu liniju ili kraja fajla i vraća string uključujući i znak za novu liniju (\n). Na primer:

Code (python):
open('file.txt').readline()
'Programming fundamental tasks\n'

open('file.txt').readline().rstrip('\n')
'Programming fundamental tasks'


readlines vraća listu linija uključujući i \n znak:

Code (python):
open('/fajl.txt').readlines()
['Programming fundamental tasks\n',
 'Database programming with python\n',
 'Object Oriented programming\n']

[line.rstrip() for line in open('fajl.txt').readlines()]
['Programming fundamental tasks',
 'Database programming with python',
 'Object Oriented programming']


read čita do kraja fajla ili n broj znakova i vraća string:

Code (python):

open('fajl.txt').read(11)
'Programming'

open('fajl.txt').read()
'Programming fundamental tasks\nDatabase programming with python\nObject Oriented programming \n'

open('fajl.txt').read().split('\n')
['Programming fundamental tasks',
 'Database programming with python',
 'Object Oriented programming',
'']

open('fajl.txt').read().splitlines()
['Programming fundamental tasks',
 'Database programming with python',
 'Object Oriented programming ']


https://realpython.com/read-write-files-python/
[ djoka_l @ 09.03.2020. 13:52 ] @
Citat:
Vidim da stavljaš zagrade pre len i na kraju.
Jel to tako bilo u python 2.x?
U trojci može i bez zagrada.


To je samo znak kućnog vaspitanja :)

Zagrade je uvek pametno stavljati. Možda su ponekad nepotrebne, ali si bar siguran kojim redosledom će se uraditi operacije...
[ a1234567 @ 09.03.2020. 16:00 ] @
Hvala, Panto, sad smo čitanje fajlova apsolvirali do u detalje. :)

Đoko, pozdravljam kućno vaspitanje. To uvek dobro dođe.
A i od viška (zagrada) glava ne boli (uvek). :)


Nego, krenuo ja da radim naredni zadatak:

Napiši program koji čita fajl sa informacijama o hemijskim elementima i skladišti ih u odgovarajući strukturu podataka.
Potom prima input od korisnika. Ako je input integer, , onda program ispisuje simbol i naziv elementa sa tim brojem protona.
Ako korisnik unese naziv ili simbol elementa, program ispisuje njegov broj protona. Takođe, program ispisuje porucu o grešci
ako ne postoji elemenat koji bi odgovarao unetom nazivu, simbolu ili broju protona. Program nastavlja da učitava input sve
dok nije uneta prazna linija.

Fajl sa elementima ima ovu strukturu:

1,H,Hydrogen
2,He,Helium
3,Li,Lithium
4,Be,Beryllium
5,B,Boron
6,C,Carbon


i pretpostavljam da bi to trebalo prepakovati u neki nested dictionary:

tabela = {"H" : {"ime" : "Hydrogen", "broj protona" : 1},
"He" : {"ime" : "Helium", "broj protona" : 2},
"Li" : {"ime" : "Lithium", "broj protona" : 3}}

Gledao sam kako od liste da napravim rečnik i sve što sam uspeo je da napravim tri liste,
Ali ne znam kako da ih na pravi način ukomponujem u jedan rečnik.
Za sad sam stigao dovde

Code:
recnik = {}
list0 = []
list1 = []
list2 = []

for red in open('elements.txt', 'r'):
    red = red.rstrip().split(',')
    list0.append(red[0])
    list1.append(red[1])
    list2.append(red[2])
    
recnik = dict(zip(list2, list0))


Ali to mi daje:

{'Hydrogen': '1', 'Helium': '2', 'Lithium': '3', 'Beryllium': '7', 'Boron': '5', 'Carbon': '6'}

što naravno nije ono što se traži. :(
[ Panta_ @ 09.03.2020. 17:38 ] @
Ne terbaju ti tolike liste da napraviš rečnik, npr:
Code (python):

tabela = {}
for red in open('elements.txt', 'r'):
    red = red.rstrip().split(',')
    tabela.update(dict({red[1]: {'ime': red[2], 'broj protona': red[0]}}))

tabela
{'H': {'ime': 'Hydrogen', 'broj protona': '1'},
 'He': {'ime': 'Helium', 'broj protona': '2'},
 'Li': {'ime': 'Lithium', 'broj protona': '3'},
 'Be': {'ime': 'Beryllium', 'broj protona': '4'},
 'B': {'ime': 'Boron', 'broj protona': '5'},
 'C': {'ime': 'Carbon', 'broj protona': '6'}}

E, sad ti vidi da li ti takva struktura odgovara.
[ B3R1 @ 09.03.2020. 17:40 ] @
Ovo je prvi zadatak u kome moras da razmisljas out-of-the-box ...

Tebi je bitno da za zadat simbol, puno ime ili broj protona izbacis sve (ili odabrane) podatke o elementu. To prakticno znaci da ti je potrebna struktura u kojoj sva tri atributa (simbol, ime, protoni) mogu u isto vreme da budu i kljucevi i vrednosti. Tu imas vise resenja.

Prvi nacin, pomalo pocetnicki, je da se formiraju 2 recnika. U prvom ce kljucevi biti imena i simboli, a vrednosti brojevi protona. Drugi ce sluziti za obrnuto mapiranje:
Code:

proton = { 'Hydrogen': 1, 'H': 1, 'Helium': 2, 'He': 2, 'Lithium': 3, 'Li': 3 ... }
ime = { 1: [ 'Hydrogen', 'H' ], 2: [ 'Helium', 'He' ], 3: ['Lithium', 'Li' ] ... }

Ostatak programa je trivijalan - ako je uneta numericka vrednost (integer) p, ispisujes ime[p].
Ako je uneta nenumericka vrednost (string) s, ispisujes proton[s].
Naravno, moras da ispitas da li se p i s nalaze unutar recnika.
Na kraju, mozes ta dva recnika da spojis i u jedan ...

Drugi, napredniji nacin je da napravis visedimenzionu hash tabelu sa ili/ili kljucevima. Prednost je sto imas samo jedan recnik i taj recnik ima svega N elemenata, gde je N broj linija u fajlu koji ucitavas (1,H,Hydrogen,2,He,Helium ...). Naravno, neces to da radis iz pocetka, ljudi su to vec napravili i zove se multi_key_dict.

Ima sigurno jos mnogo nacina ...
[ djoka_l @ 10.03.2020. 22:02 ] @
Code:
def get_test_data():
  test_data = [ [1,'H','Hydrogen'], [2,'He','Helium'], [3,'Li','Lithium'],
                [4,'Be','Beryllium'], [5,'B','Boron'], [6,'C','Carbon']]

  return test_data

def find_in_matrix( table, element):
    element = element.lower()
    for row in table:
          for col in row:
            if element == str(col).lower():
                return row
    return [ element ]
    
def output( row ):
    print()
    if len( row ) == 3:
        print('Atomic number: ', row[0])
        print('Symbol       : ', row[1])
        print('Name         : ', row[2])
    else:
        print('Matching element not found: ', row[0])

def main_loop():

    pt=get_test_data()

    while True:
       print()
       print('Enter atomic number, chemical symbol or element name')
       print('to get the rest of the data, or an empty line for end:')

       search = input()
       if len(search)==0:
           break
        
       result = find_in_matrix(pt,search)
       output(result)

    print()
    print('Bye!')

main_loop()


Code:
py .\elements.py

Enter atomic number, chemical symbol or element name
to get the rest of the data, or an empty line for end:
1

Atomic number:  1
Symbol       :  H
Name         :  Hydrogen

Enter atomic number, chemical symbol or element name
to get the rest of the data, or an empty line for end:
he

Atomic number:  2
Symbol       :  He
Name         :  Helium

Enter atomic number, chemical symbol or element name
to get the rest of the data, or an empty line for end:
carbon

Atomic number:  6
Symbol       :  C
Name         :  Carbon

Enter atomic number, chemical symbol or element name
to get the rest of the data, or an empty line for end:
fe

Matching element not found:  fe

Enter atomic number, chemical symbol or element name
to get the rest of the data, or an empty line for end:


Bye!
[ djoka_l @ 10.03.2020. 22:32 ] @
Opservacija:

mislim da sam ti jednom već napisao - inženjeru koji ima samo čekić, svaki problem izgleda kao ekser.
Tako i tebi, svaki zadatak je nerešiv ako ne znaš kako podatke da staviš u dictionary.

Moje rešenje je elementarno, praktično ne koristim ni jednu python caku, ali ti pokazuje da svaki zadatak može da se reši na više načina.
Ja obično biram najprostiji način.

Razdvojiš funkcionalnosti u FUNKCIJE.
Tako ćeš lako da dodaš učitavanje iz fajla, a ne predefinisanu tabelu koju sam ja napravio.

Ako ti se ne sviđa moj način traženja podatka promeniš samo jednu FUNKCIJU.
Ostalo ne moraš da menjaš.

Koristi FUNKCIJE, tako ćeš logičke celine svog rešenje lako zamenjivati kada smisliš bolje rešenje.
[ Panta_ @ 11.03.2020. 08:02 ] @
Evo rešenje sa pomenutim rečnikom:

Code (python):

tabela = []

for line in open('elements.txt'):
    line = line.strip().split(',')
    tabela.append({'simbol': line[1], 'ime': line[2], 'broj protona': line[0]})

while True:
    user_input = input(
        "Unesite ime, simbol ili broj protona (ili Enter za izlaz iz programa): ")
    # Ako je user_input prazan string, prekidam izvršavanje while petlje
    if user_input == '':
        print('Izlazim.')
        break
    founded = False
    for elements in tabela:
        if not founded:
            for element in elements.values():
                # Ako element value odgovara inputu, dodeljujem founded promenljivoj
                # vrednost True kao bih prekinuo dalje izvršavanje prve for petlje
                if element == user_input.title():
                    founded = True
                    # Ukoliko je input integer, ispisujem simbol, ime i broj
                    # protona. U suprotnom, ispisujem samo broj protona
                    if element.isdigit():
                        print(f"Simbol: {elements['simbol']} \
                        \nIme: {elements['ime']} \
                        \nBroj protona: {elements['broj protona']}\n"
)
                    else:
                        print(f"Broj protona: {elements['broj protona']}\n")
        else:
            break
    if not founded:
        print(f"Element {user_input} nije pronađen! Pokusajte ponovo.\n")
 


Code:
Unesite ime, simbol ili broj protona (ili Enter za izlaz iz programa): carbon
Broj protona: 6

Unesite ime, simbol ili broj protona (ili Enter za izlaz iz programa): he
Broj protona: 2

Unesite ime, simbol ili broj protona (ili Enter za izlaz iz programa): 3
Simbol: Li                         
Ime: Lithium                         
Broj protona: 3

Unesite ime, simbol ili broj protona (ili Enter za izlaz iz programa): fe
Element fe nije pronađen! Pokusajte ponovo.

Unesite ime, simbol ili broj protona (ili Enter za izlaz iz programa): 
Izlazim.


Naravno, umesto rečnika možeš da koristiš liste ili tuple, posebno za ovaj zadatak pošto ti ključevi nisu neophodni.
[ a1234567 @ 11.03.2020. 10:10 ] @
Au, šta je materijala za razmatranje.
Hvala na trudu!

Za početak sam razmotrio Pantino rešenje.
Vidim da si promenio tip strukture podataka, pa si umesto rečnika napravio listu, čiji su elementi rečnici.
Ja sam očigledno na samom početku nepotrebno zakomplikovao, misleći da treba da koristim nested dictionary.

Jedino što tvoje rešenje ne daje ispis tačno kako se traži u zadatku.

"If the user enters a non-integer value then your program should display the
number of protons for the element with that name or symbol."

Zato sam malo "dopisao" ovo pretposlednje else

Code:
tabela = []

for line in open('elements.txt'):
    line = line.strip().split(',')
    tabela.append({'simbol': line[1], 'ime': line[2], 'broj protona': line[0]})

while True:
    user_input = input(
        "Unesite ime, simbol ili broj protona (ili Enter za izlaz iz programa): ")
    # Ako je user_input prazan string, prekidam izvršavanje while petlje
    if user_input == '':
        print('Izlazim.')
        break
    founded = False
    for elements in tabela:
        if not founded:
            for element in elements.values():
                # Ako element value odgovara inputu, dodeljujem founded promenljivoj
                # vrednost True kako bih prekinuo dalje izvršavanje prve for petlje
                if element == user_input.title():
                    founded = True
                    # Ukoliko je input integer, ispisujem simbol, ime i broj
                    # protona. U suprotnom, ispisujem samo broj protona
                    if element.isdigit():
                        print(f"Simbol: {elements['simbol']} \
                        \nIme: {elements['ime']} \
                        \nBroj protona: {elements['broj protona']}\n")
                    else:
                        if element in elements['simbol']:
                            print(f"Ime: {elements['ime']} \
                            \nBroj protona: {elements['broj protona']}\n")
                        elif element in elements['ime']:
                            print(f"Simbol: {elements['simbol']} \
                            \nBroj protona: {elements['broj protona']}\n")
        else:
            break
    if not founded:
        print(f"Element {user_input} nije pronađen! Pokušajte ponovo.\n")


Sad ispisuje ovako:

Unesite ime, simbol ili broj protona (ili Enter za izlaz iz programa): Calcium
Simbol: Ca
Broj protona: 20

Unesite ime, simbol ili broj protona (ili Enter za izlaz iz programa): 100
Simbol: Fm
Ime: Fermium
Broj protona: 100

Unesite ime, simbol ili broj protona (ili Enter za izlaz iz programa): fm
Ime: Fermium
Broj protona: 100
[ Panta_ @ 11.03.2020. 12:16 ] @
Citat:
Jedino što tvoje rešenje ne daje ispis tačno kako se traži u zadatku.

"If the user enters a non-integer value then your program should display the
number of protons for the element with that name or symbol."

Zašto onda nisi tako napisao već:
Citat:
Ako korisnik unese naziv ili simbol elementa, program ispisuje njegov broj protona.

Citat:
Zato sam malo "dopisao" ovo pretposlednje else

else:
if element in elements['simbol']:
print(f"Ime: {elements['ime']} \
\nBroj protona: {elements['broj protona']}\n")
elif element in elements['ime']:
print(f"Simbol: {elements['simbol']} \
\nBroj protona: {elements['broj protona']}\n")

Dovoljno je samo u print funkciji ispred "Broj protona" da dodaš Simbol: {elements['ime'] if element in elements['simbol'] else elements['simbol']}, npr:
Code:

Zameniti

print(f"Broj protona: {elements['broj protona']}\n")

sa

print(f"Simbol: {elements['ime'] if element in elements['simbol'] else elements['simbol']}\nBroj protona: {elements['broj protona']}\n")


Moja greška, nisam video da treba i ime.

[Ovu poruku je menjao Panta_ dana 11.03.2020. u 13:51 GMT+1]

[Ovu poruku je menjao Panta_ dana 11.03.2020. u 13:52 GMT+1]
[ a1234567 @ 12.03.2020. 15:06 ] @
Citat:
B3R1:
Ovo je prvi zadatak u kome moras da razmisljas out-of-the-box ...

Tebi je bitno da za zadat simbol, puno ime ili broj protona izbacis sve (ili odabrane) podatke o elementu. To prakticno znaci da ti je potrebna struktura u kojoj sva tri atributa (simbol, ime, protoni) mogu u isto vreme da budu i kljucevi i vrednosti. Tu imas vise resenja.

Prvi nacin, pomalo pocetnicki, je da se formiraju 2 recnika. U prvom ce kljucevi biti imena i simboli, a vrednosti brojevi protona. Drugi ce sluziti za obrnuto mapiranje:
Code:

proton = { 'Hydrogen': 1, 'H': 1, 'Helium': 2, 'He': 2, 'Lithium': 3, 'Li': 3 ... }
ime = { 1: [ 'Hydrogen', 'H' ], 2: [ 'Helium', 'He' ], 3: ['Lithium', 'Li' ] ... }

Ostatak programa je trivijalan


Berislave, razmotrio sam ovu trivijalnu varijantu i napravio sa tri rečnika za listu elemenata
1,H,Hydrogen
2,He,Helium
3,Li,Lithium
4,Be,Beryllium...


U svakom su ključevi naziv elementa, simbol, odnosno broj protona:

Code:
ime = {}
simbol = {}
proton = {}

for line in open('elements.txt'):
    line = line.strip().split(',')
    ime[line[2]] = [line[1], int(line[0])]
    simbol[line[1]] = [line[2], int(line[0])]
    proton[int(line[0])] = [line[2], line[1]]

user_input = input("Unesite ime, simbol ili broj protona (ili Enter za izlaz iz programa): ")

if user_input == '':
    print('Izlazim.')
elif user_input.isdigit():
    print('Ime elementa je', proton[int(user_input)][0], '\ni njegov simbol je', proton[int(user_input)][1])
elif user_input.title() in simbol.keys():
    print('Ime elementa je', simbol[user_input.title()][0], '\ni on ima', simbol[user_input.title()][1], 'protona')
elif user_input.title() in ime.keys():
    print('Simbol elementa je', ime[user_input.title()][0], '\ni on ima', ime[user_input.title()][1], 'protona')
else:
    print('Uneta vrednost se ne nalazi u tabeli prirodnih elemenata.')


I dobijam

Unesite ime, simbol ili broj protona (ili Enter za izlaz iz programa): h
Ime elementa je Hydrogen
i on ima 1 protona

Unesite ime, simbol ili broj protona (ili Enter za izlaz iz programa): be
Ime elementa je Beryllium
i on ima 7 protona

Unesite ime, simbol ili broj protona (ili Enter za izlaz iz programa): boron
Simbol elementa je B
i on ima 5 protona

Unesite ime, simbol ili broj protona (ili Enter za izlaz iz programa): kdsjd
Uneta vrednost se ne nalazi u tabeli prirodnih elemenata.

[ a1234567 @ 12.03.2020. 15:31 ] @
Citat:
djoka_l:
Opservacija:

mislim da sam ti jednom već napisao - inženjeru koji ima samo čekić, svaki problem izgleda kao ekser.
Tako i tebi, svaki zadatak je nerešiv ako ne znaš kako podatke da staviš u dictionary.

Moje rešenje je elementarno, praktično ne koristim ni jednu python caku, ali ti pokazuje da svaki zadatak može da se reši na više načina.
Ja obično biram najprostiji način.

Razdvojiš funkcionalnosti u FUNKCIJE.
Tako ćeš lako da dodaš učitavanje iz fajla, a ne predefinisanu tabelu koju sam ja napravio.

Ako ti se ne sviđa moj način traženja podatka promeniš samo jednu FUNKCIJU.
Ostalo ne moraš da menjaš.

Koristi FUNKCIJE, tako ćeš logičke celine svog rešenje lako zamenjivati kada smisliš bolje rešenje.


Mislim da mi još treba vremena da pohvatam ove osnovne stvari. A funkcije su malo viša faza, čini mi se.
No, probaću u rešenja za naredne zadatke i njih da uključim.
[ a1234567 @ 12.03.2020. 15:38 ] @
I evo da napravim i poseban post za ovaj zadatak, lakše će se snaći oni koji budu gledali ovaj topik.

Zadatak broj 29

Napiši program koji čita fajl sa informacijama o hemijskim elementima i skladišti ih u odgovarajući strukturu podataka.
Potom prima input od korisnika. Ako je input integer, , onda program ispisuje simbol i naziv elementa sa tim brojem
protona. Ako korisnik unese naziv ili simbol elementa, program ispisuje njegov broj protona. Takođe, program ispisuje
porucu o grešci ako ne postoji elemenat koji bi odgovarao unetom nazivu, simbolu ili broju protona. Program nastavlja
da učitava input sve dok nije uneta prazna linija.

Mustra za fajl sa elementima:

1,H,Hydrogen
2,He,Helium
3,Li,Lithium
4,Be,Beryllium...


Rešenja koja su ovde bila data sam saćuvao ovde
[ a1234567 @ 18.03.2020. 04:51 ] @
Stiže evo najzad i jubilarni zadatak broj 30.

Napiši program koji čita spisak reči iz fajla i izračunava procenat reči koje koriste
određeno slovo abecede. Ispiši taj procenat za svako slovo, a na kraju i poruku
koje slovo se najređe pojavljuje. Program ignoriše znakove interpunkcije i
isto tako velika i mala slova tretira kao isto slovo.

Svoje rešenje sam postavio ovde.

Dobijam sledeći ispis:

a se javlja u 40.09 odsto reči
b se javlja u 6.23 odsto reči
c se javlja u 16.85 odsto reči
d se javlja u 18.44 odsto reči
e se javlja u 49.71 odsto reči
f se javlja u 11.07 odsto reči
g se javlja u 9.93 odsto reči
h se javlja u 21.55 odsto reči
i se javlja u 30.47 odsto reči
j se javlja u 0.48 odsto reči
k se javlja u 3.08 odsto reči
l se javlja u 17.02 odsto reči
m se javlja u 13.56 odsto reči
n se javlja u 32.13 odsto reči
o se javlja u 35.70 odsto reči
p se javlja u 9.13 odsto reči
q se javlja u 0.45 odsto reči
r se javlja u 28.23 odsto reči
s se javlja u 28.40 odsto reči
t se javlja u 41.34 odsto reči
u se javlja u 14.46 odsto reči
v se javlja u 5.26 odsto reči
w se javlja u 8.89 odsto reči
x se javlja u 1.00 odsto reči
y se javlja u 8.61 odsto reči
z se javlja u 0.62 odsto reči

Slovo koje se najređe pojavljuje je: q
[ B3R1 @ 18.03.2020. 11:46 ] @
Lepo uradjeno. Popravio si stil kodiranja, nemas vise suvisne korake. Sve u svemu, napredujes.
[ a1234567 @ 18.03.2020. 14:01 ] @
Hvala, Berislave.
To je po onome, i ćorava koka ubode neko zrno.
Tako i ja ovoga puta
[ djoka_l @ 18.03.2020. 18:19 ] @
Pridružujem se čestitkama!
Naravno, uvek može i malo bolje

Code:
import time
import re

MyWord = "abrakadabra..!-?"
regex = re.compile(r"[^a-z]+")

start=time.time()

for i in range(1_000_000):
    slova = []
    for ch in MyWord:
        if ch not in slova and ch >= "a" and ch <= "z":
            slova.append(ch)


end=time.time()
print(slova)
print(end-start)

start=time.time()

for i in range(1_000_000):
    slova=set()
    slova = set(regex.sub("", MyWord))


end=time.time()
print(slova)
print(end-start)

Code:
Rezultat:

['a', 'b', 'r', 'k', 'd']
2.6087019443511963
{'a', 'd', 'r', 'k', 'b'}
1.4458417892456055


Korišćenjem regularnog izraza i skupa umesto liste, eliminisao sam jednu petlju, jedan if sa tri logička izraza i append, pa sam na milion izvršavanja dobio upola kraće vreme.
Ovo jeste teranje maka na konac, ali pokazuje da uvek ima mesta da se unapredi algoritam i da se odabere bolja struktura podataka za dati problem.
[ Panta_ @ 18.03.2020. 20:46 ] @
Citat:
Korišćenjem regularnog izraza i skupa umesto liste, eliminisao sam jednu petlju, jedan if sa tri logička izraza i append, pa sam na milion izvršavanja dobio upola kraće vreme.


Ako zamniš ch >= "a" and ch <= "z" sa ch in 'abcdefghijklmnopqrstuvwxyz' kao i set regex sa {ch for ch in MyWord if ch in 'abcdefghijklmnopqrstuvwxyz'} dobićeš jos kraće vreme.
Code:
%timeit set(regex.sub("", MyWord))
1.36 µs per loop

%timeit {ch for ch in MyWord if ch in 'abcdefghijklmnopqrstuvwxyz'}
1.26 µs per loop

%timeit [ch for ch in MyWord if ch >= "a" and ch <= "z"]
1.4 µs per loop

%timeit [ch for ch in MyWord if ch in 'abcdefghijklmnopqrstuvwxyz']
1.07 µs per loop
[ Panta_ @ 18.03.2020. 21:30 ] @
Citat:
To je po onome, i ćorava koka ubode neko zrno.

Po mom mišljnju opet imaš koje zrno viška, na primer:
Code:

brojac = {}
for ch in 'abcdefghijklmnopqrstuvwxyz':
    brojac[ch] = 0

br_reci = 0
spisak = open('reci2.txt', 'r', encoding='utf-8')

for rec in spisak:
    rec = rec.lower().rstrip()
    
    # Lista slova koja se pojavljuju u rečima, ali bez ponavljanja.
    slova = []
    for ch in rec:
        if ch not in slova and ch >= "a" and ch <= "z":
            slova.append(ch)
    # Brojač za slova
    for ch in slova:
        brojac[ch] = brojac[ch] + 1
    # Brojač za reči
    br_reci = br_reci + 1


Imaš dve suvišne for petlje, nema potrebe da prvo dodaješ slova u brojač.
Recimo da hoćeš da prebrojiš i naša ili neka druga slova, a nemaš ih u rečniku, dobio bi Key error grešku pošto isti nije u rečniku.

Code:
spisak = open('reci2.txt', 'r', encoding='utf-8')
brojac = {}
br_reci = 0

for rec in spisak:
    rec = rec.lower().rstrip()
    
    # Lista slova koja se pojavljuju u rečima, ali bez ponavljanja.
    slova = []
    for ch in rec:
        if ch not in slova and ch >= "a" and ch <= "z":
            slova.append(ch)
       # Brojač za slova
        if ch not in brojac:
            brojac[ch]=1
        else:
            brojac[ch]+=1
    br_reci = br_reci + 1


Takođe, za brojač može da se iskoristi defaultdict iz collections modula:
Code:
from collections import defaultdict

brojac = defaultdict(int)

# Umesto if/else
if ch not in brojac:
    brojac[ch]=1
else:
    brojac[ch]+=1

# je dovoljno
brojac[ch]+=1

[ a1234567 @ 25.03.2020. 16:07 ] @
Borim se sa zadatkom broj 31:

Podaci se sastoje od preko 200 fajlova. Svaki fajl sadrži spisak od 100 imena koja su u SAD bila najpolularnija u datoj godini, zajedno s brojem upotreba svakog imena. Imena su u fajlu poređana od najviše korišćenog pa naniže. Postoje dva fajla za svaku godinu: jedan sadrži imena koja se koriste za devojčice, a drugi sadrži imena za dečake. Skup podataka uključuje podatke za svaku godinu od 1900. do 2012. godine.

Napisati program koji čita svaki fajl i identifikuje sva imena koja su bila najpopularnija najmanje u jednoj godini. Program ispisuje dve liste:
jedna sadrži najpopularnija imena za dečake, a druga za djevojčice. Nijedan spisak ne sadrži ponovljena imena.

fajlovi u folderu:
1900_BoysNames.txt
1900_GirlsNames.txt
1901_BoysNames.txt
1901_GirlsNames.txt
itd.


podaci u fajlu:
John 9830
William 8580
James 7245
George 5403
Charles 4101
Robert 3824
Joseph 3714
Frank 3477
itd.

Ako neko hoće da skine fajlove, ovde su.

Uspeo sam da pokupim unikatna imena iz prvog reda svakog fajla, ali sve u jedan fajl:

Code:
import glob

imena = []

with open('imena.txt2', 'w') as spisak:
    for filename in glob.glob('*.txt'):
        fajl = open(filename, 'r', encoding='utf-8')
        line = fajl.readline().strip().split()
        ime = line[0]
        if ime not in imena:
            imena.append(ime)
    spisak.writelines(str(imena)+'\n')


Kako da selektujem na muška i ženska imena, nemam ideju :(
[ Panta_ @ 25.03.2020. 17:02 ] @
Probaj ovako:

Code:

boys = []
girls = []
for filename in glob.glob('*txt'):
     if 'Boys' in filename:
         name = open(filename).readline().split()[0]
         if name not in boys:
             boys.append(name)
     elif 'Girls' in filename:
         name = open(filename).readline().split()[0]
         if name not in girls:
             girls.append(name)

[ a1234567 @ 26.03.2020. 04:29 ] @
Probao. Radi :)

Znači mogu detaljnije da biram koje će glob fajlove da globi, a ne samo preko ekstenzije.
To nisam bio prokljuvio.

Dobro, sad je kod ovakav

Code:
boys = []
girls = []

with open('decaci.txt2', 'w') as spisak1:
    with open('devojcice.txt2', 'w') as spisak2:
        for filename in glob.glob('*txt'):
             if 'Boys' in filename:
                 name = open(filename).readline().split()[0]
                 if name not in boys:
                     boys.append(name)
             elif 'Girls' in filename:
                 name = open(filename).readline().split()[0]
                 if name not in girls:
                     girls.append(name)
        spisak1.writelines('\n'.join(boys))
        spisak2.writelines('\n'.join(girls))

Pošto se fajlovi u koje upisujem selektovana imena nalaze u istom folderu sa imenima dece, ovaj glob krene da otvara i njih.
Zato sam, kao što vidiš, njihove extenzije promenio u .txt2.

Kako da ovome writelines dam putanju za neki drugi folder gde će upisivati fajlove sa odabranim imenima?
[ Panta_ @ 26.03.2020. 06:40 ] @
Citat:
Znači mogu detaljnije da biram koje će glob fajlove da globi, a ne samo preko ekstenzije.

glob vraća listu imena datoteka koje se završavaju sa .txt, dakle isto kao da si napisao: for filename in ['2010_GirlsNames.txt', '1917_BoysNames.txt', itd...]:
Citat:
Kako da ovome writelines dam putanju za neki drugi folder gde će upisivati fajlove sa odabranim imenima?

Navedi putanju u open('/putanja/do/decaci.txt', 'w'), ili putanja = '/putanja/do/decaci.txt', pa onda u open(putanja, 'w') itd...
[ a1234567 @ 26.03.2020. 07:22 ] @
Aha, to sa globom je u stvari onda lista imena fajlova. Kapiram.

Da, sad kad stavim putanju, radi sve kako treba.
Konačno rešenje je ovde.

Hvala, Panto!

Sad mogu da krenem na naredni zadatak....
[ Panta_ @ 26.03.2020. 08:32 ] @
Citat:
Sad mogu da krenem na naredni zadatak

Pre nego što kreneš na naredni zadatak, bio bi red da program pored imena ispiše i godine u kojima je ime bilo najpopularnije, kao i broj datih imena. Na primer:
Code:
{'Girls Names': {
    'Emma': {
        '2008': '25809'
    },
    'Emily': {
        '2001': '21113',
        '2002': '21113',
        '2004': '22547',
        '2006': '24811',
        '2003': '27868',
        '2000': '32520',
        '2005': '32520',
        '2007': '24238'
    },
    'Isabella': {
        '2009': '25809'
    }
  },
'Boys Names': {
    'Jacob': {
        '2009': '21113',
        '2002': '30552',
        '2000': '34460',
        '2008': '22547',
        '2006': '24811',
        '2004': '27868',
        '2001': '32520',
        '2007': '24238',
        '2003': '29605',
        '2005': '25809'
  }}
}
[ a1234567 @ 26.03.2020. 11:41 ] @
E ako bi bio red, onda nema druge nego da uradim, samo ako budem umeo :))

"Jer red je red, sve ja to poštujem... "
[ a1234567 @ 26.03.2020. 15:30 ] @
Evo dovde sam stigao.

Program ne prijavljuje nikakvu grešku, ali ništa ni ne upisuje u rečnike.
Negde nešto fali, ali ne mogu da uklavirim šta.

Code:
import glob

decaci = {}
devojcice = {}

with open('c:/FAJLOVI/Python_School/Stephenson_ThePythonWorkbook/decaci.txt2', 'w') as spisak1:
    with open('c:/FAJLOVI/Python_School/Stephenson_ThePythonWorkbook/devojcice.txt2', 'w') as spisak2:
        for filename in glob.glob('*txt'):
             if 'Boys' in filename:
                 name = open(filename).readline().split()[0]
                 broj = open(filename).readline().split()[1]
                 godina = filename[0:4]
                 for k1, v1 in decaci.items():
                     for k2, v2 in v1.items():
                         if name not in v2.keys():
                             decaci['Boys Names'][name][godina] = [broj]
                 
             elif 'Girls' in filename:
                 name = open(filename).readline().split()[0]
                 broj = open(filename).readline().split()[1]
                 godina = filename[0:4]
                 for k1, v1 in devojcice.items():
                     for k2, v2 in v1.items():
                         if name not in v2.keys():
                             devojcice['Girls Names'][name][godina] = [broj]
[ Panta_ @ 26.03.2020. 19:56 ] @
Fali svašta. Nema potrebe za tolikim for petljama, ionako u decaci i devojcije dictionary nemaš ništa, a i imaš već for petlju za filename. Ranije gore sam ti pomenu defaultdict iz collections modula koji kreira ključ ukoliko isti ne postoji kako ne bi dobio key error. Na primer:
Code (python):
from collections import defaultdict

decaci = defaultdict(dict)

# ili https://docs.python.org/3/library/stdtypes.html#dict.setdefault
# decaci.setdefault('Boys', {})

for filename in glob.glob('*txt'):
     if 'Boys' in filename:
         name, broj = open(filename).readline().split()
         # broj = open(filename).readline().split()[1]
         godina = filename[:4]
         if name not in decaci['Boys']:
             decaci['Boys'].update({name: {godina: broj}})
         else:
             decaci['Boys'][name].update({godina: broj})


Izlaz:

{'Boys': {
    'David': {'1960': '85928'},
    'Jacob': {
        '1999': '35342',
        '2000': '34460',
        '2001': '32520',
        '2002': '30552',
        '2003': '29605',
        '2004': '27868',
        '2005': '25809',
        '2006': '24811',
        '2007': '24238',
        '2008': '22547',
        '2009': '21113',
        '2010': '22052',
        '2011': '20269',
        '2012': '18899'},
    'James': {
        '1940': '62452',
        '1941': '66714',
        '1942': '77164',
        '1943': '80236',
        '1944': '76936',
        '1945': '74439',
        '1946': '87432',
        '1947': '94743',
        '1948': '88544',
        '1949': '86776', itd...}}})

 
[ B3R1 @ 27.03.2020. 11:09 ] @
Nisam gledao detaljno, ali ovako na brzinu palo mi je u oci nekliko detalja:
Code:

name = open(filename).readline().split()[0]
broj = open(filename).readline().split()[1]

Fajl se otvara samo jednom, a svaki sledeci poziv funkcije readline() cita sledecu linju iz fajla. Ovako kako si napisao program ce svaki put otvoriti fajl iznova i uvek procitati samo prvu liniju. Ono sto si hteo da uradis je:
Code:

        for filename in glob.glob('*txt'):
             lines = open(filename).readlines()
             if 'Boys' in filename:
                 for line in lines:
                     name = line.strip().split()[0]
                     broj = line.strip().split()[1]
                     godina = filename[0:4]
                     ...

Drugo, cemu ti sluze ove dve petlje na pocetku:
Code:

with open('c:/FAJLOVI/Python_School/Stephenson_ThePythonWorkbook/decaci.txt2', 'w') as spisak1:
    with open('c:/FAJLOVI/Python_School/Stephenson_ThePythonWorkbook/devojcice.txt2', 'w') as spisak2:

Mislim da treba samo da otvoris ta dva fajla za upisivanje bez 'with' strukture. I da svaki put u petlji samo upisujes u njih koristeci write() funkciju - npr:
Code:

spisak1 = open('c:/FAJLOVI/Python_School/Stephenson_ThePythonWorkbook/decaci.txt2', 'w')
spisak2 = open('c:/FAJLOVI/Python_School/Stephenson_ThePythonWorkbook/devojcice.txt2', 'w')
# ... Program ide dalje
# Ispis
...
spisak1.write(promenljiva + '\n')
spisak2.write(promenljiva + '\n')
# OBAVEZNO NA KRAJU:
spisak1.close()
spisak2.close()

Sledeca stvar su dictovi, odnosno hash tabele:
Code:

decaci = {}
...
                 for k1, v1 in decaci.items():
                     for k2, v2 in v1.items():
                         if name not in v2.keys():
                             decaci['Boys Names'][name][godina] = [broj]

Ispravno bi bilo:
Code:

decaci = { 'Boys Names': {} }
                 for k1, v1 in decaci.items():
                     for k2, v2 in v1.items():
                         if name not in v2.keys():
                             decaci['Boys Names'][name] = {}
                         if godina not in decaci['Boys Names'][name] :
                             decaci['Boys Names'][name][godina] = broj

Naime, decaci{} ti je hash tabela ciji je kljuc 'Boys Names', a vrednost nova hash tabela kojoj su kljucevi imena, a vrednosti treca hash tabela ciji su kljucevi godista, a vrednosti frekvencija imena:
Code:

{'Boys Names': {
    'David': {'1960': '85928'},
    'Jacob': {'1999': '35342',  '2000': '34460' }
}}

Da pojasnimo: kada definises hash tabelu decaci kao praznu (decaci = {}), Python ce ti dopustiti da kreiras key:value parove kako god zelis:
Code:

decaci['Mark'] = 1
decaci['Peter'] = 'abc123'
...

Ali kada kazes:
Code:

decaci['Mark']['1976'] = 123

dobijas gresku jer je decaci['Mark'] inicijalizovano kao skalar, a ne kao nova hash tabela. Da bi formirao hash tabelu unutar druge hash tabele moras da najpre kazes da je vrednost kljuca 'Mark' takodje hash tabela:
Code:

decaci['Mark'] = {}
decaci['Mark']['1976'] = 123

Kao sto je Panta rekao, tu moze da ti pomogne defaultdict, mada je daleko cistije raditi postepenu inicijalizaciju, jer se kasnije lakse uocavaju i ispravljaju greske.
Druga stvar koja mi upada u oci je:
Code:

decaci['Boys Names'][name][godina] = [broj]

Ovako kako si napisao ti zapravo dobijas:
{'Boys Names': {
'David': {'1960': ['85928']},
'Jacob': {'1999': ['35342'], '2000': ['34460'] }
}}
Cemu ti sluzi lista kao vrednost u ovom slucaju?

I ono poslednje - godista i frekvencije pojavljivanja imena su numericke vrednosti, pa nema smisla skladistiti ih kao stringove. Numericke vrednosti mogu da se direktno obradjuju. Pre bi imlao smisla:
Code:
name = int(line.strip().split()[0])
broj = int(line.strip().split()[1])

Za kraj jedna zanimljivost: funkcija int(x) u vecini jezika vraca nulu ako x nije numericka vrednost. Npr. int('23') ce biti 23, dok ce int('hello') biti 0. U Pythonu to nije slucaj, int('hello') ce prijaviti gresku. Ja obicno koristim modifikovanu verziju funkcije int() koja izgleda ovako:
Code:

# aint() - The int() function, as we got used in other languagues
def aint(x):
    try:
        retval = int(x)
    except:
        retval = 0
    return retval

I pozivam je sa aint(x) ... vraca nulu ako x nije numericko.
[ Branimir Maksimovic @ 27.03.2020. 11:21 ] @
Citat:
a1234567:
Borim se sa zadatkom broj 31:

Podaci se sastoje od preko 200 fajlova. Svaki fajl sadrži spisak od 100 imena koja su u SAD bila najpolularnija u datoj godini, zajedno s brojem upotreba svakog imena. Imena su u fajlu poređana od najviše korišćenog pa naniže. Postoje dva fajla za svaku godinu: jedan sadrži imena koja se koriste za devojčice, a drugi sadrži imena za dečake. Skup podataka uključuje podatke za svaku godinu od 1900. do 2012. godine.

Napisati program koji čita svaki fajl i identifikuje sva imena koja su bila najpopularnija najmanje u jednoj godini. Program ispisuje dve liste:
jedna sadrži najpopularnija imena za dečake, a druga za djevojčice. Nijedan spisak ne sadrži ponovljena imena.

fajlovi u folderu:
1900_BoysNames.txt
1900_GirlsNames.txt
1901_BoysNames.txt
1901_GirlsNames.txt
itd.


podaci u fajlu:
John 9830
William 8580
James 7245
George 5403
Charles 4101
Robert 3824
Joseph 3714
Frank 3477
itd.

Ako neko hoće da skine fajlove, ovde su.

Uspeo sam da pokupim unikatna imena iz prvog reda svakog fajla, ali sve u jedan fajl:

Code:
import glob

imena = []

with open('imena.txt2', 'w') as spisak:
    for filename in glob.glob('*.txt'):
        fajl = open(filename, 'r', encoding='utf-8')
        line = fajl.readline().strip().split()
        ime = line[0]
        if ime not in imena:
            imena.append(ime)
    spisak.writelines(str(imena)+'\n')


Kako da selektujem na muška i ženska imena, nemam ideju :(


Gde se nalaze fajlovi da probam i ja u Rust-u ili Haskell=u ;)?
[ Panta_ @ 27.03.2020. 13:28 ] @
"Gde se nalaze fajlovi da probam i ja u Rust-u ili Haskell=u ;)?"

wget --no-check-certificate https://pages.cpsc.ucalgary.ca.../PythonWorkbook/baby_names.zip
[ Branimir Maksimovic @ 27.03.2020. 21:49 ] @
evo ga Rust. Znaci program se nazalizi u diru iznad BabyNames, testirano na Linux-u mozda samo zmaeniti '/' sa '\\' za Windows.
Code:

~/.../examples/rust >>> cat girlsboys.rs                                                                                                                                                                 
use std::io;
use std::fs::File;
use std::fs::read_dir;
use std::io::prelude::*;

fn main()->io::Result<()>{
    let mut maxs_girls:Vec<(i32,String)> = Vec::new();
    let mut maxs_boys:Vec<(i32,String)> = Vec::new();
    let mut max:(i32,String);
    let mut buf = String::new();
    if let Ok(dir) = read_dir("BabyNames") {
        for file in dir {
            let file = file?;
            let mut f = File::open(file.path())?;
            buf.clear();
            let _ = f.read_to_string(&mut buf);
            max = (0,"".to_string());
            for line in buf.lines() {
                let two:Vec<_> = line.split_whitespace().collect();
                if let Ok(number) = two[1].parse::<i32>(){
                    let name = two[0];
                    if max.0 < number {
                        max = (number,name.to_string());
                    }
                }
            }
            let path = file.path();
            let fname = path.to_str().unwrap().to_string();
            let it = fname.split('_').collect::<Vec<_>>();
            let it1 = it[0].split('/').collect::<Vec<_>>();
            let year = it1[1].parse::<i32>().unwrap();
            max.0 = year;
            if it[1] == "GirlsNames.txt" {
                maxs_girls.push(max);
            } else {
                maxs_boys.push(max);
            }
        }
    } else {
        println!("Not in directory above BabyNames...");
    }
    maxs_girls.sort();
    maxs_boys.sort();
    for i in maxs_girls.iter().zip(maxs_boys) {
        println!("{:?}",i);
    }
    Ok(())
}


rezultat:
Code:

~/.../examples/rust >>> ./girlsboys                                                                                                                                                                      
((1900, "Mary"), (1900, "John"))
((1901, "Mary"), (1901, "John"))
((1902, "Mary"), (1902, "John"))
((1903, "Mary"), (1903, "John"))
((1904, "Mary"), (1904, "John"))
((1905, "Mary"), (1905, "John"))
((1906, "Mary"), (1906, "John"))
((1907, "Mary"), (1907, "John"))
((1908, "Mary"), (1908, "John"))
((1909, "Mary"), (1909, "John"))
((1910, "Mary"), (1910, "John"))
((1911, "Mary"), (1911, "John"))
((1912, "Mary"), (1912, "John"))
((1913, "Mary"), (1913, "John"))
((1914, "Mary"), (1914, "John"))
((1915, "Mary"), (1915, "John"))
((1916, "Mary"), (1916, "John"))
((1917, "Mary"), (1917, "John"))
((1918, "Mary"), (1918, "John"))
((1919, "Mary"), (1919, "John"))
((1920, "Mary"), (1920, "John"))
((1921, "Mary"), (1921, "John"))
((1922, "Mary"), (1922, "John"))
((1923, "Mary"), (1923, "John"))
((1924, "Mary"), (1924, "Robert"))
((1925, "Mary"), (1925, "Robert"))
((1926, "Mary"), (1926, "Robert"))
((1927, "Mary"), (1927, "Robert"))
((1928, "Mary"), (1928, "Robert"))
((1929, "Mary"), (1929, "Robert"))
((1930, "Mary"), (1930, "Robert"))
((1931, "Mary"), (1931, "Robert"))
((1932, "Mary"), (1932, "Robert"))
((1933, "Mary"), (1933, "Robert"))
((1934, "Mary"), (1934, "Robert"))
((1935, "Mary"), (1935, "Robert"))
((1936, "Mary"), (1936, "Robert"))
((1937, "Mary"), (1937, "Robert"))
((1938, "Mary"), (1938, "Robert"))
((1939, "Mary"), (1939, "Robert"))
((1940, "Mary"), (1940, "James"))
((1941, "Mary"), (1941, "James"))
((1942, "Mary"), (1942, "James"))
((1943, "Mary"), (1943, "James"))
((1944, "Mary"), (1944, "James"))
((1945, "Mary"), (1945, "James"))
((1946, "Mary"), (1946, "James"))
((1947, "Linda"), (1947, "James"))
((1948, "Linda"), (1948, "James"))
((1949, "Linda"), (1949, "James"))
((1950, "Linda"), (1950, "James"))
((1951, "Linda"), (1951, "James"))
((1952, "Linda"), (1952, "James"))
((1953, "Mary"), (1953, "Robert"))
((1954, "Mary"), (1954, "Michael"))
((1955, "Mary"), (1955, "Michael"))
((1956, "Mary"), (1956, "Michael"))
((1957, "Mary"), (1957, "Michael"))
((1958, "Mary"), (1958, "Michael"))
((1959, "Mary"), (1959, "Michael"))
((1960, "Mary"), (1960, "David"))
((1961, "Mary"), (1961, "Michael"))
((1962, "Lisa"), (1962, "Michael"))
((1963, "Lisa"), (1963, "Michael"))
((1964, "Lisa"), (1964, "Michael"))
((1965, "Lisa"), (1965, "Michael"))
((1966, "Lisa"), (1966, "Michael"))
((1967, "Lisa"), (1967, "Michael"))
((1968, "Lisa"), (1968, "Michael"))
((1969, "Lisa"), (1969, "Michael"))
((1970, "Jennifer"), (1970, "Michael"))
((1971, "Jennifer"), (1971, "Michael"))
((1972, "Jennifer"), (1972, "Michael"))
((1973, "Jennifer"), (1973, "Michael"))
((1974, "Jennifer"), (1974, "Michael"))
((1975, "Jennifer"), (1975, "Michael"))
((1976, "Jennifer"), (1976, "Michael"))
((1977, "Jennifer"), (1977, "Michael"))
((1978, "Jennifer"), (1978, "Michael"))
((1979, "Jennifer"), (1979, "Michael"))
((1980, "Jennifer"), (1980, "Michael"))
((1981, "Jennifer"), (1981, "Michael"))
((1982, "Jennifer"), (1982, "Michael"))
((1983, "Jennifer"), (1983, "Michael"))
((1984, "Jennifer"), (1984, "Michael"))
((1985, "Jessica"), (1985, "Michael"))
((1986, "Jessica"), (1986, "Michael"))
((1987, "Jessica"), (1987, "Michael"))
((1988, "Jessica"), (1988, "Michael"))
((1989, "Jessica"), (1989, "Michael"))
((1990, "Jessica"), (1990, "Michael"))
((1991, "Ashley"), (1991, "Michael"))
((1992, "Ashley"), (1992, "Michael"))
((1993, "Jessica"), (1993, "Michael"))
((1994, "Jessica"), (1994, "Michael"))
((1995, "Jessica"), (1995, "Michael"))
((1996, "Emily"), (1996, "Michael"))
((1997, "Emily"), (1997, "Michael"))
((1998, "Emily"), (1998, "Michael"))
((1999, "Emily"), (1999, "Jacob"))
((2000, "Emily"), (2000, "Jacob"))
((2001, "Emily"), (2001, "Jacob"))
((2002, "Emily"), (2002, "Jacob"))
((2003, "Emily"), (2003, "Jacob"))
((2004, "Emily"), (2004, "Jacob"))
((2005, "Emily"), (2005, "Jacob"))
((2006, "Emily"), (2006, "Jacob"))
((2007, "Emily"), (2007, "Jacob"))
((2008, "Emma"), (2008, "Jacob"))
((2009, "Isabella"), (2009, "Jacob"))
((2010, "Isabella"), (2010, "Jacob"))
((2011, "Sophia"), (2011, "Jacob"))
((2012, "Sophia"), (2012, "Jacob"))


[ Panta_ @ 28.03.2020. 05:16 ] @
@Branimir Maksimovic
Ime ne treba da se ponavlja, samo godine u kojima je ime bilo najpopularnije kao i broj datih imena. Na primer:
Code:
{
'Girls Names': {
    'Emily': {1998: 26177, 1996: 25148, 1997: 25729, 1999: 26535},
    'Jessica': {1993: 34979, 1995: 27938, 1994: 32113, 1990: 46461},
    'Ashley': {1991: 43489, 1992: 38451}},
'Boys Names': {
    'Michael': {1994: 44463, 1995: 41403, 1998: 36608, 1990: 65270,
        1996: 38360, 1992: 54373, 1991: 60782, 1997: 37543, 1993: 49552},
    'Jacob': {1999: 35342}}
}


Code (python):

import glob
from collections import defaultdict

names = defaultdict(dict)

for filename in sorted(glob.glob('*.txt')):
    with open(filename) as f:
        name, name_number = f.readline().split()
    name_number = int(name_number)
    year = int(filename[:4])
    if 'Boys' in filename:
        if name not in names['Boys Names']:
            names['Boys Names'].update( {name: {year: name_number} } )
        else:
            names['Boys Names'][name].update({year: name_number})
    elif 'Girls' in filename:
        if name not in names['Girls Names']:
            names['Girls Names'].update( {name: {year: name_number} })
        else:
            names['Girls Names'][name].update({year: name_number})
 


Zaboravio sam da sortiram listu:
Code:
{
'Boys Names': {
    'Michael': {1990: 65270, 1991: 60782, 1992: 54373, 1993: 49552,
1994: 44463, 1995: 41403, 1996: 38360, 1997: 37543, 1998: 36608},
    'Jacob': {1999: 35342}},
'Girls Names': {
    'Jessica': {1990: 46461, 1993: 34979, 1994: 32113, 1995: 27938},
    'Ashley': {1991: 43489, 1992: 38451},
    'Emily': {1996: 25148, 1997: 25729, 1998: 26177, 1999: 26535}}}


[Ovu poruku je menjao Panta_ dana 28.03.2020. u 06:27 GMT+1]
[ Branimir Maksimovic @ 28.03.2020. 07:46 ] @
Ma poenta je tu sad, kako cu prikazati vise manje nebitno. I u tom sto si prikazao nemas sve godine :P
[ Panta_ @ 28.03.2020. 08:05 ] @
Citat:
I u tom sto si prikazao nemas sve godine

Nema zato što sam kopira samo deo izlaza zbog veličine:
Code:
{'Boys Names': {'John': {1900: 9830, 1901: 6899, 1902: 7908, 1903: 7609, 1904: 8108, 1905: 8059, 1906: 8264, 1907: 8983, 1908: 9342, 1909: 9591, 1910: 11451, 1911: 13446, 1912: 24586, 1913: 29324, 1914: 37945, 1915: 47579, 1916: 50046, 1917: 51854, 1918: 56559, 1919: 53530, 1920: 56918, 1921: 58230, 1922: 57268, 1923: 57469}, 'Robert': {1924: 60795, 1925: 60903, 1926: 61113, 1927: 61657, 1928: 60665, 1929: 59799, 1930: 62120, 1931: 60495, 1932: 59240, 1933: 54188, 1934: 55823, 1935: 56509, 1936: 58477, 1937: 61807, 1938: 62261, 1939: 59631, 1953: 86092}, 'James': {1940: 62452, 1941: 66714, 1942: 77164, 1943: 80236, 1944: 76936, 1945: 74439, 1946: 87432, 1947: 94743, 1948: 88544, 1949: 86776, 1950: 86227, 1951: 87099, 1952: 87035}, 'Michael': {1954: 88481, 1955: 88279, 1956: 90611, 1957: 92705, 1958: 90494, 1959: 85285, 1961: 86908, 1962: 85038, 1963: 83794, 1964: 82666, 1965: 81058, 1966: 80008, 1967: 82455, 1968: 82027, 1969: 85226, 1970: 85312, 1971: 77601, 1972: 71420, 1973: 67851, 1974: 67579, 1975: 68453, 1976: 66971, 1977: 67608, 1978: 67139, 1979: 67717, 1980: 68656, 1981: 68733, 1982: 68176, 1983: 67976, 1984: 67703, 1985: 64876, 1986: 64170, 1987: 63625, 1988: 64095, 1989: 65386, 1990: 65270, 1991: 60782, 1992: 54373, 1993: 49552, 1994: 44463, 1995: 41403, 1996: 38360, 1997: 37543, 1998: 36608}, 'David': {1960: 85928}, 'Jacob': {1999: 35342, 2000: 34460, 2001: 32520, 2002: 30552, 2003: 29605, 2004: 27868, 2005: 25809, 2006: 24811, 2007: 24238, 2008: 22547, 2009: 21113, 2010: 22052, 2011: 20269, 2012: 18899}}, 'Girls Names': {'Mary': {1900: 16708, 1901: 13136, 1902: 14486, 1903: 14275, 1904: 14962, 1905: 16067, 1906: 16370, 1907: 17581, 1908: 18666, 1909: 19258, 1910: 22847, 1911: 24388, 1912: 32298, 1913: 36640, 1914: 45345, 1915: 58187, 1916: 61433, 1917: 64280, 1918: 67372, 1919: 65837, 1920: 70978, 1921: 73983, 1922: 72167, 1923: 71630, 1924: 73513, 1925: 70603, 1926: 67830, 1927: 70617, 1928: 66861, 1929: 63500, 1930: 64129, 1931: 60294, 1932: 59865, 1933: 55484, 1934: 56906, 1935: 55068, 1936: 54361, 1937: 55639, 1938: 56202, 1939: 54902, 1940: 56201, 1941: 58023, 1942: 63242, 1943: 66166, 1944: 62468, 1945: 59284, 1946: 67459, 1953: 64330, 1954: 67994, 1955: 63164, 1956: 61750, 1957: 61092, 1958: 55840, 1959: 54473, 1960: 51474, 1961: 47657}, 'Linda': {1947: 99685, 1948: 96178, 1949: 90986, 1950: 80437, 1951: 73884, 1952: 67076}, 'Lisa': {1962: 46085, 1963: 56036, 1964: 54272, 1965: 60262, 1966: 56912, 1967: 52429, 1968: 49528, 1969: 45034}, 'Jennifer': {1970: 46159, 1971: 56785, 1972: 63605, 1973: 62454, 1974: 63106, 1975: 58180, 1976: 59476, 1977: 58961, 1978: 56310, 1979: 56713, 1980: 58383, 1981: 57035, 1982: 57102, 1983: 54335, 1984: 50551}, 'Jessica': {1985: 48343, 1986: 52657, 1987: 55984, 1988: 51523, 1989: 47890, 1990: 46461, 1993: 34979, 1994: 32113, 1995: 27938}, 'Ashley': {1991: 43489, 1992: 38451}, 'Emily': {1996: 25148, 1997: 25729, 1998: 26177, 1999: 26535, 2000: 25953, 2001: 25050, 2002: 24454, 2003: 25682, 2004: 25021, 2005: 23921, 2006: 21381, 2007: 19331}, 'Emma': {2008: 18787}, 'Isabella': {2009: 22257, 2010: 22856}, 'Sophia': {2011: 21780, 2012: 22158}}}
[ Branimir Maksimovic @ 28.03.2020. 08:14 ] @
Ok :
Code:

~/.../examples/rust >>> ./girlsboys                                                                                                                                                                                               
Girls
("Ashley", [(1991, 43489), (1992, 38451)])
("Emily", [(1996, 25148), (1997, 25729), (1998, 26177), (1999, 26535), (2000, 25953), (2001, 25050), (2002, 24454), (2003, 25682), (2004, 25021), (2005, 23921), (2006, 21381), (2007, 19331)])
("Emma", [(2008, 18787)])
("Isabella", [(2009, 22257), (2010, 22856)])
("Jennifer", [(1970, 46159), (1971, 56785), (1972, 63605), (1973, 62454), (1974, 63106), (1975, 58180), (1976, 59476), (1977, 58961), (1978, 56310), (1979, 56713), (1980, 58383), (1981, 57035), (1982, 57102), (1983, 54335), (1984, 50551)])
("Jessica", [(1985, 48343), (1986, 52657), (1987, 55984), (1988, 51523), (1989, 47890), (1990, 46461), (1993, 34979), (1994, 32113), (1995, 27938)])
("Linda", [(1947, 99685), (1948, 96178), (1949, 90986), (1950, 80437), (1951, 73884), (1952, 67076)])
("Lisa", [(1962, 46085), (1963, 56036), (1964, 54272), (1965, 60262), (1966, 56912), (1967, 52429), (1968, 49528), (1969, 45034)])
("Mary", [(1900, 16708), (1901, 13136), (1902, 14486), (1903, 14275), (1904, 14962), (1905, 16067), (1906, 16370), (1907, 17581), (1908, 18666), (1909, 19258), (1910, 22847), (1911, 24388), (1912, 32298), (1913, 36640), (1914, 45345), (1915, 58187), (1916, 61433), (1917, 64280), (1918, 67372), (1919, 65837), (1920, 70978), (1921, 73983), (1922, 72167), (1923, 71630), (1924, 73513), (1925, 70603), (1926, 67830), (1927, 70617), (1928, 66861), (1929, 63500), (1930, 64129), (1931, 60294), (1932, 59865), (1933, 55484), (1934, 56906), (1935, 55068), (1936, 54361), (1937, 55639), (1938, 56202), (1939, 54902), (1940, 56201), (1941, 58023), (1942, 63242), (1943, 66166), (1944, 62468), (1945, 59284), (1946, 67459), (1953, 64330), (1954, 67994), (1955, 63164), (1956, 61750), (1957, 61092), (1958, 55840), (1959, 54473), (1960, 51474), (1961, 47657)])
("Sophia", [(2011, 21780), (2012, 22158)])
Boys
("David", [(1960, 85928)])
("Jacob", [(1999, 35342), (2000, 34460), (2001, 32520), (2002, 30552), (2003, 29605), (2004, 27868), (2005, 25809), (2006, 24811), (2007, 24238), (2008, 22547), (2009, 21113), (2010, 22052), (2011, 20269), (2012, 18899)])
("James", [(1940, 62452), (1941, 66714), (1942, 77164), (1943, 80236), (1944, 76936), (1945, 74439), (1946, 87432), (1947, 94743), (1948, 88544), (1949, 86776), (1950, 86227), (1951, 87099), (1952, 87035)])
("John", [(1900, 9830), (1901, 6899), (1902, 7908), (1903, 7609), (1904, 8108), (1905, 8059), (1906, 8264), (1907, 8983), (1908, 9342), (1909, 9591), (1910, 11451), (1911, 13446), (1912, 24586), (1913, 29324), (1914, 37945), (1915, 47579), (1916, 50046), (1917, 51854), (1918, 56559), (1919, 53530), (1920, 56918), (1921, 58230), (1922, 57268), (1923, 57469)])
("Michael", [(1954, 88481), (1955, 88279), (1956, 90611), (1957, 92705), (1958, 90494), (1959, 85285), (1961, 86908), (1962, 85038), (1963, 83794), (1964, 82666), (1965, 81058), (1966, 80008), (1967, 82455), (1968, 82027), (1969, 85226), (1970, 85312), (1971, 77601), (1972, 71420), (1973, 67851), (1974, 67579), (1975, 68453), (1976, 66971), (1977, 67608), (1978, 67139), (1979, 67717), (1980, 68656), (1981, 68733), (1982, 68176), (1983, 67976), (1984, 67703), (1985, 64876), (1986, 64170), (1987, 63625), (1988, 64095), (1989, 65386), (1990, 65270), (1991, 60782), (1992, 54373), (1993, 49552), (1994, 44463), (1995, 41403), (1996, 38360), (1997, 37543), (1998, 36608)])
("Robert", [(1924, 60795), (1925, 60903), (1926, 61113), (1927, 61657), (1928, 60665), (1929, 59799), (1930, 62120), (1931, 60495), (1932, 59240), (1933, 54188), (1934, 55823), (1935, 56509), (1936, 58477), (1937, 61807), (1938, 62261), (1939, 59631), (1953, 86092)])


program:
Code:

use std::io;
use std::fs::File;
use std::fs::read_dir;
use std::io::prelude::*;
use std::collections::BTreeMap;

fn main()->io::Result<()>{
    let mut maxs_girls:BTreeMap<String,Vec<(i32,i32)>> = BTreeMap::new();
    let mut maxs_boys:BTreeMap<String,Vec<(i32,i32)>> = BTreeMap::new();
    let mut max:(i32,String);
    let mut buf = String::new();
    if let Ok(dir) = read_dir("BabyNames") {
        for file in dir {
            let file = file?;
            let mut f = File::open(file.path())?;
            buf.clear();
            let _ = f.read_to_string(&mut buf);
            max = (0,"".to_string());
            for line in buf.lines() {
                let two:Vec<_> = line.split_whitespace().collect();
                if let Ok(number) = two[1].parse::<i32>(){
                    let name = two[0];
                    if max.0 < number {
                        max = (number,name.to_string());
                    }
                }
            }
            let path = file.path();
            let fname = path.to_str().unwrap().to_string();
            let it = fname.split('_').collect::<Vec<_>>();
            let it1 = it[0].split('/').collect::<Vec<_>>();
            let year = it1[1].parse::<i32>().unwrap();
            if it[1] == "GirlsNames.txt" {
                let r = maxs_girls.entry(max.1).or_insert(Vec::new());
                (*r).push((year,max.0));
                (*r).sort();
            } else {
                let r = maxs_boys.entry(max.1).or_insert(Vec::new());
                (*r).push((year,max.0));
                (*r).sort();
            }
        }
    } else {
        println!("Not in directory above BabyNames...");
    }
    println!("Girls");
    for i in maxs_girls {
        println!("{:?}",i);
    }
    println!("Boys");
    for i in maxs_boys {
        println!("{:?}",i);
    }
    Ok(())
}


[ djoka_l @ 28.03.2020. 09:38 ] @
One-liner Linux shell

$ echo -e '\n\nBoys:\n' ; head -1 -q BabyNames/*Boys*.txt | awk '{print $1}' | sort -u ; echo -e "\n\nGirls:\n"; head -1 -q BabyNames/*Girls*.txt | awk '{print $1}' | sort -u


Boys:

David
Jacob
James
John
Michael
Robert


Girls:

Ashley
Emily
Emma
Isabella
Jennifer
Jessica
Linda
Lisa
Mary
Sophia


Mrzelo me da napravim for petlju, pa da linija bude malo kraća...
[ djoka_l @ 28.03.2020. 09:50 ] @
Na mnogobrojne zahteve, evo kraće, sa for petljom

$ for g in 'Boys' 'Girls'; do echo -e "\n\n${g}:\n" ; head -1 -q BabyNames/*${g}*.txt | awk '{print $1}' | sort -u ; done


Boys:

David
Jacob
James
John
Michael
Robert


Girls:

Ashley
Emily
Emma
Isabella
Jennifer
Jessica
Linda
Lisa
Mary
Sophia
[ a1234567 @ 28.03.2020. 09:57 ] @
Hvala Panto i Berislave na korekcijama.
Komplikovani ovi nested rečnici :)

Berislave, nisam iz tvojih komentara još uvek uspeo da sklopim program.
Ono što sam dobio je ovo:

Code:
for filename in glob.glob('*txt'):
     lines = open(filename).readlines()
     if 'Boys' in filename:
         for line in lines:
             name = line.strip().split()[0]
             broj = line.strip().split()[1]
             godina = filename[0:4]

decaci = { 'Boys Names': {} }
for k1, v1 in decaci.items():
    for k2, v2 in v1.items():
        if name not in v2.keys():
            decaci['Boys Names'][name] = {}
        if godina not in decaci['Boys Names'][name]:
            decaci['Boys Names'][name][godina] = broj


Ali kad se kod izvrši, rečnik je još uvek prazan,
{'Boys Names': {}}

iako kad pozovem godina ispiše 2012, što znači da je prošao sve fajlove.
[ a1234567 @ 28.03.2020. 10:00 ] @
Đoko, slabo je to.
Nemaš ni godine ni brojeve.
2+
[ djoka_l @ 28.03.2020. 10:15 ] @
Citat:
Napisati program koji čita svaki fajl i identifikuje sva imena koja su bila najpopularnija najmanje u jednoj godini. Program ispisuje dve liste:
jedna sadrži najpopularnija imena za dečake, a druga za djevojčice. Nijedan spisak ne sadrži ponovljena imena.


1. Čita svaki fajl
2. Nalazi u svakom fajlu najčešće ime te godine
3. Ispisuje dve liste
4. Nijedno ime se ne ponavlja

Samo sam hteo da pokažem zašto ljudi, koji poznaju Linux/Unix, ne žele tako lako da pređu na drugi sistem.
Skoro za svaki posao, Linux ima gomilu programa koji mogu da urade ceo ili deo posla...
[ a1234567 @ 28.03.2020. 10:28 ] @
Ma šalim se malo, da razvedrim dan od ovih korona vesti.

Čim naučim Python, prelazim na učenje Linuxa :)
[ djoka_l @ 28.03.2020. 11:01 ] @
Evo legende:

for VARIJABLA in LISTA ... do ... done : Bash for petlja
echo -e: ispisuje string na standardni izlaz i (-e) interpretira specijalne znake u stringu (\n novi red)
head -1 -q: ispisuje prvih nekoliko (-1 jednu) linija i ne ispisjue (-q) naziv fajla iz kojeg su te linije
awk '{print $1}': posebna priča koja treba da se nauči (a nauči se za 2-3 sata). Ovaj awk program za svaku liniju sa ulaza, ispisuje prvu reč na izlaz
sort -u: sortira ono što mu dođe na ulaz, a (-u) izbacuje duplikate (unique sort)
| : pipe - povezuje dve komande, tako što izlaz komande sa leve strane prosleđuje na ulaz komande sa desne strane
; : razdvaja dve komande u istoj linij.
IMEVARIJABLE, $IMEVARIJABLE : ime, odnosno vrednost varijable, u primeru g i $g. ${g} je isto što i $g ali se koristi u slučajevima kada postoje neki specijalni znaci u liniji, pa da se zna šta je varijabla. Recimo $g* nije baš jasno šta je, ali je ${g}* nedvosmisleno.
[ Branimir Maksimovic @ 28.03.2020. 11:20 ] @
Citat:
djoka_l:
Na mnogobrojne zahteve, evo kraće, sa for petljom

$ for g in 'Boys' 'Girls'; do echo -e "\n\n${g}:\n" ; head -1 -q BabyNames/*${g}*.txt | awk '{print $1}' | sort -u ; done


Boys:

David
Jacob
James
John
Michael
Robert


Girls:

Ashley
Emily
Emma
Isabella
Jennifer
Jessica
Linda
Lisa
Mary
Sophia


Da al ispisujes samo imena, to i klasicni program moze kratko...
[ djoka_l @ 28.03.2020. 11:30 ] @
Ma jeste, ali je poenta u 1-lineru
Svojevremeno, kada sam išao na intervencije kod korisnika, uvek se skupi po nekoliko ljudi iz IT-a da pohvataju sve šta kucam u terminalu, da bi kasnije mogli da analiziraju šta sam radio i iskoriste u svojim programima

Meni je bilo čudno što je uvek gužva oko mene, ali kad su mi rekli razlog, počeo sam sve da zapisujem u fajlove, da ljudi mogu da analiziraju na miru...
[ B3R1 @ 28.03.2020. 15:52 ] @
Citat:
a1234567:
Komplikovani ovi nested rečnici :)
Ali kad se kod izvrši, rečnik je još uvek prazan,
{'Boys Names': {}}


Logicno da je prazno, jer program ne radi nista:
Code:

decaci = { 'Boys Names': {} }
for k1, v1 in decaci.items():
    ...

Recnik je prazan, pa for-petlja analizira taj prazan recnik i odmah zavrsava. Recnik treba inicijalizovati na pocetku, a puniti ga tokom ucitavanja linija iz fajla:

Code:

decaci = { 'Boys Names': {} }
for filename in glob.glob('*txt'):
     lines = open(filename).readlines()
     if 'Boys' in filename:
         for line in lines:
             name, broj = line.strip().split()
             godina = filename[0:4]
            if name not in decaci['Boys Names']:
                decaci['Boys Names'][name] = {}
            if godina not in decaci['Boys Names'][name]:
                decaci['Boys Names'][name][godina] = broj
...


One promenljive k1, v1, k2, v2 itd. su ti nepotrebne, bas kao i funkcija keys(). Kada pretrazujes recnik 'dict' i kazes 'for element in dict:' podrazumeva se dict.keys(). Isto tako ako ispitujes da li je kljuc k u recniku dovoljno je da kazes 'if k in dict'.

Takodje, misli da ti je ovaj 'Boys Names' cist visak. Ako vec imas posebne recnike za decake i devojcice, nema svrhe da uvodis jos jedan nivo u strukturu recnika. Dovoljno je reci:

Code:

decaci = {}
for filename in glob.glob('*txt'):
     lines = open(filename).readlines()
     if 'Boys' in filename:
         for line in lines:
             name, broj = line.strip().split()
             godina = filename[0:4]
            if name not in decaci:
                decaci[name] = {}
            if godina not in decaci[name]:
                decaci[name][godina] = broj
...

[ Branimir Maksimovic @ 28.03.2020. 17:53 ] @
A evo ga i Haskell (nije me mrzelo:)

Code:

import Data.List
import Data.List.Split
import System.Directory
import Data.Map.Strict
import Control.Monad
import Text.Printf
main = do
    files <- listDirectory "BabyNames"
    let maxs_girls = empty :: Map String [(Int,Int)]
        maxs_boys = empty :: Map String [(Int,Int)]  
    (maxs_girls',maxs_boys') <- foldM (\gb filename -> do
           cnt <- readFile $ "BabyNames/"++filename
           let [year,girlsboys] = splitOn "_" filename
               year' = read year
           let (name,number) = Data.List.foldl (\max ln -> let 
                                                     [name,number] = words ln
                                                     number' = read number
                                                 in if snd max < number' 
                                                    then (name,number')
                                                    else max ) ("",0) $ lines cnt
           return $ if girlsboys == "GirlsNames.txt" 
                        then (insertWith (++) name [(year',number)] (fst gb), snd gb)
                        else (fst gb,insertWith (++) name [(year',number)] (snd gb))
           ) (maxs_girls,maxs_boys) files :: IO (Map String [(Int,Int)], Map String [(Int,Int)])
    let a = foldlWithKey (\fv name list  -> fv ++ (printf "%s\n" $ name ++ ":" ++ show (sort list))) "" maxs_girls'
    let b = foldlWithKey (\fv name list -> fv ++ (printf "%s\n" $ name ++ ":" ++ show (sort list))) "" maxs_boys'
    putStrLn $ "Girls\n" ++ a ++ "Boys\n" ++ b


output:
Code:

~/.../examples/haskell >>> ./girlsboys                                                                                                                                                                                            
Girls
Ashley:[(1991,43489),(1992,38451)]
Emily:[(1996,25148),(1997,25729),(1998,26177),(1999,26535),(2000,25953),(2001,25050),(2002,24454),(2003,25682),(2004,25021),(2005,23921),(2006,21381),(2007,19331)]
Emma:[(2008,18787)]
Isabella:[(2009,22257),(2010,22856)]
Jennifer:[(1970,46159),(1971,56785),(1972,63605),(1973,62454),(1974,63106),(1975,58180),(1976,59476),(1977,58961),(1978,56310),(1979,56713),(1980,58383),(1981,57035),(1982,57102),(1983,54335),(1984,50551)]
Jessica:[(1985,48343),(1986,52657),(1987,55984),(1988,51523),(1989,47890),(1990,46461),(1993,34979),(1994,32113),(1995,27938)]
Linda:[(1947,99685),(1948,96178),(1949,90986),(1950,80437),(1951,73884),(1952,67076)]
Lisa:[(1962,46085),(1963,56036),(1964,54272),(1965,60262),(1966,56912),(1967,52429),(1968,49528),(1969,45034)]
Mary:[(1900,16708),(1901,13136),(1902,14486),(1903,14275),(1904,14962),(1905,16067),(1906,16370),(1907,17581),(1908,18666),(1909,19258),(1910,22847),(1911,24388),(1912,32298),(1913,36640),(1914,45345),(1915,58187),(1916,61433),(1917,64280),(1918,67372),(1919,65837),(1920,70978),(1921,73983),(1922,72167),(1923,71630),(1924,73513),(1925,70603),(1926,67830),(1927,70617),(1928,66861),(1929,63500),(1930,64129),(1931,60294),(1932,59865),(1933,55484),(1934,56906),(1935,55068),(1936,54361),(1937,55639),(1938,56202),(1939,54902),(1940,56201),(1941,58023),(1942,63242),(1943,66166),(1944,62468),(1945,59284),(1946,67459),(1953,64330),(1954,67994),(1955,63164),(1956,61750),(1957,61092),(1958,55840),(1959,54473),(1960,51474),(1961,47657)]
Sophia:[(2011,21780),(2012,22158)]
Boys
David:[(1960,85928)]
Jacob:[(1999,35342),(2000,34460),(2001,32520),(2002,30552),(2003,29605),(2004,27868),(2005,25809),(2006,24811),(2007,24238),(2008,22547),(2009,21113),(2010,22052),(2011,20269),(2012,18899)]
James:[(1940,62452),(1941,66714),(1942,77164),(1943,80236),(1944,76936),(1945,74439),(1946,87432),(1947,94743),(1948,88544),(1949,86776),(1950,86227),(1951,87099),(1952,87035)]
John:[(1900,9830),(1901,6899),(1902,7908),(1903,7609),(1904,8108),(1905,8059),(1906,8264),(1907,8983),(1908,9342),(1909,9591),(1910,11451),(1911,13446),(1912,24586),(1913,29324),(1914,37945),(1915,47579),(1916,50046),(1917,51854),(1918,56559),(1919,53530),(1920,56918),(1921,58230),(1922,57268),(1923,57469)]
Michael:[(1954,88481),(1955,88279),(1956,90611),(1957,92705),(1958,90494),(1959,85285),(1961,86908),(1962,85038),(1963,83794),(1964,82666),(1965,81058),(1966,80008),(1967,82455),(1968,82027),(1969,85226),(1970,85312),(1971,77601),(1972,71420),(1973,67851),(1974,67579),(1975,68453),(1976,66971),(1977,67608),(1978,67139),(1979,67717),(1980,68656),(1981,68733),(1982,68176),(1983,67976),(1984,67703),(1985,64876),(1986,64170),(1987,63625),(1988,64095),(1989,65386),(1990,65270),(1991,60782),(1992,54373),(1993,49552),(1994,44463),(1995,41403),(1996,38360),(1997,37543),(1998,36608)]
Robert:[(1924,60795),(1925,60903),(1926,61113),(1927,61657),(1928,60665),(1929,59799),(1930,62120),(1931,60495),(1932,59240),(1933,54188),(1934,55823),(1935,56509),(1936,58477),(1937,61807),(1938,62261),(1939,59631),(1953,86092)]


[ a1234567 @ 29.03.2020. 16:35 ] @
Branimire, svaka čast na trudu!

Evo novog izazova u narednoj poruci i za tebe i za mene :)
[ a1234567 @ 29.03.2020. 17:06 ] @
Žurka za dečijim imenima se nastavlja.

Zadatak broj 32: Pronaći imena koja su rodno neutralna

Neka imena kao što su Ben, Jonathan i Andrew se obično koriste samo za dečake,
dok su Rebecca i Flora obično rezervisane za devojčice. No, ima imena
kao što su Chris i Alex, koja se mogu koristiti i kao muška i kao ženska.

Napiši program koji nalazi i prikazuje sva dečija imena koja su korišćena i za dečake
i za devojčice u godini koju unese korisnik. Program takođe treba da generiše
odgovarajuću poruku ukoliko u odabranoj godini nije bilo rodno neutralnih imena.
Takođe, prikaži odgovarajuću poruku ako nemaš podatke za unetu godinu.


Ja sam sklepao nešto ovako:

Code:
import glob
spisak = open('c:/FAJLOVI/Python_School/Stephenson_ThePythonWorkbook/unisex.txt', 'w')

lista_m = []
lista_z = []
lista_unikat = []
imena = {}

for filename in glob.glob('*txt'):
    if 'Boys' in filename:
        lines = open(filename).readlines()
        for line in lines:
            name = line.strip().split()[0]
            godina = int(filename[0:4])
            lista_m.append(name)
            
    elif 'Girls' in filename:
        lines = open(filename).readlines()
        for line in lines:
            name = line.strip().split()[0]
            godina = int(filename[0:4])
            lista_z.append(name)
            
    lista_unikat = set(lista_m).intersection(lista_z)
    imena[godina] = lista_unikat

spisak.write(str(imena) + '\n')
spisak.close()

a rečnik imena izgleda ovako, uz "mali" problem da se javljaju neka imena kojih nema u oba spiska za datu godinu (na primer Shannon), al nemam pojma zašto:

{1900: {'Jessie', 'Willie'}, 1901: {'Jessie', 'Willie'}, 1902: {'Jessie', 'Willie'}, 1903: {'Jessie', 'Willie'}, 1904: {'Jessie', 'Willie'}, 1905: {'Jessie', 'Willie'}, 1906: {'Jessie', 'Willie'}, 1907: {'Jessie', 'Willie'}, 1908: {'Jessie', 'Willie'}, 1909: {'Jessie', 'Willie'}, 1910: {'Jessie', 'Willie'}, 1911: {'Jessie', 'Willie'}, 1912: {'Jessie', 'Willie'}, 1913: {'Jessie', 'Willie'}, 1914: {'Jessie', 'Willie'}, 1915: {'Jessie', 'Willie'}, 1916: {'Jessie', 'Willie'}, 1917: {'Jessie', 'Willie'}, 1918: {'Jessie', 'Willie'}, 1919: {'Jessie', 'Willie'}, 1920: {'Jessie', 'Willie'}, 1921: {'Jessie', 'Willie'}, 1922: {'Jessie', 'Willie'}, 1923: {'Jessie', 'Willie'}, 1924: {'Jessie', 'Willie'}, 1925: {'Jessie', 'Willie'}, 1926: {'Jessie', 'Willie'}, 1927: {'Jessie', 'Willie'}, 1928: {'Jessie', 'Willie'}, 1929: {'Jessie', 'Willie'}, 1930: {'Jessie', 'Willie'}, 1931: {'Jessie', 'Willie'}, 1932: {'Jessie', 'Willie'}, 1933: {'Jessie', 'Willie'}, 1934: {'Jessie', 'Willie'}, 1935: {'Jessie', 'Willie'}, 1936: {'Jessie', 'Willie'}, 1937: {'Jessie', 'Willie'}, 1938: {'Jessie', 'Willie'}, 1939: {'Jessie', 'Willie'}, 1940: {'Jessie', 'Willie'}, 1941: {'Jessie', 'Willie'}, 1942: {'Jessie', 'Willie'}, 1943: {'Jessie', 'Willie'}, 1944: {'Jessie', 'Willie'}, 1945: {'Jessie', 'Willie'}, 1946: {'Jessie', 'Willie'}, 1947: {'Jessie', 'Willie'}, 1948: {'Jessie', 'Willie'}, 1949: {'Jessie', 'Willie'}, 1950: {'Jessie', 'Willie'}, 1951: {'Jessie', 'Willie'}, 1952: {'Jessie', 'Willie'}, 1953: {'Jessie', 'Willie', 'Leslie'}, 1954: {'Jessie', 'Willie', 'Terry', 'Leslie'}, 1955: {'Leslie', 'Willie', 'Kim', 'Jessie', 'Terry'}, 1956: {'Leslie', 'Willie', 'Kim', 'Jessie', 'Terry'}, 1957: {'Leslie', 'Willie', 'Kim', 'Jessie', 'Terry'}, 1958: {'Leslie', 'Willie', 'Kim', 'Jessie', 'Terry'}, 1959: {'Leslie', 'Willie', 'Kim', 'Jessie', 'Terry'}, 1960: {'Leslie', 'Willie', 'Kim', 'Jessie', 'Terry'}, 1961: {'Leslie', 'Willie', 'Kim', 'Jessie', 'Terry'}, 1962: {'Leslie', 'Willie', 'Kim', 'Jessie', 'Terry'}, 1963: {'Leslie', 'Willie', 'Kim', 'Jessie', 'Terry'}, 1964: {'Leslie', 'Willie', 'Kim', 'Jessie', 'Terry'}, 1965: {'Leslie', 'Willie', 'Kim', 'Jessie', 'Terry'}, 1966: {'Leslie', 'Willie', 'Kim', 'Jessie', 'Terry', 'Tracy'}, 1967: {'Leslie', 'Willie', 'Kim', 'Jessie', 'Terry', 'Tracy'}, 1968: {'Leslie', 'Willie', 'Kelly', 'Kim', 'Jessie', 'Terry', 'Tracy'}, 1969: {'Leslie', 'Willie', 'Kelly', 'Kim', 'Jessie', 'Terry', 'Tracy'}, 1970: {'Leslie', 'Willie', 'Kelly', 'Kim', 'Jessie', 'Terry', 'Tracy'}, 1971: {'Leslie', 'Willie', 'Kelly', 'Kim', 'Jessie', 'Terry', 'Tracy'}, 1972: {'Shannon', 'Leslie', 'Willie', 'Kelly', 'Kim', 'Jessie', 'Terry', 'Tracy'}, 1973: {'Shannon', 'Leslie', 'Willie', 'Kelly', 'Kim', 'Jessie', 'Terry', 'Tracy'}, 1974: {'Shannon', 'Leslie', 'Willie', 'Kelly', 'Kim', 'Jessie', 'Terry', 'Tracy', 'Jamie'}, 1975: {'Shannon', 'Leslie', 'Willie', 'Kelly', 'Kim', 'Jessie', 'Terry', 'Tracy', 'Jamie'}, 1976: {'Shannon', 'Leslie', 'Willie', 'Kelly', 'Kim', 'Jessie', 'Terry', 'Tracy', 'Jamie'}, 1977: {'Shannon', 'Leslie', 'Willie', 'Kelly', 'Kim', 'Jessie', 'Terry', 'Tracy', 'Jamie'}, 1978: {'Shannon', 'Leslie', 'Willie', 'Kelly', 'Kim', 'Jessie', 'Terry', 'Tracy', 'Jamie'}, 1979: {'Shannon', 'Leslie', 'Willie', 'Kelly', 'Kim', 'Jessie', 'Terry', 'Tracy', 'Jamie'}, 1980: {'Shannon', 'Leslie', 'Willie', 'Kelly', 'Kim', 'Jessie', 'Terry', 'Tracy', 'Jamie'}, 1981: {'Shannon', 'Leslie', 'Willie', 'Kelly', 'Kim', 'Jessie', 'Terry', 'Tracy', 'Jamie'}, 1982: {'Shannon', 'Leslie', 'Willie', 'Kelly', 'Kim', 'Jessie', 'Terry', 'Tracy', 'Jamie'}, 1983: {'Shannon', 'Leslie', 'Willie', 'Kelly', 'Kim', 'Jessie', 'Terry', 'Tracy', 'Jamie'}, 1984: {'Shannon', 'Leslie', 'Willie', 'Kelly', 'Kim', 'Jessie', 'Terry', 'Tracy', 'Jamie'}, 1985: {'Shannon', 'Leslie', 'Willie', 'Kelly', 'Kim', 'Jessie', 'Terry', 'Tracy', 'Jamie'}, 1986: {'Shannon', 'Leslie', 'Willie', 'Kelly', 'Kim', 'Casey', 'Jessie', 'Terry', 'Tracy', 'Jamie'}, 1987: {'Shannon', 'Leslie', 'Willie', 'Kelly', 'Kim', 'Casey', 'Jessie', 'Terry', 'Tracy', 'Jamie'}, 1988: {'Shannon', 'Leslie', 'Willie', 'Kelly', 'Kim', 'Casey', 'Jessie', 'Terry', 'Tracy', 'Jamie'}, 1989: {'Jordan', 'Shannon', 'Leslie', 'Taylor', 'Willie', 'Kelly', 'Kim', 'Casey', 'Jessie', 'Terry', 'Tracy', 'Jamie'}, 1990: {'Jordan', 'Shannon', 'Leslie', 'Taylor', 'Willie', 'Kelly', 'Kim', 'Casey', 'Jessie', 'Terry', 'Tracy', 'Jamie'}...}


[ Branimir Maksimovic @ 29.03.2020. 20:51 ] @
Moras da citas i Girls i Boys za datu godinu.
[ Branimir Maksimovic @ 29.03.2020. 21:29 ] @
Evo ga Rust (malo modifikovani onaj prvi program)

Code:

use std::io;
use std::fs::File;
use std::fs::read_dir;
use std::io::prelude::*;
use std::collections::BTreeMap;
use std::collections::BTreeSet;

fn main()->io::Result<()>{
    let mut girls:BTreeMap<i32,BTreeSet<String> > = BTreeMap::new();
    let mut boys:BTreeMap<i32,BTreeSet<String> > = BTreeMap::new();
    let mut common:BTreeMap<i32,BTreeSet<String> > = BTreeMap::new();
    let mut buf = String::new();
    if let Ok(dir) = read_dir("BabyNames") {
        for file in dir {
            let file = file?;
            let mut f = File::open(file.path())?;
            buf.clear();
            let _ = f.read_to_string(&mut buf);
            let mut tmp_set = BTreeSet::new();
            for line in buf.lines() {
                let two:Vec<_> = line.split_whitespace().collect();
                tmp_set.insert(two[0].to_string());
            }
            let path = file.path();
            let fname = path.to_str().unwrap().to_string();
            let it = fname.split('_').collect::<Vec<_>>();
            let it1 = it[0].split('/').collect::<Vec<_>>();
            let year = it1[1].parse::<i32>().unwrap();
            let _ = if it[1] == "GirlsNames.txt" {
                girls.entry(year).or_insert(tmp_set)
            } else {
                boys.entry(year).or_insert(tmp_set)
            };
        }
    } else {
        println!("Not in directory above BabyNames...");
    }
    for ((y,g),(_,b)) in girls.iter().zip(boys) {
        for i in g.intersection(&b) {
            let r = common.entry(*y).or_insert(BTreeSet::new());
            (*r).insert(i.clone());
        }
    }
    for i in common {
        println!("{:?}",i);
    }
    Ok(())
}



Code:

~/.../examples/rust >>> ./commongb                                                                                                                                                                                   
(1900, {"Jessie", "Willie"})
(1901, {"Jessie", "Willie"})
(1902, {"Jessie", "Willie"})
(1903, {"Jessie", "Willie"})
(1904, {"Jessie", "Willie"})
(1905, {"Jessie", "Willie"})
(1906, {"Jessie", "Willie"})
(1907, {"Jessie", "Willie"})
(1908, {"Jessie", "Willie"})
(1909, {"Jessie", "Willie"})
(1910, {"Jessie", "Willie"})
(1911, {"Jessie", "Willie"})
(1912, {"Willie"})
(1913, {"Willie"})
(1914, {"Willie"})
(1915, {"Willie"})
(1916, {"Willie"})
(1917, {"Willie"})
(1918, {"Willie"})
(1919, {"Willie"})
(1920, {"Willie"})
(1921, {"Willie"})
(1922, {"Willie"})
(1923, {"Willie"})
(1924, {"Willie"})
(1925, {"Willie"})
(1926, {"Willie"})
(1927, {"Willie"})
(1928, {"Willie"})
(1929, {"Willie"})
(1930, {"Willie"})
(1931, {"Willie"})
(1932, {"Willie"})
(1933, {"Willie"})
(1935, {"Willie"})
(1954, {"Terry"})
(1955, {"Kim", "Terry"})
(1956, {"Terry"})
(1957, {"Terry"})
(1958, {"Terry"})
(1959, {"Terry"})
(1966, {"Tracy"})
(1967, {"Tracy"})
(1968, {"Kelly"})
(1972, {"Shannon"})
(1973, {"Shannon"})
(1974, {"Jamie"})
(1975, {"Jamie"})
(1976, {"Jamie", "Shannon"})
(1977, {"Jamie"})
(1978, {"Jamie"})
(1979, {"Jamie"})
(1986, {"Casey"})
(1987, {"Casey"})
(1988, {"Casey"})
(1989, {"Jordan", "Taylor"})
(1990, {"Jordan", "Taylor"})
(1991, {"Jordan", "Taylor"})
(1992, {"Jordan", "Taylor"})
(1993, {"Jordan", "Taylor"})
(1994, {"Jordan", "Taylor"})
(1995, {"Jordan", "Taylor"})
(1996, {"Jordan", "Taylor"})
(1997, {"Jordan", "Taylor"})
(1998, {"Jordan"})
(1999, {"Jordan"})
(2000, {"Jordan"})
(2001, {"Jordan"})
(2002, {"Jordan", "Riley"})
(2003, {"Jordan"})
(2004, {"Jordan"})
(2005, {"Jordan"})
(2006, {"Jordan"})
(2007, {"Jordan"})

[ Panta_ @ 30.03.2020. 12:00 ] @
Code (python):

import glob

files = sorted(glob.glob('*txt'))
names = {}
for file1, file2 in list(zip(files, files[1:]))[::2]:
    with open(file1) as boys_file, open(file2) as girls_file:
        boys_names = [name.split()[0] for name in boys_file]
        girls_names = [name.split()[0] for name in girls_file]
        name_exist_in_both_lists = [name for name in boys_names if name in girls_names]
        year = int(file1[:4])
        if name_exist_in_both_lists:
            names[year]=name_exist_in_both_lists

for year in names:
    print(year, ', '.join(name for name in names[year]))


Izlaz:

1900 Willie, Jessie
1901 Willie, Jessie
1902 Willie, Jessie
1903 Willie, Jessie
1904 Willie, Jessie
1905 Willie, Jessie
1906 Willie, Jessie
1907 Willie, Jessie
1908 Willie, Jessie
1909 Willie, Jessie
1910 Willie, Jessie
1911 Willie, Jessie
1912 Willie
1913 Willie
1914 Willie
1915 Willie
1916 Willie
1917 Willie
1918 Willie
1919 Willie
1920 Willie
1921 Willie
1922 Willie
1923 Willie
1924 Willie
1925 Willie
1926 Willie
1927 Willie
1928 Willie
1929 Willie
1930 Willie
1931 Willie
1932 Willie
1933 Willie
1935 Willie
1954 Terry
1955 Terry, Kim
1956 Terry
1957 Terry
1958 Terry
1959 Terry
1966 Tracy
1967 Tracy
1968 Kelly
1972 Shannon
1973 Shannon
1974 Jamie
1975 Jamie
1976 Jamie, Shannon
1977 Jamie
1978 Jamie
1979 Jamie
1986 Casey
1987 Casey
1988 Casey
1989 Jordan, Taylor
1990 Jordan, Taylor
1991 Jordan, Taylor
1992 Jordan, Taylor
1993 Jordan, Taylor
1994 Jordan, Taylor
1995 Jordan, Taylor
1996 Jordan, Taylor
1997 Jordan, Taylor
1998 Jordan
1999 Jordan
2000 Jordan
2001 Jordan
2002 Jordan, Riley
2003 Jordan
2004 Jordan
2005 Jordan
2006 Jordan
2007 Jordan
[ B3R1 @ 30.03.2020. 16:32 ] @
Citat:
a1234567:
"mali" problem da se javljaju neka imena kojih nema u oba spiska za datu godinu (na primer Shannon), al nemam pojma zašto:

Napravio si dve greske. Prva je klasican problem "kumulativnog trpanja" podataka u niz. Problem je sto promenljive lista_m, lista_z i lista_unikat praznis samo na pocetku. Svaki sledeci fajl koji otvoris ih "nasledjuje" u potpunosti i kumulativno dodaje imena u njih. Otuda ti se npr. Shannon, koji se javlja prvi put 1972. godine provlaci i dalje kroz sve naredne godine. Problem zapravo pocinje jos od 1954, gde je Leslie nasledjen(a) iz 1953. i nadalje se provlaci kroz naredne godine. Ok, ovo nije tesko resiti, inicijalizaciju treba ukloniti s vrha i staviti iza linije
lines = open(filename).readlines()
Medjutim, tu postoji jos jedan problem: glob.glob() i os.listdir() vracaju listu fajlova sortiranu po nekoj internoj logici operativnog sistema. Dok Windows sortira fajlove po imenima, Unix/Linux vraca totalno nesortirane fajlove. Znaci, trebalo bi dodati:
for filename in sorted(glob.glob('*txt')):
Na kraju, lepo je sto si iskoristio skup kao strukturu podataka, jer ti to efikasno resava 'uniq' funkciju. Ali sta ce ti onda liste koje pretvaras u skup? Zasto odmah ne koristis skup.add() za dodavanje elementa u skup? Inace, add() funkcija lepo ignorise elemente koji vec postoje u skupu, odnosno dodaje element samo ako vec nije u skupu. Takodje, s obzirom da svaka godina ima muska i zenska imena, nebitno je ispitivati da li je 'Boys' ili 'Girls' u imenu fajla i beleziti posebno muska i zenska imena.

Recimo nesto ovako (nisam testirao, moguce je da sam napravio neki bag, ali ideja je tu):

Code (python):

import glob
spisak = open('c:/FAJLOVI/Python_School/Stephenson_ThePythonWorkbook/unisex.txt', 'w')

imena = {}

for filename in sorted(glob.glob('*txt')):
    godina = int(filename[0:4])
    lines = open(filename).readlines()
    lista= set()                                         # Lista imena u fajlu, pol je nebitan
    for line in lines:
        name = line.strip().split()[0]
        lista.add(name)
    if (godina not in imena):                      # U prvom fajlu iz godine X hashtable imena je prazna
        imena[godina] = lista
    else:                                                  # U drugom fajlu iz godine X trazimo uniq(m,f)
        imena[godina] = imena[godina].intersection(lista)

spisak.write(str(imena) + '\n')
spisak.close()


[ B3R1 @ 30.03.2020. 16:50 ] @
A za to vreme u Unix shellu, one-liner:
$ cd BabyNames; grep . * | sed -e 's/ .*$//g' -e 's/_.*:/:/g' | sort | uniq -d

Za one koji bi da imaju lep ispis:
$ cd BabyNames; grep . * | sed -e 's/ .*$//g' -e 's/_.*:/:/g' | sort | uniq -d | gawk -F: '{ if ($1!=prev) printf ("\n%s", $0); else printf (", %s",$2); prev=$1 }'

[ B3R1 @ 30.03.2020. 17:17 ] @
Zadatak broj 33: Kreiranje registra imena u Excelu

Evo mog predloga za novi zadatak, prilicno lak. Oslanja se na iste podatke kao prethodna dva, a sluzi za snalazenje s raspolozivim Python modulima. Od fajlova sa imenima treba napraviti program koji generise tabelu u Excelu u sledecem formatu:

+========+========+======+======+======+
| Name | Gender | 2020 | 2019 | 2018 | ...
+========+========+======+======+======+
| Aice | F | 234 | 234 | 234 |
| Anna | F | 13 | 13 | 13 |
| Bob | M | 1234 | 1234 | 1234 |


Imena su u prvoj koloni (A) koja treba sortirati. Pol je u drugoj koloni (B) i moze da bude 'M' ili 'F'. U naredne kolone upisati frekvenciju pojavljivanja imena. Godine sortirati u opadajucem redosledu - kolona C je posldnja godina, kolona D pretposlednja itd. kao u gornjem primeru.
Vrstu koja predstavlja zaglavlje (Name / Gender / godine ...) obojiti u svetlo sivu boju.
Svaku sledecu vrstu obojiti u svetlo plavu ako su u pitanju decaci, a svetlo roze ako su u pitanju devojcice.

Program mora da generise Excel fajl koji se direktno ucitava takav kakav je, formatiran i obojen kao sto je zadato.

Kako poceti? Google => generate excel file from python ...
[ a1234567 @ 31.03.2020. 03:34 ] @
Citat:
Panta_:
Code (python):

import glob

files = sorted(glob.glob('*txt'))
names = {}
for file1, file2 in list(zip(files, files[1:]))[::2]:
    with open(file1) as boys_file, open(file2) as girls_file:
        boys_names = [name.split()[0] for name in boys_file]
        girls_names = [name.split()[0] for name in girls_file]
        name_exist_in_both_lists = [name for name in boys_names if name in girls_names]
        year = int(file1[:4])
        if name_exist_in_both_lists:
            names[year]=name_exist_in_both_lists

for year in names:
    print(year, ', '.join(name for name in names[year]))


Izlaz:

1900 Willie, Jessie
1901 Willie, Jessie
1902 Willie, Jessie
1903 Willie, Jessie
 


Panto, šta ti je ovo?
for file1, file2 in list(zip(files, files[1:]))[::2]

Šta su ti ovi indeksi [1:] i [::2]?
[ a1234567 @ 31.03.2020. 04:33 ] @
Citat:
B3R1:
Citat:
a1234567:
"mali" problem da se javljaju neka imena kojih nema u oba spiska za datu godinu (na primer Shannon), al nemam pojma zašto:

Napravio si dve greske. Prva je klasican problem "kumulativnog trpanja" podataka u niz. Problem je sto promenljive lista_m, lista_z i lista_unikat praznis samo na pocetku. Svaki sledeci fajl koji otvoris ih "nasledjuje" u potpunosti i kumulativno dodaje imena u njih. Otuda ti se npr. Shannon, koji se javlja prvi put 1972. godine provlaci i dalje kroz sve naredne godine. Problem zapravo pocinje jos od 1954, gde je Leslie nasledjen(a) iz 1953. i nadalje se provlaci kroz naredne godine. Ok, ovo nije tesko resiti, inicijalizaciju treba ukloniti s vrha i staviti iza linije
lines = open(filename).readlines()
Medjutim, tu postoji jos jedan problem: glob.glob() i os.listdir() vracaju listu fajlova sortiranu po nekoj internoj logici operativnog sistema. Dok Windows sortira fajlove po imenima, Unix/Linux vraca totalno nesortirane fajlove. Znaci, trebalo bi dodati:
for filename in sorted(glob.glob('*txt')):
Na kraju, lepo je sto si iskoristio skup kao strukturu podataka, jer ti to efikasno resava 'uniq' funkciju. Ali sta ce ti onda liste koje pretvaras u skup? Zasto odmah ne koristis skup.add() za dodavanje elementa u skup? Inace, add() funkcija lepo ignorise elemente koji vec postoje u skupu, odnosno dodaje element samo ako vec nije u skupu. Takodje, s obzirom da svaka godina ima muska i zenska imena, nebitno je ispitivati da li je 'Boys' ili 'Girls' u imenu fajla i beleziti posebno muska i zenska imena.

Recimo nesto ovako (nisam testirao, moguce je da sam napravio neki bag, ali ideja je tu):

Code (python):

import glob
spisak = open('c:/FAJLOVI/Python_School/Stephenson_ThePythonWorkbook/unisex.txt', 'w')

imena = {}

for filename in sorted(glob.glob('*txt')):
    godina = int(filename[0:4])
    lines = open(filename).readlines()
    lista= set()                                         # Lista imena u fajlu, pol je nebitan
    for line in lines:
        name = line.strip().split()[0]
        lista.add(name)
    if (godina not in imena):                      # U prvom fajlu iz godine X hashtable imena je prazna
        imena[godina] = lista
    else:                                                  # U drugom fajlu iz godine X trazimo uniq(m,f)
        imena[godina] = imena[godina].intersection(lista)

spisak.write(str(imena) + '\n')
spisak.close()




Da, kad prebacim liste u petlju, radi.
Meni je bila ideja da pokupim sva muška imena u jednu listu, sva ženska u drugu i onda nađem presek te dve liste.

Kod tvog koda mi nisu baš najjasnije neke stvari. Evo kako ga ja čitam:

Code:
for filename in sorted(glob.glob('*txt')):   # OK, sortiranje fajlova pre otvaranja, da bi išlo po godinama, mada kod men u WIn to je već sortirano.
    godina = int(filename[0:4])         # beleži prva 4 karaktera iz imena fajla, što je godina 
    lines = open(filename).readlines()       # učitava u memoriju ceo tekst fajla
    lista= set()                           # tip liste je skup, što znači nema ponavljanja
    for line in lines:      
        name = line.strip().split()[0]         # promenljiva name je indeks[0] u listi, npr. ['James', 32340]
        lista.add(name)                     # dodaje to ime u listu
                                                    OVDE IMAM PROBLEM: kad dovde izvršim program za jednu godinu sa: 
                                                    for filename in sorted(glob.glob('1990*txt')):)
                                                    u listi imam samo ženska imena:

{'Stephanie', 'Maria', 'Lindsay', 'Anna', 'Shannon', 'Julie', 'Hannah', 'Katie', 'Kelly', 'Lindsey', 'Kathleen', 'Ashley', 'Veronica', 
'Mary', 'Angela', 'Elizabeth', 'Cassandra', 'Shelby', 'Tiffany', 'Jenna', 'Brooke', 'Andrea', 'Tara', 'Jessica', 'Katelyn', 'Kelsey', 
'Amy', 'Erin', 'Alicia', 'Alexandra', 'Laura', 'Holly', 'Diana', 'Brianna', 'Gabrielle', 'Kathryn', 'Whitney', 'Sarah', 'Jennifer', 'Catherine',
 'Kristin', 'Emily', 'Amanda', 'Megan', 'Christine', 'Victoria', 'Alyssa', 'Courtney', 'Alexis', 'Erika', 'Melissa', 'Michelle', 'Danielle', 
'Sara', 'Kimberly', 'Katherine', 'Olivia', 'Ariel', 'Cynthia', 'Meghan', 'Rebecca', 'Samantha', 'Monica', 'Patricia', 'Leah', 'Christina', 
'Taylor', 'Julia', 'Morgan', 'Nicole', 'Heather', 'Marissa', 'Brittany', 'Rachel', 'April', 'Kaitlyn', 'Erica', 'Natalie', 'Brittney', 'Vanessa', 
'Caitlin', 'Abigail', 'Lisa', 'Jacqueline', 'Kristen', 'Chelsea', 'Kristina', 'Bianca', 'Molly', 'Alexandria', 'Paige', 'Jamie', 'Jordan', 'Kayla',
'Amber', 'Jasmine', 'Melanie', 'Lauren', 'Allison', 'Crystal'}

Šta se dešava sa muškim imenima? Koji je smisao ove liste?
I onda mi ni ovo što sledi nije jasno:

    if (godina not in imena):                      # U prvom fajlu iz godine X hashtable imena je prazna
        imena[godina] = lista
    else:                                                  # U drugom fajlu iz godine X trazimo uniq(m,f)
        imena[godina] = imena[godina].intersection(lista)
[ a1234567 @ 31.03.2020. 04:38 ] @
Citat:
B3R1:
Zadatak broj 33: Kreiranje registra imena u Excelu

Evo mog predloga za novi zadatak, prilicno lak. Oslanja se na iste podatke kao prethodna dva, a sluzi za snalazenje s raspolozivim Python modulima. Od fajlova sa imenima treba napraviti program koji generise tabelu u Excelu u sledecem formatu:

+========+========+======+======+======+
| Name | Gender | 2020 | 2019 | 2018 | ...
+========+========+======+======+======+
| Aice | F | 234 | 234 | 234 |
| Anna | F | 13 | 13 | 13 |
| Bob | M | 1234 | 1234 | 1234 |


Eto nama zabave u karantinu :)))
Ću da probam, pa javljam rezulate...
[ Branimir Maksimovic @ 31.03.2020. 05:53 ] @
Hehe, Beri mi zapaprio, Rust i Haskell nemaju podrsku za excel out of box ;)
Ali ima eksternih biblioteka :P

edit:
nasao za Haskell, za Rust ima samo reader :(

[Ovu poruku je menjao Branimir Maksimovic dana 31.03.2020. u 07:15 GMT+1]
[ Panta_ @ 31.03.2020. 05:55 ] @
Citat:
Panto, šta ti je ovo?
for file1, file2 in list(zip(files, files[1:]))[::2]

Šta su ti ovi indeksi [1:] i [::2]?

To je list slicing, valjda si do sada to prošao. Evo primer:
Code:
l = [1, 2, 3, 4, 5, 6]

l[1:]              # od indeksa 1 do kraja, u Pythonu indeksiranje pocinje od 0
[2, 3, 4, 5, 6]

ili sa slice

l[slice(1, None)]
[2, 3, 4, 5, 6]

l[::2]             # svaki drugi
[1, 3, 5]

ili

l[slice(None, None, 2)]
[1, 3, 5]

list(zip(l, l[1:]))
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]

Posto mi treba svaki drugi par, na primer za godine (1900, 1901), (1902, 1903), itd...

list(zip(l, l[1:]))[::2]
[(1, 2), (3, 4), (5, 6)]


Isto možeš da koristiš za string i tuple.

https://docs.python.org/2.3/whatsnew/section-slices.html
[ a1234567 @ 31.03.2020. 12:36 ] @
Ma znam slajsing, to sam odavno savladao.
Nego mi nije jasna njegova uloga u tvom kodu.
Šta ti znači da čitaš naziv fajla od indeksa [1],
pa svako drugo slovo!?

Al sad vidim da ima nekog smisla.


[ B3R1 @ 31.03.2020. 16:24 ] @
Evo, sad sam ubacio onaj kod koji sam napisao i radi ispravno.

Citat:
a1234567:
Code:

        lista.add(name)                     # dodaje to ime u listu
                                                    OVDE IMAM PROBLEM: kad dovde izvršim program za jednu godinu sa: 
                                                    for filename in sorted(glob.glob('1990*txt')):)
                                                    u listi imam samo ženska imena:

Zato sto si ga izvrsio "dovde". Program se izvrsava od pocetka do kraja. :-) Kada izvrsavas liniju po liniju verovatno dodjes do ove tacke:
Code (python):

>>> import glob
>>>
>>> imena = {}
>>>
>>> for filename in sorted(glob.glob('1910*txt')):
...     godina = int(filename[0:4])
...     lines = open(filename).readlines()
...     lista= set()                                         # Lista imena u fajlu, pol je nebitan
...     for line in lines:
...         name = line.strip().split()[0]
...         lista.add(name)
...

Verovatno si ovde pritisnuo enter, dok je kursor stajao tik uz ove tri tackice, zar ne? Ako si to uradio python je izvrsio spoljasnju for petlju (for filename ...) i u listi si dobio zenska imena, jer su muska ucitana u prvom prolazu petlje. Ako hoces da to proveris, uradi ovo (uh, sad zvucim kao ovi nasi novinski portali - "evo sta vam treba za ovo" ili "ovo vam treba za evo").
Code (python):

>>> import glob
>>>
>>> imena = {}
>>>
>>> for filename in sorted(glob.glob('1910*txt')):
...     print "\nFILE: " + filename
...     godina = int(filename[0:4])
...     lines = open(filename).readlines()
...     lista= set()                                         # Lista imena u fajlu, pol je nebitan
...     for line in lines:
...         name = line.strip().split()[0]
...         lista.add(name)
...     print str(lista)
...

FILE: 1910_BoysNames.txt
set(['Russell', 'Jim', 'Bernard', 'Daniel', 'Stephen', 'Benjamin', 'Theodore', 'Marvin', 'Leonard', 'Fred', 'Philip', 'Homer', 'Luther', 'Louis', 'Michael', 'Herbert', 'Henry', 'Thomas', 'Sam', 'Stanley', 'Paul', 'George', 'Clifford', 'Howard', 'Claude', 'Joseph', 'Alfred', 'John', 'Eugene', 'Lee', 'Frank', 'Everett', 'Samuel', 'Leo', 'William', 'Julius', 'Johnnie', 'Joe', 'Francis', 'Earl', 'Charlie', 'Edgar', 'David', 'Arthur', 'Chester', 'Allen', 'Ernest', 'Clarence', 'Alvin', 'Glenn', 'Roy', 'Oscar', 'Ray', 'Victor', 'Sidney', 'Harvey', 'Robert', 'Elmer', 'Clyde', 'Tom', 'Willie', 'Harold', 'Norman', 'Lawrence', 'Anthony', 'Vernon', 'Floyd', 'Carl', 'Herman', 'Ben', 'Harry', 'Vincent', 'Kenneth', 'Leon', 'Lester', 'Eddie', 'Peter', 'Cecil', 'Jesse', 'Jessie', 'Richard', 'Edwin', 'Ralph', 'Edward', 'Walter', 'Raymond', 'Albert', 'Andrew', 'Jack', 'James', 'Milton', 'Leroy', 'Frederick', 'Morris', 'Martin', 'Lewis', 'Charles', 'Donald', 'Lloyd', 'Melvin'])

FILE: 1910_GirlsNames.txt
set(['Sarah', 'Edith', 'Genevieve', 'Anne', 'Anna', 'Ella', 'Margaret', 'Jennie', 'Beulah', 'Helen', 'Grace', 'Lillian', 'Opal', 'Alice', 'Eleanor', 'Betty', 'Charlotte', 'Carrie', 'Marguerite', 'Pauline', 'Kathryn', 'Marion', 'Rose', 'Rosa', 'Nellie', 'Inez', 'Ellen', 'Sylvia', 'Mary', 'Martha', 'Elizabeth', 'Lucille', 'Theresa', 'Vera', 'Ruby', 'Emma', 'Minnie', 'Mattie', 'Elsie', 'Annie', 'Leona', 'Mamie', 'Doris', 'Agnes', 'Maggie', 'Ethel', 'Josephine', 'Beatrice', 'Clara', 'Thelma', 'Blanche', 'Violet', 'Dorothy', 'Bessie', 'Pearl', 'Ada', 'Ruth', 'Willie', 'Lena', 'Cora', 'Mildred', 'Gladys', 'Katherine', 'Bernice', 'Georgia', 'Eva', 'Velma', 'Jean', 'Ann', 'Lois', 'Marjorie', 'Florence', 'Gertrude', 'Jessie', 'Louise', 'Catherine', 'Viola', 'Laura', 'Esther', 'Sadie', 'Hazel', 'Virginia', 'Frances', 'Mae', 'Marie', 'Alma', 'Lillie', 'Lucy', 'Hattie', 'Ida', 'Myrtle', 'Stella', 'Edna', 'Evelyn', 'Julia', 'Bertha', 'Mabel', 'Lula', 'Fannie', 'Irene'])
 

Kao sto vidis, citaju se oba fajla, jedan za drugim.
Citat:
I onda mi ni ovo što sledi nije jasno:
Code:

    if (godina not in imena):                      # U prvom fajlu iz godine X hashtable imena je prazna
        imena[godina] = lista
    else:                                                  # U drugom fajlu iz godine X trazimo uniq(m,f)
        imena[godina] = imena[godina].intersection(lista)

Hash tabela imena se sastoji od kljuceva koji su godine, a vrednosti su skupovi imena:
{1910: set(['Jessie', 'Willie'])}

Za svaku godinu imas dva fajla - muska i zenska imena. Petlja "for filename in ..." prolazi najpre fajl sa muskim imenima, tu se promenljiva lista napuni imenima iz fajla. Potom ispitujemo da li je godina vec prisutna u hash tabeli (recniku). Ako nije dodajemo je u recnik, a vrednost ce biti skup imena (u ovom slucaju muskih). Potom se petlja "for filename ..." nastavlja citanjem fajla sa zenskim imenima gde se formira nova lista. Kada ponovo izvrsis deo koda "if godina not in imena" - godina ce vec biti definisana u tabeli, pa se izvrsava else, koji menja vrednost - postavlja tako da bude presek skupa muskih imena (trenutna vrednost imena[godina]) i zenskih imena (koja su trenutno u skupu 'lista'). Rezultat za 1910. godinu je:
{1910: set(['Jessie', 'Willie'])}



[ Panta_ @ 31.03.2020. 16:29 ] @
Citat:
Nego mi nije jasna njegova uloga u tvom kodu.
Šta ti znači da čitaš naziv fajla od indeksa [1],
pa svako drugo slovo!?

Al sad vidim da ima nekog smisla.

Da čita iz oba fajla za istu godinu kako bi izdvojio ista imena ukoliko postoje u oba fajla.

Što se tiče Excel tabele:
Code (python):

import glob
import xlsxwriter

data = {}

files = sorted(glob.glob('*.txt'), reverse=True)

for filename in files:
    year = int(filename[:4])
    if 'Boys' in filename:
        gender = 'M'
    else:
        gender = 'F'
    lines = open(filename).readlines()
    for line in lines:
        name, num = line.strip().split()
        name_num = int(num)
        if name not in data:
            data[name] = [gender, (year, name_num)]
        else:
            data[name].append((year, name_num))

book = xlsxwriter.Workbook('BabyNames.xlsx')
sheet = book.add_worksheet("My sheet")

hc = book.add_format({'bg_color': '#e0e0e0'})
gc = book.add_format({'bg_color': '#f9c7ff'})
bc = book.add_format({'bg_color': '#b8bbff'})

sheet.set_row(0, cell_format=hc)
sheet.write(0,0, 'Name')
sheet.write(0,1, 'Gender')
years = sorted(set([i[:4] for i in files]), reverse=True)
col=2
years_cols = {}
for i in years:
    sheet.write(0, col, i)
    years_cols[int(i)]=col
    col+=1

row=1
col=0
for name in sorted(data):
    if data[name][0] == 'F':
        sheet.set_row(row, cell_format=gc)
    else:
        sheet.set_row(row, cell_format=bc)
    sheet.write(row, col, name)
    col+=1
    sheet.write(row, col, data[name][0])
    for i in data[name][1:]:
        sheet.write(row, years_cols[i[0]], i[1])
    row+=1
    col=0
book.close()


Ne radi sa Google docs, jednostavno pomeri sve ćelije ulevo, ako neko želi online da testira, može na https://sheet.zoho.com.

Takođe mora da se instalira xlsxwriter: pip install xlsxwriter

[ B3R1 @ 31.03.2020. 16:32 ] @
Citat:
Branimir Maksimovic:
Hehe, Beri mi zapaprio, Rust i Haskell nemaju podrsku za excel out of box ;)
Ali ima eksternih biblioteka :P

Pa ni Python nema resenje out of the box, vec se koristi modul za to. Zapravo postoje dva, moguce i vise, ali ja znam za jedan koji radi i citanje i pisanje xlsx fajlova. Ideja zadatka je naci modul koji to radi, procitati dokumentaciju, shvatiti kako radi i iskoristiti ga. Dokumentacija sadrzi i gotov primer koji moze da se kopira i iskoristi.

Sad videh da je Panta iskoristio xslxwriter. Meni se vise svidja openpyxl.
Inace, Pandas moze da cita Excel (nisam siguran da li ima podrsku i za generisanje Excel fajlova).
[ Branimir Maksimovic @ 31.03.2020. 17:12 ] @
Znas kako da nadjem C biblioteku koja to radi pa da vrapujem, ne da mi se pored svega posla koji me ceka :P

edit:
bar sam nasao C biblioteku koja se koristi:
https://github.com/jmcnamara/libxlsxwriter

E sad e sad, wrapovati, wrapovati :p
mislim ne mora da bude user friendly ;)


[Ovu poruku je menjao Branimir Maksimovic dana 31.03.2020. u 22:58 GMT+1]
[ a1234567 @ 01.04.2020. 02:06 ] @
Citat:
B3R1:
Citat:
Branimir Maksimovic:
Hehe, Beri mi zapaprio, Rust i Haskell nemaju podrsku za excel out of box ;)
Ali ima eksternih biblioteka :P

Pa ni Python nema resenje out of the box, vec se koristi modul za to. Zapravo postoje dva, moguce i vise, ali ja znam za jedan koji radi i citanje i pisanje xlsx fajlova. Ideja zadatka je naci modul koji to radi, procitati dokumentaciju, shvatiti kako radi i iskoristiti ga. Dokumentacija sadrzi i gotov primer koji moze da se kopira i iskoristi.

Sad videh da je Panta iskoristio xslxwriter. Meni se vise svidja openpyxl.
Inace, Pandas moze da cita Excel (nisam siguran da li ima podrsku i za generisanje Excel fajlova).


Koji onda modul da koristim?

Ja sam već instalirao xlsxwriter modul i gledam dokumentaciju.
Napravio sam do pola, ali imam posle stanovitih problema. Što je i za očekivati :)
Ako ih danas ne rešim, postaviću to koliko sam uradio.
[ Panta_ @ 01.04.2020. 06:37 ] @
Citat:
Koji onda modul da koristim?

Koji god želiš (openpyxl, xslxwriter, pandas).

Inače, niko nije primetio da sam izostavio (zaboravio) ova zajednička imena za devojčice i dečake Šanon, Džesi, Džordan, Vili, itd. Evo jednostavne ispravke za prethodni kod:
Code (python):
import glob
import xlsxwriter

data = {}

files = sorted(glob.glob('*.txt'), reverse=True)

for filename in files:
    year = int(filename[:4])
    if 'Boys' in filename:
        gender = 'M'
    else:
        gender = 'F'
    lines = open(filename).readlines()
    for line in lines:
        name, name_num = line.strip().split()
        if name in data and gender != data[name][0]:
            if name+'_' not in data:
                data[name+'_'] = [gender, (year, name_num)]
            else:
                data[name+'_'].append((year, name_num))
        elif name not in data:
            data[name] = [gender, (year, name_num)]
        else:
            data[name].append((year, name_num))


book = xlsxwriter.Workbook('/tmp/BabyNames.xlsx')
sheet = book.add_worksheet("My sheet")

hc = book.add_format({'bg_color': '#e0e0e0'})
gc = book.add_format({'bg_color': '#f9c7ff'})
bc = book.add_format({'bg_color': '#b8bbff'})

sheet.set_row(0, cell_format=hc)
sheet.write(0,0, 'Name')
sheet.write(0,1, 'Gender')
years = sorted(set([i[:4] for i in files]), reverse=True)
col=2
years_cols = {}
for i in years:
    sheet.write(0, col, i)
    years_cols[int(i)]=col
    col+=1

row=1
col=0
for name in sorted(data):
    if data[name][0] == 'F':
        sheet.set_row(row, cell_format=gc)
    else:
        sheet.set_row(row, cell_format=bc)
    if '_' in name:
        new_name = name.replace('_', '')
    else:
        new_name = name
    sheet.write(row, col, new_name)
    col+=1
    sheet.write(row, col, data[name][0])
    for i in data[name][1:]:
        sheet.write(row, years_cols[i[0]], i[1])
    row+=1
    col=0
book.close()
 


Mislim da su sada tu sva imena.
[ Branimir Maksimovic @ 01.04.2020. 07:21 ] @
Vidim da xlsxwriter ima defineove za boje? Jel mora bas da u hexa obliku stavljas boje zato sto to nisu definisali kada su wrappovali bilioteku?
[ Panta_ @ 01.04.2020. 08:23 ] @
Može i sa color name, ali mi je ovako bilo lakše da u color picker izaberem boje nego npr. lightblue, lightštaveć.

https://xlsxwriter.readthedocs.io/format.html
[ Branimir Maksimovic @ 01.04.2020. 08:31 ] @
Heh, Panta haker ;)
Nego smorno mi da pravim projekt uvlacim eksterni lib, podesavam build skripte ;)
Da je bar to neko uradio za mene (Rust) pa okacio kao za Python :P
Ipak ovo treba da bude laganica za opustanje ...
[ B3R1 @ 01.04.2020. 09:36 ] @
Citat:
a1234567:
Koji onda modul da koristim?

Svejedno je. Zapravo, princip kod svih je slican i polazi od same strukture Excel dokumenta, koji se sastoji od radne sveske (workbook) i listova (sheets). Svaki od njih mora da:

* Kreira workbook
* Kreira worksheet
* Za svako polje postavlja boju pozadine, boju slova i ostale atribute i upisuje vrednost.
* Koordinate se odredjuju bilo numericki (npr. (0,0) = prvo polje levo gore) ili u Excel notaciji (npr. A1), zavisno od modula (sto se moze procitati u dokumentaciji).
[ a1234567 @ 02.04.2020. 12:17 ] @
Uzeo sam samo dve prve godine za test i to tek prvih 7-8 imena.
No, svejedno, upletoh se ko pile u kučinu...

Code:
import glob
import xlsxwriter

workbook = xlsxwriter.Workbook('Imena.xlsx')
worksheet = workbook.add_worksheet()

row = 0
col = 0
worksheet.write(row, col, 'Name')
worksheet.write(col, 1, 'Gender')

row = 0
col = 2
files = sorted(glob.glob('*txt'))
for file1, file2 in list(zip(files, files[1:]))[::2]:
    worksheet.write(row, col, file1[0:4])       #upisuje godine
    col += 1

col = 0
row = 1
it = iter(files)
for chunk in zip(it, it):
    for filename in list(chunk):
        if 'Boys' in filename:
            lines = open(filename).readlines()
            for item in lines:
                name = item.strip().split()[0]
                worksheet.write(row, col, name)        # upisuje imena
                worksheet.write(row, col + 1, 'M')      # upisuje pol
                row += 1
        else:
            lines = open(filename).readlines()
            for item in lines:
                name = item.strip().split()[0]
                worksheet.write(row, col, name)
                worksheet.write(row, col + 1, 'F')
                row += 1
col = 2
row = 1
it = iter(files)
for chunk in zip(it, it):
    for txt in list(chunk):
        lines = open(txt).readlines()
        for item in lines:
            broj = item.strip().split()[1]
            worksheet.write(row, col, broj)     # upisuje brojeve
            row += 1
    col += 1

col = 1
row = 1
for filename in files:
    if 'Boys' in filename:
        worksheet.write(row, col, 'M')
        row += 1
    else:
        worksheet.write(row, col, 'F')
        row += 1

workbook.close()

Imam problem kako da ista imena iz naredne godine na upisujem iznova, već samo brojeve za njih.

A ovo je šta trenutno dobijam

[ a1234567 @ 02.04.2020. 13:01 ] @
Sad sam pogledao Pantino rešenje, pa vidim da on prvo pravi rečnik, a onda upisuje u tabelu.
A ja krenuo direkt, da ne dangubim
[ Branimir Maksimovic @ 04.04.2020. 17:34 ] @
nije me ipak mrzelo ali nisam pravio posebnu biblioteku nego samo sta koristim.
Potrebno je imati instaliran libxlsxwiter.

Code:

use std::ffi::{CString, CStr};
#[repr(C)]
struct lxw_workbook(*mut lxw_workbook);
#[repr(C)]
struct lxw_worksheet(*mut lxw_worksheet);
#[repr(C)]
#[derive(Clone)]
struct lxw_format(*mut lxw_format);
#[link(name="xlsxwriter",kind="dylib")]
extern "C" {
    fn workbook_new(wkbk: *const i8)->*mut lxw_workbook;
    fn workbook_add_worksheet(wkbk:*mut lxw_workbook, sheetname:*const i8)->*mut lxw_worksheet;
    fn workbook_add_format(wkbk:*mut lxw_workbook)->*mut lxw_format;
    fn workbook_close(wkbk:*mut lxw_workbook)->i32;
    fn lxw_strerror(errnum:i32)->*const i8;
    fn format_set_bg_color(fmt:*mut lxw_format, color: u32);
    fn worksheet_write_string(wksht:*mut lxw_worksheet, row:u32,col:u16,s:*const i8,fmt:*const lxw_format)->i32;
}
impl lxw_workbook {
    fn new(wkbk:&str)->lxw_workbook {
        unsafe {lxw_workbook(workbook_new(CString::new(wkbk).unwrap().as_ptr())) }
    }
    fn add_worksheet(&self,sheetname:&str)->lxw_worksheet {
        unsafe {lxw_worksheet(workbook_add_worksheet(self.0,CString::new(sheetname).unwrap().as_ptr())) }
    }
    fn add_format(&self)->lxw_format {
        unsafe {lxw_format(workbook_add_format(self.0)) }
    }
    fn close(&self)->i32{
        unsafe {workbook_close(self.0)}
    }
    fn strerror(errnum:i32)->&'static str {
        unsafe { CStr::from_ptr(lxw_strerror(errnum)).to_str().unwrap() }
    }
}
impl Drop for lxw_workbook {
    fn drop(&mut self) {
        let rc = self.close();
        if rc != 0 {
            panic!("{}",lxw_workbook::strerror(rc));
        }
    }
}
impl lxw_format {
    fn set_bg_color(&self, color: u32){
        unsafe { format_set_bg_color(self.0,color); }
    }
}
impl lxw_worksheet {
    fn write_string(&self, row:u32, col:u16, s:&str,fmt:lxw_format)->Result<(),String>{
        let s = CString::new(s);
        let rc;
        unsafe { rc = worksheet_write_string(self.0,row,col,s.unwrap().as_ptr(),fmt.0);}
        if rc == 0 {
            Ok(())
        }else {
            Err(lxw_workbook::strerror(rc).to_string())
        }
    }
}

use std::io;
use std::fs::File;
use std::fs::read_dir;
use std::io::prelude::*;
use std::collections::BTreeMap;
type map_t = BTreeMap<i32,i32>;
fn main()->io::Result<()>{
    let mut common:BTreeMap<String,Vec<(char,map_t)>> = BTreeMap::new();
    let mut buf = String::new();
    if let Ok(dir) = read_dir("BabyNames") {
        for file in dir {
            let file = file?;
            let mut f = File::open(file.path())?;
            let path = file.path();
            let fname = path.to_str().unwrap().to_string();
            let it = fname.split('_').collect::<Vec<_>>();
            let it1 = it[0].split('/').collect::<Vec<_>>();
            let year = it1[1].parse::<i32>().unwrap();
            let c = if it[1] == "GirlsNames.txt" {
                'F'
            } else {
                'M'
            };
            buf.clear();
            let _ = f.read_to_string(&mut buf);
            for line in buf.lines() {
                let two:Vec<_> = line.split_whitespace().collect();
                let r = common.entry(two[0].to_string()).or_insert(vec!{(c,map_t::new())});
                (*r).last_mut().unwrap().1.insert(year,two[1].parse::<i32>().unwrap());
            }
        }
    } else {
        println!("Not in directory above BabyNames...");
    }
    let wkbk = lxw_workbook::new("example.xlsx");
    let wksht = wkbk.add_worksheet("Names");
    let hc = wkbk.add_format();
    hc.set_bg_color(0xe0e0e0);
    let gc = wkbk.add_format();
    gc.set_bg_color(0xf9c7ff);
    let bc = wkbk.add_format();
    bc.set_bg_color(0xb8bbff);

    let _ = wksht.write_string(0,0, "Name",hc.clone());
    let _ = wksht.write_string(0,1, "Gender",hc.clone());
    for (ord,(name,pair)) in common.iter().enumerate() {
        for (gender,map) in pair.iter() {
            for (ord1,(year,value)) in map.iter().rev().enumerate() {
                let _ = wksht.write_string(0,ord1 as u16+2,year.to_string().as_str(),hc.clone());
                let clr;
                if *gender == 'F' {
                    clr = gc.clone();
                    let _ = wksht.write_string(ord as u32+1,0,name,gc.clone());
                    let _ = wksht.write_string(ord as u32+1,1,"F",gc.clone());
                } else {
                    clr = bc.clone();
                    let _ = wksht.write_string(ord as u32+1,0,name,bc.clone());
                    let _ = wksht.write_string(ord as u32+1,1,"M",bc.clone());
                }
                    let _ = wksht.write_string(ord as u32+1,ord1 as u16+2, value.to_string().as_str(),clr);
                }
            }
        }
    Ok(())
}


[ Branimir Maksimovic @ 04.04.2020. 20:25 ] @
Jedan propust, imena nisam rasporedio po datumima, nego su isla u opadajucem obliku bez obzira na datum,
ispravka:
Code:

use std::ffi::{CString, CStr};
#[repr(C)]
struct lxw_workbook(*mut lxw_workbook);
#[repr(C)]
struct lxw_worksheet(*mut lxw_worksheet);
#[repr(C)]
#[derive(Clone)]
struct lxw_format(*mut lxw_format);
#[link(name="xlsxwriter",kind="dylib")]
extern "C" {
    fn workbook_new(wkbk: *const i8)->*mut lxw_workbook;
    fn workbook_add_worksheet(wkbk:*mut lxw_workbook, sheetname:*const i8)->*mut lxw_worksheet;
    fn workbook_add_format(wkbk:*mut lxw_workbook)->*mut lxw_format;
    fn workbook_close(wkbk:*mut lxw_workbook)->i32;
    fn lxw_strerror(errnum:i32)->*const i8;
    fn format_set_bg_color(fmt:*mut lxw_format, color: u32);
    fn worksheet_write_string(wksht:*mut lxw_worksheet, row:u32,col:u16,s:*const i8,fmt:*const lxw_format)->i32;
}
impl lxw_workbook {
    fn new(wkbk:&str)->lxw_workbook {
        unsafe {lxw_workbook(workbook_new(CString::new(wkbk).unwrap().as_ptr())) }
    }
    fn add_worksheet(&self,sheetname:&str)->lxw_worksheet {
        unsafe {lxw_worksheet(workbook_add_worksheet(self.0,CString::new(sheetname).unwrap().as_ptr())) }
    }
    fn add_format(&self)->lxw_format {
        unsafe {lxw_format(workbook_add_format(self.0)) }
    }
    fn close(&self)->i32{
        unsafe {workbook_close(self.0)}
    }
    fn strerror(errnum:i32)->&'static str {
        unsafe { CStr::from_ptr(lxw_strerror(errnum)).to_str().unwrap() }
    }
}
impl Drop for lxw_workbook {
    fn drop(&mut self) {
        let rc = self.close();
        if rc != 0 {
            panic!("{}",lxw_workbook::strerror(rc));
        }
    }
}
impl lxw_format {
    fn set_bg_color(&self, color: u32){
        unsafe { format_set_bg_color(self.0,color); }
    }
}
impl lxw_worksheet {
    fn write_string(&self, row:u32, col:u16, s:&str,fmt:lxw_format)->Result<(),String>{
        let s = CString::new(s);
        let rc;
        unsafe { rc = worksheet_write_string(self.0,row,col,s.unwrap().as_ptr(),fmt.0);}
        if rc == 0 {
            Ok(())
        }else {
            Err(lxw_workbook::strerror(rc).to_string())
        }
    }
}

use std::io;
use std::fs::File;
use std::fs::read_dir;
use std::io::prelude::*;
use std::collections::BTreeMap;
type map_t = BTreeMap<i32,i32>;
fn main()->io::Result<()>{
    let mut common:BTreeMap<String,Vec<(char,map_t)>> = BTreeMap::new();
    let mut buf = String::new();
    if let Ok(dir) = read_dir("BabyNames") {
        for file in dir {
            let file = file?;
            let mut f = File::open(file.path())?;
            let path = file.path();
            let fname = path.to_str().unwrap().to_string();
            let it = fname.split('_').collect::<Vec<_>>();
            let it1 = it[0].split('/').collect::<Vec<_>>();
            let year = it1[1].parse::<i32>().unwrap();
            let c = if it[1] == "GirlsNames.txt" {
                'F'
            } else {
                'M'
            };
            buf.clear();
            let _ = f.read_to_string(&mut buf);
            for line in buf.lines() {
                let two:Vec<_> = line.split_whitespace().collect();
                let r = common.entry(two[0].to_string()).or_insert(vec!{(c,map_t::new())});
                (*r).last_mut().unwrap().1.insert(year,two[1].parse::<i32>().unwrap());
            }
        }
    } else {
        println!("Not in directory above BabyNames...");
    }
    let wkbk = lxw_workbook::new("example.xlsx");
    let wksht = wkbk.add_worksheet("Names");
    let hc = wkbk.add_format();
    hc.set_bg_color(0xe0e0e0);
    let gc = wkbk.add_format();
    gc.set_bg_color(0xf9c7ff);
    let bc = wkbk.add_format();
    bc.set_bg_color(0xb8bbff);
    let mut years = BTreeMap::new();
    for (i,j) in (1900..=2012).rev().enumerate() {
        years.insert(j,i);
        let _ = wksht.write_string(0,i as u16+2,j.to_string().as_str(),hc.clone());
    }
    let _ = wksht.write_string(0,0, "Name",hc.clone());
    let _ = wksht.write_string(0,1, "Gender",hc.clone());
    for (ord,(name,pair)) in common.iter().enumerate() {
        for (gender,map) in pair.iter() {
            for (year,value) in map.iter().rev() {
                let clr;
                if *gender == 'F' {
                    clr = gc.clone();
                    let _ = wksht.write_string(ord as u32+1,0,name,gc.clone());
                    let _ = wksht.write_string(ord as u32+1,1,"F",gc.clone());
                } else {
                    clr = bc.clone();
                    let _ = wksht.write_string(ord as u32+1,0,name,bc.clone());
                    let _ = wksht.write_string(ord as u32+1,1,"M",bc.clone());
                }
                let _ = wksht.write_string(ord as u32+1,years[&*year]as u16+2,value.to_string().as_str(),clr);
            }
        }
    }
    Ok(())
}

[ Panta_ @ 06.04.2020. 07:42 ] @
Citat:
Jedan propust, imena nisam rasporedio po datumima

Zaboravio si i na zajednička imena za devojčice i dečake, tako da recimo imaš Jordan samo za devojčice.
[ Branimir Maksimovic @ 06.04.2020. 16:43 ] @
A ne, ispisujem sva imena, nema nikakve obrade. To je namerno.
[ a1234567 @ 11.04.2020. 17:38 ] @
Stiže zadatak 33.
Kopiram iz knjige, da ne prevodim...

Spell Checker
A spell checker can be a helpful tool for people who struggle to spell words correctly.
In this exercise, you will write a program that reads a file and displays all of the words
in it that are misspelled. Misspelled words will be identified by checking each word
in the file against a list of known words. Any words in the user’s file that do not
appear in the list of known words will be reported as spelling mistakes.

The user will provide the name of the file to check for spelling mistakes as a
command line argument. Your program should display an appropriate error message
if the command line argument is missing. An error message should also be displayed
if your program is unable to open the user’s file. Make solution to this exercise
so that words followed by a comma, period or other punctuation mark are not reported
as spelling mistakes. Ignore the capitalization of the words when checking their spelling.

Hint: While you could load all of the English words from the words data set
into a list, searching a list is slow if you use Python’s in operator. It is much
faster to check if a key is present in a dictionary, or if a value is present in a
set. If you use a dictionary, the words will be the keys. The values can be the
integer 0 (or any other value) because the values will never be used.


[ a1234567 @ 11.04.2020. 17:40 ] @
Ovako nešto sa pokušao:
Code:
import argparse
import re
import string
import sys

wordlist_recnik = {}

# Otvori listu engleskih reči u odnosu na koje će dati tekst biti proveravan.
# Napravi rečnik u kojem je svaka od reči key. Value je 0, jer nikada neće biti korišćeno.

with open('c:/FAJLOVI/Python_School/Stephenson_ThePythonWorkbook/wordlist.txt', "r", encoding='utf-8') as recnik:
    reci = recnik.readlines()
    reci[:] = [line.rstrip('\n') for line in reci]
    for rec in reci:
        wordlist_recnik[rec] = 0

greske = []

# Provera da su dati svi argumenti.
if len(sys.argv) != 2:
    print("Unesi ime fajla za slovnu analizu. Npr. >> 167.py fajl.txt")
    quit()
    
try:
    with open(sys.argv[1], 'r', encoding='utf-8') as tekst:
        text = tekst.read()
except:
    print("Dogodila se greška pri učitavanju fajla.")
    quit()

print(text)

def words(text):
    samo_reci = re.sub(r'[^\w\s]','',text)
    lista = samo_reci.lower().split()
    for word in lista:
        if word not in wordlist_recnik:
            greske.append(word)
    print()
    print('Ovo su reči koje treba popraviti:')
    print(*greske, sep='\n')
    return
words(text)
[ Branimir Maksimovic @ 11.04.2020. 17:46 ] @
Citat:
a1234567:
Stiže zadatak 33.
Kopiram iz knjige, da ne prevodim...

Spell Checker
A spell checker can be a helpful tool for people who struggle to spell words correctly.
In this exercise, you will write a program that reads a file and displays all of the words
in it that are misspelled. Misspelled words will be identified by checking each word
in the file against a list of known words. Any words in the user’s file that do not
appear in the list of known words will be reported as spelling mistakes.

The user will provide the name of the file to check for spelling mistakes as a
command line argument. Your program should display an appropriate error message
if the command line argument is missing. An error message should also be displayed
if your program is unable to open the user’s file. Make solution to this exercise
so that words followed by a comma, period or other punctuation mark are not reported
as spelling mistakes. Ignore the capitalization of the words when checking their spelling.

Hint: While you could load all of the English words from the words data set
into a list, searching a list is slow if you use Python’s in operator. It is much
faster to check if a key is present in a dictionary, or if a value is present in a
set. If you use a dictionary, the words will be the keys. The values can be the
integer 0 (or any other value) because the values will never be used.




Mozda bi bilo bolje da se zada i 33', tj za ulaznu rec naci najblize korektne alternative.
To ako hoces da trazis posao u guglu :P

[ a1234567 @ 11.04.2020. 17:54 ] @
Zvali su me, al sam im rekao da nemam vremena.
Učim python na elite forumu
[ a1234567 @ 12.04.2020. 04:15 ] @
Jedno pitanjce.
Nešto sam eksperimentisao, pa mi nije jasan rezultat.

Code:
x = ['Ovo ', 'je', ' test']

for i in x:
    if i[0] or i[-1] == ' ':
        print(i)

Ovo
je
test


Kako to da se 'je' nalazi u ispisu kad nema razmak!?
[ Panta_ @ 12.04.2020. 05:14 ] @
Zato što ne proverava da li ima razmak, treba:

Code:
if i[0] == ' ' or i[-1] == ' '

ili

if ' ' in i
[ a1234567 @ 12.04.2020. 07:55 ] @
Aha, mora odvojeno. Dobro.
A ja hteo da se ugledam na tebe, pa da sve smlatim ujedno, kad ono neće moći :)))
[ Panta_ @ 12.04.2020. 08:23 ] @
Evo jedan zanimljiv zadatak dok ste u izolaciji.

Na https://github.com/CSSEGISandD...ta/csse_covid_19_daily_reports
imate dnevne izveštaje u CSV formatu sa podacima o korona virus slučajevima (država, potvrđeni, umrli, oporavljeni, itd.).

E sad, treba preuzeti sve te podatke i smestiti ih u fajl npr. corona_data.json:

Code:

{
    "04-12-2020": [
        {
            "FIPS": "",
            "Admin2": "",
            "Province_State": "",
            "Country_Region": "Serbia",
            "Last_Update": "2020-04-11 22:45:13",
            "Lat": "44.0165",
            "Long_": "21.0059",
            "Confirmed": "3380",
            "Deaths": "74",
            "Recovered": "0",
            "Active": "3306",
            "Combined_Key": "Serbia"
        },
        itd...
    ], itd...
}


Dalje, napisati program koji podrazumevano (ako je pokrenut bez argumenata)
ispisuje podatke sortirane po broju potvrđenih slučajeva od najvišeg, na primer:

Code:

Country     Confirmed     Deaths     Recovered

US          526396      20463   31270
itd...
Serbia      3380        74      0


Zatim, ako je npr. unet argument top, program ispisuje 10 država sa najviše
potvrdjenih slučajeva, a pored toga i broj novih slučaja, ili npr. top deaths
sa najviše umrlih:

Code:

Top 10 Deaths:

Country  Deaths  New Deaths

US       20463   2125
Italy    19468   619
itd...

Top 10 Recovered:

Country     Recovered     New Recovered

China         77877         86
Spain         59109         3441
itd...


Dalje, dopuniti program po svom izboru, na primer pored navedenih podataka,
ispisati vreme kada su poslednji put ažurirani ili geografske kordinate,
ukupan broj potvrdjenih, umrlih i oporavljenih, ako je kao argument unet datum,
ispisati samo podatke za isti, itd.

Malo opširniji zadatak, ali eto da se zanimate dok ste u izolaciji.
[ Branimir Maksimovic @ 12.04.2020. 23:35 ] @
Jedino sad ne bih smestao u json, posto je taj format za transfer preko neta, tj serijalizaciju. Nego bolje u bazu, bar po meni.
(import iz csv-a je standardna stvar za baze)
Zgodno je sto je git repo pa moze da se svuce i apdejtuje prostim git komandama :P
[ Panta_ @ 13.04.2020. 05:25 ] @
Citat:
Nego bolje u bazu, bar po meni.

Da, ali onda i korisnik mora da je ima instaliranu. Ovako je u pitanju običan fajl. Python podrazumevano ima podršku za json i csv, kao i urllib.request modul da se preuzmu potrebni podaci (da ne mora Git da se instalira). Mislim da i Rust ima navedeno, ili pak može da se instalira preko Cargo paket menadžera.
Ako mora baza, onda preporuka za Sqlite.
[ Branimir Maksimovic @ 13.04.2020. 05:38 ] @
" ili pak može da se instalira preko Cargo paket menadžera."

Da, mora da se napravi projekt, tj Cargo.toml i da se izlistaju dependency-ji/
Nista strasno, cim nadjem vremena uradicu. Inace vec sam sve svukao u postgres :P
[ Branimir Maksimovic @ 15.04.2020. 15:10 ] @
Heh, lakse je sa git, ovako prvo moras da formiras url tj prvo da povuces preko github apija listu fajlova, parsujes json, pa onda iz liste da vuces fajl parsujes json pa base64 decode
i tek onda dobijas csv content, pa onda parsuj csv content i stavljaj u json :P
Sva sreca da za sve postoje biblioteke :P
[ Branimir Maksimovic @ 15.04.2020. 18:29 ] @
Bad news za korisnike api-ja:


Code:

{"message":"API rate limit exceeded for 109.72.51.23. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)","documentation_url":"https://developer.github.com/v3/#rate-limiting"}


Nije ni pola fajlova skinulo...
[ Panta_ @ 15.04.2020. 21:03 ] @
Ja nisam koristio api, već sam povadio linkove do csv fajlova.

Code:

from urllib.error import URLError
from urllib.request import Request, urlopen
import re

req = Request('https://github.com/CSSEGISandD...ta/csse_covid_19_daily_reports')
    try:
        with urlopen(req) as response:
            html = response.read().decode('utf-8')
    except URLError as e:
        print(e.reason)
        raise

links = re.findall('CSSEGISandData/COVID-19/blob/master/csse_covid_19_data/csse_covid_19_daily_reports.*\.csv(?=\")', html)

[ Branimir Maksimovic @ 15.04.2020. 21:47 ] @
Da, a kako ces da dodjes do csv fajlova? Problem je kada pocnes da skidas...
Inace otparsovao sam csv ostalo je smestanje u json, a tu je naravno i problem struktuiranja
podataka jer nisu svi fajlovi sa istim headerima...
[ Branimir Maksimovic @ 16.04.2020. 04:51 ] @
https://github.com/bmaxa/covid19report

Ovo je za import u json, ostaje prikaz :P

Program ce pokusavati sve dok ne upise i poslednji fajl. Limit je 60 reqs/sat

edit:
bilda se sa `cargo build --release` kada se udje u dir

[ Panta_ @ 16.04.2020. 05:55 ] @
Citat:
Da, a kako ces da dodjes do csv fajlova? Problem je kada pocnes da skidas...

Kreiram url od csv linkova i preuzimam ih na isti gore navedeni način, zatim čitam sa csv reader, itd..
Citat:
tu je naravno i problem struktuiranja podataka jer nisu svi fajlovi sa istim headerima

Da, to sam tek kasnije video da su izmenili. Takođe, treba voditi računa da su za pojedine države (USA, Kina, itd.) dati podaci pojedinačno za svaku državu, odnosno provinciju.
[ Branimir Maksimovic @ 16.04.2020. 06:11 ] @
"Kreiram url od csv linkova i preuzimam ih na isti gore navedeni način, zatim čitam sa csv reader, itd.."

kako kada dobijas html, a ne csv?
[ Panta_ @ 16.04.2020. 06:17 ] @
Citat:
bilda se sa `cargo build --release` kada se udje u dir

Neće:
Code:
error[E0554]: `#![feature]` may not be used on the stable release channel
 --> src/main.rs:1:1
  |
1 | #![feature(try_blocks)]
  | ^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0554`.
error: could not compile `covid19report`.


A, evo i razlog:
Code:
rustc --explain E0554

Feature attributes are only allowed on the nightly release channel. Stable or
beta compilers will not comply.

Example of erroneous code (on a stable compiler):

```
#![feature(non_ascii_idents)] // error: `#![feature]` may not be used on the
                              //        stable release channel
```

If you need the feature, make sure to use a nightly release of the compiler
(but be warned that the feature may be removed or altered in the future).


Probao sam sa rustup install nightly, ali opet ista greška.
[ Panta_ @ 16.04.2020. 06:20 ] @
Citat:
kako kada dobijas html, a ne csv?

https://raw.githubusercontent....9_daily_reports/04-15-2020.csv
[ Branimir Maksimovic @ 16.04.2020. 06:24 ] @
Probaj sada try_blocks ni ne koristim.
[ Branimir Maksimovic @ 16.04.2020. 06:26 ] @
Citat:
Panta_:
Citat:
kako kada dobijas html, a ne csv?

https://raw.githubusercontent....9_daily_reports/04-15-2020.csv


Hehe, dobra fora ;)
Nema veze ja uradio preko api-ja sto je komplikovanije :P

[ Panta_ @ 16.04.2020. 06:45 ] @
Citat:
Probaj sada

Sada se kompajlira, ali zaglavi na onoj poruci i ni da mrdne. ;)
Code:
"message":"API rate limit exceeded for 24.135...
[ Branimir Maksimovic @ 16.04.2020. 06:46 ] @
Pa sacekaj pise ti u koje vreme ce da resetuju brojac :P
Samo nemoj da prekidas program :P
[ Panta_ @ 16.04.2020. 07:01 ] @
Ostavio sam, do večeras će valjda da završi. :)
[ Branimir Maksimovic @ 16.04.2020. 07:03 ] @
U dva navrata zavrsi. Za jedno sat ;)

edit:
pravi ti json u diru gde startujes program.
foo.json
[ Panta_ @ 16.04.2020. 07:31 ] @
Zavrsio. ;)

Code:
"01-22-2020": {
    "Confirmed": [
      "1",
      "14",
      "6",
      "1",
      "",
      "26",
      "2",


Kod mene to izgleda ovako (malo je preglednije):

Code:
    "04-14-2020": [
        {
            "Admin2": "Abbeville",
            "Province_State": "South Carolina",
            "Country_Region": "US",
            "Confirmed": "9",
            "Deaths": "0",
            "Recovered": "0",
            "Active": "9",
            "Last_Update": "2020-04-14 23:33:31"
        },
[ Branimir Maksimovic @ 16.04.2020. 07:37 ] @
Da al ovo moje je lakse za obradu, imas po kolonama. Bar sam zato tako napravio.
[ Panta_ @ 16.04.2020. 08:21 ] @
OK. Evo kako kod mene za sad izgleda ;):
Code:
./covid19.py

 COUNTRY                            CONFIRMED           DEATHS              RECOVERED           ACTIVE

 US                                 636350              28326               52096               555928
 Spain                              177644              18708               70853               88083 
 Italy                              165155              21645               38092               105418
 Germany                            134753              3804                72600               58349 
 France                             134582              17188               31470               85924 
 United Kingdom                     99483               12894               368                 86221 
 China                              83356               3346                78311               1699


./covid19.py -d 04-14-2020

COUNTRY                            CONFIRMED           DEATHS              RECOVERED           ACTIVE

 US                                 607670              25832               47763               534075
 Spain                              172541              18056               67504               86981 
 Italy                              162488              21067               37130               104291
 France                             131361              15748               29098               86515 
 Germany                            131359              3294                68200               59865 
 United Kingdom                     94845               12129               323                 82393 
 China                              83306               3345                78200               1761

./covid19.py --top Confirmed

 Country                      Confirmed           New confirmed           

 US                            636350              30297
 Spain                         177644              5103
 Italy                         165155              2667
 Germany                       134753              3394
 France                        134582              3221
 United Kingdom                99483               4638
 China                         83356               50
 Iran                          76389               1512
 Turkey                        69392               4281
 Belgium                       33573               2454

./covid19.py --country Serbia 

Country              Serbia
Confirmed            4873
Deaths               99
Recovered            0
Active               4774
Last_Update          2020-04-15 22:56:32


Malo me zeza argument parsing, koristim getopt, a bolje da sam sa argparse, ali me sad mrzi da ponovo sve ispravljam, šta je tu je. ;)
[ Branimir Maksimovic @ 17.04.2020. 04:53 ] @
Code:

~/.../rust/covid19report >>> ./target/release/reports                                                                                                                                       ±[●●][master]
COUNTRY             CONFIRMED           DEATHS              RECOVERED           ACTIVE              
Spain               177644              18708               70853               88083               
Italy               165155              21645               38092               105418              
Germany             134753              3804                72600               58349               
France              133470              17167               30955               85348               
US                  118302              8455                0                   109847        

~/.../rust/covid19report >>> ./target/release/reports -d 04-14-2020                                                                                                                         ±[●●][master]


COUNTRY             CONFIRMED           DEATHS              RECOVERED           ACTIVE              
Spain               172541              18056               67504               86981               
Italy               162488              21067               37130               104291              
Germany             131359              3294                68200               59865               
France              130253              15729               28805               85719               
US                  110465              7905                0                   102560         

~/.../rust/covid19report >>> ./target/release/reports --key Confirmed --columns "Confirmed"                                                                                                 ±[●●][master]
Confirmed           
177644              
165155              
134753              
133470              
118302 

~/.../rust/covid19report >>> ./target/release/reports --key Country --key_value Serbia  --columns Country,Confirmed,Deaths,Recovered,Active,Last_update                                     ±[●●][master]
Country             Confirmed           Deaths              Recovered           Active              Last_update         
Serbia              4873                99                  0                   4774                2020-04-15 22:56:32 

~/.../rust/covid19report >>> ./target/release/reports -h                                                                                                                                    ±[●●][master]
Usage: ./target/release/reports [options]

Options:
    -k, --key Column name
                        set sorting key
    -f, --file filename set input file
    -d, --date mm-dd-yyyy
                        set date
    -s, --sort asc or desc
                        set sort
    -c, --columns colname1,colname2,..
                        set columns
    -r, --results number
                        set number of results
        --key_value key value
                        set particular value of key
    -t, --type numeric or string 
                        set type of key column
    -h, --help          print this help menu



To bi bilo to, ako nemas nekih primedbi :p

[ Panta_ @ 17.04.2020. 05:05 ] @
Nisu ti tačni podaci za USA, a u Kini izgleda da nema zaraženih. Kao što sam naveo u jednoj od prethodnih poruka, podaci za USA, Kina i još neke države su dati pojedinačno za države, provincije, kolonije, itd.
[ Branimir Maksimovic @ 17.04.2020. 05:10 ] @
Sumiranje kljuceva nije onako kako su podaci zadati, po provincijama i drzavama u USA. Ja ne prepoznajem kolone mozes da sortiras po bilo cemu, ovo bi zahtevalo
specijalan tretman kolone "drzava" i onda ne bi ovo moglo da se primeni na bilo kom podatku.

edit: al ajde dodacu opciju multi_key i sum_columns gde ce se naznaciti koje kolone da se sabiraju pod kojim kljucem.
[ Branimir Maksimovic @ 17.04.2020. 13:05 ] @
Sredio, dodao multi-key ali nisam sort_columns jer provalim da li ne int ili string.
Evo ga:
Code:

~/.../rust/covid19report >>> ./target/release/reports --results 10
COUNTRY             CONFIRMED           DEATHS              RECOVERED           ACTIVE              
US                  636360              636350              636350              636360              
Spain               355288              196352              248497              265727              
Italy               330310              186800              203247              270573              
Germany             269506              138557              207353              193102              
Iran                152778              81166               126322              98068               
Turkey              138784              70910               75066               131592              
France              134668              134582              134633              134617              
United Kingdom      99486               99483               99484               99485               
China               84347               83362               84340               83357               
Belgium             67146               38013               40680               55599   


kao i uvek git repo je isti https://github.com/bmaxa/covid19report

edit:
sad vidim brojevi nisu ponajbolji, nema veze, sta da se radi

[Ovu poruku je menjao Branimir Maksimovic dana 17.04.2020. u 14:24 GMT+1]
[ Branimir Maksimovic @ 17.04.2020. 13:34 ] @
sada vec bolje izgleda :)
Code:

~/.../rust/covid19report >>> ./target/release/reports --results 10                                                        
COUNTRY             CONFIRMED           DEATHS              RECOVERED           ACTIVE              
US                  636360              28326               52096               555938              
Spain               355288              37416               141706              176166              
Italy               330310              43290               76184               210836              
Germany             269506              7608                145200              116698              
Iran                152778              9554                99866               43358               
Turkey              138784              3036                11348               124400              
France              134668              17188               31521               85959               
United Kingdom      99486               12894               369                 86223               
China               84347               3352                79295               1700                
Belgium             67146               8880                14214               44052               
~/.../rust/covid19report >>>                                                               
[ Branimir Maksimovic @ 17.04.2020. 15:40 ] @
Dodao sam i -u --username i --password opcije za import pa sada moze iz cuga sa github nalogom da izvuce sve bez cekanja od sat vremena:
Code:

~/.../rust/covid19report >>> ./target/release/import_data -h  
Usage: ./target/release/import_data [options]

Options:
    -p, --password password
                        set password
    -u, --username username
                        set username
    -h, --help          this help

[ Panta_ @ 17.04.2020. 15:51 ] @
Ne računa ti to nešto dobro. Dosta su uvećani brojevi. Na primer kod mene:

Code:
COUNTRY                            CONFIRMED           DEATHS              RECOVERED           ACTIVE

 US                                 667801              32916               54703               580182
 Spain                              184948              19315               74797               90836 
 Italy                              168941              22170               40164               106607
 France                             147091              17941               33327               95823 
 Germany                            137698              4052                77000               56646 
 United Kingdom                     104145              13759               375                 90011 
 China                              83403               3346                78401               1656  
 Iran                               77995               4869                52229               20897 
 Turkey                             74193               1643                7089                65461 
 Belgium                            34809               4857                7562                22390 
 Canada                             30809               1258                9698                19853


Možeš da proveriš na https://www.worldometers.info/coronavirus/

Code:
USA     679,762     +2,192     34,705     +88     58,024     587,033     13,369     2,054     105     3,420,322     10,333
Spain     184,948         19,315         74,797     90,836     7,371     3,956     413     930,230     19,896
Italy     168,941         22,170         40,164     106,607     2,936     2,794     367     1,178,403     19,490
France     165,027         17,920         32,812     114,295     6,248     2,528     275     333,807     5,114
Germany     138,369     +671     4,105     +53     81,800     52,464     4,288     1,651     49     1,728,357     20,629
UK     108,692     +5,599     14,576     +847     N/A     93,772     1,559     1,601     215     438,991     6,467
China     82,692     +351     4,632     +1,290     77,944     116     89     57     3         
Iran     79,494     +1,499     4,958     +89     54,064     20,472     3,563     946     59     319,879     3,808
Turkey     74,193         1,643         7,089     65,461     1,854     880     19     518,143     6,144
Belgium     36,138     +1,329     5,163     +306     7,961     23,014     1,140     3,118     445     139,387     12,027
Russia     32,008     +4,070     273     +41     2,590     29,145     8     219     2     1,718,019     11,773
Brazil     30,891     +208     1,952     +5     14,026     14,913     6,634     145     9     62,985     296
Netherlands     30,449     +1,235     3,459     +144     250     26,740     1,279     1,777     202     154,911     9,041
[ Branimir Maksimovic @ 17.04.2020. 16:01 ] @
Duplo sam sabirao, evo ga sad, (pushovao popravku)
Code:

~/.../rust/covid19report >>> ./target/release/reports --results 10                                                                                                                          ±[●●][master]
COUNTRY             CONFIRMED           DEATHS              RECOVERED           ACTIVE              
US                  667801              32916               54703               580182              
Spain               184948              19315               74797               90836               
Italy               168941              22170               40164               106607              
France              147091              17941               33327               95823               
Germany             137698              4052                77000               56646               
United Kingdom      104145              13759               375                 90011               
China               83403               3346                78401               1656                
Iran                77995               4869                52229               20897               
Turkey              74193               1643                7089                65461               
Belgium             34809               4857                7562                22390               

[ Branimir Maksimovic @ 17.04.2020. 17:17 ] @
Nego razmisljam koji feature da dodam, i prvo mi padne na pamet razlika po datumima, znaci od prethodnog dana za navedena polja ;)
To umesto onog sum_columns sad ide diff_columns ;)

[ Panta_ @ 17.04.2020. 18:19 ] @
Ja sam dodao ukupan broj slučajeva što sam bio zaboravio, kao i "checking for updates, please wait" poruku.

Code:
python covid19.py --sum

 Confirmed           2152647
 Deaths              143801
 Recovered           542107
 Active              1466739
[ mjanjic @ 17.04.2020. 23:54 ] @
Ovo je za pohvalu, ali po meni ovi csv fajlovi imaju smisla ako je potrebno analizirati broj zaraženih po određenim datumima u pojedinim državama. Ili da se bar keširaju, tj. sačuvaju lokalno stariji CSV fajlovi pa da se samo proveri datum zadnje izmene (u principu, za to može da se koristi lokalni git koji bi povukao sve izmene, a python koristio fajlove iz lokalnog repozitorijuma.
Mada i u tom slučaju mogu samo da se dodaju novi podaci, da se ne otvara ponovo blizu 100 fajlova, naravno ako već ranije obrađeni fajlovi nisu menjani.


Zbirni podaci po datumima (ukupan broj zaraženih do tog datuma) su dati svi u jednoj tabeli ovde: https://github.com/CSSEGISandD...data/csse_covid_19_time_series
pa je možda lakše sve pročitati iz jednog fajla ako su potrebni samo zbirni podaci do određenog datuma, a može se lako izračunati i broj novozaraženih po datumima na osnovu razlike vrednosti u dve kolone.
[ Branimir Maksimovic @ 18.04.2020. 00:04 ] @
Nece vise to da apdejtuju, ovi dejliji su aktuelni. E sad jedino ako se koristi git mozes dobiti apdejtovane fajlove.
Inace ovo je vise za vezbanje jer sam ja sa git-om i csvkitom importovao u postgres za 5 minuta ;)
A kad je u bazi imas sql pa mozes da izvlacis kakve hoces podatke ::
Inace ovo mi je vezba da ne zardjam sa Rust-om jer radim samo C++ ;)
[ Branimir Maksimovic @ 18.04.2020. 08:33 ] @
Evo dodao diff:
Code:

~/.../rust/covid19report >>> ./target/release/reports --results 10 --key deaths --diff 04-16-2020
from 04-16-2020
COUNTRY             diff                CONFIRMED           diff                DEATHS              diff                RECOVERED           diff                ACTIVE              diff                
US                  US                  699706              31905               36773               3857                58545               3842                604388              24206               
Italy               Italy               172434              3493                22745               575                 42727               2563                106962              355                 
Spain               Spain               190839              5891                20002               687                 74797               0                   96040               5204                
France              France              149130              2039                18703               762                 35006               1679                95421               -402                
United Kingdom      United Kingdom      109769              5624                14607               848                 394                 19                  94768               4757                
Belgium             Belgium             36138               1329                5163                306                 7961                399                 23014               624                 
Iran                Iran                79494               1499                4958                89                  54064               1835                20472               -425                
China               China               83760               357                 4636                1290                77552               -849                1572                -84                 
Germany             Germany             141397              3699                4352                300                 83114               6114                53931               -2715               
Netherlands         Netherlands         30619               1236                3471                144                 315                 4                   26833               1088                


Ponosan sam na ovaj feature :P

[ Panta_ @ 18.04.2020. 10:32 ] @
Imam već taj feature ;)

Code:
python covid19.py -t Deaths

 Country                      Deaths              New Deaths              

 US                            36773               3921
 Italy                         22745               575
 Spain                         20002               687
 France                        18703               762
 United Kingdom                14607               848
 Belgium                       5163                306
 Iran                          4958                89
 China                         4636                1290
 Germany                       4352                300
 Netherlands                   3471                144

python covid19.py -t Confirmed

 Country                      Confirmed           New Confirmed           

 US                            699706              32883
 Spain                         190839              5891
 Italy                         172434              3493
 France                        149130              2039
 Germany                       141397              3699
 United Kingdom                109769              5624
 China                         83760               357
 Iran                          79494               1499
 Turkey                        78546               4353
 Belgium                       36138               1329


Takođe sam dodao i procenat smrtnosti:

Code:
python covid19.py             

 COUNTRY                            CONFIRMED           DEATHS              MORTALITY RATE %    RECOVERED           ACTIVE

 US                                 699706              36773               5.3                 58545               604388
 Spain                              190839              20002               10.5                74797               96040 
 Italy                              172434              22745               13.2                42727               106962
 France                             149130              18703               12.5                35006               95421 
 Germany                            141397              4352                3.1                 83114               53931 
 United Kingdom                     109769              14607               13.3                394                 94768 
 China                              83760               4636                5.5                 77552               1572  
 Iran                               79494               4958                6.2                 54064               20472 
 Turkey                             78546               1769                2.3                 8631                68146 
 Belgium                            36138               5163                14.3                7961                23014 
 Brazil                             33682               2141                6.4                 14026               17515 
 Canada                             32814               1355                4.1                 10545               20914 

[ Branimir Maksimovic @ 18.04.2020. 10:59 ] @
A da li moze diff dva proizvoljna datuma?
recimo:
Code:

~/.../rust/covid19report >>> ./target/release/reports --results 10 --key deaths --diff 03-10-2020 --date 03-11-2020   
from 03-10-2020
COUNTRY             diff                CONFIRMED           diff                DEATHS              diff                RECOVERED           diff                ACTIVE              diff                
China               ---                 80921               ---                 3161                ---                 61644               ---                 
Italy               ---                 12462               2313                827                 196                 1045                321                 
Iran                ---                 9000                ---                 354                 ---                 2959                ---                 
Korea, South        ---                 7755                ---                 60                  ---                 288                 ---                 
Spain               ---                 2277                582                 54                  19                  183                 151                 
France              ---                 2284                500                 48                  15                  12                  0                   
US                  ---                 1281                322                 36                  8                   8                   0                   
Japan               ---                 639                 58                  15                  5                   118                 17                  
United Kingdom      ---                 459                 ---                 8                   ---                 19                  ---                 
Cruise Ship         ---                 696                 ---                 7                   ---                 325                 ---            
[ Panta_ @ 18.04.2020. 11:40 ] @
Ne, za sada samo poslednji i pretposlednji da izračuna nove slučajeve.
[ Branimir Maksimovic @ 18.04.2020. 11:44 ] @
U medjuvremenu sam dodao procente:

Code:

~/.../rust/covid19report >>> ./target/release/reports --results 10 --key deaths --diff 03-03-2020 --date 03-04-2020     
from 03-03-2020
COUNTRY             diff                CONFIRMED           diff                DEATHS              diff                RECOVERED           diff                ACTIVE              diff                
Mainland China      ---                 80271                 120  0.15%        2981                   36  1.21%        49955                2551  5.11%        
Italy               ---                 3089                  587 19.00%        107                    28 26.17%        276                   116 42.03%        
Iran                ---                 2922                  586 20.05%        92                     15 16.30%        552                   261 47.28%        
South Korea         ---                 5621                  435  7.74%        35                      7 20.00%        41                     11 26.83%        
US                  ---                 153                    31 20.26%        11                      4 36.36%        8                       0  0.00%        
Japan               ---                 331                    38 11.48%        6                       0  0.00%        43                      0  0.00%        
Others              ---                 706                     0  0.00%        6                       0  0.00%        10                      0  0.00%        
France              ---                 285                    81 28.42%        4                       0  0.00%        12                      0  0.00%        
Australia           ---                 52                     13 25.00%        2                       1 50.00%        11                      0  0.00%        
Hong Kong           ---                 105                     5  4.76%        2                       0  0.00%        37                      0  0.00%        
[ mjanjic @ 18.04.2020. 17:07 ] @
Citat:
Panta_:
Ne, za sada samo poslednji i pretposlednji da izračuna nove slučajeve.

Pa samo umesto indeksa -1 i -2 stave se indeksi od odgovarajućih datuma. Ali, kao što reče neko ranije, lakše je ako je sve u bazi.

Takođe, zavisi da li češće trebaju brojevi po datumima ili ukupni do određenog datuma, pa tako treba i formirati kolone, odnosno u slučaju baze podatke u vrstama.
[ Branimir Maksimovic @ 18.04.2020. 18:04 ] @
Pa evo ti:
Code:

~/.../rust/covid19report >>> ./target/release/reports --results 10 --key Recovered --diff 03-29-2020 --date 04-12-2020
from 03-29-2020
COUNTRY             diff                CONFIRMED           diff                DEATHS              diff                RECOVERED           diff                ACTIVE              diff                
China               ---                 83134                1012  1.22%        3343                   39  1.17%        77956                2380  3.05%        1835                -1407 -76.68%       
Spain               ---                 166831              86721 51.98%        17209               10406 60.47%        62391               47682 76.42%        87231               28633 32.82%        
Germany             ---                 127854              65759 51.43%        3022                 2489 82.36%        60300               51089 84.72%        64532               12181 18.88%        
Iran                ---                 71686               33377 46.56%        4474                 1834 40.99%        43894               31503 71.77%        23318                  40  0.17%        
Italy               ---                 156363              58674 37.52%        19899                9120 45.83%        34211               21181 61.91%        102253              28373 27.75%        
US                  ---                 555313              414404 74.63%       22019               19552 88.80%        32988               30323 91.92%        500306              500306 100.00%      
France              ---                 133670              92962 69.55%        14412               11801 81.88%        27469               20243 73.69%        91789               60918 66.37%        
Switzerland         ---                 25415               10586 41.65%        1106                  806 72.88%        12700               11105 87.44%        11609               -1325 -11.41%       
Korea, South        ---                 10512                 929  8.84%        214                    62 28.97%        7368                 2335 31.69%        2930                -1468 -50.10%       
Canada              ---                 24299               18019 74.16%        713                   649 91.02%        7123                 6657 93.46%        16463               16463 100.00%     
[ mjanjic @ 18.04.2020. 20:18 ] @
mislio sam na Python verziju
[ Panta_ @ 18.04.2020. 21:24 ] @
Citat:
Pa samo umesto indeksa -1 i -2 stave se indeksi od odgovarajućih datuma

Pa, nije baš samo, al ajde. ;)
Code:
python covid19.py -D 04-12-2020 03-29-2020

COUNTRY                            CONFIRMED           DIFF                DEATHS              DIFF                RECOVERED           DIFF                

 US                                 554797              414204              21974               19566               32988               30323
 Canada                             24299               18032               713                 650                 7123                6657
 United Kingdom                     85201               65421               10629               9399                625                 474
 China                              83134               4542                3343                156                 77956               5421
 Netherlands                        25743               14813               2747                1976                295                 292
 Australia                          6315                2331                60                  44                  1806                1566
 Denmark                            6369                3805                273                 201                 2291                2218
 France                             133669              92961               14412               11801               27469               20243
[ mjanjic @ 18.04.2020. 21:45 ] @
Da, treba sabrati sve datume između, ako su podaci dati pojedinjačno za datume, prebacio sam se na varijantu koju sam predložio, da kolone po datumima predstavljaju broj ukupno zaraženih do tog datuma.

Ako su potrebni grafikoni za broj novorazaženih i druge slične podatke po pojedinačnim datumima, onda mogu ovi podaci, a ako je potreban grafik za broj ukupno zaraženih na svaki datum, onda je bolje imati drugi fajl sa takvim podacima.

Samo jedna stvar mi nije jasna, da li iko negde predstavlja i broj trenutno zaraženih, koji se dobija oduzimanjem broja onih koji više nemaju virus od broja ukupno zaraženih od početka praćenja podataka?


I da staviš negde na Github, da mogu da te citiraju :)
[ Panta_ @ 18.04.2020. 22:16 ] @
Citat:
Samo jedna stvar mi nije jasna, da li iko negde predstavlja i broj trenutno zaraženih, koji se dobija oduzimanjem broja onih koji više nemaju virus od broja ukupno zaraženih od početka praćenja podataka?

Da ima, aktivni slučajevi na koje sam zaboravio.

Code:
covid19.py -D 04-12-2020 03-29-2020

COUNTRY                            CONFIRMED           DIFF                DEATHS              DIFF                RECOVERED           DIFF                ACTIVE              DIFF

 US                                 554797              414204              21974               19566               32988               30323               499835              499835
 Canada                             24299               18032               713                 650                 7123                6657                16463               16463
 United Kingdom                     85201               65421               10629               9399                625                 474                 73947               55549
 China                              83134               4542                3343                156                 77956               5421                1835                -1376
 Netherlands                        25743               14813               2747                1976                295                 292                 22701               12801
 Australia                          6315                2331                60                  44                  1806                1566                4449                725
 Denmark                            6369                3805                273                 201                 2291                2218                3805                1386
 France                             133669              92961               14412               11801               27469               20243               91788               60917
[ Branimir Maksimovic @ 19.04.2020. 02:33 ] @
Nisu uneti svi podaci uvek pa ispada da us ima takvu promenu.

edit:
po kojoj koloni sortiras kada radis diff?

Ja recimo imam moguce nasetovati sorting key i koje kolone da prikaze:
Code:

~/.../rust/covid19report >>> ./target/release/reports --results 10 --key Confirmed  --diff 04-15-2020 --date 04-16-2020 --columns Active
from 04-15-2020
Active              diff                Confirmed           diff                Country             diff                
580182              24253  4.18%        667801              31451  4.71%        US                  ---                 
90836                2753  3.03%        184948               7304  3.95%        Spain               ---                 
106607               1189  1.12%        168941               3786  2.24%        Italy               ---                 
95823                9899 10.33%        147091              12509  8.50%        France              ---                 
56646               -1703 -3.01%        137698               2945  2.14%        Germany             ---                 
90011                3790  4.21%        104145               4662  4.48%        United Kingdom      ---                 
1656                  -43 -2.60%        83403                  47  0.06%        China               ---                 
20897                -782 -3.74%        77995                1606  2.06%        Iran                ---                 
65461                3261  4.98%        74193                4801  6.47%        Turkey              ---                 
22390                 364  1.63%        34809                1236  3.55%        Belgium             ---          

Kolone key i foreign_key automatski dodajem ako nije stavljeno.
foreign_key je uvek Country zato sto mislim da nema za sada smisla to unositi.


[Ovu poruku je menjao Branimir Maksimovic dana 19.04.2020. u 04:41 GMT+1]

[Ovu poruku je menjao Branimir Maksimovic dana 19.04.2020. u 04:43 GMT+1]
[ Panta_ @ 19.04.2020. 06:32 ] @
Sortiram po Confirmed, mada mogu lako da dodam sort_key kao parametar.

Code:
COUNTRY                            CONFIRMED           DIFF                DEATHS              DIFF                RECOVERED           DIFF                Active              DIFF

 US                                 554797              414204              21974               19566               32988               30323               499835              499835
 Spain                              166831              86721               17209               10406               62391               47682               87231               28633
 Italy                              156363              58674               19899               9120                34211               21181               102253              28373
 France                             133669              92961               14412               11801               27469               20243               91788               60917
 Germany                            127854              65759               3022                2489                60300               51089               64532               12181
 United Kingdom                     85201               65421               10629               9399                625                 474                 73947               55549
 China                              83134               4542                3343                156                 77956               5421                1835                -1376


Sortirano po Deaths:

Code:
COUNTRY                            CONFIRMED           DIFF                DEATHS              DIFF                RECOVERED           DIFF                Active              DIFF

 US                                 554797              414204              21974               19566               32988               30323               499835              499835
 Italy                              156363              58674               19899               9120                34211               21181               102253              28373
 Spain                              166831              86721               17209               10406               62391               47682               87231               28633
 France                             133669              92961               14412               11801               27469               20243               91788               60917
 United Kingdom                     85201               65421               10629               9399                625                 474                 73947               55549
 Iran                               71686               33377               4474                1834                43894               31503               23318               40
 Belgium                            29647               18811               3600                3169                6463                5104                19584               10538
 China                              83134               4542                3343                156                 77956               5421                1835                -1376
[ Branimir Maksimovic @ 19.04.2020. 06:38 ] @
Ja sam u medjuvremenu dodao, --no_multi_key zbog toga sto postoji kolona Combined_Key.

recimo zbog ovoga:
Code:

~/.../rust/covid19report >>> ./target/release/reports --results 10 --key Confirmed --columns Active,Combined_Key
Active              Combined_Key        Confirmed           Country             
628693              Abbeville, South Carolina, US732197              US                  
96886               Spain               191726              Spain               
107771              Italy               175925              Italy               
93217               French Guiana, France149149              France              
53483               Germany             143342              Germany             
99402               Anguilla, United Kingdom115314              United Kingdom      
1537                Anhui, China        83787               China               
69986               Turkey              82329               Turkey              
19850               Iran                80868               Iran                
23382               Belgium             37183               Belgium             


pa sad:
Code:

~/.../rust/covid19report >>> ./target/release/reports --results 10 --key Confirmed --columns Active,Combined_Key --no_multi_key
Active              Combined_Key        Confirmed           Country             
96886               Spain               191726              Spain               
107771              Italy               175925              Italy               
92663               France              147969              France              
53483               Germany             143342              Germany             
122370              New York City, New York, US135572              US                  
98753               United Kingdom      114217              United Kingdom      
69986               Turkey              82329               Turkey              
19850               Iran                80868               Iran                
122                 Hubei, China        68128               China               
23382               Belgium             37183               Belgium             

[ Branimir Maksimovic @ 19.04.2020. 06:48 ] @
A tu je i convenient opcija -l da se izlistaju postojece kolone za odredjen datum posto postoji opcija --columns
Code:

~/.../rust/covid19report >>> ./target/release/reports -l --date 02-04-2020   
Confirmed
Country/Region
Deaths
Last Update
Province/State
Recovered
~/.../rust/covid19report >>> ./target/release/reports -l    
Active
Admin2
Combined_Key
Confirmed
Country_Region
Deaths
FIPS
Last_Update
Lat
Long_
Province_State
Recovered
~/.../rust/covid19report >>>          
[ a1234567 @ 22.04.2020. 18:07 ] @
Zadatak 34:

Napisati funkciju koja će u datom engleskom tekstu izračunati zbir brojeva.
Računaju se samo posebni brojevi. Ako je broj deo reči, ne ulazi u zbir.

Mustre za text i očekivani zbir:

('hi') == 0
('who is 1st here') == 0
('my numbers is 2') == 2
('This picture is an oil on canvas '
'painting by Danish artist Anna '
'Petersen between 1845 and 1910 year') == 3755
('5 plus 6 is') == 11
('') == 0

Ja sam napravio ovakvo rešenje:

Code:
def sum_numbers(text: str) -> int:
    zbir = 0
    a = text.split()
    a = ['' if x == '1st' else x for x in a]
    for i in a:
        if i.isdigit():
            zbir += int(i)
    return zbir

print("Example:")
    print(sum_numbers(('This picture is an oil on canvas '
                       'painting by Danish artist Anna '
                       'Petersen between 1845 and 1910 year')))


[Ovu poruku je menjao a1234567 dana 22.04.2020. u 19:24 GMT+1]
[ djoka_l @ 22.04.2020. 21:21 ] @
Ne valja. Ne treba da radi samo za zadate primere nego i za druge slučajeve.
Probaj:
2nd
2020-04-22

Pa ćeš videti da ne radi kako treba.
[ djoka_l @ 22.04.2020. 22:20 ] @
Ne znam šta je cilj, da se nauče regularni izrazi ili nešto drugo.
Tvoj program ne prepoznaje int ako ima predznak + ili -
Code:

def MySum( InStr ):
  sum=0
  for i in InStr.split():
    try:
      sum += int(i)
    except:
      None
  return sum

print(MySum('1 2 3 abc 45 -11 +12a +1'))
[ a1234567 @ 23.04.2020. 05:20 ] @
Nije u zadatku tj. u tekstu predviđeno da bude brojeva sa + i -.

Nego, probao sam nešto sa pozitivnim/negativnim brojevima u listi
i sabiranjem onih sa parnim indeksom,
pa mi nije jasno zašto petlja preskače jedan index. Na primer:

lista = [-37, -36, -19, -99, 29, 20, 3, -7, -64, 84, 36, 62, 26, -76, 55, -24, 84, 49, -65, 41]

Code:
for i in lista:
     if lista.index(i) % 2 == 0:
             print(lista.index(i), i)


i dobijem ovaj ispis, sa preskočenim indeksom [16]:

0 -37
2 -19
4 29
6 3
8 -64
10 36
12 26
14 55
18 -65


Hteo sam sve te brojeve da gurnem u nova_lista i uradim sum(nova_lista)
ali stalno sam dobijao pogrešan rezultat. Nije mi bilo jasno zašto, sve dok nisam napravio ispis.
[ Branimir Maksimovic @ 23.04.2020. 05:37 ] @
To je zato sto index f-ja vraca prvi index elementa u nizu, a taj broj se vec nalazi na prethodnoj pozijiciji.
Da li postoji nacin da for vraca i index i broj kao sto recimo u Rustu to radis sa funkcijom enumerate?
[ Panta_ @ 23.04.2020. 06:16 ] @
Citat:
Da li postoji nacin da for vraca i index i broj kao sto recimo u Rustu to radis sa funkcijom enumerate

Da, sa enumerate funkcijom. ;) for i, v in enumerate(lista):...itd
[ a1234567 @ 23.04.2020. 06:34 ] @
Ovo je za mene vrlo čudno.
Očekivao sam da funkcija ide element po element i vraća index jedan za drugim.
Kakve veze ima što je isti element već bio u listi!?

[ djoka_l @ 23.04.2020. 10:32 ] @
Citat:
index() is an inbuilt function in Python, which searches for given element from start of the list and returns the lowest index where the element appears.

Dakle, index vraća poziciju PRVE pojave vrednosti u listi.

Ti u for petlji zaista dobijaš sve elemente liste, ali sa index dobijaš gde se element pojavio prvi put.

Da si napisao

for i in range(len(lista)):

dobio bi ono što si želeo, a to je indeks tekućeg elemnta u listi.

To je problem sa svakim programskim jezikom, obično dobiješ tačno ono što si napisao, a malo ređe ono što si želeo...
[ a1234567 @ 23.04.2020. 11:50 ] @
Jel tebi to logično?
Da petlja ide element po element redom, ali index ide samo do prvog pojavljivanja.
Očekivao bih da daje element i njegov index.

Da li se zna zašto je uzeto takvo rešenje?
[ djoka_l @ 23.04.2020. 12:51 ] @
Jedno je šta ti očekuješ, drugo je šta je NAPISANO u dokumentaciji.

Ono što je meni nelogično je što uopšte for petlja ide REDOM kroz listu.

U awk jeziku, recimo, foreach konstrukcija ide slučajnim redosledom kroz listu. Vraća sve elemente, ali ne onim redom kojim su uneti.
U SQL jeziku SELECT vraća redove u slučajnom rasporedu.

Ovo slučajno, treba čitati, onako kako je najbrže.
Generalno, hash tabele (a tako je implementirana lista u pythonu) elemente raspoređuju tako što je indeks elementa dobijen nekakvom transformacijum ključa.
Recimo da je indeks integer podatka dobijen tako što se radi mod 7 nad vrednošću.

Tako, kada upisuješ niz 1, 3, 5, 7, 8 tada su ti hash vreendosti 1, 3, 5, 0, 1
Ako bi hash tabelu čitao po redosledu ključeva, dobio bi niz 7, 1, 8, 3, 5
[ Branimir Maksimovic @ 23.04.2020. 13:12 ] @
Citat:
a1234567:
Ovo je za mene vrlo čudno.
Očekivao sam da funkcija ide element po element i vraća index jedan za drugim.
Kakve veze ima što je isti element već bio u listi!?



To je zato sto funkcija ide redom kroz niz i vraca indeks prvog lelemnta cija se vrednost poklapa
sa parametrom.
[ Branimir Maksimovic @ 23.04.2020. 13:25 ] @
Citat:
djoka_l:

Ono što je meni nelogično je što uopšte for petlja ide REDOM kroz listu.



Isti je i u Haskell-u, samo sto je u Haskellu u pitanju prava lista,
pa se indeks operacija retko koristi zato sto je O(n).
E sad da li se ovde uopste radi o listi ili je to zapravo niz,
kao u Rustu?
[ a1234567 @ 23.04.2020. 15:56 ] @
Citat:
Branimir Maksimovic:
Citat:
a1234567:
Ovo je za mene vrlo čudno.
Očekivao sam da funkcija ide element po element i vraća index jedan za drugim.
Kakve veze ima što je isti element već bio u listi!?



To je zato sto funkcija ide redom kroz niz i vraca indeks prvog lelemnta cija se vrednost poklapa
sa parametrom.


Onda su ga mogli nazvati i findex (od first index) :))
[ Branimir Maksimovic @ 23.04.2020. 16:18 ] @
Pa ajde razmisli kako bi ti implementirao. Ulazni parametri su niz i vrednost elementa.
[ djoka_l @ 23.04.2020. 16:40 ] @
Nikako da ti zašrafimo glavu na pravo mesto?

Šta misliš da treba da vrati komanda:

'alabama'.index('a')

Code:

py
Python 3.7.4 (tags/v3.7.4:e09359112e, Jul  8 2019, 20:34:20) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> 'alabama'.index('a')
0
>>>


Ti bi da ti index jednom vrati 0, pa 2, pa 4, pa 6.
A, ono, uvek vrati 0!
[ a1234567 @ 23.04.2020. 16:45 ] @
Da su me pitali, ja ne bih to komplikovao.
Koji je element, njegov i index i da te bog vidi:


Code:
lista = [37, 36, 19, 99, 36]

for i in lista:
    print(lista.index(i), i)

0 37
1 36
2 19
3 99
4 36


Zato sam pitao koja je logika postojećeg rešenja.
Koja je situacija kad je bolje da imaš indeks prvog istog elementa u nizu, a ne tekućeg?
Meni je to kontraintuitivno, ali bože moj, nije smak sveta. Guido tako rešio, nek mu je alal :)
[ Branimir Maksimovic @ 23.04.2020. 16:52 ] @
"a ne tekućeg?"

Takvog parametra nema. Imas samo vrednost i niz. f-ja index ni ne zna da se for vrti...
[ a1234567 @ 24.04.2020. 01:49 ] @
Vidim da nema i to mi je čudno.
A bilo bi i korisno da ima :)
[ a1234567 @ 24.04.2020. 05:31 ] @
Zanimljiv zadatak za početnike

Dat je string:
Code:
rečenica sa viškom       razmaka

koju treba ispisati inverzno, ali da svaka reč (kao i razmak) ostane na svom mestu.
Code:
acinečer as mokšiv       akamzar
[ X Files @ 24.04.2020. 09:03 ] @
Code:

s="recenica sa viskom       razmaka"
#s="  recenica sa viskom       razmaka"
#s="  "
#s=""
#s="r e c e n i ca"
#s="recenica"

i=0
s2=""
while ( i<len(s) ):
    if ( s[i] != " "):
        index = i
        length = 0
        while (i<len(s) and s[i] != " "):
            length+=1
            i+=1
        i-=1
        for j in range(length):
            s2+=s[index+length-1-j]
    else:
        s2+=" "
    i+=1
print(s)
print(s2)

Pazi, ja ne znam Python, sem baš elementarnog. Ovo je neko rešenje, ne baš skroz elegantno, da se još optimizovati.

Ako je ovi školski zadatak, onda treba videti šta je profesor zapravo želeo da vidi u rešenju (ugrađene funkcije, posebne funkcije, sintaksni slice, ...)
[ a1234567 @ 24.04.2020. 09:32 ] @
Pozdrav, Vladimire, supermoderatoru,
doborodošao na temu :)

Nije to zadatak za profesora, već sam ja pod stare dane rešio da sam sebe nešto naučim o programiranju, od kojeg pre dva meseca nisam znao ni "p".
A evo pomaže mi i nekoliko "profesora" ovde, dovoljno ljubaznih da priskoče u pomoć kad mi zapne. A zapne često :)

Dakle, kad nađem neki meni zanimljiv zadatak, ja ga ovde okačim.
Ovaj sam našao na https://checkio.org/, gde sam krenuo da rešavam gomilu zadataka od početka. Pa dokle stignem.

Moje rešenje za ovaj zadatak je (tamo traže da bude u formi funkcije):

Code:
import re

def string_unazad(text: str) -> str:
    reci = re.split(r'(\s+)', text)
    nove_reci = [rec[::-1] for rec in reci]
    nova_recenica = "".join(nove_reci)
    return nova_recenica

if __name__ == '__main__':
    print("Primer:")
    print(string_unazad('recenica sa viskom       razmaka')) 
[ Branimir Maksimovic @ 24.04.2020. 09:48 ] @
Evo i Rusta ;)
Code:

fn main() {
    let s = "rečenica sa viškom       razmaka";
    println!("{}",rev_words(s));
}

fn rev_words(words:&str)->String {
    words.to_string().split(' ').fold("".to_string(),|v,x| v +
                   &x.to_string().chars().rev().collect::<String>()+" ")
}

[ B3R1 @ 24.04.2020. 10:49 ] @
Citat:
a1234567:
Zadatak 34:
Napisati funkciju koja će u datom engleskom tekstu izračunati zbir brojeva.
Računaju se samo posebni brojevi. Ako je broj deo reči, ne ulazi u zbir.
'Petersen between 1845 and 1910 year') == 3755
'2020-02-20' == 2062

Ima vise resenja, koja se svode na isto: sve sto nije cifra zameniti razmkom, pa onda udariti split() i sabrati. Osnovacko reesnje:
Code (python):

def sum_numbers(text):
    sum = 0
    newtext = ''
    text = text.lower()
    text = text.replace('1st', ' ')
    text = text.replace('2nd', ' ')
    text = text.replace('3rd', ' ')
    for ch in text:
        newtext += ch if ch.isdigit() else ' '
    for n in newtext.split():
        sum += int(n)
    return sum
 


Resenje sa regularnim izrazima:
Code (python):

import re

def sum_numbers(text):
    sum = 0
    for n in re.sub('\D', ' ', re.sub('1st|2nd|3rd', ' ', text.lower())).split():
        sum += int(n)
    return sum
 


ili, da bude jasnije:

Code (python):

import re

def sum_numbers(text):
    sum = 0
    text = re.sub('1st|2nd|3rd', ' ', text.lower())  # Zameni 1st, 2nd i 3rd razmaknicom
    text = re.sub('\D', ' ', text)                         # Zameni sve non-digit znakove razmaknicom
    for n in text.split():
        sum += int(n)
    return sum
 


U ovom gornjem reesnju smo najpre zamenili stringove '1st', '2nd' i '3rd' razmakom. Slucaj radi i za '1ST', '2nD' i tome slicno, za sta se pobrinuo lower(). Potom u takvom stringu zamenimo sve znake koji nisu cifre (regexp '\D'). Ostatak je identican - split() to pretvori u niz kontinualnih karaktera (npr. ' 4 55 6666 ' daje ['4', '55', '6666']), sto onda saberemo.

Ako treba uzeti u obzir i znake + i -, tada je prica malcice slozenija, ali ne preterano. Najpre treba razdvojiti + i - znake koji stoje uz cifre i one koji ne stoje uz cifre. Npr. '-G' i '+A' s uobicni stringovi, dok su '-3' i '+123' brojevi. Najlakse je primeniti:
text = text.replace('-', ' -0').replace('+', ' +0')

Primer:
Code (python):

>>> text='44, is - -G 2002-02+02'
>>> text = text.replace('-', ' -0').replace('+', ' +0')
>>> text
'44, is  -0  -0G 2002 -002 +002'
 

Potom zamenimo sve sto nije cifra, + ili -:
Code (python):

>>> re.sub('[^\d+-]', ' ', text)
'44      -0  -0  2002 -002 +002'
 

Nadalje je lako, split() ce ovo gore da pretvori u niz, a int(-0) i int(+0) je uvek 0.
[ a1234567 @ 24.04.2020. 11:46 ] @
Al si ga izanalizorao, svaka čast!
Mnogo mi pomaže ovo, da vidim logiku različitih rešenja.
Hvala!
[ Panta_ @ 24.04.2020. 19:09 ] @
Code:
' '.join(word[::-1] for word in 'rečenica sa viškom       razmaka'.split(' ')) 

'acinečer as mokšiv       akamzar'
[ a1234567 @ 25.04.2020. 02:05 ] @
Panta zvani one-liner.
Nisam ništa duže ni očekivao

Lep dan vam svima želim!
[ Branimir Maksimovic @ 25.04.2020. 07:50 ] @
Evo gai Haskell:
Code:

rev words = concat $ splitSpace words
splitSpace words = splitSpace' words [] []
    where
    splitSpace' (' ':words) cumul list = cumul:[' ']: splitSpace' words [] list
    splitSpace' (c:words) cumul list = splitSpace' words (c:cumul) list
    splitSpace' [] cumul  list = cumul:list
main = do
    putStrLn $ rev "rečenica sa viškom       razmaka"

Ovo je nesto komplikovanije jer moraju da se sacuvaju razmaci inace
bi bilo samo ovo:
Code:

rev wrds = unwords $ map reverse $ words wrds
main = do
    putStrLn $ rev "rečenica sa viškom       razmaka"

[ a1234567 @ 30.04.2020. 17:01 ] @
Zadatak 35: Encryption Algorithm

Make a function that encrypts a given input with these steps:

Input: "apple"

Step 1: Reverse the input: "elppa"

Step 2: Replace all vowels using the following chart:

a => 0
e => 1
o => 2
u => 3

# "1lpp0"

Step 3: Add "aca" to the end of the word: "1lpp0aca"

Output: "1lpp0aca"

--------------------
Ja sam napravio nešto ovako
Code:
vokali = {'a': 0, 'e': 1, 'o': 2, 'i': 3, 'u': 4}
novo = ''


def encr(rec):
    obrnuto = rec[::-1]
    for i in obrnuto:
        if i in vokali:
            novo += obrnuto.replace(i, str(vokali[i]))
        novo += i
    novo += 'aca'

    return novo


encr('jabuka')


ali mi prijavljuje grešku:
UnboundLocalError: local variable 'novo' referenced before assignment
Nije mi jasno šta treba da popravim.
[ djoka_l @ 30.04.2020. 21:28 ] @
Fantastičan primer kako ne treba programirati.
Varijable vokali i novo su globalne, deklarisane su van tela funkcije. Koja je njihova svrha, ako se koriste samo u funkciji?

Možda si preskočio deo koji priča o "vidljivosti" (scope) varijabli. novo je globalna varijhabla. U telu funkcije koje se nalazi ispod deklaracije varijable, njena vrednost može da se pročita, ispiše, svašta može sa njom.

Jedena stvar ne može. NE MOŽE JOJ SE DODELITI VREDNOST.
Ako pokušaš da joj dodeliš vrednost (ako je staviš sa leve strane znaka =), u tom momentu napravi se LOKALNA varijabla sa istim imenom.

Dakle, u funkciji si pogao da napišeš print(novo), ali novo+= je potpuno nova neinicijalizovana lokalna varijabla.

Gomila jezika dozvoljava da se manipuliše globalnom varijablom. I to je ogroman izvor grešaka, takozvani side-effect.
Rezultat funkcije treba da zavisi od ulaznih varijabli, ali ne i od nečega što je deklarisano van funkcije.
Funkcija treba da vrati vrednost, ali ne treba da menja globalne varijable.

Zamisli šta bi se desilo, kada bi tvoj program radio, a ti pozvao DVA puta funkciju. novo bi imalo sadržaj od prethodnog poziva i dobio bi neočekivan rezukltat.

POMERI DEKLARACIJU VARIJABLE U TELO FUNKCIJE.

I, molim te, nemoj da me pitaš zašto ne valja to što si napisao, kao i zašto nije logično da tvoja funkcija radi...
[ a1234567 @ 01.05.2020. 07:10 ] @
Posle još malo istraživanja, dođoh do rešenja :)

Code:
def encr(rec):
    vokali = {'a': 0, 'e': 1, 'o': 2, 'i': 3, 'u': 4}
    novo = ''

    for i in rec:
        if i in vokali:
            i = str(vokali[i])
            novo += i
        else:
            novo += i 
    print(novo)
    
encr('jabuke')


ispis
j0b4k1
[ Branimir Maksimovic @ 01.05.2020. 07:44 ] @
U Haskellu nema problema posto je sve f-ja tj nema varijabli ; )
U Rustu moze globalna da bude mut, ali menjanje vrednosti mora da se stavi u "unsafe" blok.
[ Panta_ @ 01.05.2020. 18:41 ] @
Code:
'jabuke'.translate(str.maketrans({'a': '0', 'e': '1', 'o': '2', 'i': '3', 'u': '4'}))
'j0b4k1'
[ a1234567 @ 01.05.2020. 19:15 ] @
zaboravio si da obrneš reč i dodaš Acu :)

Code:
'jabuke'[::-1].translate(str.maketrans('aeou', '0123')) + 'aca'
[ a1234567 @ 03.05.2020. 13:10 ] @
ovo je zanimljivo

>>> string = 'ppy!'
>>> fruit = 'a'.join(list(string))

šta dobiješ?

papaya! :)
[ mjanjic @ 03.05.2020. 15:14 ] @
Citat:
djoka_l:

Da, ovo je recimo primer koji treba da se, između ostalih, pokazuje na časovima programiranja, umesto što se samo pokazuju ispravni primeri iz literature, pa posle imamo "programere" koji ne znaju šta da rade kad im se pojavi greška, a čini im se da je sve u redu.

Nego, za taj slučaj korišćenja globalnih promenljivih unutar definicije funkcije je zanimljivo kada se radi o nizovima. Onda .append() metoda funkcioniše bez problema (jer nije dodela nove vrednosti).
Tada će program raditi bez greške, pa će se "uspešno" koristiti globalna promenljiva na pogrešan način.
Drugi problem nastaje ako se (greškom) unutar funkcije za "novo" dodeli vrednost praznog niza (novo =[]), čime se u stvari kreira lokalna promenljiva, a globalna ostaje nepromenjena. Ako je namera bila da definisana funkcija pri pozivu menja vrednost globalne promenljive, desiće se "bug".


Al' hajde, ovo i nije toliki problem, ali ako baš mora da se koristi non-local promenljiva u funkciji, može da se primeni closure:
Code:
def multiplier_of(n):
    def multiplier(number):
        return number*n
    return multiplier

multiplywith5 = multiplier_of(5)
print(multiplywith5(9))
[ Branimir Maksimovic @ 03.05.2020. 17:17 ] @
Zato ne volim Piton. Ne znas dal definises novu varijablu ili joj dodeljujes vrednost...
[ mjanjic @ 04.05.2020. 02:36 ] @
A što, u JS je drugačije (doduše, ima var/let, pa je programer koliko-toliko siguran).

To su stvari vezane za sintaksu jezika. Mada, mnogi ne nauče dobro osnovnu sintaksu i njena značenja, pa posle...
[ a1234567 @ 04.05.2020. 08:06 ] @
Zadatak 36: Value of a sentence

Each letter in a sentence is worth its position in the alphabet (i.e. a = 1, b = 2, c = 3, etc...). However, if a word is all in UPPERCASE, the value of that word is doubled.
Create a function which returns the value of a sentence.

get_sentence_value("abc ABC Abc") ➞ 24
# a = 1, b = 2, c = 3

# abc = 1 + 2 + 3 = 6
# ABC = (1+2+3) * 2 = 12 (ALL letters are in uppercase)
# Abc = 1 + 2 + 3 = 6 (NOT ALL letters are in uppercase)

# 6 + 12 + 6 = 24

Examples
get_sentence_value("HELLO world") ➞ 176
get_sentence_value("Edabit is LEGENDARY") ➞ 251
get_sentence_value("Her seaside sea-shelling business is really booming!") ➞ 488

Notes
Ignore spaces and punctuation.
Remember that the value of a word isn't doubled unless all the letters in it are uppercase.
==========

Ja sam svoje rešenje ostavio ovde.
[ mjanjic @ 04.05.2020. 13:37 ] @
Malo sam neispavan pa sam probao neka rešenja za koja sam mislio da su jednostavnija korišćenjem find() metode, ali opet ima previše uslova (da li find() vraća -1 ili indeks karaktera).

Međutim, ne radi ti ovo dobro ako imaš npr. tekst "!Aaa", vraća nulu. Jeste da se toga nema u pravom tekstu, ali šta ako je neko pogrešio u kucanju, pa stavio razmak ispred umesto iza znaka uzvika?



Potom, zanimljivo bi bilo modifikovati kod tako da prepozna rečenice iz većeg stringa (i npr. nađe rečenicu sa najvećim brojem vrednošću).

Zanimiljivo rešenje bi bilo da se koristi nešto tipa PERMITTED_CHARS = string.ascii_letters, ili možda samo string.letters ako se prethodno pozove locale.setlocale().
Potom za svaku rečenicu ukloniti sve karaktere koji nisu slova, pa je dalje računanje vrednosti jednostavnije.
U suprotnom, malo ima previše upita oko provere da li npr. alphabet.find vraća -1 ili indeks karakera u alfabetu (alphabet je npr. string.ascii_lowercase).

Kod uvek može da se skrati, čak može dosta toga da se napravi kao složen upit u jednoj liniji, kao npr. (neki kod sa Stackoverflow, nema veze sa ovim zadatkom)
Code:
sum(i for i in array if array.index(i) % 2 == 0)*array[-1] if array != [] else 0

međutim, pitanje je da li se takav kod izvršava brže nego kod koji ima if...else strukturu. Nekada se izvršava brže, ali češće ne.
[ djoka_l @ 04.05.2020. 14:27 ] @
@a1234567

Moram nešto da te pitam, ali nemoj da se ljutiš. Cenim tvoj entuzijazam, ali prošlo je 4 meseca, a ti si na zadatku 36. Realno, tvoj napredak je ravan kursu python programiranja posle 20 časova kursa, pod uslovom da kurs ima 100 časova.

Kakav ti je plan? Realno, trebaće ti jedno dve godine da stigneš do kraja knjige.
Nama je ovo razbibriga, zadaci su na nivou rešavanja u roku od 5-10 minuta. Ne znam čime se baviš u životu, ali da si posvetio učenju pythona 6 sati nedeljno, do sada bi već mogao da praviš programe od 1000 linija KOJI RADE...
[ Branimir Maksimovic @ 04.05.2020. 14:32 ] @
Djoka:"ali da si posvetio učenju pythona 6 sati nedeljno, do sada bi već mogao da praviš programe od 1000 linija KOJI RADE... "

Jedno je Python, a drugo programiranje. Za programiranje treba mnogo vise vremena, a Python bar po meni nije najsrecnije
resenje za ucenje programiranja.
[ a1234567 @ 04.05.2020. 15:23 ] @
Đoko, cenim i ja tvoju brigu.

Zadatak je 36, ali ovde, ne u Stivensonovoj knjizi.
Tamo ih je mnogo više, ali sam ja odabrao neke koji su meni bili zanimljivi.

Pošto sam došao do kraja knjige, krenuo sam po netu da tražim ove Python challenge sajtove i naišao na Checkio,
koji je meni prilično zanimljiv, tako da sam tamo krenuo od početka. No ti početni zadaci su laki, tako da nisam hteo da ih stavljam ovde. Ali meni su dobri za utvrđivanje gradiva. Kad naiđu teži, postaviću, ne brini :)

Drugi challenge sajt koji je možda i bolji od ovog prvog je Edabit, jer možeš da biraš odmah zadatke po stepenu težine. Odatle sam uzeo poslednja dva zadatka.

Ne sećam se više da li sam objasnio svoju poziciju po pitanju svega ovoga, ali evo da probam. Ja dolazim iz oblasti humanističkih nauka, dakle nemam veze ni sa tehnikom, ni sa matematikom, a ni sam računarima. U školi sam matematiku buvalno mrzeo, što je donekle i uticalo na koju ću stranu da se usmerim u školovanju, iako mi je brat bio mašinac. Mi smo dakle po obrazovanju, interesovanjima, a onda i sposobnostima, dva potpuno različita sveta, te vas zato molim za razumevanje i strpljenje. Inače, kompjutere koristim dugo, naravno samo kao korisnik. No, isto toliko dugo me je znatiželja navodila da se pitam šta se u toj crnoj kutiji dogodi između pritisnutog tastera i ispisa na ekranu, ali nisam bio u prilici da za to odvojim vreme. Sada ga imam u ograničenim količinama i krenuo sam u istraživanje i to zaista sa velikom radošću, jer volim da učim nove stvari. A ovo je za mene kao da otkrivan novi, do sada nepoznati kontinent. Dakle, nisam ni pod kakvim pritiskom promene karijere ili slično, već je za mene ovo čist hobi i radost učenja, proširivanja vidika i obogaćivanja načina razmišljanja. Uvek su me inspirisali ljudi koji nisu fah idioti i misle da je to što rade jedina važna stvar na svetu, već oni koji imaju šire obrazovanje.

Nažalost, ne mogu učenju programiranja da posvetim 6 sati, samo onoliko koliko mi slobodno vreme dopušta, a to je sat-dva dnevno. Što na duže staze i nije tako malo. No, problem je što ja krećem ne od nule, već od minus 10 :)) Ali u isto vreme, kada sednem da rešavam neki zadatak, radim to zaista sa zadovoljstvom i uzbuđenjem pred novim izazovom. Pošto sam samouk potrošim sigurno pet puta više vremena nego da sam na nekom kursu sa živim predavačem, jer jednostavno dok rešavam zadatak nemam koga da pitam sem brata Gugla. Ali šta da mu radim. Uvek sam u životu pokušavao da uradim najbolje od onoga što mi je na raspolaganju, umesto da kukam i odustanem ili maštam šta bi bilo kad bi bilo. Dakle, moj napredak jeste spor, ali to je verovarno tako sa svakim ko je samouk. A i ako nije, who cares? :)

Ja lično sam zadovoljan. Do pre koji mesec nisam znao gomilu stvari koje sada znam. Drugi bitan faktor ograničenja je i to što moj mozak jednostavno nije navikao da razmišlja na programerski način. Skloniji je metaforama, nego algoritmima, pa su moja rešenja toliko "kreativna", da ne kažem komplikovana i pogrešna :)) Ali nadam se da ću vremenom i to savladati.

Sve u svemu, kad povučem crtu, ne mogu da kažem da sam nezadovoljan, sve dok napredujem, pa makar i mic po mic. Hvala vam svima što ste se potrudili da mi pomognete. Bez toga bi taj mic bio još manji.

Eto, malo sam odužio, ali nadam se da vam je sada lakše da se stavite u moje cipele i možda razumete zašto napredak nije brži nego što jeste :)
[ djoka_l @ 04.05.2020. 19:51 ] @
Gledao sam onaj drugi sajt (Edabit) zato što nije trebalo da se ulogujem. Pretpostavljam da je i prvi sličan. Sličan i kao project euler.

Uglavnom, ti sajtovi nisu dobri za UČENJE programiranja. Nećeš naučiti jezik tako što ćeš da rešavaš "cake". Treba da se vratiš na onu tvoju knjigu i da ponovo prođeš zadatke koje idu posle lekcija. Bitno je da naučiš KONCEPTE.

Slabo koristiš funkcije, ne koristiš exception, ne praviš projekte koji se sastoje od više python programa. Ne praviš svoje biblioteke.
Vrati se ponovo na onaj tvoj projkat rečnika. To će ti više značiti nego rešavanje ovih zadataka od 5 linija.
[ X Files @ 04.05.2020. 20:31 ] @
Slazem se sa djoka_i, poslusaj ga.
[ a1234567 @ 05.05.2020. 10:40 ] @
Mislim da sam pisanje fiunkcija utrenirao, jer na ovom jednom sajtu rešenja su isključivo u formi funkcija.
Neki od zadataka koje sam rešio do sad su ovde .
Mada još toliko nisam ni stavljao na Github.

Da, u pravu si, trebalo bi da oživim projekat rečnika.
Do sada sam od funkcija napravio pretraživanje, dodavanje nove reči i ispravljanje postojećih.
No, to je još uvek skript, ako se to tako zove. Probaću da napravim aplikaciju tako da pretraživanje ide na komandnoj liniji.
Tako da funkcioniše:

> python recnik --prevedi room

> soba, prostorija


Probaću takođe da napravim da ide u oba smera pretraživanje i prevod.
Ako me posluži sreća junačka da sve to isplivam, onda u sledećoj fazi da pravim grafički interfejs.

Đoko, šta misliš o planu? To taman do kraja godine da slistim
[ djoka_l @ 05.05.2020. 11:11 ] @
Grafički interfejs ostavi za nikad. Suviše je komplikovano za tebe, koji si još uvek na prvom programskom jeziku u životu, da se baviš Windows GUI programiranjem.

Koncentriši se na rad iz komandne linije.
Ako želiš nekakvo grafičko okruženje, bolje da to bude web, pretraživač će ti odraditi gomilu stvari, koje ti za sada ne znaš.

Za web ti treba da naučiš, ili obnoviš, znanje HTML, CSS, a onda ide Django.
Naravno, ako ne želiš da ti Django radi kao web server moraćeš da naučiš kako da napraviš WAMP okruženje i nešto malo Apache konfiguracije. Osim ako ne odlučiš da umesto Apache stavih nginx, onda moraš da naučiš kako da ga instaliraš i konfigurišeš. Neizostavno, treba da naučiš SQL i da instaliraš i postaviš MySQL bazu.

Ako misliš da je sve to komplikovano, pa Windows GUI je još komplikovaniji...

Uzgred, ja kao profesionalac, koristim Excel kada treba da napravim nešto na brzinu, a da ima grafiku, da se ne bih zamarao sa GUI na Windowsu.
Kada sam prvi put morao da napravim nešto za Windows okruženje u C++, bilo je tako zamorno, da sam sve svoje module napravio na SCOUnixu, a na windowsu ih samo kompajlirao. Toliko je bilo zamorno da postavim okruženje za rad u VisualStudio IDE, da sam lepo, ko čovek, sve odradio samo pomoću vi editora, pa onda liferovao svoje fajlove na integracioni server.
[ a1234567 @ 05.05.2020. 12:46 ] @
Pa ćemu onda služi tkinter?

Da, jedna od narednih faza bi bilo da taj rečnik stavim i na neki sajt, da bude online.
Za sada znam malo HTML. I to je nešto :)
[ Branimir Maksimovic @ 05.05.2020. 12:59 ] @
Pa dobro ne mora da se zeza sa win32 api u pythonu. Verujem da i pygtk vrsi posao dobro.
[ mjanjic @ 06.05.2020. 09:58 ] @
Generalno, mnogo će lakše naći postao ako razvija neki Web GUI (neki od framework-a ili čist JS), a ako solidno nauči programiranje, neki backend nije toliki problem. U nekoliko firmi u kojima znam programere, kažu da su Java i .NET tu negde, s tim što raste broj poslova za .NET Core, ali se traže i nodeJS, php, itd.

Uglavnom se ide na odvajanje front/back, retki su oni koji znaju i jedno i drugo na istom nivou...

HTML, CSS, JS mora da nauči osnove za Web, ali ako nije cilj rad sa implementacijom dizajna, onda neki od FW-a (react, vue, angular...).
[ Branimir Maksimovic @ 06.05.2020. 11:15 ] @
Cek da prvo nauci da programira, onda ce lako naci posao.... pisanje GUI programa je deo tog procesa.
To sto vecina firmi radi web, i poznatu kombinaciju jezika, ne mora da znaci da bas mora da se koncentrise
na to sada. Nije krenuo ni sa JS, ni sa .NET, ni sa Java, ni PHP, nego sa Pythonom.
[ mjanjic @ 07.05.2020. 07:43 ] @
Da, nego to je reakcija da mu Python nije baš dobar izbor ako hoće da radi GUI. OK ako neko odlično zna Python pa mu je lakše tako.
Python je ipak pogodniji za neke druge stvari, pa ako je nekome primarno to u čemu je Python relativno dominantan, onda OK.
[ Branimir Maksimovic @ 07.05.2020. 08:03 ] @
Pa ima ovo recimo https://github.com/Nicotine-Plus/nicotine-plus
To koristim :P
Nek prouci kako su uradili, app je 100+ GUI Python
[ a1234567 @ 07.05.2020. 09:14 ] @
Đoko, u skladu sa tvojom sugestijom,
nova verzija rečnika je na temi "Pravljenje englesko-srpskog rečnika".
Pogledaj, molim te, pa javi kako dalje.
Hvala unapred.

A ovde novi zadatak broj 37:

# You have a text and a list of words. You need to check if the words in a list appear in the
# same order as in the given text.

# Cases you should expect while solving this challenge:

# word from the list is not in the text - your function should return False;
# any word can appear more than once in a text - use only the first one;
# two words are the same - your function should return False;
# the condition is case sensitive, which means 'hi' and 'Hi' are two different words.
# text includes only English letters and spaces

# Input: Two arguments. The first one is a given text, the second is a list of words.
# Output: A bool.

def words_order(text: str, words: list) -> bool:
# your code here
return False

if __name__ == '__main__':
print("Example:")
print(words_order('hi world im here', ['world', 'here']))

# These "asserts" are used for self-checking and not for an auto-testing
assert words_order('hi world im here', ['world', 'here']) == True
assert words_order('hi world im here', ['here', 'world']) == False
assert words_order('hi world im here', ['world']) == True
assert words_order('hi world im here', ['world', 'here', 'hi']) == False
assert words_order('hi world im here', ['world', 'im', 'here']) == True
assert words_order('hi world im here', ['world', 'hi', 'here']) == False
assert words_order('hi world im here', ['world', 'world']) == False
assert words_order('hi world im here', ['country', 'world']) == False
assert words_order('hi world im here', ['wo', 'rld']) == False
assert words_order('', ['world', 'here']) == False

Ja sam uradio nešto ovako:

Code:
import collections

def words_order(text: str, words: list) -> bool:
    reci = text.split()
    dic_text = dict(enumerate(reci))
    dic_words = dict(enumerate(words))
    indexi = []

    for i in collections.Counter(words).values():
        if i > 1:
            return False

    for i in dic_words.values():
        for ind, rec in dic_text.items():
            if i in rec:
                indexi.append(ind)

    indexi1 = sorted(indexi) 
    
    if indexi == indexi1:
        return True
    else:
        return False

if __name__ == '__main__':
    print("Example:")
    print(words_order('hi world im here', ['world']))


ali mi javlja grešku na proveri
assert words_order('hi world im here', ['country', 'world']) == False

Nije mi jasno zašto to treba da bude False.
Kod mene je True, jer je jedina reč koja se javlja u tekstu, pa je time automatski redosled OK.

[ Branimir Maksimovic @ 07.05.2020. 09:21 ] @
"Nije mi jasno zašto to treba da bude False."

Pa ocigledno lista reci mora u tom redosledu da se pojavi u stringu.
[ a1234567 @ 07.05.2020. 09:33 ] @
U tome je stvar što ne mora.
U listi mogu biti reči koje se ne pojavljuju u stringu.
Ali ako u listi ima više reči koje se pojavljuju, treba proveriti da li je njihov redosed isti kao u stringu.
Mene ovaj slučaj buni zato što ima samo jedna reč koja se pojavljuje, te je otuda redosled OK, pošto je jedina.
[ Branimir Maksimovic @ 07.05.2020. 09:39 ] @
"U listi mogu biti reči koje se ne pojavljuju u stringu."

Mislim da to nisi dobro shvatio. Proveri primere ulaza i sta vraca.
[ a1234567 @ 07.05.2020. 09:46 ] @
Da, moguće je da nisam dobro ovo razumeo:
# word from the list is not in the text - your function should return False;

ako znači da svaka reč iz liste mora biti u stringu i da ako jedna nije, automatski je false
[ Branimir Maksimovic @ 07.05.2020. 10:11 ] @
Pise lepo ako jedna rec iz liste nije u tekstu, onda false.
[ a1234567 @ 07.05.2020. 10:26 ] @
Doradio i evo ova verzija je prošla.

( ͡° ͜ʖ ͡°)
[ Panta_ @ 07.05.2020. 10:34 ] @
Citat:
Generalno, mnogo će lakše naći postao ako razvija neki Web GUI (neki od framework-a ili čist JS), a ako solidno nauči programiranje, neki backend nije toliki problem. U nekoliko firmi u kojima znam programere, kažu da su Java i .NET tu negde, s tim što raste broj poslova za .NET Core, ali se traže i nodeJS, php, itd.


Šta fali Pythonu? Ima veliki izbor Python web frameworka, najpoznatiji su svakako Django i Flask, ali ima i dosta drugih. Isto tako i za razvoj GUI aplikacija.

Za razvoj Web aplikacija mu danas nije potrebno neko veliko znanje HTMLa i CSSa, ima i za tu namenu dosta frameworkova, npr. Bootstrap pa je dovoljno neko osnovno znanje. Za web server, Django i Flask dolaze podrazumevano sa istim tako da ni tu nije potrebno neko podešavanje, dovoljno je pokrenuti run server komandu, ili na primer sa gunicorn koji je lakši za podešavanje od Nginxa ili Apachea. Za bazu podataka, Django podrazumevano dolazi sa ORM podrškom za različite baze (SQLite, PostgreSQL, MariaDB, MySQL, Oracle), dok je za Flask potrebno instalirati npr. Flask-SQLAlchemy, tako da nije potrebno poznavanje SQL jezika za rad sa bazama.

Evo kao primer, ja sm onaj covid19 python skript jednostavno konvertovao u Web app uz pomoć navedenih tehnologija.

https://covid19inf.herokuapp.com/

Takođe, kome treba api, neka pogleda API dropdown menu. ;) Na primer:

Code:
curl https://covid19inf.herokuapp.com/api/latest/

curl https://covid19inf.herokuapp.com/api/\?date\=05-02-2020
[ djoka_l @ 07.05.2020. 11:14 ] @
Pogledaj ovu stranicu:
https://thispointer.com/python...here-are-duplicates-in-a-list/

U svom rešenju upotrebio si najgori algoritam za pronalaženje duplikata.
U tvom konkretnom slučaju to i nije toliko bitno, u pitanju su kratke liste i efikasnost ne igra neku veliku ulogu.
Međutim, potrebno je da, zbog učenja, pišeš EFIKASNE programe. Kao što je jedan moj profestor sa ETF-a govorio "Program mora da se završi za života programera". Uvek je voleo da spominje programere sa Matematičkog fakulteta koji pišu programe koji se završavaju posle konačnog broja koraka, a ne brzo...
[ Branimir Maksimovic @ 07.05.2020. 11:49 ] @
Kolko vidim koristi hash tabelu, sto je efikacnije od sorta u svakom slucaju. Mozda
jedino sto tu efikasnije moze da se uradi je da ne formira komplet, nego umesto counter,
da koristi obicnu, pa izadje odmah na pojavu prvog duplikata. Koliko kapiram
fora je da se vrati False ukoliko ima duplikata u listi?

edit:
no ovo trazenje reci u redosledu ima mesta za improvement svakako.
[ a1234567 @ 08.05.2020. 03:21 ] @
Zadatak broj 38, za koji nemam ideju kako ga rešiti, a da pohvata sve ove mavedene slučajeve.
Ako neko ima, eto prilike da nešto naučim.

# You are given a list of files. You need to sort this list by file extension. The files with the same extestion should be sorted by name.
#
# Some possible cases:
# Filename cannot be an empty string;
# Files without extensions should go before the files with extensions;
# Filename ".config" has an empty extenstion and name ".config";
# Filename "config." has an empty extenstion and name "config.";
# Filename "table.imp.xls" has an extesntion "xls" and name "table.imp";
# Filename ".imp.xls" has extension "xls" and name ".imp".
#
# Input: A list of filenames.
# Output: A list of filenames.

Code:
from typing import List

def sort_by_ext(files: List[str]) -> List[str]:
    # your code here
    return files


if __name__ == '__main__':
    print("Example:")
    print(sort_by_ext(['1.cad', '1.bat', '1.aa']))

    # These "asserts" are used for self-checking and not for an auto-testing
    assert sort_by_ext(['1.cad', '1.bat', '1.aa']) == ['1.aa', '1.bat', '1.cad']
    assert sort_by_ext(['1.cad', '1.bat', '1.aa', '2.bat']) == ['1.aa', '1.bat', '2.bat', '1.cad']
    assert sort_by_ext(['1.cad', '1.bat', '1.aa', '.bat']) == ['.bat', '1.aa', '1.bat', '1.cad']
    assert sort_by_ext(['1.cad', '1.bat', '.aa', '.bat']) == ['.aa', '.bat', '1.bat', '1.cad']
    assert sort_by_ext(['1.cad', '1.', '1.aa']) == ['1.', '1.aa', '1.cad']
    assert sort_by_ext(['1.cad', '1.bat', '1.aa', '1.aa.doc']) == ['1.aa', '1.bat', '1.cad', '1.aa.doc']
    assert sort_by_ext(['1.cad', '1.bat', '1.aa', '.aa.doc']) == ['1.aa', '1.bat', '1.cad', '.aa.doc']
[ djoka_l @ 08.05.2020. 08:35 ] @
HINT:
Code:

py
Python 3.7.4 (tags/v3.7.4:e09359112e, Jul  8 2019, 20:34:20) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> print(sorted( [ ('cad', '1'), ('bat', '1'), ('aa','1') ] ));
[('aa', '1'), ('bat', '1'), ('cad', '1')]
>>> quit();
[ a1234567 @ 09.05.2020. 17:51 ] @
Baš me namuči ovaj zadatak.
Lupao glavu, ali nisam uspeo da rešim sve slučajeve,
čak ni uz pomoć Đokinog hinta.

Sve što sam napravio je seckanje stringa i zamena mesta imena i ekstenzije, pa sortiranje.
Ali ostaje mi problem kad ima više fajlova bez imena.

Code:
def sort_by_ext(files):
    b = []
    for i in files:
        b.append(i.split('.'))
    # [['1', 'cad'], ['1', 'bat'], ['1', 'aa'], ['2', 'bat']]
    d = []
    for i in range(len(b)):
        d.append([b[i][1]] + [b[i][0]])
    # d = [['aa', '1'], ['bat', '1'], ['cad', '1'], ['bat', '2']]
    e = []
    e = sorted(d, key=lambda x: x[0])
    [['aa', '1'], ['bat', '1'], ['bat', '2'], ['cad', '1']]

    f = []
    for i in range(len(e)):
        f.append(e[i][1] + '.' + e[i][0])
    # f = ['1.aa', '1.bat', '2.bat', '1.cad']

    for i in range(len(f)):
        if f[i][0] == '.':
            a = f[i]
            f.remove(a)
            f.insert(0, a)
            break

    return f
[ djoka_l @ 09.05.2020. 18:52 ] @
Vrati se lepo na tvoju knjigu na odeljak o tipovima podataka. Pogledaj ponovo tip TUPLE.

>>> print(sorted( [(3,2,1), (3,1,2), (2,3,1), (2,1,3), (1,2,3), (1,3,2)] ));
[(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]

Obrati pažnjuj na to kako se tuple list sortira - prvo po prvom elementu, pa po drugom ... pa po poslednjem
Jedno vreme si se uhvatio za disctionary, pa si sve rešavao sa tim, posle si sve radio sa fajlovima, sada sve sa listama.
Kada bi jedan tip podatka bio dovoljan, ne bi pisci jezika izmišljali sve ove druge tipove.

Drugo, pogledaj split odnosno rsplit funkcije. Postoji parametar koji kaže na koliko elemenata se lista splituje. A možeš da izabereš i da li ćeš da splituješ s leva u desno ili s desna u levo.

Treće, reši onaj deo koji znaš. Kada budeš našao na primer koji ne znaš, onda zakukaj...

>>> print('a.b.c.d'.rsplit('.',1));
['a.b.c', 'd']
[ djoka_l @ 09.05.2020. 19:53 ] @
Code:
def SplitFileName( fn ):
  t=[]
  try:
    i=fn[1::].index('.')
  except:
    t=['', fn]
  else:
    t= [fn.rsplit('.',1)[1], fn]
    
  return t

print(SplitFileName('.config'))
print(SplitFileName('test.bat'))
[ a1234567 @ 10.05.2020. 14:18 ] @
Hvala za primer!

Samo ne razumem čemu ova varijabla "i" u 4. redu!?
dalje je nigde nema u funkciji.
Jel to u stvari treba da bude "t"?
Ali mi onda opet nije jasno svrha kad za drugi string dobiješ index = 3
[ a1234567 @ 10.05.2020. 14:21 ] @
Citat:
djoka_l:
Vrati se lepo na tvoju knjigu na odeljak o tipovima podataka. Pogledaj ponovo tip TUPLE.

>>> print(sorted( [(3,2,1), (3,1,2), (2,3,1), (2,1,3), (1,2,3), (1,3,2)] ));
[(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]

Obrati pažnjuj na to kako se tuple list sortira - prvo po prvom elementu, pa po drugom ... pa po poslednjem


Nisam razmišljao tuplama, jer su nepromenljive, a sortiranje je isto kao i kod liste lista.

[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
[ djoka_l @ 10.05.2020. 18:53 ] @
i samo služi za to da se podigne exception, ako u stringu postoji samo jedna tačka na prvom mestu.

Ako se exception desi (ne postoji tačka u nazivu fajla osim, možda, na prvom mestu), onda je ekstenzija prazan string, a naziv fajla ceo sadržaj varijable:
t=['', fn]

Ako se exception ne desi, onda se ide na else deo, pa se za ekstenziju uzima POSLEDNJI string posle tačke (rsplit, - sa desne strane se string splituje po tačkama, ali se uzima samo dva stringa, prvi string je sve do poslednje tačke, a drugi strig ono što je posle poslednje tačke), a naziv fajla je ceo fn:
t= [fn.rsplit('.',1)[1], fn]

fn.rsplit('.',1)[0] zanemarujem, uopšte mi nije potreban

'a.b.c.d'.rsplit('.',1) bi dao
['a.b.c', 'd']

ali mi a.b.c nije potrebno

Rezultat fiunkcije je lista od dva stringa, prvi strig je ekstenzija, drugi string je naziv fajla (s tim što ekstenzija može da bude prazan string)
[ Panta_ @ 12.05.2020. 09:44 ] @
Citat:
Baš me namuči ovaj zadatak.
Lupao glavu, ali nisam uspeo da rešim sve slučajeve,
čak ni uz pomoć Đokinog hinta.

Sve što sam napravio je seckanje stringa i zamena mesta imena i ekstenzije, pa sortiranje.
Ali ostaje mi problem kad ima više fajlova bez imena.


Sorted funkcija ima key parametar kome prosleđuješ funkciju koja treba da vrati ime fajla ako isti nema ili ima istu ekstenziju, ili u suprotnom ekstenziju, na primer:
Code:
files = ['1.cad', '1.bat', '1.aa', '.aa.doc', 'config.', '.bat', 'table.imp.xls', '.imp.xls']

sorted(files, key=tvoja_funkcija)

['.bat', '.imp.xls', 'config.', '1.aa', '1.bat', '1.cad', '.aa.doc', 'table.imp.xls']


Dakle, prvo proveriš da li fajl ima ekstenziju, ako da, proveriš da li ima još neki fajl sa istom ekstenzijom u files listi, ako da, vratiš ime fajla, ili u suprotnom ekstenziju. Obrati pažnju da se fajlovi koji počinju tačkom sortiraju ispred onih koji počinju alpha ili num karakterom.
Code:
sorted(['a', 'c', 'b', '1', '.'])

['.', '1', 'a', 'b', 'c']
[ a1234567 @ 12.05.2020. 14:06 ] @
uklavirio sam kako da proverim da li ima fajlova sa i bez ekstenzije i da ih sortiram, kao što je ovaj slučaj

Code:
def lista(fajlovi):
    nema_ext = []
    ima_ext = []
    for i in fajlovi:
        if i.rsplit('.', 1)[0] == '':
            nema_ext.append(i)
        else:
            ima_ext.append(i)
    print(sorted(nema_ext) + sorted(ima_ext))

lista(['1.cad', '1.bat', '.aa', '.bat'])


['.aa', '.bat', '1.bat', '1.cad']

ali i dalje mi nije jasno kako grupišem fajlove sa istom ekstenzijom.
[ a1234567 @ 14.05.2020. 09:29 ] @
Zadatak broj 39:

Podeli string dužine 0 < str < 100 u delove po dva znaka. Ako je broj znakova u stringu neparan, poslednjem znaku dodaj _ da bi napravio par.

Code:
def split_pairs(a):
    your code here 
    return something


if __name__ == '__main__':
    print("Example:")
    print(list(split_pairs('abcd')))

    # These "asserts" are used for self-checking and not for an auto-testing
    assert list(split_pairs('abcd')) == ['ab', 'cd']
    assert list(split_pairs('abc')) == ['ab', 'c_']
    assert list(split_pairs('abcdf')) == ['ab', 'cd', 'f_']
    assert list(split_pairs('a')) == ['a_']
    assert list(split_pairs('')) == []
    print("Coding complete? Click 'Check' to earn cool rewards!")


Moje rešenje je ovde.

[ bokinet @ 14.05.2020. 09:49 ] @
proveris da li je parni ili neparni,
dodas po potrebi da bude na dvojcicu,
i onda veslas kao da je sve sa dvojcicom devojcicom.
[ a1234567 @ 16.05.2020. 07:36 ] @
Zadatak broj 40:


# In a given word you need to check if one symbol goes right after another.
# Cases you should expect while solving this challenge:
# If more than one symbol is in the list you should always count the first one
# one of the symbols are not in the given word - your function should return False;
# any symbol appears in a word more than once - use only the first one;
# two symbols are the same - your function should return False;
# if the first instance of the second symbol comes before the first one, that should return False
# the condition is case sensitive, which mease 'a' and 'A' are two different symbols.

# Input: Three arguments. The first one is a given string, second is a symbol that shoud go first, and the third is a symbold that should go after the first one.
# Output: A bool.


Code:
def goes_after(word: str, first: str, second: str) -> bool:
 
    "tvoj kod ovde"

    return False/True


if __name__ == '__main__':
    print("Example:")
    print(goes_after('world', 'w', 'o'))

    # These "asserts" are used for self-checking and not for an auto-testing
    assert goes_after('world', 'w', 'o') == True
    assert goes_after('world', 'w', 'r') == False
    assert goes_after('world', 'l', 'o') == False
    assert goes_after('panorama', 'a', 'n') == True
    assert goes_after('list', 'l', 'o') == False
    assert goes_after('', 'l', 'o') == False
    assert goes_after('list', 'l', 'l') == False
    assert goes_after('world', 'd', 'w') == False
    assert goes_after('almaz', 'm', 'a') == False
    print("Coding complete? Click 'Check' to earn cool rewards!")


Moje rešenje ovde
[ a1234567 @ 17.05.2020. 03:29 ] @
Zadatak broj 41

Ovaj zadatak je sličan prethodnom, ali teži. Treba pronaći reč u višelinijskom u tekstu, horizontalno ili vertikalno i dati njene koordinate.
Napravio sam nešto ovako za horizontalni slučaj, ali za vertikalni nisam baš siguran kako da rešim.

# You are given a rhyme (a multiline string), in which lines are separated by "newline" (\n).
# Casing does not matter for your search, but whitespaces should be removed before your search.
# You should find the word inside the rhyme in the horizontal (from left to right) or vertical
# (from up to down) lines. For this you need envision the rhyme as a matrix (2D array). Find
# the coordinates of the word in the cut rhyme (without whitespaces).

# The result must be represented as a list -- [row_start,column_start,row_end,column_end], where
# row_start is the line number for the first letter of the word.
# column_start is the column number for the first letter of the word.
# row_end is the line number for the last letter of the word.
# column_end is the column number for the last letter of the word.
# Counting of the rows and columns start from 1.

# Input: Two arguments. A rhyme as a string and a word as a string (lowercase).
# Output: The coordinates of the word.
# Precondition: The word is given in lowercase
# 0 < |word| < 10
# 0 < |rhyme| < 300

Code:
def checkio(text, word):
    novi = text.strip().replace(' ', '')
    reci = novi.split('\n')
    red = 1
    indeks = 1
    spisak1 = []
    spisak2 = []
    duzina = len(word)
    vert = ''

    for i in novi:
        indeks += 1
        if i == word[0]:
            spisak1.append(red)
            spisak2.append(indeks)
            if reci[red-1][indeks-1:indeks-1+duzina] == word:
                return [int(spisak1[0]), int(spisak2[0]), int(spisak1[0]), int(spisak2[0])+duzina-1]
                break

        if i == '\n':
            red += 1
            indeks = 0


# These "asserts" using only for self-checking and not necessary for auto-testing
if __name__ == '__main__':
    assert checkio("""DREAMING of apples on a wall,
    And dreaming often, dear,
    I dreamed that, if I counted all,
    -How many would appear?""", "ten") == [2, 14, 2, 16]
    assert checkio("""He took his vorpal sword in hand:
    Long time the manxome foe he sought--
    So rested he by the Tumtum tree,[/quote]
    And stood awhile in thought.
    And as in uffish thought he stood,
    The Jabberwock, with eyes of flame,
    Came whiffling through the tulgey wood,
    And burbled as it came!""", "noir") == [4, 16, 7, 16]
[ mjanjic @ 17.05.2020. 19:04 ] @
Pa za vertikalan slučaj je slična petlja, samo što uzimaš slova po vertikali u reci[][], tj. u unutrašnjoj petlji je drugi indeks konstantan, a menjaš prvi. Međutim, nisu ti sve "vrste" iste dužine.

Možda bi bilo najjednostavnije konvertovati slova u numeričke ekvivalente 1-26, formirati dvodimenzionu matricu na osnovu teksta, s tim što se stavi 0 tamo gde nema dovoljno teksta - broj kolona je dužina najduže "reči", tj. stiha.

Tada može numpy paketom lako da se manipuliše vrstama i kolonama, pa je lakše pretraživati niz brojeva po koloni koji je jedna nizu numeričkih ekvivalenata za traženu reč.


Dosta bi bilo nezgodnije da treba u samoj pesmi naći reči koje se rimuju, a da se traži isto ovako po "vertikali".
[ a1234567 @ 18.05.2020. 08:05 ] @
Nema veze što su redovi nejednake dužine, svaki kreće od 0. Važne su kolone

U principu mi je jasno i za vertikalnu reč. Kada jednom nađem koordinatu prvog slova u reči,
idem nadole, red po red, po istoj koloni. Nešto ovako.
Ali iz nekog razloga ne ispada onako kako treba.

Code:
def checkio(text, word):
    novi = text.replace(' ', '').strip().split('\n')
    red = 1
    indeks = 1
    spisak1 = []
    spisak2 = []
    vert1 = []
    vert2 = []
    duzina = len(word)
    vert = ''

    for i in novi:
        for j in i:
            indeks += 1
            if j == word[0]:
                spisak1.append(red)
                spisak2.append(indeks)
                if novi[red-1][indeks-1:indeks-1+duzina] == word:
                    return [int(spisak1[0]), int(spisak2[0]), int(spisak1[0]), int(spisak2[0])+duzina-1]
                    break
        else:
            for s in novi:
                for t in s:
                    indeks += 1
                    if i == word[0]:
                        vert1.append(red)
                        vert2.append(indeks)
                        for v in range(len(word)):
                            vert += reci[red+v][indeks]
                            return [int(vert1[0]), int(vert2[0]), int(vert1[0]), int(vert2[0+len(word)])]
        
        if i == '\n':
            red += 1
            indeks = 0


# These "asserts" using only for self-checking and not necessary for auto-testing
if __name__ == '__main__':
    assert checkio("""DREAMING of apples on a wall,
And dreaming often, dear,
I dreamed that, if I counted all,
-How many would appear?""", "ten") == [2, 14, 2, 16]
    assert checkio("""He took his vorpal sword in hand:
Long time the manxome foe he sought--
So rested he by the Tumtum tree,[/quote]
And stood awhile in thought.
And as in uffish thought he stood,
The Jabberwock, with eyes of flame,
Came whiffling through the tulgey wood,
And burbled as it came!""", "noir") == [4, 16, 7, 16]

[ djoka_l @ 18.05.2020. 08:37 ] @
Ovaj kod ti je tako neuredan da je problem da se prati logika programa.
Opet pokazuješ svoju staru slabost: NE RAZUMEŠ STRUKTURE PODATAKA...

Uzmimo, kao primer, varijable spsiak1 i spisak2.

Zašto su one liste?
Šta stavljaš u listu?
Zašto radiš konverziju u int?

Kada se prođe kroz tvoj kod, jasno je da se u LISTE stavlja samo JEDNA vrednost, pa ti lista ni ne treba!
Jasno je da se u listu stavlja int, pa je konverzija NEPOTREBNA.
Jasno je da se varijablama spisak1 i spsisak2 uvek dodeljuje vrednosti red i indeks, PA TI TE VARIJABLE NI NE TREBAJU!

Code:

Umesto:

            if j == word[0]:
                spisak1.append(red)
                spisak2.append(indeks)
                if novi[red-1][indeks-1:indeks-1+duzina] == word:
                    return [int(spisak1[0]), int(spisak2[0]), int(spisak1[0]), int(spisak2[0])+duzina-1]
                    break

TREBA:

            if j == word[0]:
                if novi[red-1][indeks-1:indeks-1+duzina] == word:
                    return [red, indeks, red, indeks+duzina-1]
                    break


Pa onda imaš jedna ELSE koji nije poravnat sa IF. Bezveze se pojavio.
Pa onda imaš ovaj biser - porediš i sa novim redom, a znake za novi red si na početku izbacio:
Code:
        if i == '\n':
            red += 1
            indeks = 0



Čak ti u zadatku stoji sugestija da koristiš MATRICU, ali ti od matrice bežiš kao đavo od krsta, zato što nisi naučio da koristiš matrice.
[ mjanjic @ 18.05.2020. 13:58 ] @
Da, sa matricama može da koristi numpy paket u kome može lako da radi direktno sa kolonama, ali kada konvertuje tekst u numeričke elemente matrice, mora da dopuni sve vrste koje su kraće od najduže vrste.
Može i sa običnim Python array da se radi, ali je sa numpy dosta lakše jer može da izdvoji kolonu (npr. textArray[ : , column_index]), pa može na pretragu po traženoj reči da primeni istu funkciju koju koristi za pretragu po vrsti.
[ a1234567 @ 18.05.2020. 14:30 ] @
Hvala Đoko na sugestijama.
Ispravio, ali ne radi i dalje.

@mjanjic nije predviđeno da se koristi numpy.

Idemo dalje...

Zadatak broj 42: Ptičiji jezik

Today the bird spoke its first word: "hieeelalaooo". This sounds a lot like "hello", but with too many vowels. Stephan asked Nikola for help and he helped to examine how the bird changes words. With the information they discovered, we should help them to make a translation module.
The bird converts words by two rules:

- after each consonant letter the bird appends a random vowel letter (l ⇒ la or le);
- after each vowel letter the bird appends two of the same letter (a ⇒ aaa);

Vowels letters == "aeiouy".

You are given an ornithological phrase as several words which are separated by white-spaces (each pair of words by one whitespace). The bird does not know how to punctuate its phrases and only speaks words as letters. All words are given in lowercase. You should translate this phrase from the bird language to something more understandable.

Input: A bird phrase as a string.
Output: The translation as a string.

Code:
def translate(phrase):
  
   "your code here"

    return output


if __name__ == '__main__':
    print("Example:")
    print(translate("hieeelalaooo"))

    # These "asserts" using only for self-checking and not necessary for auto-testing
    assert translate("hieeelalaooo") == "hello", "Hi!"
    assert translate("hoooowe yyyooouuu duoooiiine") == "how you doin", "Joey?"
    assert translate("aaa bo cy da eee fe") == "a b c d e f", "Alphabet"
    assert translate("sooooso aaaaaaaaa") == "sos aaa", "Mayday, mayday"
    print("Coding complete? Click 'Check' to review your tests and earn cool rewards!")


Moje rešenje je ovde.
[ B3R1 @ 18.05.2020. 16:08 ] @
Vezano za zadatak 41 - koristis previse promenljivih koje ne sluze nicemu i tesko mozes da pohvatas gde je sta. Potrebna ti je samo jedna lista, koju dobijas split() funkcijom, sto si vec lepo uradio. Nazovimo je rows (to je ovo sto ti zoves 'novi'). Takodje, ja bih dodao i funkciju lower(), kojom eliminises mala/velika slova (tekst zadatka kaze "case is not important"):
Code (python):
rows = text.replace(' ', '').split('\n').lower()

Ta lista vec sadrzi linije teksta, koje su obicni stringovi, unutar kojih rec definisanu promenljivom word trazis funkcijom find(). Funkcija find() vraca poziciju stirnga unutar veceg stringa, pa imas:
Code (python):

>>> verse = 'The woods are lovely, dark and deep'
>>> verse.find('wood')
4
>>> verse.find('forest')
-1
 

Time resavas skeniranje teksta po horizontali. Ostaje da resis skeniranje po vertikali, sto nije toliko slozeno, imajuci u vidu da svakom slovu unutar stringa mozes da pridjes po njegovom indeksu. Na primer, ako ti rows sadrzi:
Code (python):
rows = [ 'thewoodsarelovely,darkanddeep', 'butihavepromisestokeep,', 'andmilestogobeforeisleep,' 'andmilestogobeforeisleep.' ]

Tada ti je rows[0][1] == 'h' (drugo slovo prvog reda). Znaci, nisu ti potrebni nikakvi indeksi. Jedini problem je sto su elementi liste nejednake duzine, tako da najpre moras da odredis najvecu duzinu elementa liste koja ce ti odrediti opseg skeniranja. Dobijas kod u formi:

Code (python):

def checkio (text, word):
    rows = text.replace(' ', '').split('\n')   # Smesta linije teksta u listu rows

    # Najpre odredimo maksimalnu duzinu linije
    max_len = 0
    for row in rows:
        if (len(row)>max_len):
            max_len = len(row)

    # Iteracija po vertikali, slovo po slovo svakog reda, do maksimalne duzine reda
    for j in range(0,max_len):
        col = '' # Ovde smestamo kolone teksta
        for i,row in enumerate(rows):
            if (j >= len(row)):
                continue
            col += row[j]   # Slovo na poziciji 'j' unutar stringa 'row'
        # col - ce sadrzati celu kolonu teksta
 

Ostaje ti da nadjes poziciju reci u stringovima row i col. Tu imas dve ideje. Onako skolski, pocetnicki bi bilo da kolone smestas u posebnu listu (npr. cols), koju inicijalizujes na pocetku i kada formiras kolonu (col) na kraju ovog koda gore dodas:
Code (python):

        if (col):
            cols.append(col)
 

U nastavku koda onda ponovo iteriras po svim vrstama i svim kolonama i koristis funkciju find(). To je korektno resenje, ali time nepotrebno ponovo ulazis u petlju. Da ustedis vreme, pretrazivanje stringova mozes da radis vec i u petljama gore. Prva petlja iterira po kolonama, druga za svaku kolonu skenira vrste od 0 do len(rows). U principu, dovoljno je ispitati vrste samo jednom i idealno je to uraditi tokom skeniranja prve kolone. Slicno tome, skeniranje kolone je najbolje uraditi kada se kolona formira. Time kod postaje (nisam testirao, ali mislim da je ok):
Code (python):

def checkio (text, word):
    rows = text.replace(' ', '').split('\n')   # Smesta linije teksta u listu rows

    # Najpre odredimo maksimalnu duzinu linije
    max_len = 0
    for row in rows:
        if (len(row)>m):
            max_len = len(row)

    # Iteracija po vertikali, slovo po slovo svakog reda
    for j in range(0,max_len):
        col = '' # Ovde smestamo kolone teksta
        for i,row in enumerate(rows):
            if (j == 0): # Tokom formiranja prve kolone skeniramo vrstu
                pos = row.find(word)
                if (pos >= 0):
                    return [ i, pos, i, pos+len(word)-1 ]
            if (j >= len(row)):
                continue
            col += row[j]
        pos = col.find(word)
        if (pos >= 0):
            return [ pos, j, pos+len(word)-1, j ]
    return []
 

Moze li to bolje? Moze! Recimo, ako se rec ne nalazi uopste u tekstu zasto bismo je trazili u svakom redu? Na samom pocetku funkcije treba onda dodati:
Code (python):
def checkio (text, word):
    search_rows = word in text
 

I onda u liniji gde ispitujemo da li je j == 0 izmeniti:
Code (python):

            if ((j == 0) and search_rows): # Tokom formiranja prve kolone skeniramo vrstu, samo ako je search_row == True
 

Zadatak moze da se malcice uopsti i da se traze sve koordinate gde se zadata rec nalazi ... i da se to vraca u formi:
[ [ x1, y1, z1, u1 ], [ x2, y2, z2, u2 ], ... ]

To ti ostavljam za domaci ...

[Ovu poruku je menjao B3R1 dana 18.05.2020. u 19:27 GMT+1]
[ a1234567 @ 20.05.2020. 16:16 ] @
Hvala Berislave na detaljnom objašnjenju.
Sad mi je jasno i ne izgleda teško :))

Vidi se da imaš pedagoški dar. Treba da praviš tutoriale za python na youtube :))


Idemo dalje, zadatak broj 43:

# Joe Palooka has fat fingers, so he always hits the “Caps Lock” key whenever he actually intends
# to hit the key “a” by itself. (When Joe tries to type in some accented version of “a” that needs
# more keystrokes to conjure the accents, he is more careful in the presence of such raffinated
# characters ([Shift] + [Char]) and will press the keys correctly.) Compute and return the result
# of having Joe type in the given text. The “Caps Lock” key affects only the letter keys from “a”
# to “z” , and has no effect on the other keys or characters. “Caps Lock” key is assumed to be
# initially off.

# Input: A string. The typed text.
# Output: A string. The showed text after being typed.


Code:
def caps_lock(text: str) -> str:
   "your code here"
    return string


if __name__ == '__main__':
    print("Example:")
    print(caps_lock("Why are you asking me that?"))

    # These "asserts" are used for self-checking and not for an auto-testing
    assert caps_lock(
        "Why are you asking me that?") == "Why RE YOU sking me thT?"
    assert caps_lock(
        "Always wanted to visit Zambia.") == "AlwYS Wnted to visit ZMBI."
    print("Coding complete? Click 'Check' to earn cool rewards!")


Moje rešenje je ovde.
[ mjanjic @ 21.05.2020. 21:41 ] @
Ako već postavljaš na Github, koristi samo engleski, dakle u ovom tvom kodu umesto "novi" stavi neki smislen naziv na engleskom.
[ a1234567 @ 22.05.2020. 02:40 ] @
Kad sam ja mogao da naučim engleski, neka i Englezi uče malo srpski.
Šta fali? Možda im zatreba

Ma odsad ću da krenem ćirilične varijable da pišem
[ Branimir Maksimovic @ 22.05.2020. 02:50 ] @
"Ma odsad ću da krenem ćirilične varijable da pišem "

Mislim da to moze u nekim jezicima :P

recimo c++ moze:
Code:

~/.../bmaxa_data/examples >>> cat cyr.cpp                                                           
#include <iostream>

int main() {
    int ćir = 5;
    std::cout << ćir << std::endl;
}
~/.../bmaxa_data/examples >>> g++ -O3 -march=native cyr.cpp                                         
~/.../bmaxa_data/examples >>> ./a.out                                                               
5


Naravno forum je preslovio ali u originalu u source kodu je cirlicna varijabla :P
[ mjanjic @ 22.05.2020. 03:07 ] @
Ma ne C++, ima ħ++, tu je čak i zvanična stranica: https://%D1%9B%D0%BF%D0%BF.%D1%81%D1%80%D0%B1
[ Branimir Maksimovic @ 22.05.2020. 03:27 ] @
Ja evo probao sa obicnim C++, mozes komplet program u cirilici ;)
Opalis #define za rezervisane reci i pici ;)
[ a1234567 @ 22.05.2020. 03:49 ] @
Citat:
mjanjic:
Ma ne C++, ima ħ++, tu je čak i zvanična stranica: https://%D1%9B%D0%BF%D0%BF.%D1%81%D1%80%D0%B1

haha ovo je super!

Ćiriliks - operativni sistem
[ a1234567 @ 22.05.2020. 08:17 ] @
Zadatak broj 44: Suglasnici i samoglasnici naizmenično

# Our robots are always working to improve their linguistic skills. For this mission, they
# research the latin alphabet and its applications.

# The alphabet contains both vowel and consonant letters (yes, we divide the letters).
# Vowels -- A E I O U Y
# Consonants -- B C D F G H J K L M N P Q R S T V W X Z

# You are given a block of text with different words. These words are separated by white-spaces
# and punctuation marks. Numbers are not considered words in this mission (a mix of letters and
# digits is not a word either). You should count the number of words (striped words) where the
# vowels with consonants are alternating, that is; words that you count cannot have two
# consecutive vowels or consonants. The words consisting of a single letter are not striped --
# do not count those. Casing is not significant for this mission.

# Input: A text as a string (unicode)
# Output: A quantity of striped words as an integer.
# Precondition:The text contains only ASCII symbols.
# 0 < len(text) < 105

Code:
def checkio(text):
    
    "tvoj kod ovde"
    
    return rezultat

#These "asserts" using only for self-checking and not necessary for auto-testing
if __name__ == '__main__':
    assert checkio("My name is ...") == 3, "All words are striped"
    assert checkio("Hello world") == 0, "No one"
    assert checkio("A quantity of striped words.") == 1, "Only of"
    assert checkio("Dog,cat,mouse,bird.Human.") == 3, "Dog, cat and human"
    assert checkio("To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it?") == 8
    print('If it is done - it is Done. Go Check it NOW!')


Moje rešenje ovde.
[ B3R1 @ 22.05.2020. 14:44 ] @
Previse si se upetljao s ovim indeksima i par-nepar sistemom. Pokusaj da problem resis na nacin kako bi ga resavao pesice, da nemas kompjuter. Zadas neku rec, tipa "maramica". Treba da ispitas da li u toj reci ima dva susedna samoglasnika ili suglasnika. Algoritam bi bio:

* Uvedes varijablu kojom pratis prethodno slovo u reci (npr. 'prev_ch'). U pocetku je to prazan string ('').
* Za svako slovo u reci gledas da li je samoglasnik ili suglasnik. Ako je samoglasnik i prethodno slovo je samoglasnik - prekidas petlju.
* Slicno ako je suglasnik i prethodno slovo je suglasnik.
* U suprotnom prev_ch postavljas na vrednost tekuceg karaktera i ides dalje.

Takodje, nema potrebe da imas VOWELS in CONSONANTS u posebnim promenljivim - ako slovo nije samoglasnik ono je suglasnik, nema treceg.
I nema potrebe da pravis silne liste, zapravo novi_txt3 ti uopste nije potrebna. Cemu to?

Na kraju, mnogo puta prolazis kroz istu petlju, dok sve mozes da obavis u samo jednom prolazu.

Znaci:
Code (python):

def checkio(text):
    count = 0
    words = re.split(r'[?,.!\s]', text.upper())
    for word in words:
        if (len(word) <=1 or re.search(r'[0-9]', word)):
            continue
        valid_word = True
        prev_ch = word[0]
        for ch in word[1:]:
            if ((ch in VOWELS and prev_ch in VOWELS) or (ch not in VOWELS and prev_ch not in VOWELS)):
                valid_word = False
                break
            prev_ch = ch
        if (valid_word):
            count += 1
    return count
 


Moze to i krace. Posto si u kodu vec pokazao da umes da koristis regularne izraze, njihovim koriscenjem izbegavas iteraciju po slovima:

Code (python):

def checkio(text):
    count = 0
    for word in re.split(r'[?,.!\s]', text.upper()):
        if (len(word) <=1 or re.search(r'[0-9]', word)):
            continue
        if (not re.search('[AEIOYU]{2}', word) and not re.search('[BCDFGHJKLMNPQRSTVWXZ]{2}', word)):   #  [x]{2} = najmanje dva pojavljivanja znakova iz skupa [x]
            count += 1
    return count
 


A moze i sve u jednom if-u:

Code (python):

def checkio(text):
    count = 0
    for word in re.split(r'[?,.!\s]', text.upper()):
        if (len(word) > 1  and not re.search(r'[0-9]', word) and not re.search('[AEIOYU]{2}', word) and not re.search('[BCDFGHJKLMNPQRSTVWXZ]{2}', word)):
            count += 1
    return count
 
[ a1234567 @ 22.05.2020. 17:18 ] @
Berislave, ja sam to uradio ekstenzivnom metodom da pokažem svoj raskošan talenat :)))

Ma ja sam bio prezadovoljan da sam uošte uspeo da rešim. Kako god.
Da, ta provera prethodnog slova mi je trebala, ali nisam znao kako.
Sad imam mustru.

Hvala na analizi i primerima.
Sačuvaću i proučiću, da nešto novo naučim.

To što kažeš na početku jeste vrlo važno.
Ja kad vidim zadatak, odmah krenem da kucam kod i da testiram u terminalu.
A trebalo bi prvo da napravim to što zovu pseudo kod, tj. recept, pa tek onda
da krenem da kuvam.

I tu dolazim do zadatka 45: Ukloni nepar zagrade
koji mi izgleda komplikovan, jer ne vidim jasan recept, ni kratak ni dugačak.

Prvo što mi pada na pamet je da prebrojim zagrade i stavim u rečnik.
Onda vidim kojih ima nepar, pa te uklonim. Ali nisam siguran da će to baš da radi.
Moram probati. Zavisi valjda od primera.


# Your task is to restore the balance of open and closed brackets by removing unnecessary ones,
# while trying to use the minimum number of deletions.

# Only 3 types of brackets (), [] and {} can be used in the given string.

# Only a parenthesis can close a parenthesis. That is. in this expression "(}" - the brackets
# aren’t balanced. In an empty string, i.e., in a string that doesn’t contain any brackets
# - the brackets are balanced, but removing all of the brackets isn’t considered to be an
# optimal solution.

# If there are more than one correct answer, then you should choose the one where the character
# that can be removed is closer to the beginning. For example, in this case "[(])", the correct
# answer will be "()", since the removable brackets are closer to the beginning of the line.

# Input: A string of characters () {} []
# Output: A string of characters () {} []


Code:
def remove_brackets(a):
    # your code here
    return None


if __name__ == '__main__':
    print("Example:")
    print(remove_brackets('(()()'))

    # These "asserts" are used for self-checking and not for an auto-testing
    assert remove_brackets('(()()') == '()()'
    assert remove_brackets('[][[[') == '[]'
    assert remove_brackets('[[(}]]') == '[[]]'
    assert remove_brackets('[[{}()]]') == '[[{}()]]'
    assert remove_brackets('[[[[[[') == ''
    assert remove_brackets('[[[[}') == ''
    assert remove_brackets('') == ''
    print("Coding complete? Click 'Check' to earn cool rewards!")
[ mjanjic @ 22.05.2020. 21:36 ] @
hm, sad sledeći "nivo", da se tekst napisan korejskim hangulom transkribuje u latinicu :)
https://stackoverflow.com/ques...t-hangul-lettersymbol-to-latin
[ B3R1 @ 22.05.2020. 23:55 ] @
Zadatak 45 je za neki visi kurs programiranja. Probaj da resis laksi slucaj - kada imas samo jednu vrstu zagrada - npr. ((())())()()) ...

Za resavanje tog problema potrazi na netu pojam "stack" i prouci kako rade stekovi.
[ Branimir Maksimovic @ 23.05.2020. 00:53 ] @
"Za resavanje tog problema potrazi na netu pojam "stack" i prouci kako rade stekovi."

Lepo si to uocio rekurzivne parsere sam pravio kad sam ucio pre 30 godina :P
[ a1234567 @ 23.05.2020. 08:26 ] @
Citat:
B3R1:
Zadatak 45 je za neki visi kurs programiranja. Probaj da resis laksi slucaj - kada imas samo jednu vrstu zagrada - npr. ((())())()()) ...

Za resavanje tog problema potrazi na netu pojam "stack" i prouci kako rade stekovi.


Proučio stackove. To je isto kao lista, sa append and pop.
I primenio u ovom rešenju za sve tri vrste zagrada:

Code:
o_lista = ["[","{","("] 
z_lista = ["]","}",")"]

def zagrade(string): 
    stack = []
    out = ''
    stack = [i for i in string if i in o_lista]
    for i in string:
        if i in z_lista: 
            pos = z_lista.index(i)  # pos == 2
            if o_lista[pos] in stack:
                out += o_lista[pos] + z_lista[pos]
                stack.remove(o_lista[pos])
                if len(stack) == 0:
                    return out    
    return out

print(zagrade('({[()}}]]()'))


Ispis:
(){}[]()
[ B3R1 @ 23.05.2020. 10:51 ] @
Pa i nije bas ono sto se trazi. Tvoj program za '(())' vraca '()()', a trebalo bi '(())'.
[ a1234567 @ 23.05.2020. 11:27 ] @
Kako?
Ja sam išao logikom onoga što je dato kao primer u zadatku 45.

assert remove_brackets('(()()') == '()()'
[ djoka_l @ 23.05.2020. 12:26 ] @
Tvoje rešenje UOPŠTE ne valja.

Pre svega, ne prolazi primer 3 i 4 iz originalnog zadatka.
I stalno ponavljaš iznova iste greške.
Recimo, već sam ti nekoliko puta pisao da ne stavljaš da su varijable koje koristiš SAMO u funkciji van tela funkcije (o_lista i z_lista u zadatku 45, VOWELS, CONSONANTS u zadatku 44), dupli kod (u zadatku 44), nepotrebne varijable (44) itd.

I dalje ne znaš STRUKTURE PODATAKA. Ne znaš šta je stek. Ne znaš više da koristiš ništa osim liste, kao što sam već napisao (jedno vreme sve si stavljao u fajlove, onda si naučio directory, pa si ga za sve koristio, onda liste, pa ne korisitš ništa drugo).

Opet ti kažem, tvoje učenje pythona NE NAPREDUJE. Zadaci koje si izabrao su "cake", ti nemaš OSNOVE...
Vrati se na udžbenik i ponovo pročitaj svako poglavlje i reši sve zadatke posle tog poglavlja. Udžbenik je napisan sistematski i polako te uvodi u problematiku (ako je dobar).
Ovako, rešavaš zadatke na preskok - zidaš kuću od krova, umesto da kreneš od temelja.

Zadatak 45, je van tvojih mugućnosti rešavanja. On ne samo da je težak za tebe, ni mnogi programeri ne bi ga rešili.
Ne samo da se bavi parsiranjem izraza, koji je sam po sebi nešto što se uči znatno kasnije nego osnove nekog programskog jezika, nego je još teži od toga. Samo parsiranje bi bilo umereno teško - recimo problem da proveriš da li su zagrade pravilno uparene. Ovo je jedan nivo iznad: parsiranje + oporavak od grešaka.
[ djoka_l @ 23.05.2020. 12:57 ] @
Stek ima DVE operacije PUSH / stavi na vrh steka, POP / skini sa vrha steka. Eventualno, PEEK / vrati vrednost sa vrha steka bez uklanjanja elementa (PEEK može da se uradi i kao POP-PUSH, ako već nećeš da implementiraš PEEK). UVEK RADIŠ SAMO SA SA VRHOM STEKA.

Ti si stek koristio kao listu, vadiš element iz sredine liste - to nije stek...
[ mjanjic @ 23.05.2020. 19:44 ] @
Problem uparivanja zagrada je vrlo nezgodan, čak i ako se radi o nekom tekstu (string), da ne pričamo o programskom kodu u kome treba pronaći da li ima zagrada viška ili manjka, jer to zavisi od sintakse programskog jezika i još nekih faktora (da li je funkcija, klasa, if/else blok, itd.).
Generalno, ako postoji neki editor koji ima podršku za to, a otvorenog je koda (npr. VSC), može se pogledati kako izlazi na kraj sa tim problemom. Ali je sigurno da ceo taj kod nije baš tako jednostavan, jer može da postoji paran broj levih i desnih zagrada, kao i da ugneždavanje bude ispravno, ali da opet neki kod ne može da se kompajlira jer su zagrade na pogrešnim mestima.


A što se tiče osnova programiranja, ne znam da li je Python uopšte pogodan za učenje programiranja u smislu algoritama, struktura podataka itd.
Ne uči se tek tako Pascal (ne znam da li ima i danas smisla) ili C na mnogim fakultetima na 1. godini.
C se možda i ne koristi toliko za razvoj aplikacija danas, možda više za neko embeded programiranje, kontrolere i sl., ali su mnogi jezici kasnije preuzeli sličnu sintaksu i koriste slične ili čak iste algoritme za pojedine probleme.



Ja sam imao (ne)sreću da sam studirao nešto levo, računarima se bavio na neki drugi način, tj. nisam se toliko zanimao za programiranje iako sam C i C++ naučio relativno dobro za neko osnovno programiranje što se tiče sintakse još pre 20-ak godina (relativno kasno, za današnje pojmove, ali tamo krajem 90-ih je reko ko imao računar kod kuće, tako da...), radio nešto totalno drugo sa drugim alatima, ali sam recimo pročitao "Programming Pearls" i još dosta sličnih knjiga u jednom dahu (više su me zanimali algoritmi i rešavanje problema sa matematičke tačke gledišta nego sama sintaksa jezika), knjiga je čak dostupna ovde: https://tfetimes.com/wp-conten...15/04/ProgrammingPearls2nd.pdf



djoka je potpuno u pravu, ako neko ne želi da na ispravan način recimo koristi ulančane/povezane liste ili dvostruko povezane liste, stek, binarno stablo, svoju implementaciju pretrage ili sortiranja, ili bilo šta drugo, nego nabudži neki kod bez pravilnog znanja o koracima pri rešavanju takvim problema, to je potpuno pogrešan put čak i za učenje sintakse nekog jezika, jer se na pogrešan način uči "programiranje", i tu naviku kasnije bude vrlo teško promeniti.

Ako je do vežbanja same sintakse, može da se koristi i nešto ovako: https://www.101computing.net/from-flowcharts-to-python-code/

A mogu i da se uzmu primeri iz zbirki zadataka za C/C++, Javu i slično, pa da se za ta rešenja prvo uradi slično/isto Python rešenje, a da se potom kod "optimizuje" korišćenjem onoga što Pythong pruža, a čega nema u tim drugim jezicima.
[ djoka_l @ 23.05.2020. 22:38 ] @
Evo rešenje, moj kohai, i slušaj šta ti kaže senpai.

Ovaj zadatak bi bio piece of cake da je trebalo da se samo proveri da li su zagrade pravilno uparene.
Bio bi tek malo teži da je izraz trebalo DOPUNITI nedostajućim zagradama.
Moje rešenje radi ono što je bio zadatak i ne samo što daje rešenje koje se dobije tako što se izbace znaci koji su najbliži početku, nego i daje najduže takvo rešenje.

Code:
# Class Stack implements stack as a list of items
class Stack:
     def __init__(self):
         self.items = []

     def isEmpty(self):
         return self.items == []

     def push(self, item):
         self.items.append(item)

     # Warning: pop from the empty stack raises exception IndexError
     def pop(self):
         return self.items.pop()

     def peek(self):
         return self.items[len(self.items)-1]

     def size(self):
         return len(self.items)



# Utility finctions

# myTranslate removes non-allowed characters from a string
# Parameters:
#     inString (string) input string
#     allowed (string) characters that are allowed
# Output (string):
#     string that contains only allowed characters from the inString
def myTranslate( inString, allowed ):
    # find ALL unique characters in input string (by convarting it into set)
    s=set(inString)
    for i in s:
        if i not in allowed:
            # remove not-allowed characters
            inString = inString.replace(i,'')
    return inString

# myTrim removes from string leading 'left' characters and trailing 'right' characters
# Parameters:
#    inString (string) input string
#    Left (string) leading characters to be removed
#    Right (string) trailing charactes to be removed
# Output (string):
#    left and right trimmed string
def myTrim( inString, Left, Right ):
    start = 0

    # find the position of the FIRST character not in "Left" and remove leading "Left" characters
    for i in range(len(inString)):
        if inString[i] not in Left:
            break 
        else:
            start+=1

    inString = inString[start:]
    
    # Find trailing "Right" characters and remove them from string
    end = 0
    for i in range(len(inString)):
        if inString[-1-i] not in Right:
            break
        else:
            end-=1

    if end == 0:
        return inString

    return inString[:end]
    
# removeChar deletes a single character from string at given position
# Parameters:
#   inString (string): input string
#   pos (int): character position 0..len(inString)-1
def removeChar( inString, pos):

    return (inString[:pos] + inString[pos+1:])


def remove_brackets(a):
    # First, lets define some constants
    OPENING  = '([{'               # List of opening brackets
    CLOSING  = ')]}'               # List of closing brackets
    BRACKETS = OPENING + CLOSING   # List of all brackets
    PAIRS    =  ['{}', '[]', '()'] # List of bracket pairs

    # Local function isValid
    # Parameters:
    #     expression (string): string that contains only brackets
    # Output (Boolean):
    #     True if all opening brackets are matched with corresponding closing brackets in order of apperance
    #     False otherwise
    # Require: Function uses class Stack

    def isValid(expression):
        s=Stack()
        for i in (expression):
            if i in OPENING:
                # opening bracket shuld be pushed to the stack
                s.push(i)
            else:
                # Closing bracket MUST be mached with the opening bracket from the non-empty stack top
                if s.isEmpty() or (s.pop() + i not in PAIRS):
                    # If pair of brackets are not mached, then expression is invalid
                    return False
        
        # if ALL brackets are matched, stack MUST be empty
        if s.isEmpty():
            return True
        # otherwise, brackets are unbalanced
        return False

    a=myTranslate( a, BRACKETS )    # Remove all non-breacket symbols from input string
    a=myTrim( a, CLOSING, OPENING)  # Remove closing brackets from the left side and opening brackets from the right side
                                    # of the input string, since they can not be matched with correcponding bracket

    # Now we have 'clean' string
    checkList = []  # list of potentionally valid bracket expressions

    # expression with balanced brackets MUST have even length, otherwise its useless to check if its valid
    if len(a)%2 == 1:
        for i in range(len(a)):
            # for odd expression length, add to checkList each substring derived from originall string by removing single character from expression
            checkList.append( removeChar( a, i ) )
    else:
        checkList.append(a)

    # Main loop - checking elements from the checkList
    # The first valid string is the result of the function.
    # In case that we checked ALL elemnts from checkList, return empty string

    while checkList != []:
        i = checkList[0]
        if isValid(i):
            # Qapla' (success in Klingon)!!! We made it!!!
            return i
        else:
            # remove the first (checked) element
            checkList.pop(0)
            # generate all substrings of checked element by removing TWO characters from the expression
            # and adding resulting string to the end of list
            for j in range(len(i)-1):
                for k in range(j+1, len(i)):
                    newstring = removeChar( i, k )
                    newstring = removeChar( newstring, j )
                    if newstring not in checkList:
                        checkList.append( newstring )
    
    # we chacked all posible substrings without success
    return ''
   
if __name__ == '__main__':
    print("Example:")
    print(remove_brackets('(()()'))

    # These "asserts" are used for self-checking and not for an auto-testing
    assert remove_brackets('(()()') == '()()'
    assert remove_brackets('[][[[') == '[]'
    assert remove_brackets('[[(}]]') == '[[]]'
    assert remove_brackets('[[{}()]]') == '[[{}()]]'
    assert remove_brackets('[[[[[[') == ''
    assert remove_brackets('[[[[}') == ''
    assert remove_brackets('') == ''
    print("Coding complete? Click 'Check' to earn cool rewards!")


Rezultat:
Code:
py .\rb.py
Example:
()()
Coding complete? Click 'Check' to earn cool rewards!



[Ovu poruku je menjao djoka_l dana 23.05.2020. u 23:51 GMT+1]
[ dejanet @ 24.05.2020. 17:00 ] @
Sa moje strane u C#(trudio sam se da bude citljivo svima).

Koristio sam Queue umest Stack, tj FIFO.

Code:

using System;
using System.Collections.Generic;

namespace INERPRETER_Brackets
{
    class Program
    {
        static bool IsBracket(char c, char lParen, char rParen)
        {
            return (c == lParen) || (c == rParen);
        }

        static bool IsValidString(string str, char lParen, char rParen)
        {
            int cnt = 0;
            for (int i = 0; i < str.Length; i++)
            {
                if (str[i] == lParen)
                    cnt++;
                else if (str[i] == rParen)
                    cnt--;
                if (cnt < 0)
                    return false;
            }
            return (cnt == 0);
        }

        static void RemoveInvalidBracketsByParen(ref string str, char lParen, char rParen)
        {
            if (str == null || str == "")
                return ;

            // zapamti visited string 
            HashSet<string> visit = new HashSet<string>();

            // queue 
            Queue<string> q = new Queue<string>();
            string temp;

            // pushing string kao start node u queue 
            q.Enqueue(str);
            visit.Add(str);
            while (q.Count != 0)
            {
                str = q.Peek(); q.Dequeue();
                if (IsValidString(str, lParen, rParen))
                {
                    return;
                }

                for (int i = 0; i < str.Length; i++)
                {
                    if (!IsBracket(str[i], lParen, rParen))
                        continue;

                    // remove zagradu iz str i gurni u queue ako nije obradjen ranije
                    temp = str.Substring(0, i) +
                           str.Substring(i + 1);
                    if (!visit.Contains(temp))
                    {
                        q.Enqueue(temp);
                        visit.Add(temp);
                    }
                }
            }
        }

        static string RemoveInvalidBrackets(string str)
        {
            RemoveInvalidBracketsByParen(ref str, '(', ')');
            RemoveInvalidBracketsByParen(ref str, '[', ']');
            RemoveInvalidBracketsByParen(ref str, '{', '}');
            return str;
        }

        public static void Main(string[] args)
        {
            Console.WriteLine($"'{RemoveInvalidBrackets("(()()")}'");
            Console.WriteLine($"'{RemoveInvalidBrackets("[][[[")}'");
            Console.WriteLine($"'{RemoveInvalidBrackets("[(}]]")}'");
            Console.WriteLine($"'{RemoveInvalidBrackets("[[{}()]]'")}");
            Console.WriteLine($"'{RemoveInvalidBrackets("[[[[[[")}'");
            Console.WriteLine($"'{RemoveInvalidBrackets("[[[[}")}'");
            Console.WriteLine($"'{RemoveInvalidBrackets("")}'");

        }
    }
}



Output
Code:

'()()'
'[]'
'[]'
'[[{}()]]'
''
''
''
[ a1234567 @ 25.05.2020. 17:59 ] @
Idemo dalje...

Zadatak 46: YAML

Have you ever heard of such markup language as YAML? It’s a friendly data serialization format.
In fact it’s so friendly that both people and programs can read it quite well. You can play around
with the standard by following this link.

YAML is a text, and you need to convert it into an object. But I’m not asking you to implement
the entire YAML standard, we’ll implement it step by step.

The first step is the key-value conversion. The key can be any string consisting of Latin letters and numbers.
The value can be a single-line string (which consists of spaces, Latin letters and numbers) or a number (int).

I’ll show some examples:

name: Alex
age: 12


Converted into an object.

{
"name": "Alex",
"age": 12
}


Note that the number automatically gets type int
Another example shows that the string may contain spaces.

name: Alex Fox
age: 12

class: 12b


Will be converted into the next object.

{
"age": 12,
"name": "Alex Fox",
"class": "12b"
}


Pay attention to a few things. Between the string "age" and the string "class" there is an empty string that doesn’t interfere with parsing.
The class starts with numbers, but has letters, which means it cannot be converted to numbers, so its type remains a string (str).

Input: A format string.
Output: An object.
Precondition: YAML 1.2 is being used with JSON Schema.

Code:
def yaml(a):
    # your code here
    return None


if __name__ == '__main__':
    print("Example:")
    print(yaml("""name: Alex
age: 12"""))

    # These "asserts" are used for self-checking and not for an auto-testing
    assert yaml("""name: Alex
age: 12""") == {'age': 12, 'name': 'Alex'}
    assert yaml("""name: Alex Fox
age: 12

class: 12b""") == {'age': 12,
 'class': '12b',
 'name': 'Alex Fox'}
    print("Coding complete? Click 'Check' to earn cool rewards!")


Moje rešenje je ovde.
[ B3R1 @ 26.05.2020. 13:16 ] @
YAML sam ti vec pomenuo u ovom postu. Puna specifikacija je prilicno slozena, zato i postoji 'yaml' modul kojim se sve to resava. Ali dobro, poenta je ovde vezbanje pythona. Par napomena:
Code (python):
    a = [i for i in a if len(i) != 0]
    a = sorted(a)

Cemu ovo gore? Primecujem da bas u svaki program ubacujes "list comprehension", cak i tamo gde tome nije mesto. S druge strane, onda jos i sortiras kljuceve. To su dva nepotrebna koraka kojima samo usporavas program. Ispitivanje da li je red prazan si mogao da ubacis i u "for" petlju, nakon linije 7. Nema potrebe prolaziti vise puta kroz petlju.

Druga stvar: tvoj program (linije 10-12) ne radi ono sto se trazilo u zadatku:
Citat:
The value can be a single-line string (which consists of spaces, Latin letters and numbers) or a number (int).

Ti umesto toga ispitujes da li je kljuc == 'age' i ako jeste konvertujes njegovu vrednost u int, dok npr. 'class' moze da bude isto tako int ... Ti treba da ispitas da li je vrednost (desno od dvotacke) int ili str i ako je int treba da primenis int() funkciju.
[ a1234567 @ 26.05.2020. 16:13 ] @
Berislave, hvala na komentarima.

Bio sam pod utiskom da treba sortirati, jer se redosled ulaznih i izlaznih podataka razlikuje.

Evo sad sam napravio apdejtovanu verziju i sve radi.

Code:
def yaml(a):
    recnik = {}
    b = []
    a = a.split('\n')
    a = sorted(a)
    for i in a:
        if len(i) != 0:
            b = i.split(':')
            recnik[b[0]] = b[1].strip()
    for k, v in recnik.items():
        if v.isdigit():
            recnik[k] = int(v)
        else:
            recnik[k] = v
    return recnik 
[ B3R1 @ 26.05.2020. 17:42 ] @
Dobro, to je vec bolje. Ali moze jos bolje. Opet imas dve petlje, a sve mozes da uradis u jednom potezu. Lepo si razdvojio kljuc i vrednost koristeci split(). Zasto nisi odmah ispitao da li je b[1] numericki podatak ili ne. I ako jeste, da ga odmah prebacis u int. Takodje, strip() je trebalo da primenis ranije, jer u suprotnom 'if len(i)' ce proci takve redove i imaces gresku kod funkcije split(). Znaci:
    for i in a:
i = i.strip()
if len(i) and (':' in i):
b = i.split(':')
if b[1].isdigit():
b[1] = int(b[1])
recnik[b[0]] = b[1]
return recnik

Cilj kodiranja je da sa manje prostijih alata postignes sto vise i napravis sto brzi i efikasniji program, a ne da hiltijem busis rupetinu u zidu samo da bi okacio nesto tesko 50 grama, sto si mogao da zavrsis i obicnim cekicem i ekserom.

Vezano za "less is more", evo ti jedne mozgalice, nije tesko: data je celobrojna pozitivna (int) varijabla n, n >= 0. Napisi program koji umanjuje n za 1 ako je n neparno, a uvecava ga za 1 ako je parno, ali tako da koristis sto manje karaktera (razmaci se ne broje, kao ni unos i ispis, treba mi samo kod koji ispituje i menja vrednost n). Na primer, ako je n = 49, kod treba da vrati 48, ako je npr. 62 kod treba da vrati 63. Da vidimo koliko ti karaktera treba da napravis taj kod. Mozes da koristis sve strukture podataka, sve operatore, sve module ... sve sto Python ima. I sve alate. Ukljucujuci i hilti ... :-)))
[ djoka_l @ 26.05.2020. 19:59 ] @
Citat:
Bio sam pod utiskom da treba sortirati, jer se redosled ulaznih i izlaznih podataka razlikuje.

Imao si pogrešan utisak. Ako nisi siguran, proveri:
Code:
 py
Python 3.7.4 (tags/v3.7.4:e09359112e, Jul  8 2019, 20:34:20) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> print( {"age":20, "sex":"male"} == { "sex":"male", "age":20} )
True
>>>
[ a1234567 @ 28.05.2020. 13:08 ] @
Citat:
B3R1:

Vezano za "less is more", evo ti jedne mozgalice, nije tesko: data je celobrojna pozitivna (int) varijabla n, n >= 0. Napisi program koji umanjuje n za 1 ako je n neparno, a uvecava ga za 1 ako je parno, ali tako da koristis sto manje karaktera (razmaci se ne broje, kao ni unos i ispis, treba mi samo kod koji ispituje i menja vrednost n). Na primer, ako je n = 49, kod treba da vrati 48, ako je npr. 62 kod treba da vrati 63. Da vidimo koliko ti karaktera treba da napravis taj kod. Mozes da koristis sve strukture podataka, sve operatore, sve module ... sve sto Python ima. I sve alate. Ukljucujuci i hilti ... :-)))

Ovako nešto?
Code:
if n % 2 == 0:
    print(n + 1)
else:
    print(n - 1)

[ djoka_l @ 28.05.2020. 14:04 ] @
Code:
n+=1-(n%2)*2
[ B3R1 @ 28.05.2020. 17:15 ] @
@a1234567:

Ti si iskoristio 29 karaktera i resio si ga bas skolski ... Ideja je bila da uradis sa sto manje karaktera.
Djoka je iskoristio 12 karaktera i pokazao ono sto sam hteo da kazem: ponekad kada resavas probleme moras da zaviris i ispod haube, gde se nalazi matematika. Kao sto su ti ljudi rekli: strukture podataka, matematicke operacije ...

Medjutim, ima i jos krace resenje ... zahteva svega 4 znaka. Ali da bi to resio treba se podsetiti cinjenice da su svi brojevi kojima Python i ostali jezici barataju zapravo nizovi jedinica i nula. Na primer, broj 12 je zapravo 1010 (binarno), dok je 13 zapravo 1011. U cemu se razlikuju? Kao sto vidis, samo u poslednjem bitu - parni broj ima 0, neparni 1. U opstem slucaju svaki integer mozes da predstavis kao niz bita u formi bb...bb0 ili bb...bb1, gde je deo "bb...bb" zajednicki u oba slucaja. Tebi treba operacija koja te vodece 'b' bite nece dirati, dok ce poslednji bit kao je 0 pretvoriti u 1 i obrnuto - ako je 1 da ga pretvori u 0. Za manipulacije na nivou bita u Pythonu zaduzeni su bitwise operatori. Ako uzmes XOR (^) videces da on daje rezultat koji tebi treba.
bbbbb0 ^ 000001 = bbbbb1
bbbbb1 ^ 000001 = bbbbb0
Shodno tome:
n=n^1
odnosno:
n^=1

Isti problem, nekoliko resenja, izbegavanje nepotrebnih koraka. Kao sto smo vec to rekli: osnovna aritmetika, logika, strukture podataka, pocev od najprostijih kakvi su celi brojevi, preko slozenijih (liste, hash tabele) do onih najslozenijih (ulancane liste, stabla ...). Jednom kada to savladas shvatices koju alatku kada koristiti i zasto.
[ a1234567 @ 28.05.2020. 18:01 ] @
Shvatam tvoju poentu. Pojednostavljivanje. I to je nešto čemu treba težiti.

Ali ja sam još na nivou da sam srećan ako uopšte znam kako da rešim neki zadatak.
Mnogo je onih za koje ne znam ni kako da krenem.

Verovatno ću kroz praksu doći i do nivoa da razmišljam o pojednostavljivanju.
Kad nešto uradiš sto puta, prirodno je da kreneš da razmišljaš, hej, jel može
to nekako jednostavnije!? Kao što je bilo sa ovim for petljama. Već sam ih toliko
napisao, a onda naiđem na list comprehension i vidim, može i tako. Super,
umesto tri reda, napišem jedan i idemo dalje.

Sve je to praksa. Ali meni još ostaje mnogo rada da uošte celu sintasu jezika
ili bar njene glavne delove prođem tih 100 puta, pa da onda krenem da
mozgam o pojednostavljivanju. U ovom trenutku mi je mnogo realniji zadatak
da recimo eliminišem primere kakav je bio poslednji zadatak, da ne prolazim petlju
dva puta ako može samo jednom. Već to će biti veliki korak za mene :)
[ B3R1 @ 29.05.2020. 13:23 ] @
Citat:
Shvatam tvoju poentu. Pojednostavljivanje. I to je nešto čemu treba težiti.

Da, ali nije sve samo u tome, vec u tome da ti se fragmenti znanja koje usvajas svakim danom sloze na pravom mestu u glavi. Ti si naucio prve engleske reci i odmah si uzeo Šekspira. Ili još gore, uzeo si Čoserove Kenterberijske priče, koje svega 5% visoko obrazovanih rodjenih Engleza ume da procita i uopste shvate sta su tu procitali. Na tom nivou mozda ces i uspeti da shvatis neka poglavlja, ali da sklopis celinu od svega toga - hm, tesko.

Tako je to i u programiranju. Cilje je da savladas dobro osnove, tako da kada ti se pojavi problem tacno znas da li da koristis listu, recnik ili mozda najobicniji int/float/str ... stvari tipa "list comprehension" su trikovi, ali oni ti nece pomoci ako ne shvatis OSNOVE. A osnove su da su brojevi nizovi jedinica i nula. Da je svako slovo ('A', 'B', 'C' itd. takodje niz jedinica i nula kodirana ASCII kodom. Recimo, 'A' je 65 (decimalno), odnosno 01000001, 'B' je 66 (odnosno 01000010) itd. Koliko slova ima izmedju A i M, ne racunajuci sama slova A i M? Kako ces to prebrojati? Da, verovatno ces reci:
Code:
alfabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
broj = alfabet.find('M') - alfabet.find('A') - 1

dok ce neko ko je ucio programiranje od temelja, kako i dolikuje, znati da kaze:
Code:
broj = ord('M') - ord('A') - 1

Zato sto zna da je svako slovo interno predstavljeno ASCII kodom i da se ASCII kod slova x dobija funkcijom ord(x), a karakter ciji je ASCII kod n se dobija funkcijom chr(n).

Kada naucis te stvari, na redu su slozenije. Recimo, upravljanje datumima i vremenom. Koliko je dana proteklo od Bozica do Uskrsa ove godine? Ili - zadatak sa casova programiranja iz srednje skole iz vremena mog skolovanja: ispisati vremena u toku dana (hh:mm:ss) kada se kazaljke na satu poklope. Ideja je da naucis manipulaciju vremenima i module time i datetime. A mozes i pesice, koristeci samo int i float ... Moja preporuka bi bila da pocnes od tog "pesackog" nacina.

Onda dolaze na red liste. Taman mislis da si naucio liste i krenes:
Code:

>>> a = [1, 2, 3]
>>> b = a
>>> b
[1, 2, 3]

Bas lepo radi. Ali onda u listu a dodas jos jedan element:
Code:

>>> a.append(10)
[1, 2, 3, 10]
>>> b
[1, 2, 3, 10]

WTF?! Zasto? Kako?! Odakle???!!! Pa ja sam azurirao listu a, listu b nisam ni taknuo - zar ne? A pazi sad ovo - hocu da izbrisem treci element liste b:
Code:

>>> del b[2]
>>> b
[1, 2, 10]
>>> a
[1, 2, 10]

Hmmm ... izgleda da sam ja nekako "vencao" ove dve liste, pa kud svi Turci tu i mali Mujo? E vidis, tu vec moras da zaviris malo i ispod haube. Neke slozenije strukture u Pythonu (liste, skupovi i recnici) se ponasaju malcice drugacije od nekih drugih (int, float, str, bool ...). Eventualno, naici ces na neko brzinsko objasenjenje, poput ovog ovde. Ok, covek je to objasnio na bazicnom nivou, cisto da ukapiras da kada imas listu a, pa kazes b=a, ti zapravo ne kopiras VREDNOST liste a u listu b, vec postavis POINTER liste b tamo gde je a. Ako ti treba kopija liste to mozes da uradis na vise nacina, covek je to lepo objasnio - npr:
Code:
a = [1,2,3]
b = list(a)

Ovim si dobio dve nezavisne liste, sto mozes da proveris i ako u Python shellu otkucas id(a), odnosno id(b). Tako, da ako sada dodajes elemente listi a lista b se nece menjati. Identicno se ponasaju i recnici, odnosno hash tabele:
Code:
>>> a={'name': 'John'}
>>> b=a
>>> a
{'name': 'John'}
>>> b
{'name': 'John'}
>>> a['surname']='Doe'
>>> a
{'surname': 'Doe', 'name': 'John'}
>>> b
{'surname': 'Doe', 'name': 'John'}

Ali zato:
Code:

>>> a={'name': 'John'}
>>> b=dict(a)
>>> a
{'name': 'John'}
>>> b
{'name': 'John'}
>>> a['surname']='Doe'
>>> a
{'surname': 'Doe', 'name': 'John'}
>>> b
{'name': 'John'}

I time si shvatio stvar ... mozda ... onako povrsno. Da bi shvatio stvari do kraja moras da se udubis jos vise u nacin na koji je Python implementiran. Lep tekst na tu temu je dat ovde.

Kada to ukapiras, onda ces umeti da objasnis razliku izmedju ovog koda:
Code:

>>> def modify(b):
...     b.append(3)
...
>>> a=[1,2]
>>> modify(a)
>>> a
[1, 2, 3]

i ovog drugog:
Code:

>>> def modint(x):
...     x += 1
...
>>> y = 3
>>> y
3
>>> modint(y)
>>> y
3
>>>

Iskusniji programeri, koji su vec prosli kroz nekoliko drugih, klasicnih programskih jezika, znaju za princip prenosa argumenata po vrednosti i po imenu (referenci, deskriptoru ...). U prvi mah ce shvatiti da Python prenosi skalare (bool, int, float ...) po vrednosti, a vektore (lists, dicts, sets) po referenci. Kasnije, kada se udubi u materiju, shvatice zasto je to tako. Odgovor je dat i ovde. Opet - rec je o PRINCIPU koji se uci. Jednom kada to savladas, shvatices kako to radi i u nekim drugim jezicima.

Ovo sto sam ti opisao gore su tek samo mali detalji. Kockice mozaika ... A ti detalji mogu da ti upropaste program koji pises do te mere da ga analiziras danima i uopste ne kapiras zasto ne radi ... a u pitanju su neke banalne stvari koje nisu naucio u pocetku, jer si krenuo da ucis Python s krajeva.

Mislim da je sada vreme da malo iscitas poglavlja o strukturama podataka i shvatis kako stvari funkcionisu u Pythonu. Usput mozes da radis i zadatke iz te zbirke, ali bez solidnog razumevanja teorije tapkaces u mestu ...

Nemoj ovo da shvatis kao neko pametovanje. Svi smo prosli manje-vise kroz tu istu metodu uzaludnih pokusaja u svojim prvim programerskim koracima. Pre ili kasnije smo shvatili da smo izgubili dosta vremena, pa smo seli i ucili ...

[Ovu poruku je menjao B3R1 dana 29.05.2020. u 16:28 GMT+1]