Addition of Letters

  • cpp, math
  • 4
  • 2
  • finished

Addition of numbers is basic arithmetic operation which children learn in elementary schools. What if we’d like to add letters? In that case we must define what their addition means. For example, what’s the result of a + a? The easiest answer is 2a, but it includes a number…

Pros and Cons of Letters Addition

Addition of letters isn’t something new or groundbreaking. We have only 10 digits after all and creating numeral systems with base over 10, especially the ones which are a power of 2, is natural when we’re talking about computers’ arithmetic. Hexadecimal numbers are short and to the point.

If we were to use all letters of latin alphabet, including capital letters, we’d end up with base 52 numeral system with its main feature being a complete lack of clarity. We all know that 0xFF is decimal 255, but what’s the equivalent in base52? Let’s use a computer to calculate.

a+a

Before I move to C++ implementation, I’ll answer the question I asked in the first paragraph. a + a = a. Lower-case letter a is the first letter of our system, so it’s a neutral element for addition. b is thus a neutral element for multiplication. Knowing that, we can start writing our letter system.

To the Point

The analogy of learing addition in elementary schools wasn’t pointless. Computers are like children: they perform columnar additions but very, very fast. Sum of two digits x and y at position n is x + y +CARRY,, where CARRY is the extra digit carried from addition of digits at position n-1 over the base of numeral system. For any numeral system CARRY can only have a value of 0 or 1 (or the equivalent of these numbers), because you cannot two digits over numeral system’s base.

Let’s define Alphabet class with a method add which adds two strings. Inside the class we’ll also define a LETTERS member which defines the order of letters and NEUTRAL field which defines a neutral letter for addition.

std::string Alphabet::add(std::string left, std::string right) {
    std::string new_result = "";
    char chl, chr, res;
    int sum, CARRY = 0;
    std::string::iterator itl = left.end();
    std::string::iterator itr = right.end();

    // ...
}

We also fined two iterators pointing to after-the-last element of strings. Each loop we’ll decrement these iterators to add more significant letters. Current letters are hold in chr and chl variables.

while( itl > left.begin() || itr > right.begin() || CARRY == 1) {
    --itl; --itr;

    /* Neutral character */
    chl = chr = NEUTRAL;

    if(!(itl < left.begin()))
      chl = *itl;

    if(!(itr < right.begin()))
      chr = *itr;

    sum = LETTERS.find(chl) + LETTERS.find(chr);
    res = LETTERS.at((sum + CARRY) % l_length);
    sum >= l_length ? CARRY = 1 : CARRY = 0;
    new_result.insert(new_result.begin(), res);
}

In each step of the loop we add two letters and the carry bit from the previous step and check if the sum of these 3 components is is outside of the base of our system (depicted as l_length). Depending on it, we set or reset carry bit. We also must make sure that both addition components might be a different length.

At the end we remove all a (neutral elements) from the beginning of our number and return the result

while(new_result.at(0) == NEUTRAL)
    new_result.erase(new_result.begin());
return new_result;

But Why?

I wrote this program for fun to do a little excersise: create a Fibonacci sequence made of letters. You can see the source code in git repository.