[FP101x] Credit card validation with Swift (Lab2)
I am currently taking TUDelft’s “FP101x - Intro to Functional Programming” class at edX, and I am enjoying it so far. This post is written to share my FP101x exercises that I did with Swift. The instructor of the class, Erik Meijer, even said this a while back:
At this point, @SwiftLang is probably a better, and more valuable, vehicle for learning functional programming than Haskell.
— Erik Meijer (@headinthebox) October 17, 2015
Since I could not found any swift code found in the FP101x class, I ported the haskell files to Swift playgrounds.
💳 validation - Lab2.swift
Below is the snippet of the lab2.hs exercise written in Swift
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | // Helpers public func eval(_ digits: [Int]) -> Int { return digits.reduce(0, { result, digit in return digit + (result * 10) }) } public func evalRev(_ digits: [Int]) -> Int { var result = 0 for index in stride(from: (digits.count-1), through: 0, by: -1) { result = (result * 10) + digits[index] } return result } extension Sequence { public func all(_ validateElement: (Self.Iterator.Element) -> Bool) -> Bool { return self.reduce(true) { result, element in return result && validateElement(element) } } } // Ex. 0 func toDigits(digit: Int) -> [Int] { return [] } // Ex. 1 func toDigitsRev(digit: Int) -> [Int] { return [] } // Ex. 2 func doubleSecond(digits: [Int]) -> [Int] { return [] } // Ex. 3 func sumDigits(digits: [Int]) -> Int { return 0 } // Ex. 4 func isValid(digit: Int) -> Bool { return false } // Ex. 5 func numValid(digits: [Int]) -> Int { return digits.filter(isValid).count } |
For the complete version of this exercise, you can download the full playground file : Lab2.playground. It is properly formatted with markdown and stuff, it is pretty neat! This is compatible for Xcode 8.2.1 and Swift 3.0.
Haskell version
If you are interested to check the original exercise in haskell, you can see it here.
Update: The solution 1.5 years later!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | // Ex. 0 func toDigits(digit: Int) -> [Int] { if case 0..<10 = digit { return [digit] } else { return toDigits(digit / 10) + [digit % 10] } } // Ex. 1 func toDigitsRev(digit: Int) -> [Int] { return toDigits(digit).reversed() } // Ex. 2 func doubleSecond(digits: [Int]) -> [Int] { let isEven : (Int) -> Bool = { x in x % 2 == 0 } return digits.enumerated().map { index, x in isEven(index + 1) ? x * 2 : x } } // Ex. 3 // Adding helper method to get head and tail easier // ref: http://chris.eidhof.nl/post/swift-tricks/ extension Array { func match() -> (head: Element, tail: [Element])? { guard !isEmpty else { return nil } return ( first!, Array(dropFirst()) ) } } func sumDigits(digits: [Int]) -> Int { guard let (head, tail) = digits.match() else { return 0 } return toDigits(head).reduce(0, +) + sumDigits(tail) } // Ex. 4 func isValid(digit: Int) -> Bool { return sumDigits(doubleSecond(toDigitsRev(digit))) % 10 == 0 } // Ex. 5 func numValid(digits: [Int]) -> Int { return digits.filter(isValid).count } |
That was a fun exercise! 💪