Menu
Coddy logo textTech

Compare Weeks

Part of the Logic & Flow section of Coddy's Swift journey — lesson 37 of 56.

Final feature: take two weeks of data and report the change per habit.

Each week is its own list of habit:day ops on its own line. Build two dictionaries the same way you have been, then compare them.

The interesting set of habits is the union of keys across both weeks (a habit might appear in one week but not the other). Iterate that union sorted alphabetically.

let allKeys = Set(weekA.keys).union(weekB.keys).sorted()
for name in allKeys {
    let a = weekA[name]?.count ?? 0
    let b = weekB[name]?.count ?? 0
    print("\(name): \(a) -> \(b)")
}

The ?? 0 handles the missing-key case. The weekA[name]?.count is the optional-chained way to read a count without unwrapping first, it returns nil when the key isn't there, which the ?? 0 turns into zero.

challenge icon

Challenge

Medium

Read two lines of input, each a comma-separated list of habit:day entries (one per week). For every habit that appears in either week, print one line in this format:

<habit>: <a> -> <b> <arrow>

where a is week-1 unique-day count, b is week-2 unique-day count, and arrow is:

  • UP when b > a
  • DOWN when b < a
  • SAME when b == a

Print habits in alphabetical order. After the per-habit lines, print one summary line:

Improved: <n>

where n is the count of habits with arrow UP.

For input read:1,read:3,workout:2 on line 1 and read:1,read:2,read:5,yoga:7 on line 2, the output is:

read: 2 -> 3 UP
workout: 1 -> 0 DOWN
yoga: 0 -> 1 UP
Improved: 2

Cheat sheet

To get the union of keys from two dictionaries and iterate alphabetically:

let allKeys = Set(weekA.keys).union(weekB.keys).sorted()
for name in allKeys {
    let a = weekA[name]?.count ?? 0
    let b = weekB[name]?.count ?? 0
    print("\(name): \(a) -> \(b)")
}

weekA[name]?.count uses optional chaining to get the count without unwrapping; returns nil if the key is missing. ?? 0 converts that nil to zero.

Try it yourself

func parse(_ line: String) -> [String: [Int]] {
    var habits: [String: [Int]] = [:]
    if line.isEmpty { return habits }
    for op in line.components(separatedBy: ",") {
        let parts = op.components(separatedBy: ":")
        let day = Int(parts[1])!
        if !(habits[parts[0], default: []].contains(day)) {
            habits[parts[0], default: []].append(day)
        }
    }
    return habits
}
let weekA = parse(readLine()!)
let weekB = parse(readLine()!)

// TODO: union of keys; per-habit '<name>: a -> b ARROW'; then 'Improved: <n>'
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Logic & Flow