Strona główna » Poradniki » Logomocja » LOGIA » Logia 2013/14 Etap I
 

Logia 2013/14 Etap I

· Etap I · Etap II · Etap III ·
Oryginalna treść zadań jest dostępna pod oficjalnym adresem konkursu LOGIA

Zadanie 1

Napisz bezparametrową procedurę/funkcję BUKIET, po wywołaniu której na ekranie powstanie rysunek taki, jak poniżej. Długości boków dużych kolorowych rombów wynoszą 60, a małych – 15.

Rysowanie Kwiatka

Rysunek składa się z kwiatków złożonych z czterech rombów w różnych kolorach. Niektóre kwiatki mają kolory zamienione. Praktycznym podejściem jest napisanie procedury do rysowania kwiatka w taki sposób, aby można było ustalić kolejność kolorów oraz rozmiar. W ten spoób będzie możliwe rysowanie wszystkich kwiatków w tym nawet największego pośrodku ekranu. W celu uniknięcia pisania długiego kodu rysowania kwiatka należy napisać procedurę do rysowania rombu:

  1. oto BUKIET_romb :a :k :kol
  2.   wielokąt [
  3.     ukm :kol
  4.     powtórz 2 [
  5.       np :a pw (45*:k)
  6.       np :a pw (135*:k)
  7.     ]
  8.   ]
  9. już

Procedura BUKIET_romb akcpetuje trzy argumenty: :a - długość boku rombu, :k - kierunek skrętu (tj. czy romb ma być rysowany od danego punktu na lewo k = -1 czy na prawo k = 1) oraz kolor :kol, który ustala wypełnienie rombu.

Na podstawie procedury rysującej romby można napisać funkcję rysującą kwiatek:

  1. oto BUKIET_kwiat :a :kol1 :kol2
  2.   powtórz 4 [
  3.     BUKIET_romb :a 1 :kol1
  4.     BUKIET_romb :a -1 :kol2
  5.     pw 90
  6.   ]
  7. już

Procedura akceptuje trzy argumenty: :a - długość boku rombu z które składa się kwiatek, oraz dwa kolory :kol1 i :kol2, które zostaną użyte do zamalowania kwiatka.

Procedura Główna

Procedura główna jest bardzo długa, ale można w niej wyszczególnić poszczególne etapy. Na początku (2. - 3.) ustalamy kolory i (4.) rysujemy duży kwiat, ale bez koloru. Dzięki temu wokół głównego kwiatu powstanie później obramowanie. (5. - 17.) Następnie rysujemy dalszą część obramowania (tj. wszystkie lini w tle obrazka).

  1. oto BUKIET
  2.   niech "kol1 "brązowy8
  3.   niech "kol2 "fioletowy
  4.   BUKIET_kwiat 75 "biały "biały
  5.   powtórz 4 [
  6.     pw 45
  7.     pod
  8.     np 75+75*pwk(2) lw 90
  9.     opu
  10.     BUKIET_romb 75 -1 "biały
  11.     pw 180
  12.     BUKIET_romb 75 1 "biały
  13.     pod
  14.     lw 90 ws 75+75*pwk(2)
  15.     opu
  16.     pw 45
  17.   ]

