Strona główna » Poradniki » Logomocja » LOGIA » Logia 1998/99 - Etap III
 

Logia 1998/99 - Etap III

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

Zadanie 1

Zdefiniuj funkcję ZAMIANA :ls, której parametrem jest lista słów składających się z małych liter alfabetu łacińskiego (bez polskich znaków). Wartością funkcji będzie lista składająca się z jedno- lub dwuelementowych list, powstałych z poszczególnych słów listy będącej parametrem, w następujący sposób:

  • jeśli w słowie nie będzie samogłosek, to należy wziąć jednoelementową listę zawierającą liczbę 0,
  • jeżeli w słowie będzie co najmniej jedna samogłoska, to należy wziąć dwuelementową listę zawierającą: samogłoskę najczęściej występującą w danym słowie i liczbę jej wystąpień; jeżeli w danym słowie kilka samogłosek będzie spełniało ten warunek, to należy wziąć pierwszą z nich.

Oto przykładowe wyniki:

ZAMIANA [kalinka malinka]powinno dać wynik [[a 2] [a 2]]
ZAMIANA [procedura w logo]powinno dać wynik [[o 1] [0] [o 2]]
ZAMIANA [abrakadabra hokus pokus]powinno dać wynik [[a 5] [o 1] [o 1]]

Założenia

Ze względu na fakt, że właściwy kod będzie konwertował każdy wyraz oddzielnie to funkcja ZAMIANA będzie tylko wywoływać funkcję pomocniczą i zbierać wyniki.

  1. oto ZAMIANA :ls
  2.   niech "w []
  3.   powtórz (długość :ls) [
  4.     niech "w nak ZAMIANA_wyraz element npw :ls :w
  5.   ]
  6.   wynik :w
  7. już

(2.) Przygotuj listę wynikową. (3.) Dla każdego wyrazu (4.) pobierz wynik i dopisz do listy wynikowej. (6.) Zwróć listę wynikową.

Zamiana wyrazu

Funkcja ZAMIANA_wyraz przyjmuje jeden argument :w - wyraz do zamiany. Na koniec funkcja zwraca listę, która zawiera najczęściej występującą samogłoskę. Przedstawiony poniżej kod można zooptymalizować poprzez usuwanie znalezionych samogłosek z wyrazu, ale wtedy kod stałby się mniej przejrzysty.

  1. oto ZAMIANA_wyraz :w
  2.   niech "max 0
  3.   niech "znak "
  4.   powtórz (długość :w) [
  5.     jeśli (samogłoska? element npw :w)[
  6.       niech "maxl 1
  7.       niech "npwS npw
  8.       powtórz ((długość :w) - npw) [
  9.         jeśli(element (npw + :npwS) :w = element :npwS :w)[
  10.           zwiększ "maxl
  11.         ]
  12.       ]
  13.       jeśli(:maxl > :max)[
  14.         niech "max :maxl
  15.         niech "znak element :npwS :w
  16.       ]
  17.     ]
  18.   ]
  19.   jeśli (:max <> 0) [
  20.     wynik (lista :znak :max)
  21.   ]
  22.   wynik (lista :max)
  23. już

(2.) Przyjmij, że nie ma samogłosek i (3.) zadeklaruj zmienną :znak, która w dalszej części będzie przyjmował znak samogłoski o ile jakaś samogłoska występuje. (4.) Dla każdej litery, która (5.) jest samogłoską: (6.) zadekalaruj zmienną :maxl zliczajacą ilość wystąpień samogłoski i (7.) zapamietaj numer aktualnie przeglądanego znaku. (8. - 12.) Szukaj od danego miejsca do końca wyrazu pozostałych wystąpień znalezionej samogłoski. (13.) Jeśli dana samogłoska ma więcej wystąpień niż dotychczas znaleziona to (14. - 15.) zapamiętaj dane. Użyty tutaj znak większości > gwarantuje, że jeśli będą dwie samogłoski po tyle samo wystąpień to zwrócona zostanie pierwsza znaleziona samogłoska. (19.) Sprawdź czy znaleziono samogłoskę. Jeśli tak to (20.) zwróć listę znak, ilość wystąpień. W przeciwnym razie (21.) zwróć listę z wartością 0.

Zadanie 2

Zdefiniuj funkcję LICZNP :liczba, której wartością jest lista liczbowa, zawierająca zliczenie kolejnych nieparzystych cyfr parametru będącego dowolną liczbą naturalną. Każdy element listy wynikowej mówi, ile kolejnych ("jedna za drugą") cyfr nieparzystych, ograniczonych cyframi parzystymi, początkiem, bądź końcem liczby, napotykamy w zapisie dziesiętnym parametru :liczba. Oto przykładowe wyniki:

