elemental_fighters
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| elemental_fighters [2025/10/30 13:52] – mbunic | elemental_fighters [2025/12/01 11:40] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ==== Elemental Fighters ==== | + | ==== Zadatak s Hacknite platforme - Elemental Fighters ==== |
| - | < | + | Uz zadatak je dan i izvorni kod. |
| - | Možete li odabrati pravog borca i pobijediti sve neprijatelje? | + | |
| - | Spoji se Linux naredbom nc chal.hacknite.hr 12037 ili Windows naredbom telnet chal.hacknite.hr 12037 | + | |
| - | </ | + | |
| - | Uz zadatak | + | Spajanjem na zadatak |
| - | Spajanjem na zadatak otvara se izbor borca. Mogući | + | {{ elemental_fighters: |
| - | {{ : | + | Analizom koda u zadatku može se zaključiti da zapravo ne postoji kombinacija borca koja bi ni u najsretnijem slučaju uspjela pobijediti sve neprijatelje i doći do flaga, to znači da je potrebno nešto drugo učiniti jer ne postoji |
| - | No analizom | + | Analizom |
| - | Analizom koda zanimljiva je varijabla **s**, koja je “scale”, | + | {{ elemental_fighters: |
| - | {{ : | + | Ova varijabla |
| - | Ova varijabla se kasnije u kodu množi s atributima neprijatelja: | + | Također zanimljiv dio koda je player default, koji definira player varijablu kao **Milo(" |
| - | Također, zanimljiv dio koda je **player default**, koji definira varijablu *player* kao *milo(" | + | {{ elemental_fighters: |
| - | {{ :slika3.png? | + | Ključan dio koda je funkcija kojom se inicijalizira player varijabla iz izbora igrača. |
| - | Najključniji dio koda je funkcija kojom se inicijalizira varijabla *player* iz izbora | + | {{ elemental_fighters: |
| - | {{ :slika4.png? | + | Ovdje se može vidjeti da se koristi funkcija **eval**, kojime se fighter unos poziva kao funkcija, a fighterType kao argument. |
| - | Ovdje se može vidjeti da se koristi **eval** funkcija, kojom se *fighter* unos poziva kao funkcija, a *fighterType* kao argument. | + | Može se vidjeti da su fighteri zapravo funkcije: |
| - | Sukladno tome, može se vidjeti da su *fighteri* zapravo funkcije: \\ | + | {{ elemental_fighters:slika5.png? |
| - | {{ : | + | a fighterType vrijednosti su definirane u rječniku, te se parsiraju pri pozivanju |
| - | Vrijednosti *fighterType* definirane su u rječniku te se parsiraju pri pozivanju *fighter* | + | To znači da je unosom fighterType (" |
| - | To znači da se unosom *fighterType* (“Odaberite element borca”) zapravo definira argument funkcije, a unosom *fighter* (“Odaberite borca”) definira funkcija | + | Svaki unos prolazi kroz validate_input funkciju, koja je filter koji određuje koji su unosi dozvoljeni, a koji nisu. |
| - | No svaki unos prolazi kroz **validate_input**, | + | {{ elemental_fighters: |
| - | {{ : | + | Kako bi provjerili |
| - | + | ||
| - | Kako bismo provjerili možemo | + | |
| < | < | ||
| Line 48: | Line 43: | ||
| </ | </ | ||
| - | < | + | Odaberite element borca (Ice, Fire, Acid): aaaa |
| - | Odaberite element borca (Ice, Fire, Acid): aaaa | + | |
| Odaberite borca (Zorn, Krev, Milo)list | Odaberite borca (Zorn, Krev, Milo)list | ||
| - | </ | ||
| - | {{ : | + | {{ elemental_fighters: |
| - | Vidimo da je program vratio listu u kojoj se nalaze svi znakovi iz stringa koji smo poslali kao prvi argument, te oko njih znakovi zagrada | + | Vidimo da je program vratio listu u kojoj se nalaze svi znakovi iz stringa koji smo poslali kao prvi argument, te oko njih znakovi za zagrade, koji su znakovi zagrada oko fighterType varijable (vidi sliku 4). |
| - | Slično, možemo pozvati: | + | Slično |
| < | < | ||
| len(" | len(" | ||
| </ | </ | ||
| + | |||
| + | Poziva se na ovakav način. | ||
| < | < | ||
| - | Odaberite element borca (Ice, Fire, Acid): aaa | + | Odaberite element borca (Ice, Fire, Acid): aaa |
| Odaberite borca (Zorn, Krev, Milo)len | Odaberite borca (Zorn, Krev, Milo)len | ||
| </ | </ | ||
| - | {{ : | + | {{ elemental_fighters: |
| - | Vidimo da program vraća 5, što odgovara trima znakovima "a" | + | Vidimo da program vraća 5, što je točno 3 znakova |
| - | No flag nije zapisan | + | Flag nije zapisan |
| - | Dobar pristup | + | Dobar pristup bi bio mijenjanje varijable **s** na slici 2, koja je skala jačine protivnika. Ako bi tu varijablu mogli smanjiti ili pretvoriti u 0, protivnici bi bili puno slabiji, dok činjenica da je unos potrošen na mijenjanje varijable |
| - | No cijeli | + | Cijeli |
| - | Potrebno je pronaći način kako mijenjati druge varijable u globalnom kontekstu programa (poput varijable *s*) unutar **eval** funkcije, čiji se rezultat pridružuje varijabli *player*. | + | < |
| + | " | ||
| + | </ | ||
| - | Osim **expressiona** koje izvršava *eval*, u Pythonu postoji i **statement**, | + | vraćena vrijednost je 4, |
| - | Slično **eval**, postoji funkcija **exec**, koja je namijenjena za izvršavanje *statementa* (ali može izvršavati i *expressione*). Ona može definirati ili mijenjati varijable u globalnom kontekstu programa ako se pokreće u globalnom kontekstu. | + | < |
| - | Primjer: `exec(" | + | len(" |
| - | Pregledom funkcije za validaciju unosa (slika | + | </ |
| + | |||
| + | vraćena vrijednost je 5, i bilo koja vrijednost koja će biti vraćena nakon izvršavanja ekspresije u **eval** funkciji će biti pridružena varijabli **player** (vidi sliku 4). | ||
| + | |||
| + | Potrebno je pronaći način kako mijenjati druge varijable u globalnom kontekstu programa, kao varijablu **s**, unutar **eval** funkcije, čiji se rezultat izvršavanja pridružuje varijabli **player**. | ||
| + | |||
| + | Osim **expression** u Pythonu, koji izvršava izraz i vraća izračunatu vrijednost izraza, postoji i **statement**, | ||
| + | |||
| + | Primjer **statement-a** | ||
| + | |||
| + | < | ||
| + | a = 0 | ||
| + | </ | ||
| + | |||
| + | , no pošto **statement** ne vraća ništa | ||
| + | |||
| + | < | ||
| + | b = (a = 0) | ||
| + | </ | ||
| + | |||
| + | je neispravan Python kod, kao što bi bilo i da se eval koristio. | ||
| + | |||
| + | < | ||
| + | eval(" | ||
| + | </ | ||
| + | |||
| + | (probajte u Python interpreteru). | ||
| + | |||
| + | Slično | ||
| + | |||
| + | < | ||
| + | exec(" | ||
| + | </ | ||
| + | |||
| + | Pregledom funkcije za validaciju unosa na slici 6 vidi se da funkcija **exec** nije zabranjena. | ||
| - | Dakle, | + | Znači da se funkcija |
| - | Iz ovoga se može zaključiti da bi potencijalno | + | Iz ovoga se može zaključiti da potencijalni način |
| < | < | ||
| Line 94: | Line 125: | ||
| </ | </ | ||
| - | Unos bi izgledao ovako: | + | Čime bi unos izgledao ovako: |
| < | < | ||
| Line 101: | Line 132: | ||
| </ | </ | ||
| - | Pokretanjem ovog unosa (slika | + | Pokretanjem ovog unosa, prikazanog na slici 9, pojavljuje se greška. |
| - | {{ : | + | {{ elemental_fighters: |
| - | Greška je *invalid syntax*, koju zapravo baca parser **eval** funkcije. On pregledava kod prije izvršavanja | + | Greška je invalid syntax, koju zapravo baca parser **eval** funkcije, koji pregledava kod prije nego će se izvršiti da odredi |
| - | Opisana ponašanja | + | Opisana ponašanja su prikazana |
| - | {{ : | + | {{ elemental_fighters: |
| - | Na slici je prikazano da **eval** može izvršiti | + | Na slici je prikazano da **eval** može izvršiti: |
| - | Može se zaključiti da je cilj napisati takav kod koji će **eval** parser odobriti, | + | < |
| - | Ovdje pomaže činjenica da **exec** može izvršavati i *expression*, | + | a==3 |
| + | </ | ||
| - | Način da se to postigne je korištenjem Pythonovog | + | jer je to zapravo validan |
| - | {{ : | + | Način kako se ovo može postići je korištenjem Pythonovog "walrus" operatora, koji je zapravo **expression**, |
| - | Na slici 11. može se vidjeti kako funkcionira *walrus* operator. On evaluira izraz `1 == 1`, što je `True`, tu vrijednost vraća kao rezultat *if* statementu, ali istovremeno postavlja tu vrijednost varijabli *a*. | + | Walrus operator |
| - | *Walrus* operatorom se može napisati validan *expression* koji nakon evaluacije mijenja vrijednost odabrane varijable (npr. varijable *s*). | + | {{ elemental_fighters: |
| - | No *walrus* operator se ne može sam izvršavati unutar **eval** | + | Na slici 11 može se vidjeti kako funkcionira |
| - | Ako se stave zagrade oko njega, izraz | + | |
| + | Walrus operatorom se može napisati validan **expression**, | ||
| + | |||
| + | Walrus | ||
| + | |||
| + | {{ elemental_fighters: | ||
| + | |||
| + | No ako se stave zagrade oko njega, izraz: | ||
| < | < | ||
| Line 131: | Line 170: | ||
| </ | </ | ||
| - | postaje validan *expression*, | + | postaje validan |
| + | |||
| + | {{ elemental_fighters: | ||
| + | |||
| + | Ovo je slučaj i u kodu zadatka, zato što se oko unosa dodaju zagrade, što je prikazano na slici ispod. | ||
| + | |||
| + | {{ elemental_fighters: | ||
| - | {{ : | + | Kada su zagrade oko unosa, unutar zagrada mora biti validan **expression**, |
| - | Ovo je zapravo slučaj u kodu zadatka, jer se oko unosa dodaju zagrade (vidi sliku ispod). | + | {{ elemental_fighters: |
| - | Kada su zagrade oko unosa, unutar njih mora biti validan *expression*. | + | To čini ovaj pristup neizvedivim: |
| - | `s=0` to nije jer je *statement*, | + | |
| < | < | ||
| Line 145: | Line 189: | ||
| </ | </ | ||
| - | nije moguće. | ||
| - | Ali *walrus* | + | " |
| - | Zato se može izvršiti i ovako: | + | {{ elemental_fighters: |
| + | |||
| + | I zato se također | ||
| + | |||
| + | {{ elemental_fighters: | ||
| + | |||
| + | Što je, uz dodavanje zagrada, zapravo ekvivalentno ovom kodu: | ||
| + | |||
| + | {{ elemental_fighters: | ||
| + | |||
| + | Odnosno ovome, nakon zamjene stringova da se sve vidi u jednoj liniji: | ||
| + | |||
| + | {{ elemental_fighters: | ||
| + | |||
| + | I ovo je format inicijalizacije **player** varijable u zadatku, pa time i rješenja ovog zadatka; ove zagrade su iste kao i u liniji koda inicijalizacije **player** varijable **eval** funkcijom na slici 4. | ||
| + | |||
| + | Nakon toga se mogu raditi daljnje redukcije, zamjenom **eval** funkcije i njenih argumenata s ekvivalentnim kodom, pa primjenom istog postupka za **exec** funkciju s proslijeđenim argumentima. Nakon redukcija ta linija koda postaje ekvivalentna samo walrus operatoru unutar zagrada. | ||
| + | |||
| + | {{ elemental_fighters: | ||
| + | |||
| + | Sada je poznato rješenje i način kako rješava zadatak. | ||
| + | |||
| + | Rješenje se može unijeti | ||
| < | < | ||
| Line 156: | Line 221: | ||
| </ | </ | ||
| - | Time se izvršava postupak koji postavlja varijablu | + | Izvršava se prethodno opisan |
| + | |||
| + | {{ elemental_fighters: | ||
| + | |||
| + | ==== Eval / Exec i global scope ==== | ||
| + | |||
| + | Budući da je ovo izvršeno u global scopeu, **exec** može promijeniti vrijednost scale varijable **s**, dok, da se izvršavao unutar funkcije, ne bi mogao promijeniti niti lokalnu varijablu unutar istog scopea kao funkcija. | ||
| - | Ovo ne bi bilo moguće bez *walrus* operatora jer **eval** parser vidi samo *statement*, | + | {{ elemental_fighters: |
| - | Pošto se ovo izvršava u **global scopeu**, **exec** može promijeniti vrijednost globalne varijable *s*. | + | Dok je pri izvršavanju |
| - | Da se izvršavalo unutar funkcije, ne bi moglo promijeniti ni lokalne varijable u istom *scopeu*. | + | |
| - | Pri izvršavanju u globalnom *scopeu* ovo postaje moguće i daje konačno rješenje zadatka. | + | {{ elemental_fighters: |
| + | Ovo pravilo vrijedi i za **eval** i za **exec**, obje funkcije mogu mijenjati globalne varijable samo kada se izvršavaju u globalnom scopeu. | ||
elemental_fighters.1761832333.txt.gz · Last modified: 2025/12/01 11:40 (external edit)