Skip to content

Instantly share code, notes, and snippets.

@cozzin
Last active October 12, 2018 02:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cozzin/5df41339c14d7faef708b5ac59b1e533 to your computer and use it in GitHub Desktop.
Save cozzin/5df41339c14d7faef708b5ac59b1e533 to your computer and use it in GitHub Desktop.
Swift Memoization
class CachedClassifier {
private var sumCache = [Int: Int]()
func sumOfFactors(_ number: Int) -> Int {
if let cachedValue = sumCache[number] {
return cachedValue
}
let sum = aliquotSum(factors(number))
sumCache[number] = sum
return sum
}
func isFactor(candidate: Int, number: Int) -> Bool {
return number % candidate == 0
}
func factors(_ number: Int) -> Set<Int> {
guard number > 1 else {
return Set<Int>(arrayLiteral: 1)
}
var factors = Set<Int>()
factors.insert(1)
factors.insert(number)
(2..<number).forEach {
if isFactor(candidate: $0, number: number) {
factors.insert($0)
}
}
return factors
}
func aliquotSum(_ factors: Set<Int>) -> Int {
let sum = factors.reduce(0, +)
let targetNumber = factors.max() ?? 0
return sum - targetNumber
}
func isPerfect(_ number: Int) -> Bool {
return sumOfFactors(number) == number
}
}
class Classifier {
static func isFactor(candidate: Int, number: Int) -> Bool {
return number % candidate == 0
}
static func factors(_ number: Int) -> Set<Int> {
guard number > 1 else {
return Set<Int>(arrayLiteral: 1)
}
var factors = Set<Int>()
factors.insert(1)
factors.insert(number)
(2..<number).forEach {
if isFactor(candidate: $0, number: number) {
factors.insert($0)
}
}
return factors
}
static func aliquotSum(_ factors: Set<Int>) -> Int {
let sum = factors.reduce(0, +)
let targetNumber = factors.max() ?? 0
return sum - targetNumber
}
static func isPerfect(_ number: Int) -> Bool {
return aliquotSum(factors(number)) == number
}
}
func memoize<T: Hashable, U>(_ function: @escaping (T) -> U) -> (T) -> U {
var cache = [T: U]()
func memoizedFunction(x: T) -> U {
if let cachedValue = cache[x] {
return cachedValue
}
let value = function(x)
cache[x] = value
return value
}
return memoizedFunction
}
let memoizedClassfier = memoize(Classifier.isPerfect)
// http://kka7.tistory.com/67
func processTime(blockFunction: () -> Void) {
let startTime = CFAbsoluteTimeGetCurrent()
blockFunction()
let processTime = CFAbsoluteTimeGetCurrent() - startTime
print("수행 시간 = \(processTime)")
}
let cachedClassifier = CachedClassifier()
let memoizedClassfier = memoize(Classifier.isPerfect)
print("최적화하지 않은 예")
processTime {
(0...999).forEach {
_ = Classifier.isPerfect($0)
}
}
print("최적화하지 않은 예(두 번째 실행)")
processTime {
(0...999).forEach {
_ = Classifier.isPerfect($0)
}
}
print("합을 캐시한 예")
processTime {
(0...999).forEach {
_ = cachedClassifier.isPerfect($0)
}
}
print("합을 캐시한 예(두 번째 실행)")
processTime {
(0...999).forEach {
_ = cachedClassifier.isPerfect($0)
}
}
print("부분적 메모이제이션")
processTime {
(0...999).forEach {
_ = memoizedClassfier($0)
}
}
print("부분적 메모이제이션(두 번째 실행)")
processTime {
(0...999).forEach {
_ = memoizedClassfier($0)
}
}
func memoize<T: Hashable, U>(_ body: @escaping ((T) -> U, T) -> U) -> (T) -> U {
var memo = [T: U]()
var result: ((T) -> U)!
result = { x in
if let q = memo[x] { return q }
let r = body(result, x)
memo[x] = r
return r
}
return result
}
let factorial = memoize { factorial, x in x == 0 ? 1 : x * factorial(x - 1) }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment