Listy zadań HTML
L01 - Lista 1
Lista 1
Termin wykonania:
12.03.2025
Zad 1 - 1 pkt
Zaimplementuj funkcję przyjmującą jeden argument typu Int drukującą wszystkie liczby od 1 do podanej wartości.
Jeżeli liczba jest podzielna przez:
- 3 - funkcja drukuje "trzy"
- 5 - funkcja drukuje "piec"
- 3 i 5 - funkcja drukuje "trzypiec"
- W każdym innym przypadku funkcja drukuje wartość liczbową
val num: Int = 15
println(foo(num))
>> 1
>> 2
>> trzy
>> 4
>> piec
>> trzy
>> 7
>> 8
>> trzy
>> piec
>> 11
>> trzy
>> 13
>> 14
>> trzypiec
Zad 2 - 1 pkt
Stwórz program, który sprawdzi, czy podane przez użytkownika słowo jest palindromem (czytane tak samo od lewej do prawej, jak i od prawej do lewej).
val word = "abba"
println(isPalindrome(word))
>> true
Zad 3 - 1 pkt
Napisz program, który wygeneruje trójkąt Pascala o zadanej wysokości. Trójkąt Pascala to struktura liczbowa, w której każda liczba to suma dwóch liczb znajdujących się bezpośrednio nad nią w poprzednim rzędzie.
val height: Int = 4
println(printPascal(height))
>> 1
>> 1 1
>> 1 2 1
>> 1 3 3 1
Zad 4 - 2 pkt
Napisz program, który sprawdzi czy podana liczba jest liczbą doskonałą, obfitą lub niedomiarową, na podstawie jej sumy alikwotowej.
val number: Int = 28
println(isPerfect(number))
>> perfect
val number: Int = 12
println(isPerfect(number))
>> abundant
val number: Int = 8
println(isPerfect(number))
>> deficient
Przykłady:
- 28: $1 + 2 + 4 + 7 + 14 = 28$ - doskonała
- 12: $1 + 2 + 3 + 4 + 6 = 16$ - obfita
- 8: $1 + 2 + 4 = 7$ - niedomiarowa
Zad 5 - 2 pkt
Napisz program, który sprawdzi czy podana liczba jest liczbą Armstronga.
val number: Int = 153
println(checkArmstrong(number))
>> true
Przykłady: $$153 = 1^3 + 5^3 + 3^3 = 1 + 125 + 27$$ $$9 = 9^1$$ $$154 \neq 1^3 + 5^3 + 4^3 = 1 + 125 + 64$$
Zad 6 - 1 pkt
Napisz funkcję, która sprawdzi, czy podana liczba jest liczbą pierwszą.
val number: Int = 17
println(isPrime(number))
>> true
Zad 7 - 1 pkt
Zaimplementuj funkcję, która obliczy sumę wszystkich liczb parzystych od 1 do podanej wartości (włącznie).
val n: Int = 10
println(sumEven(n))
>> 30
Zad 8 - 1 pkt
Napisz funkcję, która zliczy liczbę samogłosek w podanym słowie (bez rozróżniania wielkości liter).
Przyjmij samogłoski: a, e, i, o, u, y.
val word = "Programowanie"
println(countVowels(word))
>> 6
Oceny
| ocena | punkty |
|---|---|
| 3,0 | 6 pkt |
| 3,5 | 7 pkt |
| 4,0 | 8 pkt |
| 4,5 | 9 pkt |
| 5,0 | 10 pkt |
Lista 2
Termin wykonania:
26.03.2025
Zad 1 - 1 pkt
Zrefaktoryzuj podany kod z podejścia imperatywnego do stylu Kotlin idiomatic. Użyj funkcji zakresu: let, run, apply, also (minimum 3 z 4).
Kod startowy (imperatywny)
data class UserInput(val name: String?, val email: String?, val age: String?)
data class UserProfile(
var name: String = "",
var email: String = "",
var age: Int = 0,
var isAdult: Boolean = false
)
fun buildProfile(input: UserInput?, logs: MutableList<String>): UserProfile? {
if (input == null) {
logs.add("Input is null")
return null
}
if (input.name == null) {
logs.add("Name is null")
return null
}
val name = input.name.trim()
if (name.length < 3) {
logs.add("Name too short")
return null
}
if (input.email == null) {
logs.add("Email is null")
return null
}
val email = input.email.trim().lowercase()
if (!email.contains("@")) {
logs.add("Invalid email")
return null
}
if (input.age == null) {
logs.add("Age is null")
return null
}
val age = input.age.toIntOrNull()
if (age == null) {
logs.add("Age is not a number")
return null
}
val profile = UserProfile()
profile.name = name
profile.email = email
profile.age = age
profile.isAdult = age >= 18
logs.add("Profile created for $email")
return profile
}
Zachowaj to samo działanie funkcji i tę samą sygnaturę.
Zad 2 - 1 pkt
Zaimplementuj właściwości rozszerzające:
val <T> List<T>.tail: List<T>zwracającą listę wszystkich elementów listy oprócz pierwszegoval <T> List<T>.head: Tzwracającą pierwszy element listy
Zad 3 - 1 pkt
Zaimplementuj funkcję isSorted(lst: List<A>, order: (A, A) -> Boolean): Boolean sprawdzającą czy lista List<A> jest posortowana zgodnie z funkcją porównawczą.
Przykładowo:
input:
>> isSorted(listOf(1, 2, 3, 4), {i: Int, j: Int -> i < j})
output:
>> true
input:
>> isSorted(listOf(1, 1, 1, 1), {i: Int, j: Int -> i==j})
output:
>> true
input:
>> isSorted(listOf("ahyyhh", "bkjn", "cnn", "duu"), {i: String, j: String -> i.first() < j.first()})
output:
>> true
Zad 4 - 1 pkt
Napisz funkcje safeParseAndClassify(input: String?): String, ktora:
- zwraca
BRAK_DANYCH, gdyinput == nulllub pusty string, - parsuje liczbe calkowita bez uzycia
!!, - zwraca
PARZYSTAlubNIEPARZYSTAdla poprawnego wejscia.
Zad 5 - 1 pkt
Napisz funkcję check zwracającą liczbę Int. Funkcja przyjmuje długość preambuły N: Int oraz listę List: List<Int>.
- Lista zawiera tylko liczby dodatnie
- Każda liczba musi być sumą dwóch różnych liczb z preambuły
- Jeżeli waruunek jest spełniony, przesuwamy preambułę o jeden i sprawdzamy ponownie
- Jeżeli nie znajdziemy elementu niepasującego, funkcja zwraca
-1
Załóżmy że wywołujemy check(3, listOf(1, 2, 3, 5, 7, 12, 30)), poniżej wszystkie kroki :
Funkcja zwraca pierwszą liczbę na liście, która nie spełnia tego warunku.
input:
>> check(2, listOf(1, 2, 3, 4, 5, 6))
output:
>> 4
input:
check(5, listOf(35, 25, 15, 25, 47, 40, 62, 55, 65, 95, 102, 117, 150, 182, 127, 219, 299, 277, 309, 576))
output:
127
Pytania:
- Czym w Kotlinie jest typ Any i czym różni się od Any?? (1 pkt)
- Czym różni się Unit od Nothing? Podaj typowe zastosowanie każdego z nich. (1 pkt)
- Jaka jest różnica między val a var? (1 pkt)
- Dlaczego val nie oznacza zawsze pełnej niezmienności obiektu? (1 pkt)
- Kiedy używamy const val i jakie są ograniczenia const val? (1 pkt)
- Na czym polega Null Safety w Kotlinie? Jak oznaczyć typ nullowalny? (1 pkt)
- Do czego służy operator bezpiecznego wywołania ?. ? (1 pkt)
- Do czego służy operator Elvisa ?: ? Podaj typowy przypadek użycia. (1 pkt)
- Dlaczego operator !! jest niebezpieczny i kiedy może prowadzić do błędu? (1 pkt)
- Czym when w Kotlinie różni się od switch znanego z innych języków? (1 pkt)
- Jaka jest różnica między zakresami 1..5, 1 until 5, 5 downTo 1, 1..10 step 2? (1 pkt)
- Jaka jest różnica między stosem (Stack) a stertą (Heap) w kontekście JVM/Kotlin? (1 pkt)
- Co zwykle trafia na stos, a co trafia na stertę w kontekście JVM/Kotlin? (1 pkt)
- Co to jest boxing (opakowywanie) i kiedy w Kotlinie może wystąpić? (1 pkt)
- Na jakiej zasadzie Garbage Collector uznaje obiekt za „śmieć”? (1 pkt)
- Opisz krótko fazy Mark, Sweep, Compact. (1 pkt)
- Na czym polega hipoteza generacyjna („większość obiektów umiera młodo”)? (1 pkt)
- Jaką rolę pełnią Eden, Survivor Space i Old Generation? (1 pkt)
- Co to jest memory leak i dlaczego GC nie zawsze „rozwiązuje problem pamięci”? (1 pkt)
- Co dają argumenty domyślne i argumenty nazwane w funkcjach Kotlin? (1 pkt)
- Do czego służy vararg? Jak przekazać wiele argumentów do takiej funkcji? (1 pkt)
- Czym jest funkcja rozszerzająca (extension function)? Jaka jest jej główna zaleta? (1 pkt)
- Czym jest funkcja infiksowa (infix fun) i kiedy można jej użyć? (1 pkt)
- Co to jest funkcja wyższego rzędu (higher-order function)? (1 pkt)
- Czym jest lambda w Kotlinie i czym różni się od funkcji nazwanej? (1 pkt)
- Do czego służą referencje do funkcji (::), np. ::println albo String::length? (1 pkt)
- Wymień co najmniej 3 scope functions i podaj główną różnicę między nimi (dostęp przez this/it oraz co zwracają). (1 pkt)
- Co daje modyfikator inline przy funkcjach przyjmujących lambdy? (1 pkt)
- Co oznacza tailrec i jaki problem rozwiązuje? (1 pkt)
- Co to jest funkcja generyczna i jak zapisujemy parametr typu w Kotlinie? (1 pkt)
- Jak ograniczyć typ generyczny i do czego służy where? (1 pkt)
- Co to jest type erasure (wymazywanie typów) i jaki ma skutek dla generyków na JVM? (1 pkt)
- Po co używa się reified i dlaczego działa tylko z inline? (1 pkt)
- Na czym polega przeciążanie operatorów w Kotlinie? Podaj przykład. (1 pkt)
Oceny
| ocena | punkty |
|---|---|
| 3,0 | 6 pkt |
| 3,5 | 7 pkt |
| 4,0 | 8 pkt |
| 4,5 | 9 pkt |
| 5,0 | 10 pkt |
Lista 3
Termin wykonania:
gr. 16.04.2025
Zadania 3-9 wykonaj wykorzystując metody transformacji, filtrowania, testowania (map, all, groupBy, etc.), oraz łańcuchowania metod.
val numbers = listOf(5, 12, 3, 19, 8)
val result = number
.filter {it > 5}
.map {it * 2}
.sorted()
.joinToString(" - ")
println(result)
>>> 16 - 24 - 38
Zad 1 - 1 pkt
Wykorzystując właściwości zbiorów (Set) napisz funkcję findDuplicates przyjmującą listę liczb całkowitych jako argument i zwracającą posortowaną rosnąco listę wszystkich duplikatów.
val lst = listOf(0, 1, 1, 1, 4, 4, 4, 9, 3, 3, 3, 3, 3, 3)
println(findDuplicates(lst))
>> (1, 3, 4)
Zad 2 - 1 pkt
Napisz funkcję addToBoolean zwracającą mapę Map<Integer, Boolean> (Kotlin - Map<Int, Boolean>). Funkcja dodaje do mapy 20 elementów, kluczami są liczby 1-20.
- Jeżeli klucz jest parzysty, wartość ustawiamy na
true - Jeżeli klucz jest nieparzysty - wartość jest
false.
println(addToBoolean())
>> {1=false, 2=true, 3=false, 4=true ...}
Zad 3 - 1 pkt
Napisz funkcję suma(a: List<Int>): Int zwracającą sumę wszystkich dodatnich liczb w liście (wykorzystaj operacje transformacji kolekcji, przykładowo map, filter, reduce ...)
input:
>> suma(listOf( 1, -4, 12, 0, -3, 29, -150))
output:
>> 42
Zad 4 - 1 pkt
Napisz funkcję countElements przyjmującą listę List<List<String>> i zwracającą mapę zawierającą liczbę wystąpień każdego elemetu. Wykorzystaj operacje transformacji kolekcji, przykładowo map, filter, reduce ...
input:
countElements(listOf(listOf("a", "b", "c"), listOf("c", "d", "f"), listOf("d", "f", "g")))
output:
{ a: 1, b: 1, c: 2, d: 2, f: 2, g: 1 }
Zad 5 - 1 pkt
Napisz funkcję evenPositiveSquare przyjmującą listę liczb Int i zwracającą listę wszystkich dodatnich liczb o indeksach nieparzystych podniesionych do kwadratu. Wykorzystaj operacje transformacji kolekcji, przykładowo map, filter, reduce ...
input:
evenPositiveSquare(listOf(1, 2, 3, 5, -6, -1, -1, 2, 3))
output:
[4, 25, 4]
Zad 6 - 1 pkt
Napisz funkcję perm przyjmującą List<Int> zwracającą listę list wszystkich możliwych permutacji. Wykorzystaj operacje transformacji kolekcji, przykładowo map, filter, reduce ...
input
perm(listOf(1, 2, 3))
output
[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
Zad 7 - 1 pkt
Napisz funkcję srt przyjmującą listę String. Funkcja zwraca posortowaną względem pierwszej litery listę pogrupowanych par, zawierających tylko String o parzystej długości (List<Pair<String, List<String>>>). Wykorzystaj operacje transformacji kolekcji, przykładowo map, filter, reduce ...
input:
srt(listOf(
"cherry",
"blueberry",
"citrus",
"apple",
"apricot",
"banana",
"coconut")
)
output:
[[ b, [banana] ], [ c, [cherry, citrus] ] ]
Zad 8 - 1 pkt
Wykorzystując Map, zaimplementuj funkcję konwertującą słowo na numer telefonu.
val word = "franek
println(convert(word))
>> 3337772663355
Zad 9 - 1 pkt
Dany jest zbiór wyników studentów zapisanych jako lista obiektów klasy StudentScore:
data class StudentScore(val name: String, val subject: String, val score: Int)
Napisz funkcję analyzeResults, która przyjmie listę StudentScore i zwróci Triple<Map<String, List<StudentScore>>, List<StudentScore>, List<String>>:
- Mapę przedmiotów z listami studentów, którzy zdali.
- Listę studentów, którzy nie zdali.
- Listę przedmiotów, w których wszyscy studenci zdali.
val students = listOf(
StudentScore("Alice", "Math", 78),
StudentScore("Bob", "Math", 45),
StudentScore("Charlie", "Physics", 92),
StudentScore("Dave", "Physics", 55),
StudentScore("Eve", "Physics", 40),
StudentScore("Frank", "CS", 60),
StudentScore("Grace", "CS", 80),
)
val (passedBySubject, failed, subjectsAllPassed) = analyzeResults(students)
println("Zdani studenci według przedmiotów: $passedBySubject")
println("Niezdani studenci: $failed")
println("Przedmioty, w których wszyscy zdali: $subjectsAllPassed")
>>> Zdani studenci według przedmiotów: {Math=[StudentScore(name=Alice, subject=Math, score=78)], Physics=[StudentScore(name=Charlie, subject=Physics, score=92), StudentScore(name=Dave, subject=Physics, score=55)], CS=[StudentScore(name=Frank, subject=CS, score=60), StudentScore(name=Grace, subject=CS, score=80)]}
>>> Niezdani studenci: [StudentScore(name=Bob, subject=Math, score=45), StudentScore(name=Eve, subject=Physics, score=40)]
>>> Przedmioty, w których wszyscy zdali: [CS]
Zad 10 - 1 pkt
Do klasy Point zmień działanie operatorów, tak aby możliwe były następujące operacje:
data class Point(val x: Int, val y: Int)
val p1 = Point(1, 1)
val p2 = Point(2, 2)
input: p1 + p2 output: (3, 3)
input: p1 += 1 output: (2, 2)
input: p1 - p2 output: (-1, -1)
input: p1 * p2 output: (2, 2)
input: p1++ output: (2, 2)
input: p1-- output: (0, 0)
input: !p1 output: (-1, -1)
Oceny
| ocena | punkty |
|---|---|
| 3,0 | 6 pkt |
| 3,5 | 7 pkt |
| 4,0 | 8 pkt |
| 4,5 | 9 pkt |
| 5,0 | 10 pkt |
Lista 4
Termin wykonania:
07.05.2026
Zadania wykonaj wykorzystując metody transformacji, filtrowania, testowania (map, all, groupBy, etc.), oraz łańcuchowania metod.
val numbers = listOf(5, 12, 3, 19, 8)
val result = number
.filter {it > 5}
.map {it * 2}
.sorted()
.joinToString(" - ")
println(result)
>>> 16 - 24 - 38
Przygotujmy dane dla aplikacji zarządzającej kosztami posiadanych samochodów. Dla uproszczenia zakładamy koszty tylko z roku 2025.
Typ kosztu zdefiniujemy jako enum class.
enum class CostType(val costType: String) {
REFUELING("Tankowanie"),
SERVICE("Serwis"),
PARKING("Parking"),
INSURANCE("Ubezpieczenie"),
TICKET("Mandat")
}
Model danych zawiera typ kosztu, datę oraz kwotę.
data class Cost (
val type: CostType,
val date: LocalDate,
val amount: Int
)
W objekcie DataProvider znajduje się wygenerowana lista kosztów.
import kotlin.random.*
object DataProvider {
val generalCosts = List(5) {
Cost(
CostType
.values()[Random.nextInt(CostType.values().size)],
LocalDate.of(
2025,
Random.nextInt(1,13),
Random.nextInt(1,28)),
Random.nextInt(5000)
)
}
}
Zad 1 - 1 pkt
Napisz funkcję groupedCostMap przyjmującą listę kosztów List<Cost>, która zwróci mapę kosztów pogrupowaną według miesiąców i posortowaną rosnąco .
input:
>> groupedCostMap(DataProvider.generalCosts)
generując 5 elementów
output:
>> {JANUARY=[Cost(type=INSURANCE, date=2025-01-15, amount=2263)], APRIL=[Cost(type=SERVICE, date=2025-04-20, amount=1933)], AUGUST=[Cost(type=INSURANCE, date=2025-08-24, amount=1524), Cost(type=PARKING, date=2025-08-13, amount=2350)], DECEMBER=[Cost(type=PARKING, date=2025-12-15, amount=529)]}
Zad 2 - 2 pkt
Napisz funkcję drukującą wszystkie koszty.
- koszty powinny być pogrupowane według miesięcy
- koszty powinny być posortowane według dat
format:
<miesiąc>
<dzień> <koszt> <kwota>
<dzień> <koszt> <kwota>
...
<miesiąc>
<dzień> <koszt> <kwota>
<dzień> <koszt> <kwota>
output:
JANUARY
01 INSURANCE 2012 zł
15 PARKING 300 zł
APRIL
04 SERVICE 1933 zł
DECEMBER
24 TICKET 2500 zł
Zad 3 - 1 pkt
Zdefiniuj typ wyniku raportu miesięcznego jako sealed class:
NoCosts– gdy w danym miesiącu nie ma żadnych kosztów,WithinLimit(total: Int)– gdy suma kosztów w miesiącu jest mniejsza lub równa limitowi,OverLimit(total: Int, exceededBy: Int)– gdy suma kosztów przekracza limit.
Następnie zaimplementuj funkcję:
fun classifyMonthlyCosts(costs: List<Cost>, month: Month, limit: Int): MonthlyCostStatus
Wymagania:
- filtruj koszty tylko dla podanego miesiąca,
- policz sumę (sumOf),
- zwróć odpowiedni wariant sealed class,
- bez klasycznych pętli.
Przykład wykonania:
val costs = listOf(
Cost(CostType.REFUELING, LocalDate.of(2025, 1, 10), 300),
Cost(CostType.PARKING, LocalDate.of(2025, 1, 12), 50),
Cost(CostType.SERVICE, LocalDate.of(2025, 2, 4), 1200)
)
println(classifyMonthlyCosts(costs, Month.JANUARY, 400))
println(classifyMonthlyCosts(costs, Month.FEBRUARY, 1000))
println(classifyMonthlyCosts(costs, Month.MARCH, 500))
>> WithinLimit(total=350)
>> OverLimit(total=1200, exceededBy=200)
>> NoCosts
Zad 4 - 1 pkt
Zdefiniuj interfejs:
interface CostFormatter {
fun format(cost: Cost): String
}
oraz singleton object implementujący ten interfejs (np. PlCostFormatter), który formatuje koszt w postaci:
DD TYPE KWOTA zł
Następnie napisz funkcję:
fun formatCosts(costs: List<Cost>, formatter: CostFormatter): String
Wymagania:
- koszty mają być posortowane po dacie rosnąco,
- każda linia ma być sformatowana przez formatter,
- wynik zwracany jako jeden String (np. joinToString("\n")),
- użyj łańcuchowania metod (bez klasycznej pętli).
val costs = listOf(
Cost(CostType.PARKING, LocalDate.of(2025, 1, 15), 30),
Cost(CostType.SERVICE, LocalDate.of(2025, 1, 5), 900)
)
println(formatCosts(costs, PlCostFormatter))
>> 05 SERVICE 900 zł
>> 15 PARKING 30 zł
Pytania:
- Jaka jest różnica między kolekcją read-only (List, Set, Map) a kolekcją mutowalną (MutableList, MutableSet, MutableMap) w Kotlinie? (1 pkt)
- Dlaczego Kotlin rozdziela interfejsy kolekcji na read-only i mutable na poziomie systemu typów? (1 pkt)
- Jakie są najważniejsze cechy List? (1 pkt)
- Jakie są najważniejsze cechy Set? (1 pkt)
- Dlaczego dwa zbiory (Set) mogą być równe mimo innej kolejności elementów? (1 pkt)
- Jakie są najważniejsze cechy Map i czym różni się klucz od wartości? (1 pkt)
- Co się stanie, gdy do mapy dodamy wartość pod istniejącym już kluczem? (1 pkt)
- Jak iterować po mapie z użyciem destrukturyzacji (for ((k, v) in map)) i dlaczego to wygodne? (1 pkt)
- Do czego służy funkcja map w przetwarzaniu kolekcji? (1 pkt)
- Czym różnią się map, mapKeys i mapValues? (1 pkt)
- Do czego służą zip i unzip? Co się dzieje, gdy kolekcje mają różne długości? (1 pkt)
- Czym różni się associateBy od associateWith? (1 pkt)
- Kiedy lepiej użyć associateBy, a kiedy groupBy? (1 pkt)
- Do czego służy groupBy i jaki typ danych zwykle zwraca? (1 pkt)
- Czym różnią się od siebie funkcje testujące all, any, none? (1 pkt)
- Do czego służy filter i czym różni się od map? (1 pkt)
- Czym różni się klasa od obiektu (instancji) w programowaniu obiektowym? (1 pkt)
- Jaką rolę pełni blok init w klasie Kotlin? (1 pkt)
- Kiedy używa się konstruktora drugorzędnego (secondary constructor)? (1 pkt)
- Jakie są modyfikatory dostępu w Kotlinie? (1 pkt)
- Czym data class różni się od zwykłej klasy? (1 pkt)
- Do czego służy copy() i dlaczego jest ważne przy niemutowalności danych? (1 pkt)
- Czym różni się == od === w Kotlinie? (1 pkt)
- Które pola data class biorą udział w equals() i hashCode() — wszystkie czy tylko część? (1 pkt)
- Po co używa się enum class i czym różni się od zwykłej klasy? (1 pkt)
- Do czego służą słowa kluczowe open, override i final override? (1 pkt)
- Czym różni się klasa abstrakcyjna od klasy open? (1 pkt)
- Czym różni się abstract fun od open fun? (1 pkt)
- Czym jest sealed class i jaki problem rozwiązuje? (1 pkt)
- Dlaczego sealed class dobrze nadaje się do modelowania stanów (np. Loading / Success / Error)? (1 pkt)
- Czym różni się klasa zagnieżdżona (nested) od klasy wewnętrznej (inner) w Kotlinie? (1 pkt)
- Dlaczego inner class wymaga instancji klasy zewnętrznej i co daje this@Outer? (1 pkt)
- Czym jest deklaracja object w Kotlinie i do czego służy? (1 pkt)
- Co oznacza, że obiekt object jest inicjalizowany leniwie (lazy)? (1 pkt)
- Czym różni się object declaration (nazwany singleton) od object expression (anonimowy obiekt)? (1 pkt)
- Kiedy używa się object expression zamiast tworzenia osobnej klasy? (1 pkt)
- Czy obiekt tworzony przez object może implementować interfejs albo dziedziczyć po klasie? (1 pkt)
- Co to jest data object i kiedy jest przydatny? (1 pkt)
- Czym jest interfejs w Kotlinie i co oznacza, że definiuje „kontrakt”? (1 pkt)
- Czy klasa może implementować wiele interfejsów, ale dziedziczyć tylko po jednej klasie, czy na odwrót? (1 pkt)
- Jak rozwiązać konflikt metod domyślnych, gdy dwa interfejsy implementowane przez tą samą klasę mają metodę o tej samej sygnaturze? (1 pkt)
- Jaką rolę pełni interfejs jako typ? (1 pkt)
- Co to jest interfejs markerowy (znacznikowy) i do czego może służyć? (1 pkt)
- Czym jest interfejs funkcyjny (SAM) i jaki warunek musi spełniać? (1 pkt)
- Po co w Kotlinie używa się fun interface? (1 pkt)
- Na czym polega konwersja SAM i jaka jest jej praktyczna korzyść? (1 pkt)
- Co to jest companion object i do czego służy w Kotlinie? (1 pkt)
- Co to jest klasa generyczna i jaką korzyść daje parametr typu <T>? (1 pkt)
Oceny
| ocena | punkty |
|---|---|
| 3,0 | 6 pkt |
| 3,5 | 7 pkt |
| 4,0 | 8 pkt |
| 4,5 | 9 pkt |
| 5,0 | 10 pkt |
Lista 5
Termin wykonania:
21.05.2026
Zad 1 - 2 pkt
Do aplikacji Counter dodaj przycisk pozwalający zmniejszyć stan licznika, oraz przysick pozwalający zresetować stan licznika (ustawić na wartość 0). UI aplikacji przygotuj według poniższego wzoru. Zmiana orientacji urządzenia powoduje przeładowanie aplikacji i zmianę ui (zakaz blokowania orientacji). Stan licznika musi być zachowany przy zmianie orientacji urządzenia.
Kod startowy:
@Composable
fun CounterExample(){
var counter by remember { mutableIntStateOf(0) }
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxSize()
){
Spacer(modifier = Modifier.weight(0.3f))
Text(
text = counter.toString(),
fontSize = 250.sp,
textAlign = TextAlign.Center,
modifier = Modifier.weight(1f)
)
Button(
modifier = Modifier.fillMaxWidth(),
shape = RectangleShape,
onClick = { counter++ }
){
Text(text = "Count UP")
}
}
}
Zad 2 - 3 pkt
Przygotuj aplikację Kalkulator.
- aplikacja może działać tylko na dwóch liczbach całkowitych
- obsługuje dodawanie, odejmowanie, dzielenie (należy obsłużyć wyjątek dzielenia przez
0), mnożenie - po naciśnięciu przycisku z działaniem wyświetlany jest wynik
- możesz wykorzystać pola
TextFieldlubOutlinedTextField - aplikacja musi zachować dane przy zmianie konfiguracji urządzenia (np przy zmianie orientacji)
- Zmiana orientacji urządzenia powoduje przeładowanie aplikacji i zmianę ui (zakaz blokowania orientacji).
- aby uniknąć błędów przy wpisywaniu danych możesz wykorzystać atrybut
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)polaTextField - UI przygotuj w oparciu o poniższą grafikę
Pytania:
- Kiedy w Kotlinie używa się lateinit i jaki problem rozwiązuje? (1 pkt)
- Co się stanie, jeśli odczytamy właściwość lateinit przed inicjalizacją? (1 pkt)
- Do czego służy zapis ::property.isInitialized i kiedy jest przydatny? (1 pkt)
- Na czym polega delegacja właściwości (delegated properties) w Kotlinie? (1 pkt)
- Jaką rolę pełni słowo kluczowe by w delegacji właściwości? (1 pkt)
- Jakie metody operatorowe musi udostępniać delegat do odczytu i zapisu? (1 pkt)
- Do czego służy parametr KProperty<*> w metodach delegata? (1 pkt)
- Co oznacza zapis KProperty<*> (projekcja gwiazdkowa, star-projection) i dlaczego jest użyteczny w delegatach? (1 pkt)
- Jak działa by lazy i kiedy warto go używać? (1 pkt)
- Jak działa Delegates.observable i kiedy callback jest wywoływany: przed czy po zmianie wartości? (1 pkt)
- Kiedy lambda w Delegates.vetoable jest wywoływana i co oznacza zwracane Boolean? (1 pkt)
- Jaką rolę pełni plik AndroidManifest.xml w aplikacji Android? (1 pkt)
- Jakie informacje są deklarowane w manifeście (podaj przynajmniej 3 przykłady)? (1 pkt)
- Do czego służy wpis <uses-permission> w manifeście? (1 pkt)
- Co oznacza action MAIN w intent-filter aktywności? (1 pkt)
- Co oznacza category LAUNCHER i jaki ma wpływ na widoczność aplikacji? (1 pkt)
- Jak zmieniła się rola Activity w podejściu Jetpack Compose względem klasycznego View System? (1 pkt)
- W jakiej metodzie cyklu życia aktywności najczęściej inicjalizujemy UI? (1 pkt)
- Czym różnią się onStart() i onResume()? (1 pkt)
- Czym różnią się onPause() i onStop() z punktu widzenia widoczności/interaktywności i zasobów? (1 pkt)
- Jakie trzy zagnieżdżone cykle życia aktywności możńa wyróżnić? (1 pkt)
- Do czego służy Bundle w kontekście zachowania stanu aktywności? (1 pkt)
- Czym różni się przywracanie stanu w onCreate(savedInstanceState) od onRestoreInstanceState(savedInstanceState)? (1 pkt)
- Czym jest Context w Androidzie i do czego daje dostęp? (1 pkt)
- Czym różni się Application Context od Activity Context? (1 pkt)
- Dlaczego przekazywanie Activity Context do singletona może powodować wyciek pamięci? (1 pkt)
- Dlaczego w Androidzie w ogóle potrzebny jest Context? (1 pkt)
- Dlaczego Activity jest obiektem typu Context, mimo że sama nie implementuje wszystkich operacji systemowych? (1 pkt)
- Czym jest Intent i do czego służy w Androidzie? (1 pkt)
- Czym różni się intencja jawna (explicit intent) od niejawnej (implicit intent)? (1 pkt)
- Jakie trzy główne elementy bierze pod uwagę system przy rozwiązywaniu intencji niejawnej? (1 pkt)
- Jaka jest rola intent-filter w manifeście przy intencjach niejawnych? (1 pkt)
- Co się dzieje, gdy intencję niejawną może obsłużyć więcej niż jedna aplikacja? (1 pkt)
- Jaki wyjątek może wystąpić przy startActivity(intent) dla intencji niejawnej i kiedy? (1 pkt)
- Czym jest setContent w Activity i jaką rolę pełni w Compose? (1 pkt)
- Czym różnią się layouty Column, Row i Box? (1 pkt)
- Czym różni się dp od sp i dlaczego sp stosujemy do tekstu? (1 pkt)
- Czym jest Modifier w Compose i do czego służy? (1 pkt)
- Dlaczego kolejność wywołań w łańcuchu Modifier ma znaczenie? (1 pkt)
- Czym różnią się pojęcia Arrangement i Alignment w Row/Column? (1 pkt)
- Czym jest kompozycja (Composition) w Jetpack Compose? (1 pkt)
- Czym jest rekompozycja (Recomposition) i kiedy zachodzi? (1 pkt)
- Czy funkcja @Composable może być wywołana z dowolnego miejsca kodu? Uzasadnij. (1 pkt)
- Jaką rolę pełni mutableStateOf(...) w Compose? (1 pkt)
- Jaką rolę pełni remember { ... } i dlaczego samo mutableStateOf nie wystarcza? (1 pkt)
- Co się stanie ze stanem zapisanym przez remember po zmianie konfiguracji (np. obrót ekranu)? (1 pkt)
- Czym rememberSaveable różni się od remember? (1 pkt)
- Czym różni się zapis stanu val x = remember { mutableStateOf(...) } od var x by remember { mutableStateOf(...) }? (1 pkt)
- Co daje delegacja by przy pracy ze stanem Compose? (1 pkt)
- Na czym polega wzorzec State Hoisting? (1 pkt)
- Jakie są dwie cechy komponentu stateless w Compose? (1 pkt)
- Co oznacza jednokierunkowy przepływ danych (Unidirectional Data Flow) w Compose? (1 pkt)
Oceny
| ocena | punkty |
|---|---|
| 3,0 | 6 pkt |
| 3,5 | 7 pkt |
| 4,0 | 8 pkt |
| 4,5 | 9 pkt |
| 5,0 | 10 pkt |
Lista 6
Termin wykonania:
11.06.2025
Zadanie 1 - 2 pkt
Stwórz aplikację wyświetlającą listę elementów, gdzie kliknięcie elementu uruchamia akcję systemową za pomocą Intenta.
- Zdefiniuj listę danych, np. listę ulubionych stron internetowych (jako
List<String>zawierająca adresyURL).
val websites = listOf(
"https://www.google.com",
"https://developer.android.com",
"https://kotlinlang.org"
)
- W głównej funkcji
@ComposableużyjLazyColumndo wyświetlenia elementów tej listy. Każdy element powinien być osobnym wierszem (np. w komponencie Text wewnątrzRowlubColumn, z odpowiednimmodifier = Modifier.clickable { ... }). - Po kliknięciu na element listy (adres URL):
- Uzyskaj
Context(np. za pomocąLocalContext.current). - Stwórz
Intentz akcjąIntent.ACTION_VIEW. - Ustaw dane dla Intenta na
Uri.parse(clickedUrl). - Uruchom aktywność za pomocą
context.startActivity(intent).
Oczekiwane działanie: Aplikacja wyświetla listę adresów URL. Kliknięcie adresu powinno otworzyć go w domyślnej przeglądarce internetowej urządzenia.
Zadanie 2 - 5 pkt
Stwórz aplikację w Jetpack Compose umożliwiającą przeglądanie list zadań oraz podsumowania ocen, z nawigacją między trzema ekranami za pomocą dolnego paska nawigacyjnego oraz klikalnych elementów listy.
Wymagania Aplikacji:
Aplikacja ma składać się z trzech głównych ekranów:
- E1 - Ekran List Zadań (
AssignmentListsScreen): Wyświetla listę wszystkich dostępnych list zadań. Dla każdej listy pokazuje nazwę przedmiotu, otrzymaną ocenę oraz liczbę zadań na tej liście. Elementy tej listy są klikalne. - E2 - Ekran Ocen (
GradesSummaryScreen): Wyświetla podsumowanie ocen, pokazując średnią ocenę (ze wszystkich list) dla każdego przedmiotu. - E3 - Ekran Szczegółów Listy (
ListDetailScreen): Wyświetla szczegółową zawartość (zadania) wybranej listy zadań – numer zadania, treść zadania i maksymalną liczbę punktów.
Nawigacja:
- Użytkownik może przełączać się między ekranami E1 i E2 za pomocą dolnego paska nawigacyjnego (
NavigationBar). - Kliknięcie na element listy na ekranie E1 powoduje przejście do ekranu E3, który wyświetla szczegóły klikniętej listy zadań. Wymaga to przekazania identyfikatora wybranej listy jako argumentu nawigacji.
Struktury Danych (Przykładowe):
// Reprezentuje pojedyncze zadanie na liście
data class Task(
val id: Int,
val description: String,
val maxPoints: Int
)
// Reprezentuje całą listę zadań z danego przedmiotu
data class AssignmentList(
val id: String, // Unikalny identyfikator listy, np. "PUM1_Lista1"
val subject: String, // Nazwa przedmiotu, np. "Programowanie Urządzeń Mobilnych 1"
val listNumber: Int, // Numer listy, np. 1
val grade: Double, // Otrzymana ocena za listę
val tasks: List<Task> // Lista zadań wchodzących w skład tej listy
)
// Przykładowe dane
val sampleAssignmentLists = listOf(
AssignmentList("PUM1_L1", "Programowanie Urządzeń Mobilnych 1", 1, 4.5, listOf(
Task(1, "Implementacja FizzBuzz", 3), Task(2, "Sprawdzenie palindromu", 3), Task(3, "Trójkąt Pascala", 4)
)),
AssignmentList("PUM1_L2", "Programowanie Urządzeń Mobilnych 1", 2, 5.0, listOf(
Task(1, "Funkcje rozszerzające", 4), Task(2, "Funkcje wyższego rzędu", 6)
)),
AssignmentList("SO_L1", "Systemy Operacyjne", 1, 3.5, listOf(
Task(1, "Implementacja semafora", 5), Task(2, "Problem producenta-konsumenta", 5)
)),
AssignmentList("SO_L2", "Systemy Operacyjne", 2, 4.0, listOf(
Task(1, "Algorytmy szeregowania CPU", 6), Task(2, "Zarządzanie pamięcią", 4)
))
// Dodaj więcej danych dla lepszego testowania
)
Pytania:
- Jaką rolę pełni parametr innerPadding przekazywany przez Scaffold do zawartości? (1 pkt)
- Czym różni się zwykła Column od LazyColumn pod względem wydajności dla długich list? (1 pkt)
- Dlaczego LazyColumn nazywa się „leniwy”? (1 pkt)
- Dlaczego MutableList nie jest wystarczająca do reaktywnej listy w Compose? (1 pkt)
- Do czego służy mutableStateListOf i co daje w kontekście rekompozycji? (1 pkt)
- Co jest nie tak z val list = mutableListOf<T>() wewnątrz @Composable? (1 pkt)
- Jaką rolę pełni NavController? (1 pkt)
- Jaką rolę pełni NavHost? (1 pkt)
- Czym jest NavGraph? (1 pkt)
- Do czego służy rememberNavController() i dlaczego używa remember? (1 pkt)
- Co oznacza parametr startDestination w NavHost? (1 pkt)
- Do czego służy composable("route") { ... } w definicji grafu nawigacji? (1 pkt)
- Jak przekazuje się argument wymagany w Navigation Compose (np. id) — jaka jest składnia trasy? (1 pkt)
- Dlaczego trzeba jawnie określić typ argumentu (NavType.StringType, IntType)? (1 pkt)
- Jaką rolę pełni backStackEntry w lambdzie composable(...)? (1 pkt)
- Jak działa navController.popBackStack() i kiedy się go używa? (1 pkt)
- Po co obserwować currentBackStackEntryAsState() przy integracji nawigacji z dolnym paskiem? (1 pkt)
- Do czego służy launchSingleTop = true w nawigacji z dolnym paskiem? (1 pkt)
- Czym jest wzorzec Singleton i jaki problem rozwiązuje? (1 pkt)
- Co oznacza, że object jest inicjalizowany leniwie? (1 pkt)
- Kiedy można rozważyć Double-Checked Locking zamiast prostego by lazy? (1 pkt)
- Na czym polega idea Double-Checked Locking (dwa sprawdzenia instancji)? (1 pkt)
- Po co używa się synchronized(...) w Double-Checked Locking? (1 pkt)
- Jaką rolę pełni @Volatile w implementacji singletona? (1 pkt)
- Czym jest wzorzec Builder i kiedy bywa przydatny? (1 pkt)
- Jakie cechy ma klasyczny Builder w stylu Java? (1 pkt)
- Czym jest wzorzec Factory (Factory Method) i jaki problem rozwiązuje? (1 pkt)
- Jak można zaimplementować prostą fabrykę w Kotlinie? (1 pkt)
- Po co używa się operator fun invoke(...)? (1 pkt)
- Czym jest wzorzec Repository w kontekście aplikacji mobilnych? (1 pkt)
- Co oznacza Single Source of Truth (SSOT) w kontekście repozytorium? (1 pkt)
- Czym są adnotacje w Kotlinie/Androidzie? (1 pkt)
- Podaj 2 zastosowania adnotacji w Androidzie. (1 pkt)
- Na czym polega wzorzec Observer (Obserwator)? (1 pkt)
- Jaki problem rozwiązuje Observer w porównaniu do aktywnego odpytywania (polling)? (1 pkt)
- Na czym polega wzorzec State i jaki problem rozwiązuje? (1 pkt)
- Czym różni się „wzorzec State” od „Compose State” (mutableStateOf)? (1 pkt)
- Na czym polega wzorzec Strategy (Strategia)? (1 pkt)
- Na czym polega wzorzec Mediator i jaki problem rozwiązuje? (1 pkt)
Oceny
| ocena | punkty |
|---|---|
| 3,0 | 6 pkt |
| 3,5 | 7 pkt |
| 4,0 | 8 pkt |
| 4,5 | 9 pkt |
| 5,0 | 10 pkt |