//===--- RomanNumbers.swift -----------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// import TestsUtils // // Mini benchmark implementing roman numeral conversions to/from integers. // Measures performance of Substring.starts(with:) and String.append(), // with very short string arguments. // public let RomanNumbers = [ BenchmarkInfo( name: "RomanNumbers", runFunction: run_RomanNumbers, tags: [.api, .String, .algorithm]) ] let romanTable: DictionaryLiteral = [ "M": 1000, "CM": 900, "D": 500, "CD": 400, "C": 100, "XC": 90, "L": 50, "XL": 40, "X": 10, "IX": 9, "V": 5, "IV": 4, "I": 1, ] extension BinaryInteger { var romanNumeral: String { var result = "" var value = self outer: while value > 0 { var position = 0 for (i, (key: s, value: v)) in romanTable[position...].enumerated() { if value >= v { result += s value -= Self(v) position = i continue outer } } fatalError("Unreachable") } return result } init?(romanNumeral: String) { self = 0 var input = Substring(romanNumeral) outer: while !input.isEmpty { var position = 0 for (i, (key: s, value: v)) in romanTable[position...].enumerated() { if input.starts(with: s) { self += Self(v) input = input.dropFirst(s.count) position = i continue outer } } return nil } } } @inline(never) func checkRomanNumerals(upTo limit: Int) { for i in 0 ..< limit { CheckResults(Int(romanNumeral: identity(i.romanNumeral)) == i) } } @inline(never) public func run_RomanNumbers(_ N: Int) { for _ in 0 ..< 10 * N { checkRomanNumerals(upTo: 1100) } }