"""
Exercise 2: set-based deduplication and grouping

Implement two functions:

  dedupe_preserve_order(items) -> list
      Removes duplicates from `items`, keeping only the FIRST
      occurrence of each value, preserving original order.
      Must use a set internally to track "seen" values for O(1)
      membership checks (not `if x not in result`, which is O(n)).

  common_and_unique(list_a, list_b) -> tuple(set, set, set)
      Returns (common, only_in_a, only_in_b) using set operations:
        common     = items in both
        only_in_a  = items only in list_a
        only_in_b  = items only in list_b
"""

def dedupe_preserve_order(items):
    # TODO: implement using a `seen` set + a result list.
    pass


def common_and_unique(list_a, list_b):
    # TODO: implement using set algebra (&, -).
    pass


# --- self-check: do not modify below this line ---
r1 = dedupe_preserve_order([3, 1, 3, 2, 1, 4])
r2 = common_and_unique([1, 2, 3, 4], [3, 4, 5, 6])

checks = [
    (r1, [3, 1, 2, 4]),
    (r2, ({3, 4}, {1, 2}, {5, 6})),
]

all_passed = all(actual == expected for actual, expected in checks)
for actual, expected in checks:
    print(f"got {actual!r}, expected {expected!r} -> {'PASS' if actual == expected else 'FAIL'}")

print("ALL PASS" if all_passed else "SOME FAILED")
