Created
July 31, 2017 22:12
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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