Strona główna » Poradniki » Logomocja » LOGIA » Logia 2017/18 Etap II
 

Logia 2017/18 Etap II

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

Zadanie 1

Tablica Polibiusza jest kwadratową tabelą zawierającą litery alfabetu łacińskiego. Kolumny numerujemy od 0 do 4, a wiersze od 1 do 5. Kodujemy słowo, zastępując każdą literę sumą numerów wiersza i kolumny, w których stoi. Na przykład litera s zostanie zastąpiona liczbą 6.

01234
1abcde
2fghi/jk
3lmnop
4qrstu
5vwxyz

Napisz jednoparametrową procedurę/funkcję koduj, której parametrem jest słowo składające się z co najmniej 2 i co najwyżej 18 małych liter alfabetu łacińskiego. Po jej wywołaniu na środku ekranu powstaje rysunek zakodowanego słowa. Każdą literę słowa zastępujemy liczbą, według zasady podanej powyżej, a następnie rysujemy zawijas stopnia takiego, jak liczba odpowiadająca zakodowanej literze. Pierwszy odcinek zawijasa jest poziomą kreską. Każdy kolejny odcinek zawijasa jest o 4 krótszy od poprzedniego. Odległości między kolejnymi zawijasami są równe 1/5 długości najdłuższego odcinka. Szerokość rysunku wynosi 780.

Zawijasy stopnia 4
Zawijasy stopnia 5
Zawijasy stopnia 9
koduj ″logomocja

Rozwiązanie

Rozwiązywanie zadania warto rozpocząć od napisania procedury do rysowania pojedynczej spirali. Będzie ona przyjmować dwa argumenty: długość najdłuższego boku :a oraz ile odcinków ma zostać narysowanych :st.

  1. oto koduj_spirala :a :st
  2.   powtórz :st [
  3.     np :a lw 90
  4.     niech "a :a-4
  5.   ]
  6. już

Rozwiązywanie zadania warto rozpocząć od napisania procedury do rysowania pojedynczej spirali. Będzie ona przyjmować dwa argumenty: długość najdłuższego boku :a oraz ile odcinków ma zostać narysowanych :st.

Teraz można przejść do napisania głównej funkcji koduj. Na początku wyznaczamy odpowiednie rozmiary i przesuwamy się do lewego, dolnego rogu, gdzie rozpoczynamy całe rysowanie.

  1. oto koduj :słowo
  2.   niech "n długość :słowo
  3.   niech "szer 780
  4.   niech "a :szer / (:n*1.2 - 0.2)
  5.   pod
  6.   ws :a/2 pw 90
  7.   ws :szer/2
  8.   opu
  9.   powtórz :n [
  10.     niech "teraz poz
  11.     niech "znak ascii (element npw :słowo)
  12.     jeśli (:znak >= ascii "j)[
  13.       zmniejsz "znak
  14.     ]
  15.     niech "znak :znak - (ascii "a)
  16.     niech "r reszta :znak 5
  17.     niech "suma :r + (:znak - :r)/5 + 1
  18.     koduj_spirala :a :suma
  19.     pod
  20.     ustalPoz :teraz
  21.     ustalKierunek 90
  22.     np :a*1.2
  23.     opu
  24.   ]
  25. już

W pętli spirala jest rysowana dla każdego znaku. W celu uzyskania wartości dla wczytanego znaku należy pobrać znak i przeliczyć go na kod ASCII. Następnie sprawdzamy czy litera jest powyżej literki i. Jeśli tak to zmniejszamy wartość o 1. Dzięki temu litery I j J będą miały tą samą pozycję. Następnie numer kolumny to reszta dzielenia pozycji znaku w alfabecie podzielona przez 5, a wiersza to pozycja minus poprzednio wyliczona reszta i podzielona przez 5. Dodanie jedynki rekompensuje indeksowanie wierszy od 1. Po każdym narysowaniu pętli wracamy do pozycji z której rozpoczęliśmy rysowanie, kierujemy się w prawo i kontynuujemy rysowania przesuwając się do przodu.

Zadanie 2

W Turtlandii przygotowują neon do zawieszenia na dwóch słupach. Słupy stoją w rzędzie, odległość pomiędzy dwoma sąsiednimi wynosi 2. Dział marketingu uzależnia wybór słupów od oceny zdefiniowanej jako suma ich wysokości i odległości między nimi.