Pozostały kod rysuje pozostałe kwiatki odpowiednio przestawiając kolory. W celu lepszego zrozumienia polecam dopisać na koniec każdej pętli polecenie czekaj 1000, aby na spokojnie obejrzeć co po kolei jest rysowane.

  1.   BUKIET_kwiat 60 :kol1 :kol2
  2.   powtórz 8 [
  3.     np 75 pw 45
  4.     np 75
  5.     jeżeli (reszta npw 2 = 1) [
  6.       BUKIET_kwiat 15 :kol1 :kol2
  7.     ][
  8.       BUKIET_kwiat 15 :kol2 :kol1
  9.     ]
  10.     ws 75 lw 45
  11.     ws 75
  12.     pw 45
  13.   ]
  14.   powtórz 4 [
  15.     pw 45
  16.     pod
  17.     np 75+75*pwk(2)
  18.     opu
  19.     lw 90 np 75
  20.     BUKIET_kwiat 15 :kol1 :kol2
  21.     ws 150 pw 180
  22.     BUKIET_kwiat 15 :kol1 :kol2
  23.     ws 75
  24.     pod
  25.     lw 90 ws 75+75*pwk(2)
  26.     opu
  27.     pw 45
  28.   ]
  29.   powtórz 8 [
  30.     pod np 75+75*pwk(2) opu
  31.     jeżeli (reszta npw 2 = 1) [
  32.       BUKIET_kwiat 15 :kol2 :kol1
  33.     ][
  34.       BUKIET_kwiat 15 :kol1 :kol2
  35.     ]
  36.     pod ws 75+75*pwk(2) opu
  37.     pw 45
  38.   ]
  39. już

Zadanie 2

Napisz dwuparametrową procedurę/funkcję WARSTWY, po wywołaniu której na środku ekranu powstanie rysunek składający się z tylu przylegających do siebie warstw kwadratów, ile wynosi wartość pierwszego parametru (od 1 do 25). Drugi parametr określa długość boku kwadratu stanowiącego dolną warstwę (od 100 do 200). Każda kolejna warstwa położona wyżej, zawiera o jeden kwadrat więcej. Szerokość każdej warstwy jest identyczna, kwadraty wewnątrz warstwy są tej samej wielkości, a lewe krawędzie poszczególnych warstw położone są na jednym odcinku.

WARSTWY 4 200
WARSTWY 22 100

Rozwiązanie

W celu narysowania rysunku na środku ekranu to trzeba znać zarówno jego wysokość jak i szerokość. Najprotszym sposobem na wyznaczenie wysokości będzie (2. - 5.) wywołanie pętli dla :n poziomów, ale jedynie po to, aby zsumować odpowiednie wartości. Mając już wysokość (6. - 9.) można przejść do rysowania.

  1. oto WARSTWY :n :a
  2.   niech "h 0
  3.   powtórz (:n) [
  4.     niech "h :h + :a/npw
  5.   ]
  6.   pod
  7.   ws :h/2 pw 90
  8.   ws :a/2 lw 90
  9.   opu
  10.   powtórz (:n) [
  11.     niech "ile npw
  12.     powtórz (:ile) [
  13.       powtórz 4 [
  14.         np :a/:ile pw 90
  15.       ]
  16.       pw 90 np :a/:ile
  17.       lw 90
  18.     ]
  19.     pw 90 ws :a
  20.     lw 90 np :a/:ile
  21.   ]
  22. już

(10.) Każda rysowana warstwa jest złożona z (11.) tylu elementów jaki jest aktualny numer poziomu, wartość musimy zapamiętać, aby wykorzystać to do (12. - 18.) rysowania jednego poziomu. Pamiętajmy, że bok kwadratu na poziomie :ile wynosi :a/:ile.

Zadanie 3

Napisz jednoparametrową procedurę/funkcję WARKOCZ, po wywołaniu której na środku ekranu powstanie rysunek plecionki takiej, jak te przedstawione poniżej. Wysokość rysunku wynosi 54. Parametr określa liczbę powtarzających się fragmentów warkocza i może przyjmować wartości od 1 do 7.

WARKOCZ 1
WARKOCZ 3
WARKOCZ 4

Rozwiązanie

Zadanie można uprościć do rysowania w kółko jednego symbolu i zamiany koloru. Dopiero po narysowaniu wszystkich kolorowych elementów zostanie nałożona na nie siatka. To znacząco upraszcza zadanie. Na początek procedury rozpoczynamy od zadeklarowania kilku zmiennych:

  1. oto WARKOCZ :n
  2.   niech "kol [żółty niebieski4 zielony3]
  3.   niech "h 54
  4.   niech "a :h/(4.5*pwk(2))
  5.   niech "d :a*pwk(2)
  6.   niech "ile 4 + 3*(:n - 1)
  7.   niech "ilek (:ile-2)*3+3.5
  8.   pod
  9.   ws :h/2 pw 90
  10.   ws :d*(:ilek)/2 lw 90
  11.   opu

Ustalane zmienne to (2.) kolejność kolorów, (3.) wysokość rysunku, (4.) bok pojedynczego kwadratu oraz (5.) jego przekątna. Dodatkowo potrzebujemy wiedzieć (6.) z ilu przekątnych składa się podstawa oraz (7.) ile jest do narysowania elementów. Potem (8. - 11.) przechodzimy do rysowania.

W dalszej części kodu: (12. - 16.) rysujemy figurę w lewym dolnym rogu oraz (19. - 29.) wszystkie znajdujące się pomiędzy pierwszą i ostatnią. Kolor ustalamy (22.) wybierając cyklicznie kolejny element z dostąpnej listy kolorów.

  1.   wielokąt [
  2.     ukm (pierw :kol)
  3.     np (:d*2) pw 135
  4.     np (:a*4)
  5.   ]
  6.   niech "i 2
  7.   pw 90
  8.   powtórz (:ile - 2) [
  9.     np :d*3
  10.     wielokąt [
  11.       ukm (element :i :kol)
  12.       lw 135
  13.       np (:a*3) pw 90
  14.       np (:a*2) pw 90
  15.       np (:a*5)
  16.     ]
  17.     niech "i (reszta :i 3) + 1
  18.   ]
  19.   np :d*3
  20.   wielokąt [
  21.     ukm (element :i :kol)
  22.     lw 135
  23.     np (:a*3) pw 90
  24.     np (:a*2) pw 90
  25.     np (:a*2) pw 45
  26.     np (:d*1.5)
  27.   ]

W tym momencie znajdujemy się w prawym dolnym rogu i musimy zmienić (39.) listę kolorów oraz (40.) zresetować licznik wyboru koloru, aby rozpocząć rysowanie górnej warstwy. (43. - 64.) Rysowanie górnej warstwy odbywa się w identyczny sposób jak dolnej.

  1.   wielokąt [
  2.     ukm (pierw :kol)
  3.     np (:d*2) pw 135
  4.     np (:a*4)
  5.   ]
  6.   niech "i 2
  7.   pw 90
  8.   powtórz (:ile - 2) [
  9.     np :d*3
  10.     wielokąt [
  11.       ukm (element :i :kol)
  12.       lw 135
  13.       np (:a*3) pw 90
  14.       np (:a*2) pw 90
  15.       np (:a*5)
  16.     ]
  17.     niech "i (reszta :i 3) + 1
  18.   ]
  19.   np :d*3
  20.   wielokąt [
  21.     ukm (element :i :kol)
  22.     lw 135
  23.     np (:a*3) pw 90
  24.     np (:a*2) pw 90
  25.     np (:a*2) pw 45
  26.     np (:d*1.5)
  27.   ]
  28.   niech "kol [niebieski4 żółty zielony3]
  29.   niech "i 1
  30.   np :d*0.5 lw 90
  31.   np :d*2.5
  32.   wielokąt [
  33.     ukm (ost :kol)
  34.     lw 45 np :a
  35.     pw 90 np :a
  36.   ]
  37.   np :d*2 lw 90
  38.   powtórz (:ile - 1) [
  39.     wielokąt [
  40.       ukm (element :i :kol)
  41.       lw 45
  42.       np (:a*5) pw 90
  43.       np (:a*2) pw 90
  44.       np (:a*3)
  45.     ]
  46.     np :d*3
  47.     niech "i (reszta :i 3) + 1
  48.   ]
  49.   wielokąt [
  50.     ukm (element :i :kol)
  51.     np (:d/2) lw 90
  52.     np (:d/2)
  53.   ]

Rysunek jest już prawie ukończony, ale brakuje jeszcze podziału rysunku na kwadraty. Choć nie jest to widoczne na pierwszy rzut oka to zamiast rysować kwadraty to można narysować zygzaki, które po odpowiednim narysowaniu zaczną tworzyć kwadraty. Końcówka kodu używa dodatkowej procedury WARKOCZ_zygzak.

  1.   wielokąt [
  2.     ukm (pierw :kol)
  3.     np (:d*2) pw 135
  4.     np (:a*4)
  5.   ]
  6.   niech "i 2
  7.   pw 90
  8.   powtórz (:ile - 2) [
  9.     np :d*3
  10.     wielokąt [
  11.       ukm (element :i :kol)
  12.       lw 135
  13.       np (:a*3) pw 90
  14.       np (:a*2) pw 90
  15.       np (:a*5)
  16.     ]
  17.     niech "i (reszta :i 3) + 1
  18.   ]
  19.   np :d*3
  20.   wielokąt [
  21.     ukm (element :i :kol)
  22.     lw 135
  23.     np (:a*3) pw 90
  24.     np (:a*2) pw 90
  25.     np (:a*2) pw 45
  26.     np (:d*1.5)
  27.   ]
  28.   niech "kol [niebieski4 żółty zielony3]
  29.   niech "i 1
  30.   np :d*0.5 lw 90
  31.   np :d*2.5
  32.   wielokąt [
  33.     ukm (ost :kol)
  34.     lw 45 np :a
  35.     pw 90 np :a
  36.   ]
  37.   np :d*2 lw 90
  38.   powtórz (:ile - 1) [
  39.     wielokąt [
  40.       ukm (element :i :kol)
  41.       lw 45
  42.       np (:a*5) pw 90
  43.       np (:a*2) pw 90
  44.       np (:a*3)
  45.     ]
  46.     np :d*3
  47.     niech "i (reszta :i 3) + 1
  48.   ]
  49.   wielokąt [
  50.     ukm (element :i :kol)
  51.     np (:d/2) lw 90
  52.     np (:d/2)
  53.   ]
  54.   np :d/2 lw 90
  55.   np :h pw 180
  56.   powtórz 4 [
  57.     pw 45
  58.     WARKOCZ_zygzak :a :ilek-1 1
  59.     np :a lw 90
  60.     WARKOCZ_zygzak :a :ilek-1 -1
  61.     np :a pw 45
  62.   ]
  63.   pw 45
  64.   WARKOCZ_zygzak :a :ilek-1 1
  65.   np :a
  66. już

Procedura pomocnicza

Rysowanie zygzaków polega na rysowaniu dwóch prostopadłych kresek pod kątem 45 stopni.

  1. oto WARKOCZ_zygzak :a :ile :k
  2.   powtórz (:ile) [
  3.     np :a pw 90*:k
  4.     np :a lw 90*:k
  5.   ]
  6. już

Zadanie 4

Napisz dwuparametrową funkcję PIRAMIDA, której wynikiem jest łączna długość odcinków tworzących piramidę. Pierwszy parametr określa liczbę poziomów piramidy, a drugi – długość boku każdego z kwadratów. Każdy z parametrów może przyjmować wartości od 1 do 1000.

PIRAMIDA 4 30
PIRAMIDA 5 10
PIRAMIDA 4 30jest 840
PIRAMIDA 5 10jest 400

Rozwiązanie

W celu zliczenia wszystkich elementów należy najpierw spojrzeć na każdy poziom jak na niedokończoną od dołu piramidę. Wtedy można zauważyć, że pierwszy poziom ma 3 kreski, drugi 5, trzeci 7 itd. W ten sposób na n poziomach będzie 3 + 5 + 7 + .. + (2n + 1) odcinków, ale jeszcze należy doliczyć dolny odcinek złożony z n odcinków. To rozumowanie zostało zaimplementowane w poniższej funkcji PIRAMIDA:

  1. oto PIRAMIDA :n :a
  2.   niech "ile :n
  3.   powtórz (:n) [
  4.     niech "k :n - npw + 1
  5.     niech "ile :ile + 2*:k + 1
  6.   ]
  7.   wynik :ile*:a
  8. już