1.2.25 · D4Introduction to Programming (Python)

Exercises — Sets — unique elements, set operations (union, intersection, difference)

2,770 words13 min readBack to topic

Throughout, and are Python sets. We reuse only four symbols, all defined in the parent:

  • (union, Python |) — "in or ",
  • (intersection, Python &) — "in and ",
  • (difference, Python -) — "in but not ",
  • (symmetric difference, Python ^) — "in exactly one of them".

If any of those feels shaky, the truth-table view lives in Boolean Logic — AND, OR, XOR.


Level 1 — Recognition

Can you read a set correctly and predict its size/contents?

Recall Solution 1.1

WHAT: A set stores each value at most once — duplicate inserts are silently dropped. WHY: each value is hashed to an address; if that address already holds an equal value, insertion is skipped (the mechanism in Hashing and Hashable Types). Collapsing duplicates: . There are 4 distinct values, so len(s) prints 4.

Recall Solution 1.2
  • a = {} → an empty dictionary (Python breaks the {} tie in favour of dicts — see Dictionaries — key-value & why {} is a dict).
  • b = set() → the empty set ✅. len(b) is 0.
  • c = {0} → a set with one element, the number 0. It is not empty; len(c) is 1. So only b is an empty set.
Recall Solution 1.3

Membership x in t answers "is an element equal to x present?" — case-sensitive for strings.

  • "cat" in tTrue (exact match present).
  • "Cat" in tFalse ("Cat""cat"; different hash, different bucket).
  • "bird" not in tTrue ("bird" is absent, so not in is true).

Level 2 — Application

Run the four operations by hand on concrete data.

Figure — Sets — unique elements, set operations (union, intersection, difference)
Recall Solution 2.1

Read the Venn picture above: left-only petal is , the lens in the middle is , the right-only petal is .

  • Union = everything in either petal or the lens = .
  • Intersection = only the shared lens = .
  • Difference = left petal (in , not ) = .
  • Reverse difference = right petal = . Note — order matters for .
  • Symmetric difference = both petals, lens removed = .
Recall Solution 2.2

(a) set(nums) collapses to . Wrapping in list() gives those four values, but order is not guaranteed — the set is arranged by hash, not by when you inserted. So all we can promise about the contents is the set . (b) To keep first-seen order, use dict.fromkeys (dict keys are unique and remember insertion order):

ordered = list(dict.fromkeys(nums))   # [7, 3, 1, 9]

First appearances are 7, then 3, then 1, then 9 → [7, 3, 1, 9].

Recall Solution 2.3
  • (a) both = intersection post1 & post2 = .
  • (b) only post1 = difference post1 - post2 = (the only tag in post1 missing from post2).
  • (c) exactly one = symmetric difference post1 ^ post2 = (hashing only in post1, lists only in post2).

Level 3 — Analysis

Reason about behaviour, mutation, and cost.

Recall Solution 3.1

Key distinction: union returns a new set and leaves the caller untouched; update mutates in place and returns None.

  • (i) A is unchanged by .union(...){1, 2}.
  • (ii) C is the fresh union → {1, 2, 3}.
  • (iii) D.update(B) folds B into D{1, 2, 3}.
Recall Solution 3.2

(a) One membership test costs for a set (single hash → one bucket) and for a list (scan all ). Doing it times: (b) Worst case each of the lookups scans all items: The set version does about hash lookups instead — a factor of fewer. That gap is why sets exist for membership work.

Recall Solution 3.3

A set element must be hashable — roughly, immutable so its hash never changes (see Hashing and Hashable Types).

  • (a) OK ✅ — tuples are immutable, hence hashable.
  • (b) TypeError ❌ — a list is mutable, so unhashable.
  • (c) OK ✅ — an int, a str, and a 1-element tuple are all hashable.
  • (d) TypeError ❌ — a plain set is itself mutable, so it can't be an element. (The immutable cousin frozenset would work.)

Level 4 — Synthesis

Combine operations to solve a real task; verify an identity.

Recall Solution 4.1

Left side — symmetric difference (in exactly one set): Right side — union minus the shared middle: Both give ✔. The picture: union collects everything; the intersection is the "double-counted" lens; remove it and only the two exclusive petals survive — exactly "in one set only."

Recall Solution 4.2

(a) editor beyond guest = editor - guest = . (b) admin-only vs the union of the others: Because editor | guest = , subtracting from admin leaves {"delete"}. (c) "every guest action is an editor action" is the subset test guest <= editor (equivalently guest.issubset(editor)). Since guest = {"read"} and "read" ∈ editor, this is True.


Level 5 — Mastery

Design and prove — no hand-holding.

Recall Solution 5.1

WHAT: flatten every value into one set, then take its length. WHY a set: it dedups automatically and joins effortlessly via union. Using set().union(*map(set, data)) unions all sublists at once:

distinct = set().union(*map(set, data))
print(len(distinct))

Values seen: → distinct set → count 4. (Equivalently len({x for row in data for x in row}) — a set comprehension.)

Recall Solution 5.2

(a) Take , : So is not symmetric. (b) The symmetric difference is order-independent because it unions both differences: Same result → ✔. Union is commutative, so wrapping the two (non-symmetric) differences in a union restores symmetry.

Recall Solution 5.3

Design idea: keep a seen set. Walk left to right; if the current item is already in seen, it's the first repeat — return it. Membership is , so total is .

def first_dup(seq):
    seen = set()
    for x in seq:
        if x in seen:      # O(1) check
            return x
        seen.add(x)
    return None

Trace on [3, 1, 4, 1, 5, 3]:

step x seen before check in seen? action
1 3 {} no add 3
2 1 {3} no add 1
3 4 {1,3} no add 4
4 1 {1,3,4} yes return 1

Answer: 1 (the second 1 is the first value seen twice).


Recall Self-test checklist
  • I can predict len after duplicates collapse. Level 1 ::: yes
  • I compute all four ops from a Venn picture. Level 2 ::: yes
  • I explain union vs update and the vs gap. Level 3 ::: yes
  • I verify and model permissions. Level 4 ::: yes
  • I design an duplicate detector and prove non-commutativity. Level 5 ::: yes

Connections

  • Parent topic
  • Boolean Logic — AND, OR, XOR — the AND/OR/XOR behind
  • Big-O Notation & Time Complexity — why the set version wins
  • Hashing and Hashable Types — why membership works
  • Tuples — immutable sequences — valid hashable set elements
  • Lists — ordered, indexed collections — order vs speed trade-off
  • Dictionaries — key-value & why {} is a dict{} is a dict, dict.fromkeys keeps order