Arkusz 2018, matura maj

Zadanie 1.1 (0-3)

Analiza algorytmu
Analiza algorytmu
Rozważamy następujący algorytm:
Dane:
  n – liczba całkowita dodatnia
Wynik:
  p – liczba całkowita dodatnia

p ← 1
q ← n
dopóki p < q wykonuj
  s ← (p+q) div 2
(*)  jeżeli s*s*s < n wykonaj
    p ← s+1
  w przeciwnym wypadku
    q ← s

Uwaga: zapis div oznacza dzielenie całkowite. Podaj wynik działania algorytmu dla wskazanych w tabeli wartości n. 
n  p
28  ?
64  ?
80  ?
Polecam samodzielnie spróbować zrozumieć algorytm oraz spojrzeć na tabelkę - może okazać się, że zrozumiesz jak rozwiązać zadanie bez czytania poniższego tekstu!

Przedstawione mamy dane [n], wynik jaki powinniśmy uzyskać [p] oraz algorytm, czyli lista instrukcji, które wykonujemy od góry do dołu.
Patrząc na algorytm widzimy 3 zmienne: p, q i s.
Strzałka (←) oznacza, że do zmiennej (np. p) przypisywana jest jakaś wartość: przykładowo na początku algorytmu widzimy, że do p przypisujemy 1 (p ← 1).

Kolejna linia programu pokazuje, że do zmiennej możemy też przypisywać wartość innej zmiennej, w tym przypadku zmiennej q przypisujemy wartość n. n jest to stała, której wartość określamy podczas samego startu algorytmu (spójrz na tabelę z zadania 1.1.)

W następnej linii znajdujemy pętlę dopóki (while), w której warunek określa do kiedy będą wykonywały się polecenia położone pod samą pętlą.

Jeśli warunek pętli (p musi być mniejsze niż q) jest prawdziwy, wykonujemy następne komendy.
s ← (p+q) div 2 oznacza, że zmiennej s przypisujemy wartość dzielenia całkowitego (czyli dzielenia, w którym zawsze wychodzą liczby całkowite, np.: 5/2=2, czy 15/2=7) sumy zmiennych p+q. A więc przykładowo dla p=4 i q=7 działania będą następujące:
(6+7) div 2 → 13 div 2 → 6
s ← 6

Następnie znajdziemy warunek (jeżeli s^3<n), od którego zależy, jakie polecenie się wykona:
jeśli jest to prawda: p←s+1, q zostaje takie samo;
jeśli nie: q←s, p zostaje takie samo.
Trzeba pamiętać, że n jest stałe, ponieważ otrzymujemy go na początku, a później jego wartość nie ulega zmianie.

Po wykonaniu przypisania s+1 bądź s do p lub q, wracamy do warunku pętli. Jeśli nadal jest prawdziwy (p bądź q uległo zmianie, więc trzeba to sprawdzić) to powtarzamy wszystkie te czynności, a jeśli fałszywy - kończymy wykonywanie algorytmu i podajemy wynik w postaci wartości zmiennej p.

Do rozwiązywania zadań z algorytmami proponuje wam stworzenie prostej tabelki, w której rozbierzemy kod na części pierwsze.
Składa się ona z kilku części:
• p - wartość zmiennej p. Jak widzimy, początkowo przyjmuje wartość 1;
• q - podobnie jak wyżej, lecz na początku przyjmuje wartość stałej n;
• warunek p<q - od niego zależy, czy algorytm się zakończy, czy dalej kontynuowana będzie pętla, dla ułatwienia zapisujemy TAK/KONIEC;
• s - przypisujemy jej wynik dzielenia całkowitego sumy zmiennych p+q. Należy pamiętać o kolejności wykonywania działań (najpierw dodawanie w nawiasach, dopiero potem dzielenie);
• warunek s^3<n - trzeba pamiętać, że n jest niezmienne. Od tego warunku zależy, czy zmieni się wartość zmiennej p, czy q. Dla ułatwienia zapisujemy co musimy zrobić: czy q←s, czy p←s+1;
• (opcjonalnie) końcowa wartość zmiennych p i q.

Na zdjęciu pokazuje kolejne kroki rozwiązywania zadania dla dwóch pierwszych przykładów. Z trzecim już dasz radę, prawda?
W razie pytań pisz śmiało!

Zadanie 1.2 (0-2)

Analiza algorytmu
Analiza algorytmu
Rozważamy następujący algorytm:
Dane:
  n – liczba całkowita dodatnia
Wynik:
  p – liczba całkowita dodatnia

p ← 1
q ← n
dopóki p < q wykonuj
  s ← (p+q) div 2
(*)  jeżeli s*s*s < n wykonaj
    p ← s+1
  w przeciwnym wypadku
    q ← s

