Skip to content

Instantly share code, notes, and snippets.

@AvdLee
Last active August 1, 2023 19:30
Show Gist options
  • Save AvdLee/0ff618b7d149be631050994ee8246bff to your computer and use it in GitHub Desktop.
Save AvdLee/0ff618b7d149be631050994ee8246bff to your computer and use it in GitHub Desktop.
KeyTimeValues Coding Challenge
let keyTimeValues: [TimeInterval: Float] = [
0.4: 0.0,
0.45: 1.0,
0.475: 1.0,
0.5: 1.0,
0.525: 1.0,
0.55: 0.0,
0.575: 1.0,
0.6: 1.0,
0.65: 1.0,
0.7: 0.0
]
/// The challenge:
/// The keys represent animation key times, the values represent values. Some key times repeat the same value of the previous keytime.
/// How would you reduce the above dictionary in such way that the values do not repeat themselves
/// more than once?
/// For example, this group:
/// 0.45: 1.0,
/// 0.475: 1.0,
/// 0.5: 1.0,
/// 0.525: 1.0,
///
/// The keytime 0.475 and 0.5 don't change the value and are, therefore, redundant in key frame animations.
///
/// Expected outcome:
let expectedOutcome: [TimeInterval: Float] = [
0.4: 0.0,
0.45: 1.0,
0.525: 1.0,
0.55: 0.0,
0.575: 1.0,
0.65: 1.0,
0.7: 0.0
]
@simonberner
Copy link

simonberner commented Jul 30, 2023

Great stuff @AvdLee ! Even if it takes me ages to solve such challenges, keep those coming 🙂

Here is what I came up with:

/// Reduce repeating values if they occur more than once in a dictionary.
/// - Parameter keyTimeValues: A dictionary of key-time-value pairs.
/// - Returns: A reduced dictionary.
func reduceRepeatingValues(_ keyTimeValues: [TimeInterval : Float]) -> Dictionary<TimeInterval, Float> {
    var result: [TimeInterval : Float] = [:]
    var previousValue: Float?
    var previousKey: TimeInterval?

    for key in keyTimeValues.keys.sorted() {
        let currentValue = keyTimeValues[key]

        // If the previous value has not changed, cache the current key as previousKey and continue with the next key in the loop
        if previousValue == currentValue {
            previousKey = key
            continue
        }

        // Value has changed: unwrap (because these vars are defined as optional) and add the previous key/value pair to the result
        if let pKey = previousKey, let pValue = previousValue {
            result[pKey] = pValue
        }

        // Store the current key/value pair to the result
        result[key] = currentValue

        // Cache the current key/value pair as the new previous pair
        previousKey = key
        previousValue = currentValue
    }
    return result
}

var result = reduceRepeatingValues(keyTimeValues)
assert(result == expectedOutcome, "Oh no, I failed!")

@AvdLee
Copy link
Author

AvdLee commented Jul 31, 2023

Well done @simonberner 💪🏼

@Loradim
Copy link

Loradim commented Jul 31, 2023

I guess I'm struggling with the example or explanation

let keyTimeValues: [TimeInterval: Float] = [
    0.4: 0.0,
    0.45: 1.0,
    0.475: 1.0,
    0.5: 1.0,
    0.525: 1.0,
    0.55: 0.0,
    0.575: 1.0,
    0.6: 1.0,
    0.65: 1.0,
    0.7: 0.0
]

/// Expected outcome:
let expectedOutcome: [TimeInterval: Float] = [
    0.4: 0.0,
    0.45: 1.0,
    0.525: 1.0,
    0.55: 0.0,
    0.575: 1.0,
    0.65: 1.0,
    0.7: 0.0
]

Why does 0.475 and 0.5 get removed but not 0.525? It's still repeating a value of 1.0.

I guess I'm missing out on something, would you mind pointing me towards that?

@KieranConlon
Copy link

If you have a repeating value, then keep the first and last instance of that value.
Not sure if this colour-coded version helps; essentially remove the values within the red boxes.
image

@Loradim
Copy link

Loradim commented Jul 31, 2023

@KieranConlon : Thank you !!

@MasoudRoosta
Copy link

MasoudRoosta commented Aug 1, 2023

@AvdLee It's my solution:

let keyTimeValues: [TimeInterval: Float] = [
0.4: 0.0,
0.45: 1.0,
0.475: 1.0,
0.5: 1.0,
0.525: 1.0,
0.55: 0.0,
0.575: 1.0,
0.6: 1.0,
0.65: 1.0,
0.7: 0.0
]

extension Dictionary<TimeInterval, Float>{
    func optmizedDict() -> Dictionary<TimeInterval, Float>{
        var tempElement: Dictionary<TimeInterval, Float>.Element? = nil
        return reduce([:]) { partialResult, element in
            var partialResult = partialResult
            if element.value != tempElement?.value && tempElement != nil {
                partialResult[tempElement!.key] = tempElement!.value
                partialResult[element.key] = element.value
            }
        
            tempElement = element
            return partialResult
        }
    }
}


let result = keyTimeValues.optmizedDict().sorted{$0.0 < $1.0}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment