-5
\$\begingroup\$

Write two functions/programs which take an ASCII code of character (8-bit unsigned integer) and one of them converts char to uppercase and other to lowercase.

That is, they must be equivalent to following functions:

unsigned char toUpper(unsigned char c){
    if (c >= 97 && c <= 122) return c - 32;
    return c;
}
unsigned char toLower(unsigned char c){
    if (c >= 65 && c <= 90) return c + 32;
    return c;
}

However you are not allowed to use branching (ifs, gotos), loops and comparison and logical operators. Recursion, language built-in functions, regular expressions, arrays and objects also not allowed. You may use only arithmetic and bitwise operations on 8-bit unsigned integers.

Score:

1 - for | & ^ ~ >> << operators
1.11 - for + - operators
1.28 - for * operator
1.411 - for / % operators

Answer with lowest total score (for two functions added) wins. If answers with equal score than first (oldest) answer wins.

\$\endgroup\$
4
  • \$\begingroup\$ Are regular expressions allowed? If yes, this is a duplicate of Converting a string to lower-case. \$\endgroup\$
    – ProgramFOX
    Commented Aug 19, 2014 at 13:24
  • 1
    \$\begingroup\$ @ProgramFOX No. \$\endgroup\$
    – Somnium
    Commented Aug 19, 2014 at 13:25
  • \$\begingroup\$ This good valid question deserves more upvotes. If you are an anti-micro-optimization kind of a guy, then you shouldn't even be at this question, let alone allowing your own biases and prejudices to cloud your judgement and downvote this legitimate question. Also, off-topicly, I would be very interested (fascinated) to see how you generated those score numbers. I'm not criticizing them, rather, just the opposite, I'm intrigued. Mabey you could comment a link to a resource about it? \$\endgroup\$
    – Jack G
    Commented Aug 10, 2017 at 16:13
  • \$\begingroup\$ @lolzerywowzery How I chose scores: At start I defined approximate scores I want operations should have, like 1, 1.1, 1.3 and 1.4. Then with trial and error I modified them a bit so equal score is unlikely with small operator amount. Checked that in Mathematica. \$\endgroup\$
    – Somnium
    Commented Aug 10, 2017 at 18:55

4 Answers 4

8
\$\begingroup\$

C and other languages with integer division, 15.204 14.644 14.084 11.864

unsigned char toUpper(unsigned char c){
    return c - ((c/97) ^ (c/123)) << 5;
}

unsigned char toLower(unsigned char c){
    return c + ((c/65) ^ (c/91)) << 5;
}
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Just realized that toUpper gives wrong value for n in range [194 - 245] and toLower for almost all n >= 130. \$\endgroup\$
    – Somnium
    Commented Aug 19, 2014 at 14:17
  • 3
    \$\begingroup\$ @Somnium. Afaik ASCII contains only 128 characters. Everything else is extended ASCII which does not seem to be part of your spec. \$\endgroup\$ Commented Aug 19, 2014 at 14:36
  • 1
    \$\begingroup\$ @MartinBüttner Forgot about that fact. Then your solution is ok. \$\endgroup\$
    – Somnium
    Commented Aug 19, 2014 at 15:36
3
\$\begingroup\$

C, C++ and related languages, 6.22

unsigned char toggle(unsigned char c, unsigned char lo, unsigned char hi)
{
    unsigned char m = (unsigned char)((lo - c) ^ (hi - c)) >> 7;
    return c ^ (m << 5);
}

unsigned char toUpper(unsigned char c)
{
    return toggle(c, 96, 122);
}

unsigned char toLower(unsigned char c)
{
    return toggle(c, 64, 90);
}
\$\endgroup\$
4
  • 1
    \$\begingroup\$ Your score is 12.44 - total score for 2 functions. \$\endgroup\$
    – Somnium
    Commented Aug 19, 2014 at 15:38
  • \$\begingroup\$ That seems unreasonable - there is only one instance of each operator, not two, and there was nothing in the rules to forbid factoring out common code. \$\endgroup\$
    – Paul R
    Commented Aug 19, 2014 at 16:27
  • 1
    \$\begingroup\$ One more time I failed writing rules. \$\endgroup\$
    – Somnium
    Commented Aug 19, 2014 at 17:44
  • \$\begingroup\$ If merging common code allowed, why not share all operators? (char xor(char a, char b){return a^b}) @Somnium \$\endgroup\$
    – l4m2
    Commented Nov 10, 2018 at 17:22
2
\$\begingroup\$

C, 11.482

My functions I have found before posting question, I hope there will better ones.

unsigned char toUpper(unsigned char c){
    unsigned char a = c - 97;
    return c - ((32 - a / 26) & 32);
}
unsigned char toLower(unsigned char c){
    unsigned char a = c - 65;
    return c + ((32 - a / 26) & 32);
}
\$\endgroup\$
0
0
\$\begingroup\$

C (gcc), 9.042 step score

uchar toUpper(uchar c){
    return c^(((uchar)(c+133)/230)<<5);
}
uchar toLower(uchar c){
    return c^(((uchar)(c+165)/230)<<5);
} // 9.042 step score

Try it online!

C (gcc), 2.11 existance score

uchar sub(uchar a, uchar b) {return a-b;}
uchar shr(uchar a, uchar b) {return a>>b;}
uchar add(uchar a, uchar b) {return sub(a, sub(0, b));}
uchar isneg(uchar a) {return shr(a, 7);}
uchar reach230(uchar a) {return shr(add(isneg(a),isneg(sub(229,a))),1);}
uchar dif(uchar a) {uchar t=reach230(a); t=add(t,t); t=add(t,t); t=add(t,t); t=add(t,t); t=add(t,t); return t;}
uchar toUpper(uchar c){ return sub(c,dif(add(c,133))); }
uchar toLower(uchar c){ return add(c,dif(add(c,165))); }

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.