Uwaga: zapis div oznacza dzielenie całkowite. Podaj najmniejszą oraz największą liczbę n, dla której wynikiem działania algorytmu będzie p = 10
Jak można zauważyć rozwiązując poprzednie zadanie (1.1., patrz poprzednie zadanie), dla n równego zarówno 28 jak i 64: p, jak i q równa się 4.
Jeśli rozwiązałeś przykład z n=80, otrzymany wynik p powinien wynosić 5. Możemy więc wysnuć hipotezę, że wraz z rosnącym n, p będzie się zwiększać.
Dlaczego tak się dzieje? 🤔
Decydują o tym dwa czynniki:
a) p ostatecznie zawsze będzie równało się q. Wynika to zarówno z warunku pętli (p= n. Jest to klucz do rozwiązania zadania: udowodniliśmy już, że ostatecznie p=q, a więc teraz musimy ustalić, jakie n będzie potrzebne, aby uzyskać wynik q=10.
Rozwijając myśl z podpunktu a):
- s w najgorszym przypadku będzie równe (1+q) div 2, ponieważ początkowo p=1; np.: p=3, q=11: s=(3+11) div 2 = 7: wartość mniejsza niż q
- s w najlepszym przypadku będzie równa (q+q-1) div 2, co pokazaliśmy wyżej; np.: p=3, q=4: s=(3+4) div 2 = 3: wartość mniejsza niż q

Oznacza to, że q będzie malało, aż warunek s^3= n, a w innym wypadku to p będzie dążyło do q.

A więc, aby przewidzieć, jakie n potrzebujemy, żeby q było równe określonej liczbie (w przypadku tego zadania 10), musimy podnieść tą liczbę do potęgi 3 - voilà! otrzymaliśmy naszą górną granicę, aby uzyskać pożądaną liczbę: dla p=q=10 będzie to 1000! 😃
Dolną granicę możemy wyliczyć, bazując na górnej. Otóż - jeśli dla maksymalnie 1000 uzyskamy p równe 10, oznacza to, że 1001 da nam już inną liczbę - 11. A więc pierwsza liczba, dla której p wyjdzie równe 11, będzie miała zapis 10^3+1 - za dziesiątkę możemy wstawić jakąkolwiek liczbę, ważne jest to, że stanowi ona liczbę, którą chcemy uzyskać w p^3+1. (użycie p czy q jest zamienne, co udowodniliśmy w podpunkcie a.)

Podsumowując:
- dolna granica=(p-1)^3+1, dla 10: (10-1)^3+1=9^3+1=730
- górna granica=p^3, dla 10: 10^3=100

i oto nasz wynik! 😄

Zadanie 1.3 (0-1)

Analiza algorytmu
Analiza algorytmu
Rozważamy następujący algorytm:
Dane:
  n – liczba całkowita dodatnia
Wynik:
  p – liczba całkowita dodatnia

p ← 1
q ← n
dopóki p < q wykonuj
  s ← (p+q) div 2
(*)  jeżeli s*s*s < n wykonaj
    p ← s+1
  w przeciwnym wypadku
    q ← s

Uwaga: zapis div oznacza dzielenie całkowite. Dla każdej liczby całkowitej n > 1 instrukcja oznaczona w algorytmie symbolem (*)
wykona się
A. mniej niż 2·log₂n razy.
B. więcej niż n/2, ale mniej niż n razy.
C. więcej niż n+1, ale mniej niż 2n razy.
D. więcej niż n² razy.
Aby rozwiązać to zadanie, warto wiedzieć czym jest złożoność obliczeniowa algorytmów i co oznaczają te wszystkie zapisy w odpowiedziach.
A więc czym ona jest? 🤔
Jak wiemy - każde urządzenie różni się szybkością, pamięcią i wieloma innymi parametrami. 💻
Jednak wiemy, że niektóre algorytmy są szybsze, a inne wolniejsze. Żeby to ustalić potrzeba jednej w "miarę" dokładnej miary, która jednoznacznie określi, co ile czasu zajmie. 🕰
Korzystamy w tym celu złożoności obliczeniowej, która stwierdza, ile obliczeń (rozkazów) wykonujemy, aby rozwiązać jakiś problem, co bezpośrednio przekłada się na czas wykonania. ⌛ (Psst.. złożoność może także służyć do liczenia ile algorytm zjada pamięci, wtedy mówimy o złożoności pamięciowej! 📚)

W zadaniu pojawia się pytanie: ile razy wykona się instrukcja "jeżeli..." (oznaczona *)? 🤔
Otóż, spójrzmy na algorytm.
Widzimy, że instrukcja ta znajduje się wewnątrz pętli. Pytanie więc możemy zmienić: ile razy wykona się pętla?
Ano, jak głosi warunek pętli: tyle razy, aż p przestanie być mniejsze niż q. 😐
Super. Dużo nam to mówi. dzięki pętlo.
Ale nie poddajemy się. Oznacza to, że znów musimy wrócić do ulubionej analizy najlepszego algorytmu na świecie! 🤗

Jak ustaliliśmy przy rozwiązywaniu poprzedniego zadania (1.2.), q dąży do tego, żeby być równe zaokrąglonemu w górę pierwiastkowi 3 stopnia z n (wynika to z warunku s*s*s < n, a inaczej: s < ∛n)

Z zapisu s=(p+q) div 2 (i deklaracji w przeciwnym wypadku..) wychodzi, że q początkowo będzie się kurczyło o połowę, aż osiągnie wartość najbliższą (ale większą) pierwiastkowi 3 stopnia z n.
Ile operacji "jeżeli" wykonamy, dążąc do tej liczby?
Niestety - specjalistą matematycznym nie jestem. 😔

Dlatego pokażę też inny, łatwiejszy sposób, ale nie jest pewne, że w każdej sytuacji będzie można w prosty sposób go zastosować. 🤷‍♀️
Możemy cofnąć się do zadania 1.1. i po kolei posprawdzać każdy wynik oraz odpowiedzi w tym zadaniu:
- dla n=28 wykonaliśmy 5 sprawdzeń;
- dla n=64: 6 sprawdzeń;
- dla n=80: także 6.

Teraz podstawmy to w miejsce każdej odpowiedzi:
A.) mniej niż 2*log2n razy: czyli podstawiamy: 2*log2(28)≅9.6 - hmm, wykonaliśmy 5 sprawdzeń, a 5<9.6, więc na razie się zgadza. Musimy być jednak pewni, więc wykonujemy kolejne obliczenia. 🙄
2*log2(64)=12, znów się zgadza! możemy zatem zakładać, że jest to prawidłowa odpowiedź, w sumie mogliśmy już wcześniej, jeśli wiedzieliśmy, że logarytmy rosną wraz z podstawioną liczbą. Ale może akurat ominęliśmy tę lekcję matematyki. 🤷‍♀️
Ale bądźmy skrupulatni i dokończmy dla ostatniego przykładu:
2*log2(64)≅12,6; 12,6>6, więc wszystko jest okej
Muszę jednak was ostrzec. ⚠ Nie zawsze taka metoda będzie dobra, ponieważ może zdarzyć się przypadek, w którym będzie istniała jakaś głupia liczba, która zepsuje nam nasz cały plan. 🤦‍♂️ Na przykład: nie obliczyliśmy ile instrukcji jeżeli wykonamy dla n=1000, a więc co jeśli? 😮 W przypadku tego algorytmu nie popełnimy błędu, ale zawsze lepiej być pewnym, niż nie być - na szczęście istnieje sposób, który nas w 100% upewni: spójrzcie na inne odpowiedzi! 🧐

Powyższe wartości, które wskazują ile instrukcji "jeżeli..." zostanie wykonane, muszą być fałszywe dla innych odpowiedzi, bo tylko jedna może być prawdziwa.
A więc sprawdźmy:
B.) więcej niż n/2, ale mniej niż n razy. Brzmi kusząco, jednak spójrzmy: dla n=28; 5 sprawdzeń. 28/2=14. 5 to chyba nie więcej niż 14? 🙄
C.) więcej niż n+1, ale mniej niż 2n razy. Yyyyyy.. jeśli n/2 się nie zgadzało, to to też wydaje się być... niepasujące, prawda?
D.) więcej niż n^2 razy. No tutaj to już przegięli. Ile?!

A więc teraz możemy spać spokojnie będąc pewnym, że postawiliśmy odpowiedź prawidłowo. 🛏

Pocieszająco brzmi fakt, że metodą wykluczania błędnych odpowiedzi, możemy wskazać prawidłową - a więc możemy ominąć liczenie logarytmów. 🤗 Jednak dla waszego bezpieczeństwa, lepiej je powtórzcie, jeśli zapomnieliście. A nuż się przydadzą. 🔪

Zadanie 2.1 (0-2)

Krajobraz
Krajobraz
W pewnym paśmie górskim znajduje się n szczytów, które będziemy przedstawiać jako punkty
w układzie kartezjańskim na płaszczyźnie. Wszystkie punkty leżą powyżej osi OX, tzn. druga
współrzędna (y) każdego punktu jest dodatnia.
W punkcie (0,0) stoi obserwator. Jeśli dwa szczyty A i B mają współrzędne (xA, yA) oraz
(xB, yB), to mówimy, że:
• szczyt A jest dla obserwatora widoczny na lewo od B, jeśli xA/yA < xB/yB;
• szczyt B jest widoczny na lewo od A, jeśli xA/yA > xB/yB.
Wiemy, że żadne dwa szczyty nie leżą w jednej linii z obserwatorem, a zatem dla obserwatora
te szczyty nie zasłaniają się nawzajem. Ilustrację przykładowego położenia szczytów można
zobaczyć na poniższym rysunku:

(układ kartezjański od lewej do prawej)
D(-2,2), A(1,3), B(3,4), C(2,1)

