Last active
October 13, 2017 01:59
-
-
Save ryanwarsaw/c678427d1282ed33aa7c6ae589b217fb to your computer and use it in GitHub Desktop.
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
struct LargeInt { | |
var digits: [Int8] = []; | |
/** | |
* Default constructor if we don't want to provide a value, this is removed when we create our own so we have to do this dummy method. | |
**/ | |
init() { | |
digits.append(0); | |
} | |
/** | |
* Failable initializer that attempts to convert each String character into an Int8 value to build the LargeInt, or returns nil if it fails. | |
* This can fail for many reasons, including foreign symbols in the input (i.e. #$%^&*()!@-_=+) or characters, anything that can't be converted to an Int8 value. | |
**/ | |
init?(_ value: String) { | |
for (_, character) in String(value).characters.enumerated() { | |
if (Int8(String(character)) != nil) { | |
digits.append(Int8(String(character))!); | |
} else { | |
return nil; | |
} | |
} | |
} | |
/** | |
* Compress the digits array back down into a String, and return the result as a string. | |
**/ | |
func toString() -> String { | |
return digits.map(String.init).joined(); | |
} | |
/** | |
* Operator overload for the + symbol, so we can do things like: LargeInt("99") + LargeInt("111"). | |
**/ | |
static func +(left: LargeInt, right: LargeInt) -> LargeInt { | |
// Bigger & Smaller aren't defined by the value they hold, rather the amount of "digits" within the total number. | |
let bigger: LargeInt; | |
let smaller: LargeInt; | |
if (left.digits.count > right.digits.count) { | |
bigger = left; | |
smaller = right; | |
} else { | |
bigger = right; | |
smaller = left; | |
} | |
let maxIndex = bigger.digits.count; | |
var result: [Int8] = []; | |
var carryOver: Bool = false; | |
for i in 0..<maxIndex { | |
var sum: Int8 = 0; | |
// If true, we need to carry over the one from the previous iteration. | |
if (carryOver) { | |
sum += 1; | |
carryOver = false; | |
} | |
// if the index is present in both numbers then we add, otherwise we copy the value into the result (Because we can't add it to a non-existent index). | |
if (smaller.digits.indices.contains((smaller.digits.count - 1) - i) && bigger.digits.indices.contains((maxIndex - 1) - i)) { | |
sum += bigger.digits[(maxIndex - 1) - i] + smaller.digits[(smaller.digits.count - 1) - i]; | |
} else { | |
sum += bigger.digits[(maxIndex - 1) - i]; | |
} | |
// If the number is longer than one digit long, trim it and set the "carryOver" boolean to true. | |
if (String(sum).characters.count != 1) { | |
sum = sum % 10; | |
carryOver = true; | |
} | |
result.append(sum); | |
} | |
// This is a special edge case for if the last digit (right-to-left) needs carried over. We reverse the result, so we just append "1" for the carry over. | |
if (carryOver) { | |
result.append(1); | |
carryOver = false; | |
} | |
// We're going to compress the array back down into a String and return a new instance of LargeInt with the result. | |
return LargeInt(result.reversed().map(String.init).joined())!; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment