# Informatyka — zadanie 6.5

> Źródło: matura.lol — https://matura.lol/question/maturazai-informatyka-inf-2019-05/zad/6.5
> Wersja Markdown strony zadania (dla asystentów AI). Przy cytowaniu podaj matura.lol i link powyżej.

- arkusz: Informatyka · Matura · maj 2019 (rozszerzona)
- rok: 2019
- poziom: rozszerzona
- typ: open
- punkty: 2
- działy: Bazy danych

## Treść

Zadanie 6.5. (0-2)
Istnieją marki, których wszystkie perfumy należą do tylko jednej rodziny zapachów. Podaj listę
wszystkich nazw takich marek. Lista powinna zawierać nazwy marek i nazwy odpowiednich
rodzin zapachów.
Do oceny oddajesz:
• plik tekstowy wyniki6.txt zawierający odpowiedzi do poszczególnych zadań.
(odpowiedź do każdego zadania powinna być poprzedzona jego numerem)
• plik(i) zawierający(e) komputerową realizację Twoich obliczeń o nazwie(nazwach):
Wypełnia
egzaminator
Nr zadania
6.1.
6.2.
6.3
6.4
6.5.
Maks. liczba pkt.
1
3
3
3
2
Uzyskana liczba pkt.
MIN_1R
BRUDNOPIS (nie podlega ocenie)

## Rozwiązanie — maturazai.pl (AI)

## Poprawna odpowiedź

**Marki, których wszystkie perfumy należą do dokładnie jednej rodziny zapachów:**

| Nazwa marki | Rodzina zapachów |
| **Ightce** | aromatyczna |
| **X ICologne** | orientalno-drzewna |
| **Nnick a Kieffo** | orientalna |
| **Enmith** | kwiatowo-orientalna |
| **Issmkunstwerke** | orientalna |

Istnieje 5 takich marek. Kluczowa interpretacja: marka może mieć WIELE perfum, ale wszystkie muszą mieć tę samą wartość `rodzina_zapachow`.

## Sposób 1 - SQL (GROUP BY z HAVING COUNT DISTINCT = 1)

```sql
SELECT m.nazwa_m, MIN(p.rodzina_zapachow) AS rodzina
FROM marki m
INNER JOIN perfumy p ON m.id_marki = p.id_marki
GROUP BY m.id_marki, m.nazwa_m
HAVING COUNT(DISTINCT p.rodzina_zapachow) = 1;

**Wyjaśnienie:**
- Grupujemy perfumy po marce.
- `COUNT(DISTINCT rodzina_zapachow) = 1` → marka ma tylko 1 unikalną rodzinę.
- `MIN(rodzina_zapachow)` zwraca tę jedyną rodzinę (można też `MAX` - wynik ten sam, bo unikalna).

**Wynik:**
Ightce | aromatyczna
X ICologne | orientalno-drzewna
Nnick a Kieffo | orientalna
Enmith | kwiatowo-orientalna
Issmkunstwerke | orientalna

## Sposób 2 - Python (zbiory)

```python
from collections import defaultdict

# Wczytaj marki: id -> nazwa
marki = {}
with open('marki.txt', encoding='utf-8') as f:
f.readline() # naglowek
for linia in f:
idm, nazwa = linia.strip().split('\t')
marki[idm] = nazwa

# Dla kazdej marki zbierz zbior rodzin
rodziny_per_marka = defaultdict(set)
with open('perfumy.txt', encoding='utf-8') as f:
f.readline()
for linia in f:
idp, nazwa, idm, rodzina, cena = linia.strip().split('\t')
rodziny_per_marka[idm].add(rodzina)

# Wybierz marki z dokladnie jedna rodzina
for idm, zbior in rodziny_per_marka.items():
if len(zbior) == 1:
rodzina = next(iter(zbior))
print(f'{marki[idm]:25} | {rodzina}')

## Sposób 3 - arkusz kalkulacyjny (tabela przestawna)

**Krok 1:** Wczytaj perfumy.txt. Dodaj kolumnę nazwa marki (WYSZUKAJ.PIONOWO po id_marki w marki.txt).

**Krok 2:** Tabela przestawna:
- Wiersze: `nazwa_m`
- Wartości: `rodzina_zapachow` z funkcją LICZBA UNIKATOWYCH (lub LICZ.UNIKATOWE.WARTOŚCI).

**Krok 3:** Filtruj wiersze, gdzie liczba unikalnych rodzin = 1.

**Krok 4:** Dla pozostałych marek znajdź tę jedyną rodzinę: `=INDEKS( )` lub przez drugą tabelę przestawną.

## Reference algorytmiczny - COUNT DISTINCT w HAVING

> Reference - Filtr na zagregowanej unikalności:
> - `COUNT(DISTINCT kol) = 1` → wszystkie wartości w grupie są identyczne.
> - `HAVING` filtruje grupy PO agregacji (nie pojedyncze wiersze - to robi WHERE).
> - W Pythonie: `len(set( )) == 1` lub porównanie pierwszej i ostatniej wartości po sortowaniu.
> - **Zwracanie wartości grupowej:** `MIN(kol)` lub `MAX(kol)` dla unikalnej wartości - daje tę jedyną wartość.

## Schemat oceniania CKE

> Klucz CKE (zadanie 6.5, max 2 pkt):
> - **2 pkt** - pełna prawidłowa odpowiedź: nazwy 5 marek i 5 odpowiednich rodzin zapachów.
> - **1 pkt** - tylko prawidłowa lista 5 marek (bez rodzin).
> - **1 pkt** - lista 3 lub 4 marek z 5 w parze z prawidłową nazwą rodziny zapachów.
> - **0 pkt** - błędna lub brak.

## Typowe pułapki

- **`COUNT(rodzina_zapachow) = 1`** zamiast `COUNT(DISTINCT rodzina_zapachow) = 1` - to pierwsze daje marki z tylko JEDNYM perfumem (a my chcemy marki z wieloma perfumami, byle z tej samej rodziny).
- **Pominięcie marki z 1 perfumem** - jeśli marka ma tylko 1 perfum, to oczywiście ma 1 rodzinę. Te marki też zaliczają się do wyniku.
- **Brak JOIN z `marki`** - w perfumy.txt jest tylko id_marki, potrzebujemy nazwa_m.
- **GROUP BY tylko po id_marki** - niektóre silniki SQL wymagają wszystkich kolumn z SELECT także w GROUP BY (poza agregatami). Dla pewności dodaj `m.nazwa_m` do GROUP BY.
- **Pominięcie kolumny z rodziną** - utrata 1 pkt z 2.
- **Marki nie mające w ogóle perfum** - INNER JOIN je odfiltruje, a to dobrze (marka bez perfum nie ma rodziny).

## Złożoność obliczeniowa

- SQL z GROUP BY + COUNT DISTINCT: O(N log N) dla sortowania per grupa.
- Python z defaultdict set: O(N) jedno przejście + O(M) wybieranie marek.
- **Całkowita: O(N + M)** liniowa.

## Linki

- [dane JSON](https://matura.lol/api/question/maturazai-informatyka-inf-2019-05/zad/6.5)
- [otwórz w wyszukiwarce](https://matura.lol/?problem=maturazai-informatyka-inf-2019-05%2Fzad%2F6.5)

## Podobne zadania

- [Zadanie 6.5](https://matura.lol/question/informatyka-2019-maj-matura-rozszerzona-2/zad/6.5) — Zadanie 6.5. (0-2) Istnieją marki, których wszystkie perfumy należą do tylko jednej rodziny zapachów. Podaj listę wszystkich nazw takich marek. Lista powinna za

_Ostatnia aktualizacja danych: 2026-10-03_