W tym przykładzie, patrząc od lewej do prawej strony, obserwator widzi kolejno szczyt D,
szczyt A, szczyt B i szczyt C.
Współrzędne szczytów dane są w dwóch tablicach X[1..n] oraz Y[1..n] – szczyt numer i ma
współrzędne (X[i], Y[i]). Napisz algorytm (w pseudokodzie lub wybranym języku programowania), który znajdzie i poda
współrzędne skrajnie lewego szczytu, tzn. widocznego dla obserwatora na lewo od wszystkich
pozostałych szczytów.
Specyfikacja:
Dane:
  n – liczba całkowita dodatnia
  X[1..n] – tablica liczb całkowitych
  Y[1..n] – tablica liczb całkowitych dodatnich
  Para (X[i], Y[i]) to współrzędne jednego szczytu, i = 1, 2, …, n.
  Żadne dwa szczyty nie leżą w jednej linii z obserwatorem.
Wynik:
  x, y – współrzędne skrajnie lewego szczytu spośród tych opisanych w tablicach X i Y.
Po kolei - wszystko zaczyna się od n, czyli liczby szczytów, które będzie trzeba porównać. A więc potrzebna będzie z pewnością pętla.
Dalej - musimy dobrze zrozumieć, kiedy który szczyt będzie znajdować się w jakim miejscu. Informacje o tym znajdują się tutaj:
"Jeśli dwa szczyty A i B mają współrzędne (xA, yA) oraz
(xB, yB), to mówimy, że:
• szczyt A jest dla obserwatora widoczny na lewo od B, jeśli xA/yA < xB/yB;
• szczyt B jest widoczny na lewo od A, jeśli xA/yA > xB/yB."
Z tego możemy wyciągnąć wniosek, że im mniejszy jest wynik stosunku x do y, tym nasz szczyt będzie bardziej wysunięty ku lewej stronie. Przykładowo: Dla szczytu A(8, 4) stosunek wynosi 8/4=2, szczyt B(3, 6) natomiast będzie miał stosunek równy 0,5. Oznacza to, że B będzie po lewej stronie A, ponieważ stosunek współrzędnych szczytu B jest mniejszy! Zrozumiałe, prawda? 😎

Okej, przypomnijmy, co mamy obliczyć: "napisz algorytm, który [...] poda współrzędne skrajnie lewego szczytu".
Czyli najpierw będziemy mieli pętlę, która wykona się n razy, a potem porównywamy kolejne stosunki współrzędnych i wybierzemy ten, który jest najmniejszy!
Proponuję zastosować tutaj algorytm na element minimalny, o którym możemy poczytać np. tutaj, jeśli go jeszcze nie znamy.

Zapisujemy więc w pseudokodzie:

lewy_indeks = 1 // indeks szczytu najbardziej na lewo
i = 2
dopóki i <= n:
  szczyt = X[i]/Y[i]
  lewy_szczyt = X[lewy_indeks]/Y[lewy_indeks]
  jeżeli szczyt < lewy_szczyt:
    lewy_indeks = i
  i += 1
x = X[lewy_indeks]
y = Y[lewy_indeks]

Zaledwie kilkoma linijkami udało się zdobyć dwa punkty, a można jeszcze bardziej skrócić ten pseudokod, do czego zachęcam! 😉
Musieliśmy skorzystać ze zmiennej lewy_indeks, ponieważ w wymogach zadania jest "Wynik: x, y – współrzędne skrajnie lewego szczytu [...]". Trzeba jednak pamiętać, że indeks to nie to samo co wartość zmiennej, o czym zdarza się zapominać w pośpiechu. Dlatego też dałem w nazwie "indeks", żeby czasem się nie pomylić. Warto poświęcić kilka liter więcej, żeby uniknąć jakiejś pomyłki 😅
Krajobraz
W pewnym paśmie górskim znajduje się n szczytów, które będziemy przedstawiać jako punkty
w układzie kartezjańskim na płaszczyźnie. Wszystkie punkty leżą powyżej osi OX, tzn. druga
współrzędna (y) każdego punktu jest dodatnia.
W punkcie (0,0) stoi obserwator. Jeśli dwa szczyty A i B mają współrzędne (xA, yA) oraz
(xB, yB), to mówimy, że:
• szczyt A jest dla obserwatora widoczny na lewo od B, jeśli xA/yA < xB/yB;
• szczyt B jest widoczny na lewo od A, jeśli xA/yA > xB/yB.
Wiemy, że żadne dwa szczyty nie leżą w jednej linii z obserwatorem, a zatem dla obserwatora
te szczyty nie zasłaniają się nawzajem. Ilustrację przykładowego położenia szczytów można
zobaczyć na poniższym rysunku:

(układ kartezjański od lewej do prawej)
D(-2,2), A(1,3), B(3,4), C(2,1)

W tym przykładzie, patrząc od lewej do prawej strony, obserwator widzi kolejno szczyt D,
szczyt A, szczyt B i szczyt C.
Współrzędne szczytów dane są w dwóch tablicach X[1..n] oraz Y[1..n] – szczyt numer i ma
współrzędne (X[i], Y[i]). Napisz algorytm (w pseudokodzie lub wybranym języku programowania), który przestawi elementy tablic X i Y tak, aby szczyty były uporządkowane w kolejności, w której obserwator widzi je od lewej do prawej strony. 
Aby otrzymać maksymalną ocenę, Twój algorytm powinien mieć złożoność czasową kwadratową lub mniejszą. 

