What is the best way of implementing this letter valuing function?

Hi. I'm probably overthinking all of this, but it's worth the try. I'm trying to implement a function that will return a short int when passed a char according to the Pythagorean numerology table. It goes exactly as you might imagine, except that every time the value exceeds 9 it gets truncated back to 1, as shown in:
1
2
3
4
123456789
ABCDEFGHI
JKLMNOPQR
STUVWXYZ

Problem is: I'm obsessed with code efficiency but have no basis or knowledge on algorithm optimization as I'm merely a casual programmer that tries to code small utilities for personal use. This is the lazy and probably astronomically inefficient way that I've found to do such a task:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
short int letterValue(char a)
{
	if(!(a >= 'a' && a <= 'z') && !(a >= 'A' && a <= 'Z'))
	{
		return 0;
	}
	else
	{
		if(a >= 'a' && a <= 'i')
		{
			return (int)a - 96;
		}
		if(a >= 'j' && a <= 'r')
		{
			return int(a) - 105;
		}
		if(a >= 's' && a <= 'z')
		{
			return int(a) - 124;
		}
		if(a >= 'A' && a <= 'I')
		{
			return (int)a - 64;
		}
		if(a >= 'J' && a <= 'R')
		{
			return int(a) - 73;
		}
		if(a >= 'S' && a <= 'Z')
		{
			return int(a) - 82;
		}
	}
	return -1;
}


All help is welcome in improving this code. How would you do it?
Last edited on
What about this?

(assuming that only ASCII characters from 'A' to 'Z' and 'a' to 'z' are considered valid input)

1
2
3
4
5
6
7
8
9
short int letterValue(char a)
{
    a = toupper(a);
    if ((a >= 'A') && (a <= 'Z')
    {
        return 1 + ((((int)c) - 65) % 9);
    }
    return -1;
}


Function toupper() converts characters to upper case, so that no special-casing is needed for upper- and lower-case. Then use the modulus operator (%) to get the remainder of division by 9. Finally add one.
Last edited on
if obsessed with efficiency you can write an inefficient function and dump a lookup table, replace the function with that such that result = table[letter]. If this is ascii, its a small table. If its unicode, let us know? Usually for unicode I would do a unordered map of the key/values and then you DO need a function to handle all other values to a default result.
Last edited on
Yes, use a look up table, if the look up is to be done many times.
Ideally, avoid making non-portable assumptions about the locale (about the specific encoding of characters).

For instance, for narrow characters:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <limits>
#include <array>

static constexpr std::size_t NUM_CHARS = std::numeric_limits<unsigned char>::max() + 1 ;
using look_up_table_t = std::array<int,NUM_CHARS> ;

look_up_table_t make_lookup_table()
{
    // our alphabet
    static constexpr char alphabet_uc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;
    static constexpr char alphabet_lc[] = "abcdefghijklmnopqrstuvwxyz" ;
    static_assert( sizeof(alphabet_uc) == sizeof(alphabet_lc) ) ; // sanity check

    look_up_table_t table {{}}; // initialize to all zeroes

    // initialise table: set values for the characters in our alphabet;
    // the ones not in our alphabet remain zeroes
    std::size_t i = 0 ;
    int value = 1 ;
    for( ; alphabet_lc[i] != 0 ; ++i )
    {
        // for narrow character types, each possible bit pattern
        // of the representation represents a distinct value.
        table[ alphabet_uc[i] ] = table[ alphabet_lc[i] ] = value ;
        ++value ;
        if( value == 10 ) value = 1 ;
    }

    return table ;
}

int letter_value( char ch )
{
    static const look_up_table_t table = make_lookup_table() ; // initialize once

    // unsigned char has the same value representation as the corresponding signed char
    return table[ch] ;
}


Topic archived. No new replies allowed.