-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNumbers.swift
203 lines (143 loc) · 5.6 KB
/
Numbers.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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
//
// EENumbers.swift
// galaxy
//
// Created by Tony Thomas on 02/05/16.
// Copyright © 2016 Tony Thomas. All rights reserved.
//
import Foundation
/**
The struct represents a galaxy number its made of galaxy numerals 'GalaxyNumeral', like pish, prok etc
*/
struct GalaxyNumber {
//MARK: properties
//The raw numerals in an array, used array because it is ordered elements
var rawValue : [GalaxyNumeral]
//MARK: methods
/*
Get the equivalent roman number.
- returns : a 'RomanNumber' if the conversion succeeds
*/
func getRomanNumber()->RomanNumber?{
var romanNumber : RomanNumber? = nil
do{
//Roman numbers are formed using roman numerals, so we map the galaxy numerals
//to corresponding roman numerals
try romanNumber = RomanNumber(numerals: rawValue.map {
return $0.getRomanNumeral()
})
}
catch Error.InvalidRomanNumber{
Log.print("Invalid roman number")
return nil
}
catch{
Log.print("Unknown exception in creating RomanNumber")
return nil
}
return romanNumber
}
}
/**
The struct represents a roman number its made of roman numerals 'RomanNumeral', like I, V , X etc
*/
struct RomanNumber {
//MARK: properties
//An array of roman numerals
var rawValue : [RomanNumeral]
//Pattern for condition
//Some roman numerals can be repeated, but with a limit of 3 in a single block
let repetitionPatternMoreThanThree = "(.)\\1{3,}"
//Pattern for condition
//Some roman numerals cannot be repeated
var repetitionPatternMoreThanOne = "(.)\\1{1,}"
//MARK: methods
/*
Get the equivalent roman number.This conversion checks the conditions
and throws an error if anything fail
- parameter : an array of roman numerals
*/
init(numerals: [RomanNumeral]) throws{
//Get the raw number in the form XXLV
let rawNumber = numerals.reduce("") { (combined : String, romanNumeral:RomanNumeral) -> String in
combined + romanNumeral.faceName
}
//Find patterns if any, which are repeating
let result = StringParser.findInText(rawNumber, pattenOfInterest:repetitionPatternMoreThanThree)
guard result == nil else{
throw Error.InvalidRomanNumber
}
//Some roman numerals cannot be repeated, if so, this number is invalid
for romanNumeral in numerals{
if romanNumeral.canRepeate{
continue;
}
else{
//Replace the pattern to find specific repeating roman numeral eg :(.)\\1{1,} --> (M)\\1{1,}
repetitionPatternMoreThanOne = repetitionPatternMoreThanOne.stringByReplacingOccurrencesOfString(".", withString: romanNumeral.faceName)
let result = StringParser.findInText(rawNumber, pattenOfInterest:repetitionPatternMoreThanOne)
guard result == nil else{
throw Error.InvalidRomanNumber
}
}
}
//Not all small values can be substracted from large value
for var i = 0; i < numerals.count-1; ++i {
if numerals[i]<numerals[i+1] &&
!numerals[i].canSubstractFrom(numerals[i+1]){
throw Error.InvalidRomanNumber
}
}
rawValue = numerals
}
//MCMXLIV = 1000 + (1000 − 100) + (50 − 10) + (5 − 1) = 1944
func getArabicNumber()throws ->ArabicNumber {
var arabicNumberSum = ArabicNumber(rawValue: 0);
for var i = 0; i < rawValue.count-1; ++i {
if rawValue[i]<rawValue[i+1] {
arabicNumberSum -= rawValue[i].arabicEquivalent
}
else{
arabicNumberSum += rawValue[i].arabicEquivalent
}
}
//add last element
arabicNumberSum += rawValue[rawValue.count-1].arabicEquivalent
return arabicNumberSum
}
}
/**
The struct represents a arabic number etc 100
*/
struct ArabicNumber {
//MARK: properties
var rawValue : Double
//MARK: methods
init( rawValue : Double){
self.rawValue = rawValue
}
func stringValue()->String{
return String(rawValue)
}
}
//MARK: ArabicNumber operator functions
//operator functions for the 'ArabicNumber' struct
func > (arabicNumber1:ArabicNumber, arabicNumber2:ArabicNumber)->Bool{
return arabicNumber1.rawValue > arabicNumber2.rawValue
}
func < (arabicNumber1:ArabicNumber, arabicNumber2:ArabicNumber)->Bool{
return arabicNumber1.rawValue < arabicNumber2.rawValue
}
//overflow error is not considering in the following operator functions
func += (inout arabicNumber1:ArabicNumber, arabicNumber2:ArabicNumber){
arabicNumber1.rawValue += arabicNumber2.rawValue
}
func -= (inout arabicNumber1:ArabicNumber, arabicNumber2:ArabicNumber){
arabicNumber1.rawValue -= arabicNumber2.rawValue
}
func *= (inout arabicNumber1:ArabicNumber, arabicNumber2:ArabicNumber){
arabicNumber1.rawValue *= arabicNumber2.rawValue
}
func /= (inout arabicNumber1:ArabicNumber, arabicNumber2:ArabicNumber){
arabicNumber1.rawValue /= arabicNumber2.rawValue
}