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

Dec 26, 2021 at 2:49am
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 Dec 26, 2021 at 3:06am
Dec 26, 2021 at 3:53am
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 Dec 26, 2021 at 4:17am
Dec 26, 2021 at 4:02am
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 Dec 26, 2021 at 4:03am
Dec 26, 2021 at 4:33am
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.