Strona główna » Poradniki » Logomocja » LOGIA » Logia 2011/12 Etap I
 

Logia 2011/12 Etap I

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

Zadanie 1

Napisz procedurę ORNAMENT, po wywołaniu której będzie rysowany motyw taki, jak poniżej. Proporcje dla ośmiokąta odczytaj z rysunku pomocniczego obok. Długości boków stykających się trójkątów gwiazdek różnej wielkości są w proporcji 1 do 2. Szerokość ornamentu wynosi co najmniej 700.

Rysunek pomocniczy
ORNAMENT

Rozwiązanie

Rozwiązanie zostało podzielone na trzy procedury: ORNAMENT_EL rysuje pojedynczy element ze wzoru, ORNAMENT_FRAGMENT rysuje całą gwiazdę złożoną z 9 elementów, a główna procedura ORNAMENT pozycjonuje rysunek na stronie i rysuje trzy fragmenty oraz dobiera kolory.

Rysowanie elementu

Procedura ORNAMENT_EL przyjmuje następujące argumenty: :a - długość boku szczęściokąta oraz kolory :kol1 oraz :kol2, gdzie kolory odpowiadają kolejno mniejszemu i większemu trójkątowi.

  1. oto ORNAMENT_EL :a :kol1 :kol2
  2.   pod
  3.   np :a*1.5 pw 90
  4.   ws :a*0.5
  5.   opu
  6.   powtórz 4 [
  7.     wielokąt [
  8.       ukm :kol1
  9.       lw 60 np :a
  10.       pw 120 np :a
  11.     ]
  12.     np :a pw 45
  13.     wielokąt [
  14.       ukm :kol2
  15.       lw 60 np (:a*pwk(2))
  16.       pw 120 np (:a*pwk(2))
  17.     ]
  18.     np (:a*pwk(2)) pw 45
  19.   ]
  20.   pod
  21.   np :a*0.5 lw 90
  22.   ws :a*1.5
  23.   ukm "żółty11
  24.   zam
  25.   opu
  26. już

Rozpoczynamy rysowanie od środka elementu tj. środka sześcianu, więc: (2. - 5.) przesuwamy się do jednego z rogów, a następnie (6.) rysujemy cztery identyczne fragmenty tj. można zauważyć, że cztery razy rysujemy (7. - 11.) mały, a potem (13. - 17.) duży trójkąt w międzyczasie przechodząc do kolejnych rogów. Na koniec (20. - 22.) wracamy do początkowego ustawienia i (23. - 24.) zamalowywujemy środkowy rysunek.

Rysowanie fragmentu

Procedura ORNAMENT_FRAGMENT przyjmuje takie same argumenty jak procedura ORNAMENT_EL.

  1. oto ORNAMENT_FRAGMENT :a :kol1 :kol2
  2.   ORNAMENT_EL :a :kol1 :kol2
  3.   niech "h :a*2.25+(:a*pwk(3))*0.75
  4.   powtórz 4 [
  5.     pod np :h opu
  6.     ORNAMENT_EL :a/2 :kol2 :kol1
  7.     pod ws :h opu
  8.     pw 90
  9.   ]
  10.   pw 45
  11.   niech "b :a*pwk(2)
  12.   niech "h :b*1.75+(:b*pwk(3))*0.75
  13.   powtórz 4 [
  14.     pod np :h opu
  15.     ORNAMENT_EL :b/2 :kol1 :kol2
  16.     pod ws :h opu
  17.     pw 90
  18.   ]
  19.   lw 45
  20. już

Procedurę rozpoczynamy od (2.) narysowaniu elementu pośrodku następnie (3.) obliczamy odległość środka fragmentu od środka mniejszych elementów i (4. - 10.) rysujemy cztery mniejsze gwiazdki. Podobnie (12. - 20.) postępujemy podczas rysowania brakujących czterech elementów.

Procedura główna

W głównej procedurze pozostaje jedynie wywołać rysowanie fragmentów w odpowiednim miejscu i z odpowiednimi parametrami. W tym przypadku (2.) określamy bok :a sześciokątów największych elementów i na tej podstawie (3.) wyliczamy odległość pomiędzy środkami fragmentów. Następnie (4. - 10.) rysowane są trzy fragmenty.

  1. oto ORNAMENT
  2.   niech "a 25
  3.   niech "w 3.5*:a+(pwk(3))*:a+(1.5*pwk(2))*:a+(pwk(6))*:a
  4.   pod lw 90 np :w pw 90 opu
  5.   ORNAMENT_FRAGMENT :a "czerwony "brązowy
  6.   pod pw 90 np :w lw 90 opu
  7.   ORNAMENT_FRAGMENT :a "brązowy "czerwony
  8.   pod pw 90 np :w lw 90 opu
  9.   ORNAMENT_FRAGMENT :a "czerwony "brązowy
  10. już

Zadanie 2

Napisz procedurę DRZEWO :ile, która tworzy rysunek drzewa składającego się z brązowego pnia i zielonej korony zakończonej rzędem ciemnozielonych liści. Wysokość rysunku jest stała i wynosi 470. Parametr :ile może przyjmować wartości od 2 do 26 i określa liczbę elementów pnia oraz liczbę poziomych zielonych gałęzi.

DRZEWO 1
DRZEWO 2

Strategia

Drzewo jest złożone z dwóch figur: rombu oraz trójkąta. Warto zauważyć, że bok trójkąta jest równy bokowi romba. Jest to szczególnie ważne podczas wyliczania boku figur w głównej procedurze. W celu uproszczenia zapisu kodu dla każdej z figur została napisana oddzielna procedura, która pozwala narysować wybraną figurę w środku gdzie stoi żółw.

Rozwiązanie

Rysowanie trójkąta

Procedura DRZEWO_TRÓJKĄT przyjmuje dwa argumenty: :h - wysokość elementu w drzewie oraz :kol - kolor danego elementu.

  1. oto DRZEWO_TRÓJKĄT :h :kol
  2.   niech "a 2*:h/pwk(3)
  3.   pod
  4.   ws :h/2 lw 90
  5.   ws :a/2
  6.   opu
  7.   wielokąt [
  8.     ukm :kol
  9.     powtórz 3 [
  10.       np :a
  11.       pw 120
  12.     ]
  13.   ]
  14.   pod
  15.   np :a/2 pw 90
  16.   np :h/2
  17.   opu
  18. już

Rysowanie rombu

Na podobnej zasadzie do procedury DRZEWO_TRÓJKĄT działa procedura DRZEWO_ROMB

  1. oto DRZEWO_ROMB :h :kol
  2.   niech "a :h/pwk(2)
  3.   pod
  4.   ws :h/2 lw 45
  5.   opu
  6.   wielokąt [
  7.     ukm :kol
  8.     powtórz 4 [
  9.       np :a
  10.       pw 90
  11.     ]
  12.   ]
  13.   pod
  14.   pw 45 np :h/2
  15.   opu
  16. już

Procedura główna

W głównej procedurze na początku należy wyliczyć kilka wielkości: (2.) :n - łączna ilość elementów, (3. - 4.) :w - określa łączą wysokość elementów (przekątne rombów i wysokości trójkątów). Na tej podstawie można (5.) wyliczyć bok rombów i trójkątów. Następnie (6.) :ht to wysokość trójkąta, a :hr rombu.

  1. oto DRZEWO :ile
  2.   niech "n 2*(:ile + 1) - 1
  3.   niech "w (2*:ile - 1)*pwk(2)
  4.   niech "w :w + pwk(3)
  5.   niech "a 470/:w
  6.   niech "ht (:a*pwk(3))/2
  7.   niech "hr :a*pwk(2)
  8.   pod ws 470/2-:ht/2 opu
  9.   DRZEWO_TRÓJKĄT :ht "brązowy
  10.   pod np :ht/2+:hr/2 opu
  11.   powtórz (:ile - 1) [
  12.     DRZEWO_ROMB :hr "brązowy
  13.     pod np :hr opu
  14.   ]
  15.   powtórz (:ile) [
  16.     niech "k 2*npw - 1
  17.     pod
  18.     pw 90 np :hr*(npw - 1)
  19.     lw 90
  20.     opu
  21.     powtórz (:k) [
  22.       DRZEWO_ROMB :hr "zielony
  23.       pod
  24.       lw 90 np :hr
  25.       pw 90
  26.       opu
  27.     ]
  28.     pod
  29.     pw 90 np :hr*npw
  30.     lw 90
  31.     opu
  32.     pod np :hr opu
  33.   ]
  34.  
  35.   pw 180
  36.   niech "k 2*:ile - 1
  37.   pod
  38.   ws (:ht-:hr)/2 pw 90
  39.   np :hr*(:ile - 1) lw 90
  40.   opu
  41.   powtórz (:k) [
  42.     DRZEWO_TRÓJKĄT :ht "zielony3
  43.     pod
  44.     lw 90 np :hr
  45.     pw 90
  46.     opu
  47.   ]
  48. już

Po wstępnych obliczeniach (7.) przesuwamy się na środek korzenia i (8.) go rysujemy. Następnie (10. - 13.) rysujemy pień o :ile - 1 rombach. Następny etap (14. - 33.) polega na narysowaniu zielonej korony drzewa. Należy pamiętać, że w każdym kolejnym wierszu jest o dwa romby więcej do narysowania czyli w i-tej rzędzie korony jest 2·:i - 1 elementów. Na koniec (35.) obracamy żółwia do góry nogami i (36. - 47.) rysujemy górną część korony.

Zadanie 3

Czy zastanawiałaś/eś się kiedyś, ile masz dni? Zadanie jest na pozór proste. Trzeba jednak pamiętać o uwzględnieniu lat przestępnych. Rok przestępny to taki rok, który jest podzielny przez 4, ale nie jest podzielny przez 100 lub jest podzielny przez 400.

Napisz funkcję IMD :rok :miesiąc :dzień, której wartością jest liczba dni, która upłynęła od danej daty do dnia 28 listopada 2011 roku (data zakończenia 1 etapu). Przyjmij, że podana data jest poprawna i jest późniejsza niż 31 grudnia 1582 roku i wcześniejsza niż 28 listopada 2011 roku.

IMD 1998 06 14 jest 4915
IMD 1990 11 29 jest 7669
IMD 2011 11 27 jest 1

Strategia

Istnieją dwa główne podejścia do tego zadania. Jedno z nich opiera się na zliczeniu oddzielnie ilości dni w roku pomiędzy datami oraz każdego miesiąca w latach rozpoczęcia i zakończenia. Jednak zdecydowanie prostszym rozwiązaniem jest potraktować dzień, miesiąc i rok jako swojego rodzaju liczniki. Wtedy wystarczy zliczyć ile dni się dodało, aby otrzymać szukaną datę.

Rozwiązanie

Czy rok przestępny?

Oczywiście licznik dni jest uzależniony od miesiąca i roku w przypadku miesiąca Luty, który ma 29 dni jeśli rok jest przestępny. Z tego względu została dopisana dodatkowa funkcja IMD_przestepny, która dla podanego roku zwraca czy jest to rok przestępny w postaci wartości logicznej.

  1. oto IMD_przestępny :rok
  2.   jeśli (I (reszta :rok 4 = 0) (reszta :rok 100 <> 0)) [
  3.     wynik "prawda
  4.   ]
  5.   jeśli (reszta :rok 400 = 0) [
  6.     wynik "prawda
  7.   ]
  8.   wynik "fałsz
  9. już

Funkcja główna

W funkcji głównej początkowo (2.) deklarowany jest licznik dni oraz (3.) liczba dni w każdym miesiącu. Dni są dodawane dopóki (4.) nie zostanie uzyskana konkretna data. Jak można zauważyć bardzo łatwo w tym algorytmie zmienić datę końcową.

  1. oto IMD :rok :miesiąc :dzień
  2.   niech "ile 0
  3.   niech "m [31 28 31 30 31 30 31 31 30 31 30 31]
  4.   dopóki [LUB LUB (:dzień <> 28) (:miesiąc <> 11) (:rok <> 2011)][
  5.     zwiększ "ile
  6.     zwiększ "dzień
  7.     jeśli (:dzień > element :miesiąc :m) [
  8.       jeśli NIE (I I (:miesiąc = 2) (:dzień = 29) IMD_przestępny :rok) [
  9.         zwiększ "miesiąc
  10.         niech "dzień 1
  11.         jeśli (:miesiąc > 12) [
  12.           zwiększ "rok
  13.           niech "miesiąc 1
  14.         ]
  15.       ]
  16.     ]
  17.   ]
  18.   wynik :ile
  19. już

Kiedy data wciąż nie jest poprawna to (5.) zwiększamy ile dodajemy dni i (6.) dodajemy jeden dzień. (7.) Oczywiście należy sprawdzić czy w danym miesiącu istnieje taki numer dnia, bo jeśli nie to (9.) zwiększamy miesiąc, a (10.) dzień ustalamy na pierwszy. Tak samo w przypadku (11.) miesięcy, ponieważ jest ich tylko 12 to, gdy zmienna :miesiac przyjmie wartość większą od 12 to (13.) zwiększamy rok i (14.) resetujemy numer miesiąca do 1. Wracając do sprawdzania ilości dni to (8.) należy się upewnić ile dni ma aktualnie Luty.

Zadanie 4

Napisz procedurę KWIAT :ir :iwk, która rysuje na środku ekranu kwiat złożony z samych okręgów. Parametr :ir oznacza liczbę okręgów rysowanych wzdłuż promienia, a parametr :iwk - liczbę okręgów rysowanych wokoło. Okręgi wokoło są rysowane symetrycznie wokół środka kwiatka. Parametr :ir przyjmuje wartości od 1 do 9, a :iwk od 2 do 60. Długość promienia wynosi co najmniej 150.

KWIAT 1 6
KWIAT 3 5
KWIAT 5 3
KWIAT 2 8
KWIAT 5 16
KWIAT 3 42

Rozwiązanie

W zadaniu został podany promień minimalny, który w rozwiązaniu przyjmuje za stały i na jego podstawie (2.) wyliczam promień pojedynczego kółka. Potem (3.) Dla każdego ramienia: (4. - 6.) przechodzę do środka najbliższego okręgu i (7. - 10.) rysuje odpowiednią ilość okręgów przechodząc od środka do środka. (11. - 12.) Po powrocie: (13.) obracam żółwia, aby narysować kolejne ramię rysunku.

  1. oto KWIAT :ir :iwk
  2.   niech "r 150/:ir
  3.   powtórz (:iwk) [
  4.     pod
  5.     np :r/2
  6.     opu
  7.     powtórz (:ir) [
  8.       okrąg :r
  9.       pod np :r opu
  10.     ]
  11.     pod
  12.     ws :r*(:ir + 0.5)
  13.     pw 360/:iwk
  14.     opu
  15.   ]
  16. już