Reputation:
I have a dictionary of dictionaries that describe a person's name and date of birth and date of death.
var people = [ "Michael": [ "birth": 1900, "death" : 1975 ], "John": [ "birth": 1973, "death" : 2000 ], "Julian": [ "birth": 1950, "death" : 1985 ] ]
I would like to determine what years all members were simultaneously alive.
Here is my rather brute and unscalable implementation:
var years = [Int]()
var overlap = [Int]()
var overlapTwice = [Int]()
var overlapThree = [Int]()
for life in people.values {
var birth = Int(life["birth"]!)
var death = Int(life["death"]!)
for year in birth..<death {
if !years.contains(year) {
years.append(year)
} else {
overlap.append(year)
}
}
}
for x in overlap {
if !overlapTwice.contains(x) {
overlapTwice.append(x)
} else {
overlapThree.append(x)
}
}
print(overlapThree)
I would like to know the right way to solve this problem, as mine would obviously require writing a loop for every additional range
Upvotes: 2
Views: 1259
Reputation: 14973
As @rmaddy already mentioned, you can just get the range from the maximum birth year to the minimum death year. I suggest however to change your data structure, as it's not safe and typos can happen:
typealias Person = (name : String, lifeRange : Range<Int>)
let people : [Person] = [
("Michael", 1900..<1973),
("John", 1973..<2000),
("Julian", 1950..<1985)
]
func commonYearRange(people: [Person]) -> Range<Int>? {
guard let
minYear = people.map({ $0.lifeRange.startIndex }).maxElement(),
maxYear = people.map({ $0.lifeRange.endIndex }).minElement()
where minYear <= maxYear else { return nil }
return minYear..<maxYear
}
commonYearRange(people) // 1973..<1975
Upvotes: 1
Reputation: 318814
There's a much simpler way to solve this. Do a single loop. Keep track of the maximum birth year and the minimum death year. That will be your range.
If max birth ends up greater than min death then there is no overlap.
The following is written mostly as pseudo-code since I am not fluent in Swift:
var maxBirth = 0 // start with small value
bar minDeath = 9999 // start with large value
for life in people.values {
var birth = Int(life["birth"]!)
var death = Int(life["death"]!)
if birth > maxBirth {
maxBirth = birth
}
if death < minDeath {
minDeath = death
}
}
Your overlap range will be from maxBirth to minDeath.
Upvotes: 3