[FP101x] Validasi kartu kredit dengan Swift (Lab2)

Sekarang saya sedang mengambil kelas online TUDelft’s “FP101x - Intro to Functional Programming” di edX, dan ternyata seru juga. Postingan ini ditulis karena saya ingin berbagi solusi dari latihan-latihan dari kelas FP101x yang saya kerjakan ulang dengan Swift. Bahkan sang pengajar kelas tersebut, Erik Meijer, beberapa waktu lalu nge-tweet seperti ini :

Tapi karena sampai sekarang saya belum menemukan kode Swift di kelas FP101x, jadi saya tulis ulang kode haskell dari kelas FP101x ke Swift playground.

Validasi 💳 - Lab2.swift

Berikut kutipan dari latihan lab2.hs yang saya tulis kembali dengan 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
45
// 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
}

Versi lengkapnya latihan ini bisa diunduh sebagai playground : Lab2.playground. Playground-nya sudah diformat sedemikian rupa dengan markdown, jadi lebih rapi aja gitu. Playground dibuat dengan Xcode 8.2.1 and Swift 3.0.

playground

Versi haskell

Kalau tertarik untuk mengecek latihan aslinya dalam haskell, bisa dilihat di sini.

Pembaruan: Solusi 1.5 tahun kemudian!

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

// Menambahkan fungsi bantuan untuk mempermudah mendapatkan head dan tail
// 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
}

Latihan yang sangat seru dan menantang! 💪