Git Product home page Git Product logo

romannumeralkit's Introduction

RomanNumeralKit

CocoaPods Version Languages Platform

Build Status codecov

First-class Roman numeral support for Swift.

When in Rome, code as the Romans code.

Introduction

Meaningful usage of this framework requires understanding what Roman numerals are. Background information can be found on Wikipedia.

Features

  • Constants provided for all 3,999 standard Roman numerals.
  • Support for subtractive and additive notations.
  • Arithmetic using Roman-numeral-oriented algorithms - no integer calculations!
  • Conversions to-and-from popular types (e.g. String, Int).
  • Extensions for real-world usage (e.g. copyright text).
  • Conformance to all applicable numeric protocols.

Limitations

Fixed Numerical Range

Standard Roman numerals as we understand them were limited to values from 1 to 3,999. There is no concept of 0. Modern scholars have proposed extensions of the numeric system to support values greater than 3,999 but we do not recognize any of these extensions and decry the proposers to be heretics.

Most programs do not deal with numbers higher than 3,999, and the world won't exist past the year 3,999 in the Gregorian calendar, so there is no need to worry.

iPhone Model Names

RomanNumeralKit does not support conversions to-and-from recent iPhone model names such as "Xs".

Requirements

  • iOS 10.0+ / macOS 10.12+ / tvOS 10.0+ / watchOS 3.0+
  • Xcode 10.2+
  • Swift 5+

Installation

CocoaPods

Add RomanNumeralKit to your Podfile:

pod 'RomanNumeralKit', '~> 1.0.0`

Please visit the CocoaPods website for general CocoaPods usage and installation instructions.

Swift Package Manager

Add RomanNumeralKit to the dependencies value of your Package.swift:

dependencies: [
    .package(url: "https://github.com/kylehughes/RomanNumeralKit.git", from: "1.0.0")
]

Usage

Import RomanNumeralKit at the top of the Swift file you want to use it in.

import RomanNumeralKit

Constants

Constants are provided for all valid Roman numerals, from 1 to 3,999. You should never need to use an initializer unless you are doing conversions from other types.

All constants can be accessed directly by their using their uppercase Unicode characters.

print(MMCDIX)           // Prints "MMCDIX"
print(MMCDIX.symbols)   // Prints "[M, M, C, D, I, X]"

XCTAssertEqual(MMCDIX, RomanNumeral(.M, .M, .C, .D, .I, .X))    // True

Conversions

We provide convenient mechanisms to convert RomanNumerals to-and-from popular types.

It should be noted that these are true conversions: the backing values of RomanNumeral instances are groups of tally marks. We do not hold Intreferences because it would not be in the spirit of the framework.

Constructors

Constructors are provided to convert Ints and Strings to RomanNumerals.

print(RomanNumeral(from: 2409))     // Prints "MMCDIX"
print(RomanNumeral(from: "MMCDIX")) // Prints "MMCDIX"

We also support conversions from Int and String literals when the RomanNumeral type can be inferred.

let numeralFromInt: RomanNumeral = 2409
let numeralFromString: RomanNumeral = "MMCDIX"

print(numeralFromInt)       // Prints "MMCDIX"
print(numeralFromString)    // Prints "MMCDIX"

Properties

Instance-level properties are provided to convert RomanNumerals into Int and String values.

print(MMCDIX.intValue)      // Prints "2409"
print(MMCDIX.stringValue)   // Prints "MMCDIX"

We also provide various *Convertible protocols to allow types to return different RomanNumeral and RomanNumeralSymbol representations of themselves.

Arithmetic

Addition, subtraction, and multiplication operations are supported (and required) thanks to our conformance to the Numeric protocol. We use algorithms that allow us to directly manipulate the Roman numeral symbols as opposed to doing conversions to-and-from Ints.

XCTAssertEqual(MD + CMIX, MMCDIX)   // True
XCTAssertEqual(MMM - DXCI, MMCDIX)  // True
XCTAssertEqual(XI * CCXIX, MMCDIX)  // True

Performance

Our committment to authenticity does have implications.

The following table compares the performance Int arithmetic operations to Roman numeral arithmetic operations on a new MacBook Pro.

Operation (100x) Int RomanNumeral % Slower
Addition 0.00000127s 0.151s 11,889,663.78%
Subtraction 0.00000151s 0.0761s 5,992,025.98%
Multiplication 0.00000204s 0.0575s 4,527,459.06%

It should be noted that this is much faster than any person from Ancient Rome could do arithmetic. Who can take issue with progress?

Copyright Text

The most useful feature we provide is automatic formatting of Copyright text.

print(MDCCLXXVI.copyrightText)  // Prints "Copyright © MDCCLXXVI"

Additive Notation

The default notation for this framework is subtractive notation - that is what instances of RomanNumerals represent. We provide the AdditiveRomanNumeral struct for initialization of numerals using additive notation. We also support conversions between the notations.

Both notations implement the RomanNumeralProtocol protocol and support the same general interface.

let additiveNumeral = AdditiveNotation(.M, .M, .C, .C, .C, .C, .V, .I, .I, .I, .I)

print(additiveNumeral)              // Prints "MMCCCCVIIII"
print(additiveNumeral.intValue)     // Prints "2409"

XCTAssertEqual(additiveRomanNumeral.romanNumeral, MMCDIX)           // True
XCTAssertEqual(MMCDIX.additiveRomanNumeral, additiveRomanNumeral)   // True

Extensions

We provide a variety of extensions on existing Swift types to make common operations easier.

Calendar & DateComponent Extensions

Calendar objects, and the DateComponents they produce, are able to convert years into RomanNumerals.

if let currentYear = Calendar.current.currentYearAsRomanNumeral {
    print(currentYear)                  // Prints "MMXIX"
    print(currentYear.intValue)         // Prints "2019"
    print(currentYear.copyrightText)    // Prints "Copyright © MMXIX"
}

if let americasBirthYear = Calendar.current.yearAsRomanNumeral(fromDate: americasBirthDate) {
    print(americasBirthYear)                // Prints "MDCCLXXVI"
    print(americasBirthYear.intValue)       // Prints "1776"
    print(americasBirthYear.copyrightText)  // Prints "Copyright © MDCCLXXVI"
}

Int & String Extensions

We conform Int and String to the *RomanNumeralConvertible protocols to complete the ouroboros with these foundational types.

print(2409.romanNumeral)                    // Prints "MMCDIX"
print(2409.additiveRomanNumeral)            // Prints "MMCCCCVIIII"
print("MMCDIX".romanNumeral)                // Prints "MMCDIX"
print("MMCCCCVIIII".additiveRomanNumeral)   // Prints "MMCCCCVIIII"

Authors

Kyle Hughes

my twitter

Contributions

RomanNumeralKit is not accepting source contributions at this time.

License

RomanNumeralKit is available under the MIT License.

romannumeralkit's People

Contributors

kylehughes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

romannumeralkit's Issues

Implement the main numeric system without referencing Foundation

The Romans were able to implement their numeric system without relying on decimal conversion: we should be able to as well.

The general idea is that intValue and stringValue references should be moved exclusively to the Extensions folder and should not be part of the main body. Theoretically these extensions could be published as a separate framework (?). All math should be done using Roman numeral arithmetic, not relying on decimal arithmetic. Integer values should not be stored constants but rather computed properties; there should be a cost for desertion just like there is for **RomanNumeralConvertible types.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.