Algorytm może używać wyłącznie instrukcji sterujących, operatorów arytmetycznych, operatorów logicznych, porównań i przypisań do zmiennych. Zabronione jest używanie funkcji bibliotecznych dostępnych w językach programowania.
Specyfikacja:
Dane:
  n – liczba całkowita dodatnia
  X[1..n] – tablica liczb całkowitych
  Y[1..n] – tablica liczb całkowitych dodatnich
Para (X[i], Y[i]) to współrzędne jednego szczytu, i = 1, 2, …, n.
Żadne dwa szczyty nie leżą w jednej linii z obserwatorem.
Wynik:
  X[1..n], Y[1..n] – tablice zawierające współrzędne danych szczytów, uporządkowanych w kolejności, w której obserwator widzi je od lewej do prawej strony.
Podsumujmy co należy zrobić:
- obliczamy stosunek współrzędnych podanego szczytu, który informuje, w jakiej kolejności będziemy widzieli szczyty (mówiliśmy o tym w poprzednim zadaniu)
- porównamy ją z innymi szczytami, żeby dowiedzieć się, po której stronie widzimy ten szczyt
- przestawimy elementy tablic X i Y, jeśli ich aktualna pozycja jest błędna

Okazuje się, że chodzi w tym zadaniu tak naprawdę o sprawdzenie naszej wiedzy z sortowania. 😎

Pada tu dodatkowo stwierdzenie "złożoności czasowej". Można o niej przeczytać w tym poście.
W skrócie: oznacza ona ilość operacji, które musimy wykonać, w porównaniu do danych wejściowych, oznaczonych symbolem n. Złożoność kwadratowa oznacza, że ilość operacji wykonanych będzie równa n^2, czyli dla n=10 możemy wykonać 100 operacji, więc dla maksymalnej liczby punktów powinniśmy wykonać maksymalnie 100 operacji 😉 Nie musimy jednak liczyć dokładnie, ile operacji będzie wykonywać nasz algorytm 😌 Wystarczą szacunki: najbardziej "obliczeniochłonne" są pętle - pętla dla n razy wykona się... n razy! jeśli jednak zagnieździmy pętlę w pętli, da nam to n*n, czyli n^2, co stanowi limit złożoności - możemy więc stworzyć co najwyżej zagnieżdżoną pętlę.

Do rozwiązania tego zadania możemy wykorzystać każdy algorytm sortujący, którego złożoność jest mniejsza niż n^2. Mamy więc ze standardowych (szkolnych) do wyboru: sortowanie bąbelkowe, przez wybór czy przez wstawianie. 
My dzisiaj zajmiemy się bąbelkowym, do innych zapewne wrócimy przy następnych zadaniach, ale jeśli chcesz dowiedzieć się o nich więcej, spójrz np. tutaj.

Okej, na czym więc polega sortowanie bąbelkowe? 🤔
Chodzi tu o porównywanie ze sobą kolejnych par elementów i zamianie ich kolejności, jeśli jeden nie spełnia warunku (np. pierwszy jest większy od drugiego, a mamy posortować rosnąco). Po sprawdzeniu tej pary, przechodzimy do następnej i tak aż do końca tablicy.
Trzeba jednak pamiętać, że jeden przebieg pętli nie wystarczy, aby posortować tablicę. 
Weźmy przykład: tablica n=[5, 3, 6, 1], którą chcemy posortować rosnąco.
Kolejne etapy sortowania wyglądają tak:
1. 5 > 3? TAK, więc zamieniamy: [3, 5, 6, 1]
2. 5 > 6? NIE, więc zostawiamy: [3, 5, 6, 1]
3. 6 > 1? TAK, więc zamieniamy: [3, 5, 1, 6]

