-
-
Notifications
You must be signed in to change notification settings - Fork 159
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #161 from robtimp/swift3-all-your-base
All Your Base exercise
- Loading branch information
Showing
4 changed files
with
184 additions
and
5 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
enum BaseError: ErrorProtocol { | ||
case invalidInputBase | ||
case invalidOutputBase | ||
case negativeDigit | ||
case invalidPositiveDigit | ||
} | ||
|
||
struct Base { | ||
|
||
static func outputDigits(inputBase: Int, inputDigits: [Int], outputBase: Int) throws -> [Int] { | ||
guard inputBase >= 2 else { | ||
throw BaseError.invalidInputBase | ||
} | ||
|
||
guard outputBase >= 2 else { | ||
throw BaseError.invalidOutputBase | ||
} | ||
|
||
let sum = try getSum(digits: inputDigits, base: inputBase) | ||
let result = getDigits(sum: sum, base: outputBase) | ||
|
||
return result | ||
} | ||
|
||
private static func getSum(digits: [Int], base: Int) throws -> Int { | ||
var multiplier = 1 | ||
var sum = 0 | ||
|
||
for digit in digits.reversed() { | ||
guard digit >= 0 else { | ||
throw BaseError.negativeDigit | ||
} | ||
guard digit < base else { | ||
throw BaseError.invalidPositiveDigit | ||
} | ||
|
||
sum += digit * multiplier | ||
multiplier *= base | ||
} | ||
|
||
return sum | ||
} | ||
|
||
private static func getDigits(sum: Int, base: Int) -> [Int] { | ||
var sum = sum | ||
var digits = [Int]() | ||
var multiplier = 1 | ||
|
||
while sum > 0 { | ||
multiplier *= base | ||
let value = sum % multiplier | ||
let digit = value / (multiplier / base) | ||
digits.append(digit) | ||
sum -= value | ||
} | ||
|
||
return digits.reversed() | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
#if swift(>=3.0) | ||
import XCTest | ||
#endif | ||
|
||
class AllYourBaseTest: XCTestCase { | ||
|
||
func errorThrown<T, U: ErrorProtocol>(byExpression expression: @autoclosure () throws -> T) -> U? { | ||
do { | ||
let _ = try expression() | ||
return nil | ||
} catch { | ||
return error as? U | ||
} | ||
} | ||
|
||
func testSingleBitOneToDecimal() { | ||
XCTAssertEqual(try! Base.outputDigits(inputBase: 2, inputDigits: [1], outputBase: 10), [1]) | ||
} | ||
|
||
func testBinaryToSingleDecimal() { | ||
XCTAssertEqual(try! Base.outputDigits(inputBase: 2, inputDigits: [1, 0, 1], outputBase: 10), [5]) | ||
} | ||
|
||
func testSingleDecimalToBinary() { | ||
XCTAssertEqual(try! Base.outputDigits(inputBase: 10, inputDigits: [5], outputBase: 2), [1, 0, 1]) | ||
} | ||
|
||
func testBinaryToMultipleDecimal() { | ||
XCTAssertEqual(try! Base.outputDigits(inputBase: 2, inputDigits: [1, 0, 1, 0, 1, 0], outputBase: 10), [4, 2]) | ||
} | ||
|
||
func testDecimalToBinary() { | ||
XCTAssertEqual(try! Base.outputDigits(inputBase: 10, inputDigits: [4, 2], outputBase: 2), [1, 0, 1, 0, 1, 0]) | ||
} | ||
|
||
func testTrinaryToHexadecimal() { | ||
XCTAssertEqual(try! Base.outputDigits(inputBase: 3, inputDigits: [1, 1, 2, 0], outputBase: 16), [2, 10]) | ||
} | ||
|
||
func testHexadecimalToTrinary() { | ||
XCTAssertEqual(try! Base.outputDigits(inputBase: 16, inputDigits: [2, 10], outputBase: 3), [1, 1, 2, 0]) | ||
} | ||
|
||
func test15BitInteger() { | ||
XCTAssertEqual(try! Base.outputDigits(inputBase: 97, inputDigits: [3, 46, 60], outputBase: 73), [6, 10, 45]) | ||
} | ||
|
||
func testEmptyList() { | ||
XCTAssertEqual(try! Base.outputDigits(inputBase: 2, inputDigits: [], outputBase: 10), []) | ||
} | ||
|
||
func testSingleZero() { | ||
XCTAssertEqual(try! Base.outputDigits(inputBase: 10, inputDigits: [0], outputBase: 2), []) | ||
} | ||
|
||
func testMultipleZeros() { | ||
XCTAssertEqual(try! Base.outputDigits(inputBase: 10, inputDigits: [0, 0, 0], outputBase: 2), []) | ||
} | ||
|
||
func testLeadingZeros() { | ||
XCTAssertEqual(try! Base.outputDigits(inputBase: 7, inputDigits: [0, 6, 0], outputBase: 10), [4, 2]) | ||
} | ||
|
||
func testNegativeDigit() { | ||
let error: BaseError? = errorThrown(byExpression: try Base.outputDigits(inputBase: 2, inputDigits: [1, -1, 1, 0, 1, 0], outputBase: 10)) | ||
XCTAssertTrue(error == .negativeDigit) | ||
} | ||
|
||
func testInvalidPositiveDigit() { | ||
let error: BaseError? = errorThrown(byExpression: try Base.outputDigits(inputBase: 2, inputDigits: [1, 2, 1, 0, 1, 0], outputBase: 10)) | ||
XCTAssertTrue(error == .invalidPositiveDigit) | ||
} | ||
|
||
func testFirstBaseIsOne() { | ||
let error: BaseError? = errorThrown(byExpression: try Base.outputDigits(inputBase: 1, inputDigits: [], outputBase: 10)) | ||
XCTAssertTrue(error == .invalidInputBase) | ||
} | ||
|
||
func testSecondBaseIsOne() { | ||
let error: BaseError? = errorThrown(byExpression: try Base.outputDigits(inputBase: 2, inputDigits: [1, 0, 1, 0, 1, 0], outputBase: 1)) | ||
XCTAssertTrue(error == .invalidOutputBase) | ||
} | ||
|
||
func testFirstBaseIsZero() { | ||
let error: BaseError? = errorThrown(byExpression: try Base.outputDigits(inputBase: 0, inputDigits: [], outputBase: 10)) | ||
XCTAssertTrue(error == .invalidInputBase) | ||
} | ||
|
||
func testSecondBaseIsZero() { | ||
let error: BaseError? = errorThrown(byExpression: try Base.outputDigits(inputBase: 10, inputDigits: [7], outputBase: 0)) | ||
XCTAssertTrue(error == .invalidOutputBase) | ||
} | ||
|
||
func testFirstBaseIsNegative() { | ||
let error: BaseError? = errorThrown(byExpression: try Base.outputDigits(inputBase: -2, inputDigits: [1], outputBase: 10)) | ||
XCTAssertTrue(error == .invalidInputBase) | ||
} | ||
|
||
func testSecondBaseIsNegative() { | ||
let error: BaseError? = errorThrown(byExpression: try Base.outputDigits(inputBase: 2, inputDigits: [1], outputBase: -7)) | ||
XCTAssertTrue(error == .invalidOutputBase) | ||
} | ||
} |
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