Strona główna » Poradniki » Logomocja » LOGIA » Logia 2016/17 Etap III
 

Logia 2016/17 Etap III

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

Zadanie 1 (litera)

Napisz jednoparametrową funkcję litera, której parametrem jest niepusta lista słów składających się z małych liter alfabetu łacińskiego. Wynikiem funkcji jest ta litera, która występuje najczęściej. Jeśli jest więcej niż jedna taka litera, to wynikiem funkcji jest uporządkowana rosnąco lista liter mających tę własność.

litera [ala ma kota]"a
litera [julka lubi psy][l u]

Strategia

Niezależnie od tego w którym słowie występuje litera ma ona zawsze taką samą wartość co każda inna. Oznacza to, że na początku listę słów można zamienić na listę liter, która będzie zawierać wszystkie litery z podanych słów. Taka lista następnie zostanie posortowana, a program będzie zliczał kolejne grupki takich samych liter.

Rozwiązanie

Poniżej zostało przedstawione przykładowe rozwiązanie:

  1. oto litera :słowa
  2.   niech "tab []
  3.   powtórz (długość :słowa) [
  4.     niech "el element npw :słowa
  5.     powtórz (długość :el) [
  6.       niech "tab nak element npw :el :tab
  7.     ]
  8.   ]
  9.   niech "tab sortuj :tab
  10.   niech "w []
  11.   niech "max 0
  12.   niech "licznik 0
  13.   niech "ost "
  14.   powtórz (długość :tab) [
  15.     niech "el element npw :tab
  16.     jeżeli(:el <> :ost) [
  17.       jeśli (:licznik > :max) [
  18.         niech "w []
  19.         niech "max :licznik
  20.       ]
  21.       jeśli (:licznik = :max) [
  22.         niech "w nak :ost :w
  23.       ]
  24.       niech "licznik 1
  25.     ][
  26.       zwiększ "licznik
  27.     ]
  28.     niech "ost :el
  29.   ]
  30.   wynik :w
  31. już

(2. - 8.) Wyodrębnij wszystkie pojedyncze litery, a następnie (9.) posortuj ją. Następnie (9. - 29.) przeprowadź liczenie kolejnych elementów. Liczenie odbywa się poprzez porównywanie kolejnych elementów i zwiększana licznika. Jeśli po napotkaniu (16.) dwóch różnych liter (17.) :licznik jest większy od aktualnego :max to lista liter :w zostaje zresetowana, a jeśli (21.) :licznik wynosi tyle co :max to (22.) litera zostaje dopisana na listę wynikową. Na koniec (30.) zwrócony zostaje wynik.

Zadanie 2 (abc)

Jaś przygotował naszyjnik dla Małgosi. Małgosia poprosiła go o usunięcie niektórych koralików tak, aby wszystkie niebieskie koraliki były przed czerwonymi i zielonymi, a wszystkie czerwone – przed zielonymi. Pozostałe koraliki mogą występować w dowolnych miejscach.

Napisz jednoparametrową funkcję abc, której wynikiem jest minimalna liczba koralików do usunięcia. Parametrem funkcji jest niepuste słowo złożone z małych liter alfabetu łacińskiego opisujące kolory kolejnych koralików w oryginalnym naszyjniku. Kolejne znaki oznaczają kolory: n – niebieski, c – czerwony, z - zielony, a pozostałym literom przypisane są inne kolory. Liczba koralików jest nie większa niż 10 000.

abc "nncnnbffbbbccczzzcz2
abc "zzzznnnnz4

    Zadanie 3 (planeta)

    Na pewnej planecie domy mają adresy będące parami liczb całkowitych dodatnich – ich współrzędnych. Rozmiar planety to maksymalna możliwa wartość współrzędnej. Na planecie o rozmiarze N jest N x N adresów, od (1, 1) do (N, N).

    Po planecie można poruszać się tylko w kierunkach północ↔południe oraz wschód↔zachód (nie po skosie), także w kółko. Odległość między domami jest sumą minimalnych różnic współrzędnych. Na przykład dla planety o rozmiarze 10 dom o adresie (6, 7) jest oddalony od domu o adresie (7, 9) o 1 + 2 = 3, a dom o adresie (1, 4) jest oddalony od domu o adresie (8, 9) o 3 + 5 = 8, a nie 7 + 5 = 12.

    Na planecie wyróżniamy osiedla, tj. rozłączne zbiory domów. Osiedla mogą składać się z jednego lub większej liczby domów. Dom należy do osiedla, gdy jego odległość od pewnego domu tego osiedla jestnie większa niż 5. Jeśli odległość od danego domu do każdego innego na planecie jest większa niż 5, to taki dom stanowi jednodomowe osiedle.

    Napisz dwuparametrową funkcję planeta, której pierwszym parametrem jest rozmiar planety, a drugim lista adresów domów. Wynikiem jest liczba domów w osiedlu składającym się z największej liczby domów. Na planecie stoją co najmniej 2 domy i nie więcej niż 5 000. Rozmiar planety jest nie mniejszy niż 2 i nie większy niż 5 000. Adresy domów nie powtarzają się.

    planeta 12 [[3 1][1 1][1 3][2 12][9 5][8 6]]4
    planeta 100 [[6 6][6 11][11 6][11 11][80 80]]4

    Strategia

    Podczas rozwiązywania zadania należy zwrócić uwagę, że można poruszać się dookoła planety. Oznacza to, że czasem opłaca się iść np. do punktu w lewo zamiast w prawo. Do wyliczania odległości pomiędzy dwoma planetami służy funkcja planeta_odl, która dla podanych pozycji :poz1 i :poz2 określa ich odległość.

    1. oto planeta_odl :n :poz1 :poz2
    2.   niech "d planeta_wartosc :n pierw :poz1 pierw :poz2
    3.   niech "d :d + planeta_wartosc :n ost :poz1 ost :poz2
    4.   wynik :d
    5. już

    Dodatkowa funkcja pomocnicza planeta_wartosc pozwala określić najkrótszy odcinek do przebycia pomiędzy dwoma wartościami poprzez uwzględnianie chodzenia dookoła planety.

    1. oto planeta_wartosc :n :a :b
    2.   niech "d1 abs (:b - :a)
    3.   jeżeli (:d1 < :n - :d1) [
    4.     wynik :d1
    5.   ][
    6.     wynik :n - :d1
    7.   ]
    8. już

    Rozwiązanie

    Oto przykładowe rozwiązanie.

    1. oto planeta :n :lista
    2.   niech "w []
    3.   powtórz (długość :lista) [
    4.     niech "w nak 0 :w
    5.   ]
    6.   niech "os 0
    7.   powtórz (długość :lista) [
    8.     niech "el element npw :lista
    9.     niech "t 0
    10.     powtórz (długość :lista) [
    11.       niech "d element npw :lista
    12.       jeśli (I (:d <> :el)
    13.                         (element npw :w <> 0)
    14.                         (planeta_odl :n :d :el) <= 5) [
    15.         niech "t element npw :w
    16.       ]
    17.     ]
    18.     jeśli (:t = 0) [
    19.       zwiększ "os
    20.       niech "t :os
    21.     ]
    22.     niech "w zastąp npw :w :t
    23.   ]
    24.   niech "w zd sortuj :w 0
    25.   niech "ost pierw :w
    26.   niech "max 0
    27.   niech "licznik 0
    28.   dopóki [nie puste? :w][
    29.     niech "el pierw :w
    30.     niech "w bp :w
    31.     jeżeli (:el = :ost) [
    32.       zwiększ "licznik
    33.     ][
    34.       jeśli (:licznik > :max)[
    35.         niech "max :licznik
    36.       ]
    37.       niech "ost :el
    38.       niech "licznik 1
    39.     ]
    40.   ]
    41.   wy :max
    42. już

    (2. - 5.) Początkowo wszystkie domy są w jednym osiedlu. Dopiero później (6. - 23.) jest to werfyikowane i odpowiednie wartości korygowane. Na koniec (24. - 40.) zliczane są wszystkie kolejne grupy liczb i sprawdzane jest, która grupa jest najbardziej liczna i jej rozmiar (41.) zostaje na koniec zwrócony.

    Zadanie 4 (zawody)

    Zawodnicy (co najmniej dwóch, co najwyżej dwudziestu sześciu) przed startem otrzymują identyfikatory oznaczone kolejnymi wielkimi literami alfabetu łacińskiego (A, B, C, ... itd.), których nie zmieniają podczas zawodów. Zawody składają się z kolejnych rund. Sekwencja zawodników w kolejnych rundach zostaje zachowana, ale zawodników ubywa. Po każdej rundzie odpada zawodnik, który w danej rundzie uzyskał najmniej punktów. Wyniki każdej rundy zapisywane są w liście zawierającej liczby punktów uzyskanych przez kolejnych zawodników w tej rundzie (zakładamy, że każdy zawodnik ma inną liczbę punktów).

    Napisz jednoparametrową funkcję zawody, której parametrem jest poprawna lista opisująca przebieg zawodów, tj. lista wyników kolejnych rund. Wynikiem funkcji jest litera oznaczająca zawodnika, który zwyciężył, czyli wygrał ostatnią rundę.

    zawody [[8 9]]"B 
    zawody [[4 0 2 1][1 2 3][2 1]]"C(po pierwszej rundzie odpadł zawodnik B, potem A, a w ostatniej lepszy był C niż D)

    Strategia

    W każdej rundzie należy wybrać osobę, która najwolniej biegła i ją usunąć z listy. Proces ten powinien być powtarzany, aż zostanie tylko jeden zawodnik.

    Rozwiązanie

    Oto przykładowe rozwiązanie:

    1. oto zawody :lista
    2.   niech "l []
    3.   powtórz (długość pierw :lista) [
    4.     niech "l nak znak ((ascii "A) + npw - 1) :l
    5.   ]
    6.   powtórz (długość :lista) [
    7.     niech "el element npw :lista
    8.     niech "min 1
    9.     powtórz (długość :el) [
    10.       jeśli (element npw :el < element :min :el) [
    11.         niech "min npw
    12.       ]
    13.     ]
    14.     niech "l bezElnum :min :l
    15.   ]
    16.   wynik pierw :l
    17. już

    (2. - 5.) Przygotuj listę zawodników. Następnie (6.) Dla każdego wyniku (7. - 13.) szukaj indeksu elementu o najmniejszej wartości i (14.) usuń zawodnika o tym samym indeksie co miała znaleziona najmniejsza wartość. Na koniec (16.) zwróć pozostałego zawodnika.