-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\$
  • \$\begingroup\$ Are regular expressions allowed? If yes, this is a duplicate of Converting a string to lower-case. \$\endgroup\$ – ProgramFOX Aug 19 '14 at 13:24
  • 1
    \$\begingroup\$ @ProgramFOX No. \$\endgroup\$ – Somnium Aug 19 '14 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 Giffin Aug 10 '17 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 Aug 10 '17 at 18:55
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\$
  • 1
    \$\begingroup\$ Your score is 12.44 - total score for 2 functions. \$\endgroup\$ – Somnium Aug 19 '14 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 Aug 19 '14 at 16:27
  • 1
    \$\begingroup\$ One more time I failed writing rules. \$\endgroup\$ – Somnium Aug 19 '14 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 Nov 10 '18 at 17:22
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\$
  • 1
    \$\begingroup\$ Just realized that toUpper gives wrong value for n in range [194 - 245] and toLower for almost all n >= 130. \$\endgroup\$ – Somnium Aug 19 '14 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\$ – Martin Ender Aug 19 '14 at 14:36
  • 1
    \$\begingroup\$ @MartinBüttner Forgot about that fact. Then your solution is ok. \$\endgroup\$ – Somnium Aug 19 '14 at 15:36
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
\$\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, privacy policy and cookie policy

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