Jak widać, nasza tablica ciągle nie jest posortowana. Aby do tego doszło, musimy powyższe kroki powtarzać, tyle razy, ile wynosi n-1 (chodzi o to, że tyle wykonań pętli jest potrzebne, żeby przesunąć skrajny element tablicy (np. ostatni) do pierwszego (zakładając, że ma on tam się znaleźć - tak jak w naszym przykładzie). Dla powyższej tablicy musielibyśmy wykonać te kroki 3 razy 😉 
Zapiszmy to wszystko w pseudokodzie:
powtarzaj n-1 razy:
  dla i=1, 2.. do n-1:
    jeśli n[i] < n[i+1]:
      n[i], n[i+1] = n[i+1], n[i] // zamiana
To co zapisaliśmy wyżej jest tak naprawdę kluczem do rozwiązania naszej zagadki ze szczytami 😃
Wystarczy, że podstawimy odpowiednie dane i uzyskamy odpowiedź! Musimy przecież zrobić to samo, tylko że dla tablicy X i Y. Do dzieła!
powtarzaj n-1 razy:
  dla i=1, 2.. do n-1:
    poz_1 = X[i]/Y[i]
    poz_2 = X[i+1]/Y[i+1]
    jeśli poz_1 > poz_2:
      X[i], X[i+1] = X[i+1], X[i]
      Y[i], Y[i+1] = Y[i+1], Y[i]
Voilà! tak oto wygląda nasz ukończony algorytm. 🤯
poz_1 i poz_2 oznaczają pozycje, im mniejsza tym bardziej na lewo widzimy szczyt.
Mamy posortować od szczytów najbardziej na lewo, do tych najbardziej na prawo: dlatego też sprawdzamy, czy poz_1 > poz_2. Jeśli poz_1 jest większy - trzeba zamienić.

Zadanie 3.1 (0-1)

Test
Test
Oceń prawdziwość podanych zdań. Zaznacz P, jeśli zdanie jest prawdziwe, albo F – jeśli jest
fałszywe.
W każdym zadaniu punkt uzyskasz tylko za komplet poprawnych odpowiedzi. Na pewnym serwerze WWW znajduje się strona napisana w języku PHP, a jej kod zawiera fragmenty w języku JavaScript. Pewien komputer-klient pobrał i wyświetlił tę stronę.
Wiadomo, że:
1. kod PHP jest wykonywany przez komputer – serwer. [P/F]
2. kod JavaScript jest wykonywany przez komputer – klient. [P/F]
3. podczas wykonywania kodu PHP zawsze pobierane są dane od klienta. [P/F]
4. podczas wykonywania kodu JavaScript mogą być pobierane dodatkowe dane zarówno od klienta, jak i od serwera. [P/F]
Czytając te polecenia można lekko się zmieszać - nie wiem dlaczego, ale CKE dodało do nazewnictwa klient/serwer komputer, co może prowadzić do nadinterpretacji. Tłumacząc: ważne jest jedynie pojawienie się określenia klient lub serwer - słowo komputer zostało użyte tutaj w bliżej nieokreślonym celu 🤷‍♀️

Okej, przejdźmy do zadań:
1. kod PHP jest wykonywany przez komputer – serwer: język PHP został stworzony w celu m.in. dynamicznego tworzenia strony po stronie serwera - chodzi tu o to, że np. jeśli przekażemy serwerowi dane uwierzytelniające to możemy uzyskać dostęp do elementów strony, które nie pojawią się dla zwykłego użytkownika. Innymi słowy: na podstawie przekazanych parametrów kod języka PHP potrafi wygenerować różniące się od siebie strony i czynność ta zachodzi na serwerze. Zaznaczamy więc PRAWDA 😀 PS. ta strona została własnie napisana z użyciem PHP! 

2. kod JavaScript jest wykonywany przez komputer – klient: jednym z zadań JavaScriptu (JS) jest wprowadzenie większej interaktywności do strony. Pamiętasz, jak ostatnio kliknąłeś na jakieś zdjęcie na Facebooku, albo wysłałeś wiadomość? To wszystko sprawka JavaScriptu! 😎 Dostarczany jest on przez serwer wraz z plikami strony (np. .html) do klienta i to właśnie po lokalnej stronie się wykonuje. Możemy zaznaczyć PRAWDA. 

3. podczas wykonywania kodu PHP zawsze pobierane są dane od klienta: kod PHP może pobierać dane z różnych źródeł: np. strona z pogodą może odwoływać się najpierw do serwera pogodynkowego ⛅, a dopiero potem przekaże zdobyte dane klientowi. Oznacza to tyle, że niekoniecznie klient musi dostarczać te dane. Możemy z lekkim sercem zakreślić FAŁSZ. 😌

4. podczas wykonywania kodu JavaScript mogą być pobierane dodatkowe dane zarówno od klienta, jak i od serwera: jak wyżej wspominalyśmy, jednym z zadań JS jest wprowadzenie interaktywności do strony. Nie jest jednak to jedyne możliwe zastosowanie: język JS jest baaaardzo rozbudowany i jedną z opcji tworzenie zapytań do serwerów - w tym naszego serwera. Przykładem jest np. przewijanie facebookowej tablicy: może doświadczyliście kiedyś sytuacji, gdy skończyły się posty i pojawiło się kółeczko, które oznacza ładowanie się nowych. Wtedy właśnie do gry wchodzi pobieranie dodatkowych danych od serwera, w tym wypadku - postów. Dane od klienta także mogą być bez problemu pobierane - przykładem jest np. aktualny czas. Tak więc zaznaczamy PRAWDA. 🥳

Dzisiaj zajęliśmy się tematyką stron WWW, która tak często jest pomijana na lekcjach informatyki. Zachęcam was zatem do spróbowania własnych sił w przeróżnych kursach na YouTubie, czy na np. KhanAcademy, bo jak widać - i takie zadania mogą się pojawić. 😀

Zadanie 3.2 (0-1)

Test
Test
Oceń prawdziwość podanych zdań. Zaznacz P, jeśli zdanie jest prawdziwe, albo F – jeśli jest
fałszywe.
W każdym zadaniu punkt uzyskasz tylko za komplet poprawnych odpowiedzi. 1. Plakat do druku lepiej przygotować w modelu barw RGB niż CMYK. [P/F]
2. Kolor żółty jest kolorem podstawowym w modelu RGB. [P/F]
3. W wyniku nałożenia się składowych Yellow i Magenta w modelu CMYK otrzymamy kolor czerwony. [P/F]
4. W modelu barw CMYK litera C pochodzi od angielskiego słowa contrast. [P/F]
Opowiedzmy może najpierw trochę o tych wszystkich nazwach i ich znaczeniu. 
Przede wszystkim przewijają się skróty RGB i CMYK - co one oznaczają? Stanowią one modele barw, czyli upraszczając: sposób uzyskiwania różnych kolorów! 🎨 Może pamiętacie jeszcze z lekcji plastyki, że czerwony połączony z zielonym da nam żółty, a niebieski z czerwonym purpurowy? RGB stanowi skrót właśnie od tych trzech składowych: Red (czerwony), Green (zielony), Blue (niebieski). 
Warto tutaj dodać, tak na przyszłość, że model RGB jest addytywny: oznacza to, że barwy powstają przez łączenie się (dodawanie) ze sobą barw podstawowych, a wynika to z tego, że ten model może być wykorzystany jedynie w przypadku urządzeń emitujących światło! W takim wypadku wyświetlanie przez monitor kolorów przypomina mieszanie barw na palecie.
Model CMYK działa zgoła inaczej. Wykorzystuje on barwy: Cyan (cyjan, przypomina jaskrawy niebieski),Magenta (fuksja, osobiście wygląda mi na róż, choć co ja tam wiem 🤷‍♂️), Yellow (żółty, uff, wreszcie jakiś normalny kolor!) i... Key (kolor kluczowy) bądź blacK (czarny)! Z tym ostatnim jest trochę problemu, bo pojawia się wiele interpretacji tej litery - dla nas jednak najważniejsze, że najczęściej jest to czarny. (przy okazji odpowiedzieliśmy na pytanie 4, ha!). Zestaw tych czterech barw trzeba niestety regularnie wymieniać w drukarce. 🖨
Teraz kluczowe pytanie: po co nam potrzebne kilka modeli?
Hmm... odpowiedź tkwi w kartce papieru! Różni się ona od wyświetlacza, prawda? Możemy co prawda kolorować kartkę kredkami, ale gdy tylko zajdzie słońce lub zgaśnie światło... nie będzie nic widać! Dlaczego? bo kartka nie emituje własnego światła, tak jak robią to monitory. Ona odbija światło, a dana farba czy kredka pochłania pewien zakres fal, co w ostateczności daje nam wrażenie określonej barwy: dlatego CMYK nazywany jest modelem subtraktywnym (bo odejmuje niektóre długości fal). Może to wydawać się skomplikowane, ale warto zagłębić się w temat na w razie czego! 😎

Wracając do naszych zadań, przejdźmy do odpowiedzi:
1. Plakat do druku lepiej przygotować w modelu barw RGB niż CMYK. [P/F] - jak powiedzieliśmy, RGB wykorzystujemy przy emitowaniu światła, a CMYK do drukowania! Zaznaczamy fałsz. ❌

2. Kolor żółty jest kolorem podstawowym w modelu RGB. [P/F] - red, green, blue, hmm... żółtego nie widzę, fałsz!

3. W wyniku nałożenia się składowych Yellow i Magenta w modelu CMYK otrzymamy kolor czerwony. [P/F] 
Tutaj przyda nam się wyobraźnia do wizualizacji takiego połączenia, jednak jest też inny sposób! W wyniku łączenia się barw CMY (tak, bez K), powstają barwy podstawowe RGB oraz po środku (gdy zmieszamy cyjan, żółty oraz magentę) kolor czarny. Ciężko, aby kolor czerwony powstał z żółtego i jaskrawego niebieskiego, prawda? z tego ostatniego i magenty także (w wyniku takiego połączenia powstanie zwykły niebieski!). A więc metodą eliminacji został nam tylko żółty i magenta, czyli jest to prawda.

4. W modelu barw CMYK litera C pochodzi od angielskiego słowa contrast. [P/F] - C jak... cyjan! Czyli fałsz.

Jak widać, informatyka to nie tylko algorytmy czy programowanie, jest w niej też trochę... koloru! 🌈
Test
Oceń prawdziwość podanych zdań. Zaznacz P, jeśli zdanie jest prawdziwe, albo F – jeśli jest
fałszywe.
W każdym zadaniu punkt uzyskasz tylko za komplet poprawnych odpowiedzi. Wskaż zdania prawdziwe dla języka SQL.
1. W wynikach zapytania postaci SELECT (...) ORDER BY (...) zawsze dostajemy rekordy uporządkowane ściśle rosnąco według wskazanego pola. [P/F]
2. Zapytanie UPDATE może zmienić wartości pól w bazie danych. [P/F]
3. Zapytanie postaci SELECT * FROM tabela1 WHERE pole LIKE (...) może w pewnych warunkach dać wszystkie rekordy z tabeli tabela1. [P/F]
4. Wynik zapytania SELECT * FROM tabela1 JOIN tabela2 ON tabela1.pole = tabela2.pole może być pusty przy niepustych tabelach tabela1 oraz tabela2. [P/F]
1. W wynikach zapytania postaci SELECT (...) ORDER BY (...) zawsze dostajemy rekordy uporządkowane ściśle rosnąco według wskazanego pola. [P/F] 
Instrukcja SELECT w języku SQL (język zapytań do baz danych) pozwala nam wybrać dane rekordy, a ORDER BY - sortuje nam wynik według podanego bądź podanych po niej kolumnach. Pytanie więc odnosi się przede wszystkim do kwestii tego, czy sortowanie musi zawsze być rosnące, czy malejące?  Odpowiedzieliśmy sobie na nie przy okazji poprzedniego zadania z tego arkusza! www.fb.com/informatura/posts/118685263078528. 
W dużym skrócie: to, jak chcemy posortować wyniki, zależy tylko od nas. Wykorzystujemy do tego celu słowa kluczowe ASC (od ascending - rosnąco) i DESC (descending - malejąco). Tak więc nie zawsze rekordy są uporządkowane rosnąco! Zaznaczamy fałsz.

2. Zapytanie UPDATE może zmienić wartości pól w bazie danych. [P/F] - jak sama nazwa wskazuje, instrukcja UPDATE coś aktualizuje. Jak z niej korzystamy? UPDATE nazwa_tabeli SET kolumna1=wartość1, kolumna2=wartość2... WHERE warunek_aktualizacji. Możemy więc z tego zapisu wywnioskować, że zmieniamy poszczególne wartości występujące w tabeli, czyli wartości pól! Prawda.

3. Zapytanie postaci SELECT * FROM tabela1 WHERE pole LIKE (...) może w pewnych warunkach dać wszystkie rekordy z tabeli tabela1. [P/F]
W tym przypadku trzeba wiedzieć, jak funkcjonuje operator LIKE. Oznacza on tyle co "podobny", czy "przypominający". Przykład: SELECT * FROM konie WHERE imie LIKE "Atena"; - zwróci on nam wszystkie rekordy, w których koń ma na imię Atena. 🐴 Instrukcja ta jednak nie służy tylko do zwykłego porównywania, to, co ją wyróżnia, to możliwość zastosowania znaków wieloznacznych (wildcards): znak "%" oznacza dowolny ciąg znaków (także pusty!), a znak "_" - jeden, dowolny znak. 
Tak więc możemy zadać powyższą kwerendę z klauzulą WHERE imie LIKE "At%" i w ten sposób uzyskamy nie tylko rekord z imieniem Atena, ale także np. Atrymoniusz! Można też zastosować sam znak wieloznaczny "%", który sprawi, że otrzymamy wszystkie rekordy, więc tak, możemy uzyskać wszystkie rekordy w pewnych warunkach. Prawda!

4. Wynik zapytania SELECT * FROM tabela1 JOIN tabela2 ON tabela1.pole = tabela2.pole może być pusty przy niepustych tabelach tabela1 oraz tabela2. [P/F] 
Tutaj potrzebna nam jest powtórka z łączenia tabel. A więc w SQLu mamy możliwość łączenia ze sobą kilku tabel, na podstawie m.in. wspólnej kolumny, którą posiadają obie tabele - możemy otrzymać wtedy wynik zawierający wartości z tabeli A i z tabeli B. 
Istnieje wiele typów złączeń, np.: INNER, LEFT, RIGHT, czy OUTER, ale to temat na osobną lekcję. Tutaj jak widzimy: przed JOIN nie ma żadnego z wcześniej wymienionych typów - w takim wypadku stosujemy domyślne łączenie, jakim jest INNER JOIN (złączenie wewnętrzne, część wspólna). Jest to chyba najprostsze z możliwych sposobów na spięcie ze sobą tabel. Chodzi w nim o to, że wartości zostaną połączone tylko wtedy, gdy w tabela1.pole będzie znajdowała się taka sama wartość, jak w tabela2.pole: oczywiście możliwe do podania wartości mogą się różnić od tych, te tutaj są dostosowane do zadania "JOIN tabela2 ON tabela1.pole = tabela2.pole". 
Czyli jeśli w danym rekordzie tabela1.pole byłoby równe 1, a tabela2.pole także przyjęłoby wartość 1, to doszłoby do złączenia i wypisalibyśmy wszystkie wartości z tych rekordów! Jeśli natomiast wartości te różniłyby się, to nie wypisałaby się żadna z krotek (rekordów). 
Wracając do naszego zadania: czy wynik łączenia wewnętrznego dwóch niepustych tabel może być pusty? Jak najbardziej! Wystarczy, że pole1 nie będzie w żadnym polu2 sobie równe. ⚖ Zaznaczamy więc prawdę. ✔