Skip to content

Commit be0b339

Browse files
authored
Merge pull request #22340 from apple/revert-22300-revert-22227-a-tall-white-fountain-played
[benchmark] RomanNumbers Reloaded
2 parents 520b801 + 5f92040 commit be0b339

File tree

1 file changed

+36
-57
lines changed

1 file changed

+36
-57
lines changed

benchmark/single-source/RomanNumbers.swift

Lines changed: 36 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -12,84 +12,63 @@
1212

1313
import TestsUtils
1414

15-
//
1615
// Mini benchmark implementing roman numeral conversions to/from integers.
17-
// Measures performance of Substring.starts(with:) and String.append(),
16+
// Measures performance of Substring.starts(with:), dropFirst and String.append
1817
// with very short string arguments.
19-
//
18+
19+
let t: [BenchmarkCategory] = [.api, .String, .algorithm]
20+
let N = 270
2021

2122
public let RomanNumbers = [
2223
BenchmarkInfo(
23-
name: "RomanNumbers",
24-
runFunction: run_RomanNumbers,
25-
tags: [.api, .String, .algorithm])
24+
name: "RomanNumbers2",
25+
runFunction: {
26+
checkId($0, upTo: N, { $0.romanNumeral }, Int.init(romanSSsWdF:)) },
27+
tags: t),
2628
]
2729

30+
@inline(__always)
31+
func checkId(_ n: Int, upTo limit: Int, _ itor: (Int) -> String,
32+
_ rtoi: (String) -> Int?) {
33+
for _ in 1...n {
34+
CheckResults(
35+
zip(1...limit, (1...limit).map(itor).map(rtoi)).allSatisfy { $0 == $1 })
36+
}
37+
}
38+
2839
let romanTable: KeyValuePairs<String, Int> = [
29-
"M": 1000,
30-
"CM": 900,
31-
"D": 500,
32-
"CD": 400,
33-
"C": 100,
34-
"XC": 90,
35-
"L": 50,
36-
"XL": 40,
37-
"X": 10,
38-
"IX": 9,
39-
"V": 5,
40-
"IV": 4,
40+
"M": 1000, "CM": 900, "D": 500, "CD": 400,
41+
"C": 100_, "XC": 90_, "L": 50_, "XL": 40_,
42+
"X": 10__, "IX": 9__, "V": 5__, "IV": 4__,
4143
"I": 1,
4244
]
4345

4446
extension BinaryInteger {
47+
// Imperative Style
48+
// See https://www.rosettacode.org/wiki/Roman_numerals/Encode#Swift
49+
// See https://www.rosettacode.org/wiki/Roman_numerals/Decode#Swift
50+
4551
var romanNumeral: String {
4652
var result = ""
47-
var value = self
48-
outer:
49-
while value > 0 {
50-
var position = 0
51-
for (i, (key: s, value: v)) in romanTable[position...].enumerated() {
52-
if value >= v {
53-
result += s
54-
value -= Self(v)
55-
position = i
56-
continue outer
57-
}
53+
var n = self
54+
for (numeral, value) in romanTable {
55+
while n >= value {
56+
result += numeral
57+
n -= Self(value)
5858
}
59-
fatalError("Unreachable")
6059
}
6160
return result
6261
}
6362

64-
init?(romanNumeral: String) {
63+
init?(romanSSsWdF number: String) {
6564
self = 0
66-
var input = Substring(romanNumeral)
67-
outer:
68-
while !input.isEmpty {
69-
var position = 0
70-
for (i, (key: s, value: v)) in romanTable[position...].enumerated() {
71-
if input.starts(with: s) {
72-
self += Self(v)
73-
input = input.dropFirst(s.count)
74-
position = i
75-
continue outer
76-
}
65+
var raw = Substring(number)
66+
for (numeral, value) in romanTable {
67+
while raw.starts(with: numeral) {
68+
self += Self(value)
69+
raw = raw.dropFirst(numeral.count)
7770
}
78-
return nil
7971
}
80-
}
81-
}
82-
83-
@inline(never)
84-
func checkRomanNumerals(upTo limit: Int) {
85-
for i in 0 ..< limit {
86-
CheckResults(Int(romanNumeral: identity(i.romanNumeral)) == i)
87-
}
88-
}
89-
90-
@inline(never)
91-
public func run_RomanNumbers(_ N: Int) {
92-
for _ in 0 ..< 10 * N {
93-
checkRomanNumerals(upTo: 1100)
72+
guard raw.isEmpty else { return nil }
9473
}
9574
}

0 commit comments

Comments
 (0)