Napisz jednoparametrową funkcję neon, której wynikiem jest najwyższa możliwa ocena. Parametr jest listą wysokości kolejnych słupów (ma co najmniej 2 elementy, co najwyżej 500). Wysokość każdego słupa wynosi od 1 do 10 000.

neon [10 4 5 7 1 4 1]24
neon [1 10 1]13

Rozwiązanie

Rozwiązanie zadania polega na policzeniu sumy dla każdej pary wartości i znalezienie maksimum pośród nich. Oto przykładowa implementacja funkcji neon:

  1. oto neon :słupy
  2.   niech "n długość :słupy
  3.   niech "maksimum 0
  4.   powtórz :n [
  5.     niech "x npw
  6.     powtórz (:n - :x) [
  7.       niech "y :x + npw
  8.       niech "suma (element :x :słupy)
  9.       niech "suma :suma + (element :y :słupy)
  10.       niech "suma :suma + abs(:y - :x) * 2
  11.       jeśli :suma > :maksimum [
  12.         niech "maksimum :suma
  13.       ]
  14.     ]
  15.   ]
  16.   wynik :maksimum
  17. już

W celu wybrania wszystkich par przechodzimy po kolejnych elementach i dla każdego parujemy z każdym elementem następującym po nim. W ten sposób uzyskujemy dwie pozycje elementów :x oraz :y. Dla takiej pary liczymy sumę, a następnie sprawdzamy czy nie jest to nowe maksimum.

Zadanie 3

Adam ma papierową torebkę. Wrzuca do niej cukierki, a następnie częstuje nimi znajomych. Cukierki są wrzucane i wyciągane pojedynczo. Postępuje tak wielokrotnie: wrzuca i częstuje. Adam zastanawia się, ile razy w torebce było dokładnie n cukierków.

Napisz dwuparametrową funkcję ilerazy, której pierwszym parametrem jest n (od 1 do 10 000). Drugim parametrem funkcji jest parzystej długości lista dodatnich liczb całkowitych, zawierająca na przemian liczby wrzucanych i wyjmowanych cukierków. Na przykład lista zawierająca 4, 1, 3 i 2 oznacza, że kolejno do torebki zostały wrzucone cztery cukierki, wyjęty jeden, wrzucone trzy i wyjęte dwa. Długośćlisty wynosi od 2 do 1 000. Wynikiem funkcji jest liczba określająca, ile razy w torebce było dokładnie n cukierków.

ilerazy 2 [3 2]2kolejno w koszyku: 0, 1, 2, 3, 4, 5, 4, 3, 2, 3, 4, 5
ilerazy 4 [5 3 5 3 2 1]4kolejno w koszyku: 0, 1, 2, 3, 4, 5, 4, 3, 2, 3, 4, 5, 6, 7, 6, 5, 4, 5, 6, 5

Rozwiązanie

W zadaniu najwygodniej jest użyć podwójnej pętli: jedna przechodzi po kolejnych wartościach z listy, a druga odpowiednio zwiększa i zmniejsza wartość.

  1. oto ilerazy :n :lista
  2.   niech "teraz 0
  3.   niech "zm 1
  4.   niech "ile 0
  5.   powtórz (długość :lista) [
  6.     powtórz (element npw :lista)[
  7.       niech "teraz :teraz + :zm
  8.       jeśli (:teraz = :n) [
  9.         zwiększ "ile
  10.       ]
  11.     ]
  12.     niech "zm :zm * -1
  13.   ]
  14.   wynik :ile
  15. już

Na początku deklarowane są następujące zmienne :teraz - ile jest aktualnie cukierków w koszyku, zm - będzie określać czy dokładamy do koszyczka czy wyjmujemy oraz :ile - ile razy w koszyczku było :n elementów. Dla każdego elementu wykonujemy pętle, która tyle razy zmienia zawartość koszyka jaki element przeglądamy. Po każdej zmianie sprawdzamy czy w koszyku jest poszukiwana ilość. Po zakończeniu pętli wewnętrznej zmieniamy dokładanie na wyjmowanie (lub odwrotnie) poprzez zmianę wartości zmiany :zm na przeciwną (czyli mnożymy przez -1).