Last active
April 4, 2019 12:15
-
-
Save O-O-wl/0ca3796702b6a7e4e2b21c9bfd935b0d to your computer and use it in GitHub Desktop.
STEP2 - 추가 학습꺼리
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
enum Unit : String { | |
case cm = "cm" | |
case m = "m" | |
case inch = "inch" | |
case yard = "yard" | |
case g = "g" | |
case kg = "kg" | |
case oz = "oz" | |
case lb = "lb" | |
case L = "L" | |
case pt = "pt" | |
case qt = "qt" | |
case gal = "gal" | |
case error = "error" | |
func defaultUnit ()->[Unit]{ | |
switch self { | |
case .cm,.m,.inch,.yard: | |
return [.cm,.m,.inch,.yard] | |
case .g,.kg,.oz,.lb: | |
return [.g,.kg,.oz,.lb] | |
case .L,.pt,.qt,.gal : | |
return [.L,.pt,.qt,.gal] | |
case .error: | |
return [.error] | |
} | |
} | |
} | |
typealias value = Double | |
typealias UnitRatio = Double | |
typealias beforeUnit = Unit | |
typealias afterUnit = Unit | |
struct units { | |
var beforeUnit : beforeUnit | |
var afterUnit : afterUnit | |
} | |
func getUnitRatioTable()->[beforeUnit:[afterUnit:UnitRatio]]{ | |
let unitRatioTable : [beforeUnit:[afterUnit:UnitRatio]] = | |
[ | |
.m: | |
[ .cm: 100, | |
.inch: 39.3701, | |
.yard: 1.09361 | |
], | |
.cm: | |
[ .m: 0.01, | |
.inch: 0.393701, | |
.yard: 0.0109361 | |
], | |
.inch: | |
[ | |
.m: 0.0254, | |
.cm: 2.54, | |
.yard: 0.0277778 | |
], | |
.yard: | |
[ | |
.cm: 91.44, | |
.m: 0.9144, | |
.inch: 36 | |
], | |
.g: | |
[ | |
.kg: 0.001, | |
.oz: 0.035274, | |
.lb: 0.00220462 | |
], | |
.kg: | |
[ | |
.g: 1000, | |
.oz: 35.274, | |
.lb: 2.20462 | |
], | |
.oz: | |
[ | |
.g: 28.3495, | |
.kg: 0.0283495, | |
.lb: 0.0625 | |
], | |
.lb:[ | |
.g: 453.592, | |
.kg: 0.453592, | |
.oz: 16 | |
], | |
.L:[ | |
.pt: 2.11338, | |
.qt: 1.05669, | |
.gal: 0.21997 | |
], | |
.pt:[ | |
.L: 0.56826, | |
.qt: 0.516027, | |
.gal: 0.129007 | |
], | |
.qt:[ | |
.L: 1.136520, | |
.pt: 2.401895, | |
.gal: 0.300237 | |
], | |
.gal:[ | |
.L: 4.404884, | |
.pt: 9.309178, | |
.qt: 4.654589 | |
] | |
] | |
return unitRatioTable | |
} | |
func getRatios( units: (beforeUnit,[afterUnit])) ->[(UnitRatio)]{ | |
var unitRatioTable = getUnitRatioTable() | |
var (beforeUnit,afterUnits) = units | |
var ratios = [UnitRatio]() | |
for i in 0..<afterUnits.count{ | |
ratios.append(unitRatioTable[beforeUnit]![afterUnits[i]]!) | |
} | |
return ratios | |
} | |
func convert(userInput:String)->[String]{ | |
let (value,units) = recognize(userInput: userInput) | |
if units == (.error,[.error]){ | |
return ["지원하지 않는 단위 입니다."] | |
} | |
let ratios = getRatios(units:units) | |
var results = [String]() | |
for i in 0..<ratios.count { | |
results.append( " \(calculatedValueString(value: value, ratio: ratios[i])) \(units.1[i]) \n") | |
} | |
return results | |
} | |
func calculatedValueString(value:Double,ratio:UnitRatio)->String{ | |
let result = value * ratio | |
return confirmNumber(number: result) | |
} | |
func confirmNumber(number:Double)->String{ | |
if(number.remainder(dividingBy: 1)==0){ | |
return "\(Int.init(number))" | |
}else{ | |
return "\(number)" | |
} | |
} | |
func recognize(userInput : String)->(value,(beforeUnit,[afterUnit])){ | |
let value = getValue(userInput: userInput) | |
let units = getUnits(userInput: userInput) | |
return (value,units) | |
} | |
func getValue (userInput:String)->Double{ | |
let pattern = "[0-9.]+" | |
let value = usingRegex(userInput: userInput, pattern: pattern) | |
return Double.init(value)! | |
} | |
func getUnits(userInput:String)->(beforeUnit,[afterUnit]){ | |
let pattern = "[^0-9.]+" | |
let units = usingRegex(userInput: userInput, pattern: pattern) | |
let beforeAndAfterUnits = units.split(separator: " ") | |
guard let beforeUnit = Unit.init(rawValue: String(beforeAndAfterUnits[0])) else{ | |
return (.error,[.error]) | |
} | |
var afterUnits = [afterUnit]() | |
// 변경할 단위값 입력 | |
if beforeAndAfterUnits.count > 1 { | |
afterUnits = getAfterUnits(afterUnits: String(beforeAndAfterUnits[1])) | |
// 변경할 단위값 미 입력 | |
}else{ | |
afterUnits = beforeUnit.defaultUnit().filter{ | |
unit in | |
if unit == beforeUnit{ | |
return false | |
} | |
return true | |
} | |
} | |
return (beforeUnit,afterUnits) | |
} | |
func getAfterUnits(afterUnits:String)->[afterUnit]{ | |
let afterUnitsArray = afterUnits.split(separator: ",") | |
var afterUnits = [afterUnit]() | |
for unit in afterUnitsArray { | |
afterUnits.append(Unit.init(rawValue: String(unit))!) | |
} | |
return afterUnits | |
} | |
func usingRegex( userInput:String ,pattern:String ) -> String{ | |
let regexUnits = try! NSRegularExpression.init(pattern: pattern, options: []) | |
let matchs = regexUnits.firstMatch(in: userInput, options: [], range: NSRange.init(location: 0, length: userInput.count)) | |
let part = NSString.init(string: userInput).substring(with: (matchs?.range)!) | |
return part | |
} | |
func unitConverter(){ | |
let quitCommends = ["q","quit"] | |
while(true){ | |
let availableUnits = getUnitRatioTable().keys.map{ | |
unit in | |
return unit.rawValue | |
} | |
print(" 변환할 값을 입력하세요 \n 가능한 단위: \(availableUnits)\n") | |
let inputValue = readLine() | |
for quitCommend in quitCommends { | |
if(quitCommend == inputValue){ | |
break | |
} | |
} | |
let results = convert(userInput: inputValue!) | |
for result in results { | |
print(result) | |
} | |
} | |
} | |
unitConverter() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment