| 767 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |      1 | // A case of catastrophic backtracking in Swift
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |      2 | //---------------------------------------------
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |      3 | // example provided by Martin Mikusovic
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |      4 | //
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |      5 | // regex: (a*)*b
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |      6 | // strings: aa...a
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |      7 | //
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |      8 | // compile with
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |      9 | //
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     10 | // swiftc catastrophic.swift
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     11 | //
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     12 | // run with for example
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     13 | //
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     14 | // time ./catastrophic 20
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     15 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     16 | import Foundation
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     17 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     18 | let args = CommandLine.arguments
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     19 | if args.count >= 2, let count = Int(args[1]) {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     20 |     let s = String(repeating: "a", count: count)
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     21 |     calculateTime {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     22 |         let _ = s ~= "(a*)*b"
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     23 |     }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     24 | } else {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     25 |     print("Please enter a valid number argument.")
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     26 | }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     27 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     28 | func calculateTime(block: () -> ()) {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     29 |     let start = DispatchTime.now()
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     30 |     block()
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     31 |     let end = DispatchTime.now()
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     32 |     let nanoTime = end.uptimeNanoseconds - start.uptimeNanoseconds
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     33 |     let timeInterval = Double(nanoTime) / 1_000_000_000
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     34 |     print("\(timeInterval) s")
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     35 | }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     36 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     37 | extension String {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     38 |     static func ~=(lhs: String, rhs: String) -> Bool {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     39 |         guard let regex = try? NSRegularExpression(pattern: rhs) else { return false }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     40 |         let range = NSRange(location: 0, length: lhs.utf16.count)
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     41 |         return regex.firstMatch(in: lhs, options: [], range: range) != nil
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     42 |     }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     43 | }
 |