LICZNP 1233501powinno dać w wyniku [1 3 1]
LICZNP 90powinno dać w wyniku [1]
LICZNP 2200powinno dać w wyniku listę pustą, czyli []

Zadanie to można rozwiązać analizując po kolei kolejne cyfry. W każdej iteracji znaleziony znak ma sprawdzaną parzystość. W przypadku, gdy jest nieparzysty i poprzednia też była nieparzysta to zwiększa licznik. Jednak jeśli cyfra jest parzysta, a poprzednia nie to należy dopisać licznik na koniec listy. Problem może sprawić liczba bez parzystej na początku. Z tego powodu w algorytmie nawet jeśli liczba wyniesie 0 to jest wykonywane wcześniej wspomniane równanie.

  1. oto LICZNP :liczba
  2.   niech "w []
  3.   niech "licznik 0
  4.   dopóki [
  5.     "prawda
  6.   ][
  7.     jeśli (I reszta reszta :liczba 10 2 = 0 :licznik <> 0) [
  8.       niech "w nap :licznik :w
  9.       niech "licznik 0
  10.     ]
  11.     jeśli (reszta reszta :liczba 10 2 = 1) [
  12.       zwiększ "licznik
  13.     ]
  14.     jeśli (:liczba = 0) [
  15.       wynik :w
  16.     ]
  17.     niech "liczba int (:liczba / 10)
  18.   ]
  19. już

Przygotuj zmienną (2.) pod listę wynikową, (3.) do zliczania wystąpień cyfr nieparzystych. (4.) Ze względu na fakt, że zwracanie wyniku przerywa wykonywanie programu, a nie znamy (i nie chcemy) znać długości cyfry to (5.) program działa wewnątrz nieskończonej pętli. (7.) Jeśli wykryta cyfra jest nieparzysta oraz licznik jest różny od zera, czyli wcześniej zostały znalezione cyfry nieparzyste, to (8.) dopisz liczbę do listy wynikowej i (9.) zresetuj licznik. (11.) Jeśli następna cyfra jest nieparzysta to (12.) zwiększ :licznik. (14.) Jeśli po sprawdzeniach okazuje się, że liczba to 0 to: (15.) zwróć listę wynikową. Jeśli jednak nie to przejdź do następnej iteracji (17.) wpierw usuwając ostatnią cyfrę z liczby.

Zadanie 3

Napisz procedurę GLIZDAWCE :ls, która rysuje odpowiedni rysunek wężyków. Parametrem procedury jest lista składająca się ze słów złożonych z małych i wielkich liter alfabetu łacińskiego (bez polskich znaków). Przy tym:

  • liczba wężyków odpowiada liczbie słów w parametrze :ls,
  • każdy wężyk składa się z tylu sześciokątów, ile jest liter w danym słowie,
  • litery są reprezentowane przez sześciokąty, które można wpisać w kwadrat - tak, jak to widać na rysunku poniżej:

  • sześciokąt odpowiadający nieparzystym (pierwszej, trzeciej, piątej,...) literom w danym słowie jest obrócony w lewo, a sześciokąt odpowiadający parzystym literom jest obrócony w prawo,
  • wszystkie sześciokąty odpowiadające spółgłoskom mają zamalowane wnętrza,
  • wielkie litery są reprezentowane przez sześciokąty dwa razy większe, niż te dla małych liter,
  • rysunek jest możliwie duży i umieszczony na środku ekranu.

Przykładowo GLIZDAWCE [Warszawski Konkurs Informatyczny] powinno narysować następujący rysunek:

Założenia

Chociaż nie jest to wymagane warto rozpisać kod na kilka procedur. W ten sposób łatwiej będzie poprawić wybraną część kodu. W przedstawionym rozwiązaniu funkcja GLIZDAWCE oblicza wymiary rysunku i go rysuje, GLIZDAWCE_kolor zwraca kolor w zależności od znaku, GLIZDAWCE_RYS - rysuje pojedynczy symbol, a GLIZDAWCE_słowo rysuje cały wyraz.

Kolor

Pisanie programu najlepiej zacząć od najprotszej funkcji: GLIZDAWCE_kolor, która przyjmuje jeden argument :litera. (2.) Jeśli :litera jest samogłoską to (3.) zwraca biały kolor. (4.) W przeciwnym szary.

  1. oto GLIZDAWCE_kolor :litera
  2.   jeśli (samogłoska? :litera) [
  3.     wy "biały
  4.   ]
  5.   wy "szary
  6. już

Symbol

Cały rysunek składa się z jednego symbolu narsowanego wiele razy. Funkcja GLIZDAWCE_RYS pozwala dostosować wysokość symbolu (nie długość jego boku) argumentem :h. Ponadto funkcja przyjmuje argument :kierunek, który określa orientację symbolu (0 każdy parzysty symbol w słowie, a 1 każdy nieparzysty) oraz :kolor - kolor wypełnienia symbolu.

  1. oto GLIZDAWCE_RYS :h :kierunek :kolor
  2.   niech "a :h / 2
  3.   niech "b :a * pwk(2)
  4.   jeśli(:kierunek = 1) [
  5.     pod
  6.     np :h pw 90
  7.     opu
  8.   ]
  9.   wielokąt [
  10.     ukm :kolor
  11.     powtórz 2 [
  12.       np :a
  13.       pw 45
  14.       np :b
  15.       pw 45
  16.       np :a
  17.       pw 90
  18.     ]
  19.   ]
  20.   jeśli(:kierunek = 1) [
  21.     pod
  22.     lw 90 ws :h
  23.     opu
  24.   ]
  25. już

Wylicz (2.) bok sześciokąt na boku kwadratu i (3.) bok sześciokąta nie leżącego na obramowaniu kwadratu. (4. - 8.) Jeśli narysowany ma być symbol dla znaku o indeksie nieparzystym to odpowiednio przesuń żółwia. (9. - 19.) Narysuj symbol i (20. - 24.) sprawdź czy żółw nie musi wykonać dodatkowego przesunięcia.

Słowo

Do rysowania całego pojedynczego słowa można wykorzystac procedurę GLIZDAWCE_słowo, która przyjmuje dwa argumenty :h - wysokość pierwszego symbolu oraz :w - wyraz do przeanalizowania.

  1. oto GLIZDAWCE_słowo :h :w
  2.   GLIZDAWCE_RYS :h 1 GLIZDAWCE_kolor pierw :w
  3.   pod
  4.   pw 90 np :h
  5.   lw 90
  6.   opu
  7.   powtórz ((długość :w) - 1) [
  8.     GLIZDAWCE_RYS :h/2 reszta (npw+1) 2 GLIZDAWCE_kolor element (npw+1) :w
  9.     pod
  10.     pw 90 np :h/2
  11.     lw 90
  12.     opu
  13.   ]
  14.   pod
  15.   pw 90 ws :h*((długość :w) + 1)/2
  16.   lw 90
  17.   opu
  18. już

(2.) Narysuj duży symbol i (3. - 6.) przesuń żółwia do lewego dolnego rogu następnego rysunku. (7.) Dla każdej pozostałej litery: (8.) rysuj symbol o odpowiednim kierunku u kolorze. Wykorzystywane są do tego funkcje GLIZDAWCE_RYS oraz GLIZDAWCE_kolor. Potem (9. - 12.) przesuń dalej. Po zakończeniu rysowania (14. - 17.) wróć tam skąd została rozpoczęta procedura.

Glizdawce

Dotychczas dopisany kod potrafi narysować dowolne słowo i odpowiednio dostosować wysokości symboli oraz kolory. Główna funkcja GLIZDAWCE ma teraz dwa zadania: wyliczyć wysokości symboli, a nastepnie je narysować.

  1. oto GLIZDAWCE :ls
  2.   niech "h 460
  3.   niech "w 700
  4.   niech "a :h / (długość :ls)
  5.   niech "max długość pierw :ls
  6.   powtórz ((długość :ls) - 1) [
  7.     jeśli (:max < długość element npw + 1 :ls)[
  8.       niech "max długość element npw + 1 :ls
  9.     ]
  10.   ]
  11.   jeśli((:a*(:max + 1))/2 > :w)[
  12.     niech "a 2 * :w / (:max + 1)
  13.   ]
  14.   pod
  15.   np :a*(długość :ls)/2 - :a pw 90
  16.   ws (:a*(:max + 1))/4 lw 90
  17.   opu
  18.   powtórz (długość :ls) [
  19.     GLIZDAWCE_słowo :a element npw :ls
  20.     pod
  21.     ws :a
  22.     opu
  23.   ]
  24. już

Określ maksymalną (2.) wysokość i (3.) szerokosć rysunku. (4.) Oblicz wysokość symbolu na podstawie wysokości. Następnie (5. - 10.) znajdź nadłuższy wyraz i (11.) sprawdź czy rysunek zmieści się na szerokość. Jeśli nie to (12.) oblicz wymiary symbolu na podstawie szerokości rysunku. W kolejnym etapie procoedury (14. - 17.) przejdź do rysowania i (18. - 23.) Narysuj wszystkie wyrazy.