Sur Ba Programming Challenge
Kedves mindenki,
Azt találtam ki, hogy megtanítom SurBát kesztyűbe dum programozni. Ebből a célból pedig majd egyre gonoszabb és gonoszabb programozási kihívásokkal gyötröm majd pókhálós agyát. De hogy ne csak neki jusson a jóból, mindenki részt vehet a vidámságban!
Általános megjegyzések
- A csellendzs Python nyelven fog zajlani, egyrészt mert a Python elhíresült arról, hogy jó oktató nyelv, másrészt mert így nekem is lesz valami kihívás benne, lévén ezen sorok írásakor még nem tudok saját Pythonul.
- Egy használható Python bevezető található a http://www.learnpython.org oldalon. Ebből a "Hello, World!" fejezettől a "Functions" fejezetig érdemes megemészteni az ott találhatóakat.
- Web programozás és rajzolás lesz a téma!
2017.VII.23
Adásszünet
Kedves nézőink,
Megszakítjuk adásunkat, hogy bosszantsuk Önöket.
Továbbá: http://spectrum.ieee.org/static/interactive-the-top-programming-languages-2017
Üdvözlettel,
A rendező gárda.
2017.VI.29
A rekurziótól begolyózom
#!/usr/bin/python
import cgi
import cgitb
cgitb.enable()
form = cgi.FieldStorage()
def get_int_param(name, default):
val = form.getvalue(name)
if (val is None):
return default
return int(val)
def draw_circle(cx, cy, r):
return '<circle cx="%f" cy="%f" r="%f" style="fill: none; stroke: #000000; " stroke-width="%d" />' % (cx, cy, r, 1)
def draw_circle_fractal(cx, cy, r, depth):
result = draw_circle(cx, cy, r);
if (depth > 0):
r2 = r * 0.464101615
r3 = r2 * 0.5773502690
result = result + draw_circle_fractal(cx, cy - r + r2, r2, depth - 1)
result = result + draw_circle_fractal(cx - r2, cy + r3, r2, depth - 1)
result = result + draw_circle_fractal(cx + r2, cy + r3, r2, depth - 1)
return result
print """Content-type: image/svg+xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 600 600"
version="1.1"
height="600"
width="600">
<g>%s</g>
</svg>
""" % draw_circle_fractal(300, 300, 300, get_int_param("depth", 4));
http://apocalypse.rulez.org/~upi/surba/circles.py?depth=2 [source]
http://apocalypse.rulez.org/~upi/surba/circles.py?depth=6 [source]
(Lehetőleg 6 feletti mélységben NE, mert megdöglik a számítógép!)
Hát húha. Itt egy csomó minden történt, ami eddig nem történt. Én meg nem szeretem, ha a dolgok másmilyenek! Lássuk, mi minden újdonsággal szolgál a mai csoda!
Függvények: Eddig csak a Python saját beépített függvényeit használtuk fel, mint pl az int
, valamint a könyvárból előcsemegézett függvényeket, mint a cgi.FieldStorage
. Eljött most az ideje, hogy sajátokat is csináljunk. Például, a get_int_param
azt a bravúrt oldja meg nekünk, hogy beolvas és rögtön egész számmá alakít egy paramétert nekünk, ha pedig hiányozna (None
az értéke), akkor egy alapértelmezett számot ad vissza helyette.
Ráadásul a függvények más függvényeket is meg tudnak hívni, például a draw_circle_fractal
meghívja a draw_circle
nevűt. Ha egy függvény pedig önmagát hívja meg, akkor azt rekurzív függvénynek hívjuk, és rettegünk tőle, hogy nehogy végtelen ciklust eredményezzen.
String formattálás: Eddig stringeket csak a +
operátorral rakosgattunk össze. Van egy kényelmesebb módszer is: a formattálás, ami a stringet követő %
operátorral működik. Fedezzük fel ennek a rejtelmeit!
Feladatok
- Mi a szent szar a 0.464101615 és 0.5773502690? Ezek hogyan jöttek ki az UPinak?
- Legyen paraméterezhető a körök vonalvastagsága, alapértelmezetten legyen 1.
- A páros mélységben található köröket töltsük ki kék, a páratlanokat zöld színnel.
- Ne három kör legyen egyben, hanem négy.
- Bónusz feladat: Ne is, inkább öt!
- Bónuszabb feladat: Rajzoljuk ki a Koch-görbét.
- Legbónuszabb feladat: Rajzoljuk ki a Sárkány-görbét.
2017.VI.28
Ha egy listát tudnék vezetni az összes esetről...
...szerencsére tudok. A Pythonban létezik egy "lista" nevű adatszerkezet, ami pont az, amit a név alapján gondolnánk.
Egy üres listát a []
literállal hozhatunk létre, vagy akár rögtön bele is rámolhatunk dolgokat: [10, 20.3, "alma", x]
egy listát hoz létre amiben egy egész, egy valós, egy szöveg és az x
változó értéke van.
#!/usr/bin/python
import random
import cgitb
cgitb.enable()
numbers = []
for x in range(0, 50):
numbers.append(random.randrange(0, 1000));
print "Content-type: text/html\n\n"
print "<h1>Numbers!</h1>"
print "<p>I love numbers. Here's a few for you:<br>", numbers, "</p>"
print "<p>The length of the list is ", len(numbers), ". The third element in the list is ", numbers[2], "</p>"
largest = -1
for num in numbers:
if (num > largest):
largest = num
print "<p>The largest number is <b>", largest, "</b>"
http://apocalypse.rulez.org/~upi/surba/list.py [source]
Vegyük észre:
- A cgitb modul komoly segítséget jelent Python programok hibáinak felderítésében. Ha a program futása közben történik valami gikszer, akkor szépen kiírja színes-szagos formában. Akkor nem segít, ha a program szintaktikai hiba miatt nem értelmezhető, ilyenkor csak a PuTTY-os módszer célravezető.
- A
for
egy új ciklus szervező utasítás ami egy megadott intervallumon halad végig, vagy egy lista tartalmán. - A
print
parancs képes egy teljes listát kiírni. - A lista hosszát a
len
eljárással tudhatjuk meg. - A listában tetszőleges elemet meg tudunk címezni a
lista[szám]
formulával. Az elemeket 0-tól számozzuk, mind mindig, tehát alist[2]
a harmadik elemet adja vissza.
Feladatok
- Legyen paraméterezhető a lista mérete!
- Írjuk ki a legkisebb számot is a listában.
- Írjuk ki a páros számokat.
- Hogyan lehetne a második for ciklust úgy megírni, hogy nem használjuk fel azt a tudásunkat, hogy a legkisebb lehetséges szám a 0?
- Írjuk ki a számok átlagát.
- Bónusz feladat: Írjuk ki a számokat növekvő sorrendben!
2017.VI.26
Játék a véletlennel
Kicsit visszatérünk a vektorgrafikához, mert miért ne! Az alábbi program véletlenszerűen rajzol egy négyszöget:
#!/usr/bin/python
import random
coords = ''
i = 0
while (i < 4):
coords = coords + str(random.randrange(1, 62)) + ","
coords = coords + str(random.randrange(1, 62)) + " "
i = i + 1
print """Content-type: image/svg+xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 64 64"
version="1.1"
height="600"
width="600">
<g>
<path d="M """ + coords + """ z"
style="fill: none; stroke: #000000;" />
</g>
</svg>
""";
http://apocalypse.rulez.org/~upi/surba/polygon.py [source]
Vegyük észre:
- Az
import
paranccsal lehet a Python terjedelmes könyvtárából elemeket berántani a programunkban. Enélkül csak néhány egészen alapvető és közhasznú függvény áll rendelkezésre. - A Pythonban vannak eljárások, ezek közül kettőt látunk itt: a
random.randrange
ésstr
nevűket.- Egy függvényt úgy lehet meghívni, hogy a neve után zárójelek között és vesszővel elválasztva felsoroljuk a paramétereit. Futás közben a eljárás majd szépen lefut, és behelyettesít valamilyen visszatérési értéket a helyére.
- A
random.randrange(1, 62)
eljárás egy egész számot generál az [1, 62) intervallumban. Az eljárás két egész szám paramétert vár, és egy egész számmal tér vissza. - Mivel a Python
+
operátora nem hajlandó számot és szöveget "összeadni", ezért a számokat azstr(szám)
eljárással szöveggé alakítjuk kézi hajtással. Ez az eljárás egy szám paramétert vár és egy szöveggel tér vissza, ami a számnak a tízes számrendszerű reprezentációja lesz. - Később megtanuljuk majd, hogyan csináljunk saját eljárásokat is.
- A koordináta-párokat az elején állítjuk össze, majd ügyesen belegyömöszöljük a kiírt SVG dokumentumba egy óvatlan pillanatban.
Feladatok
- Legyen a sokszög éleinek a száma is véletlenszerű, háromszögtől nyolcszögig.
- Legyen a sokszög éleinek száma véletlenszerű 4 és 12 között, de mindenképpen páros.
- Bónusz feladat: Legyen a sokszög színe is véletlenszerű.
- Bónusz feladat: Generáljunk négyzetet. Ha elfajuló, akkor pirosra színezzük ki, ha normális, akkor zöldre.
2017.VI.25
Paraméterek
Nagyon szuper egy program, ami lefut meg minden, megcsinálja a dolgát, más meg ne szóljon bele. Ezek a programok (hacsak valami véletlenszerűség nincs beléjük építve) mindig ugyanazt fogják csinálni, akárhányszor indítjuk el. Uncsi. Érdekes módon, a programok többsége nem így működik!
A weboldalaknál például szoktak lenni bemeneti értékek amiket a felhasználó valahogy kitölt, pl egy login űrlap vagy egy QR kód generáló. Az egyik módszer, amivel egy weboldalnak paraméter adható át az, ha a cím végén van egy kérdőjel, és utána név=érték
lista &
jelekkel elválasztva, például: https://duckduckgo.com/?q=miafasz&t=canonical&ia=videos
#!/usr/bin/python
import cgi, cgitb
form = cgi.FieldStorage()
a = form.getvalue('a')
b = form.getvalue('b')
print "Content-type: text/html\n\n"
print "<h1>This is addition</h1>"
print "<p>a = ", a, "</p>"
print "<p>b = ", b, "</p>"
print "<p>a + b = ", (a + b), "</p>"
print "<p>a + b = ", (int(a) + int(b)), " (numeric)</p>"
if (int(a) % 2 == 1):
print "<p>a is odd.</p>"
if (not (int(b) % 2 == 1)):
print "<p>b is even.</p>"
http://apocalypse.rulez.org/~upi/surba/parameters.py?a=10&b=20 [source]
Most, átmeneti jelleggel, ne ragadjunk le annál, hogy pontosan mi történik az "import" kezdetű, és azt követő három sorban. Elégedjünk meg azzal, hogy így ki tudjuk termelni az a
és b
változókba az azonos nevű paramétereket, amiket a T. Felhasználó a weboldalnak átadott.
További újdonság, hogy nem text/plain
a tartalom típusa, hanem text/html
; ez azzal az örömteli eseménnyel jár, hogy a <h1>
és </h1>
("heading 1") közötti részből egy címsor lesz, míg a <p>
-ből pedig bekezdés ("paragraph").
Vegyük észre:
- A Python különbséget tesz a szöveges változó és a numerikus változó között. Ha két szöveges változót adunk össze a
+
operátorral, akkor összefűzi őket, míg ha két numerikusat, akkor összeadja. (A Python is lehet hülye.) - Az
int(...)
függvény elvégzi nekünk azt a szívességet, hogy szöveges"10"
-ből numerikus10
értéket gyárt. (Ha nem végezhető a el a konverzió, mert mondjuka="alma"
, akkor ott szépen megdöglik a programunk.) %
operátor maradékot képez két egész szám között, pla % 2
aza
változó paritását adja vissza (0 vagy 1).- Az
if (...):
hasonló elven működik, mint awhile
egy korábbi fejezetben: a törzsében található rész akkor fog lefutni (egyszer), ha a zárójelben található feltétel "igaz".
Feladatok
- Próbáljuk ki a programot különböző bemenetekkel (pozitív, negatív számok, nem egész szám, szöveg).
- Az
if (not (int(b) % 2 == 1)):
rész egyszerűsíthető. Hogyan? - Írunk egy programot, ami egy harmadik paramétert is vár (mondjuk
c
). Ha ac
értéke"A"
(add), akkor összeadja a két számot, ha"S"
akkor kivonja, és ha"M"
akkor összeszorozza. - Írjunk egy programot, ami eldönti az
a
ésb
számról, hogy relatív prímek-e. - Írjunk egy programot, ami eldönti egy
a
számról, hogy prím-e. - Bónusz feladat: Írjunk egy programot, ami eldönti egy
a
számról, hogy négyzetszám-e