Skip to content

Instantly share code, notes, and snippets.

@igorcferreira
Created July 31, 2017 22:12
Show Gist options
  • Save igorcferreira/189a85073c1d8551258c4e3ef067d2ae to your computer and use it in GitHub Desktop.
Save igorcferreira/189a85073c1d8551258c4e3ef067d2ae to your computer and use it in GitHub Desktop.
This is a sample code of the resolution of the FizzBuz code test
import Foundation
//: This is a sample code of the resolution of the FizzBuz code test, explained by [Tom Scott on the YouTube](https://youtu.be/QPZ0pIK_wsc)
/// The InputRule protocol is used to abstract a type that have a specific rule
protocol InputRule {
associatedtype ModifierInput
var rule: ModifierInput { get }
}
/// The Modifier protocol is used to abstract a type that can modify an input base on a rule
protocol Modifier: InputRule {
associatedtype ModifierOutput
var modifier: ModifierOutput { get }
/// Method that can be used to mutate an input
/// based in the rule and modifier setup in the type
///
/// - Parameter value: Input that will be mutated
/// - Returns: The mutated value, or nil if doesn't fit the rule
func checkAndModify(value: ModifierInput) -> ModifierOutput?
}
/// Typealias created to label the closure parameters
typealias ModifierMapper<T, U> = (input: T, rule: T, modifier: U)
/// GenericModifier is an abstraction of a Modifier
struct GenericModifier<T, U> : Modifier {
let rule: T
let modifier: U
/// Closure that will actually perform the map of the input
let mapper: (ModifierMapper<T, U>) -> U?
init(rule: T, modifier: U, mapper: @escaping (ModifierMapper<T, U>) -> U?) {
self.rule = rule
self.modifier = modifier
self.mapper = mapper
}
func checkAndModify(value: T) -> U? {
return self.mapper((input: value, rule: rule, modifier: modifier))
}
}
/// Mapper used in the FuzzBizz logic
let mapper: (Int, Int, String) -> String? = {
if ($0 % $1) == 0 {
return $2
} else {
return nil
}
}
//#-editable-code
let rules:[GenericModifier<Int, String>] = [GenericModifier(rule: 3, modifier: "Fizz", mapper: mapper),
GenericModifier(rule: 5, modifier: "Buzz", mapper: mapper),
GenericModifier(rule: 7, modifier: "Fuzz", mapper: mapper),
GenericModifier(rule: 11, modifier: "Bizz", mapper: mapper)]
let inputs = 1...100
//#-end-editable-code
let outputs = inputs.map { (value) -> String in
var output: String = ""
rules.forEach {
output = output + ($0.checkAndModify(value: value) ?? "")
}
// output.characters is used to support Swift 3.1, Swift 3.2, and Swift 4
if output.characters.count == 0 {
return String(describing: value)
} else {
return output
}
}
outputs.forEach {
print($0)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment