The Daily WTF: Curious Perversions in Information Technology
Welcome to TDWTF Forums Sign in | Join | Help
in Search

Best ones?

Last post 05-26-2007 5:55 PM by asuffield. 57 replies.
Page 1 of 2 (58 items) 1 2 Next >
Sort Posts: Previous Next
  • 05-17-2007 5:27 AM

    Best ones?

    I've seen lots of wonderful and/or horrible things here, both on the main site and in this contest, and I think WTFs can be divided in two main categories, at least when talink about code: things that are just so utterly complicated and/or convoluted they could easily win an Obfuscated <Put Your Language Here> Contest, and things that are just simple, neat, to the point, and leave you screaming in horror and wanting to use some really heavy and/or really sharp tool on the programmer who created them.

    I personally prefer the latter ones, and all my entries follow this pattern; I think a Real WTF(TM) should slam you in the face with the uttermost violence, instead of making you look, search and try to understand what at all is it all about. Also, simple (but powerful) WTFs have two added benefits: they can easily be understood by someone who doesn't even know the language they're written in, and they can be quickly shared with your friends; something like "hey, this guy's deleting an object from inside it, WTF?!?" or in "patching in-memory ASM code at runtime, now *that*'s crazy!", or even "wow, the calculator is executed on a network server to which the GUI connects and submits operations using XML, what had the programmer smoked?"; as opposed to "what the heck's going on in this 500-lines function who returns the sum of two numbers? Let's see... oh, that's a bitshift... ok, recursion... damn, what was that variable for? Argh, headache!".

    What do you think about this? :-)

  • 05-17-2007 5:39 AM In reply to

    Re: Best ones?

    I went for sort-of a WTF onion approach. Many layers of WTFs. From the basic concept of the methods and the way they are written though to the final compiled program that does weird things that even a novice user would be annoyed or amused by.
    Download my OMGWTF entry, Romanorum Computus
  • 05-17-2007 8:00 AM In reply to

    • wacco
    • Not Ranked
    • Joined on 05-13-2007
    • Posts 11

    Re: Best ones?

    I went for the very clear approach, by putting the data in so many different data structures (which could've been all used for calculating the end result, but aren't) for all kinds of different intermediate checks (A complete binary tree for getting the entered equasion from infix to postfix, but not using said binary tree to simply calculate the result for example). So yeah, it's all very readable, but definately WTFy. I don't like the IOCCC entries here at all, the rules clearly states that "I’ve decided to exclude Ugly Code as an option altogether. In other words, entries for this contest will need to focus on clean and human-readable code that is, first and foremost, Clever and, if desired, Buggy.". Which makes those gigantic "I don't use the / operator" functions really missing the point of the competition, if I read the rules correctly.

    On a slightly related note, a friend of mine just pointed at some serious bugs in my code which I didn't see until a minute ago. Unintentional bugs in an intentionally WTF program are ehm, somewhat embarrasing. Or bonuspoints. Idunno, just don't try calculating things like 90 - 9 / 9, the precedence of / over - makes it swap the values, causing 9 / 9 - 90, or -89 as a result.

  • 05-17-2007 8:57 AM In reply to

    Re: Best ones?

    or even "wow, the calculator is executed on a network server to which the GUI connects and submits operations using XML, what had the programmer smoked?"

     How did you see my entry? ;-)

     

    But yeah, I prefer the second type too, although throwing in some memory leaks, random crashes, and really bad error checking is always fun. 

  • 05-17-2007 9:05 AM In reply to

    Re: Best ones?

    burntfuse:
    or even "wow, the calculator is executed on a network server to which the GUI connects and submits operations using XML, what had the programmer smoked?"

    How did you see my entry? ;-)

    I had the same idea, and I would indeed have used it if the contest was .NET based... but I just hate C-based Win32 APIs.

    But yeah, I prefer the second type too, although throwing in some memory leaks, random crashes, and really bad error checking is always fun.

    My fist entry shouts something along the lines of "you're not allowed to do this!" if you try to use decimal or negative numbers... it's just too much pain to handle those when your calculator is based on manipulating strings.

  • 05-17-2007 10:49 AM In reply to

    • macavenger
    • Not Ranked
    • Joined on 05-15-2007
    • Fairbanks, AK
    • Posts 7

    Re: Best ones?

    Massimo:
    My first entry shouts something along the lines of "you're not allowed to do this!" if you try to use decimal or negative numbers... it's just too much pain to handle those when your calculator is based on manipulating strings.

    Tell me about it...I never realized just how hard subtraction actually is until I tried to break it down to work on strings, character-by-character. In my code, I managed to eliminate ints entierly... makes for some fun lines like char buffer[`~']; :p 
    Aluminum iMac 20" C2D 2.4 GHz/300 GB/3 GB
  • 05-17-2007 10:53 AM In reply to

    Re: Best ones?

    My fist entry shouts something along the lines of "you're not allowed to do this!" if you try to use decimal or negative numbers... it's just too much pain to handle those when your calculator is based on manipulating strings.

     

    I handled them easily. I just pass the number through the string-to-float and float-to-string functions I wrote (which did about 30 times more calculations than the calculator itself) until I've got numbers I can work with.  Basically, I just ignored problem characters.  0.6 * 5 = 30.  Negative numbers work for addition.  For multiplication, though... well... an hour wasn't enough for it to complete on a Core 2 Duo system.


    Oh, when you said "handle" them you meant handle them correctly.  My bad.

  • 05-17-2007 10:57 AM In reply to

    Re: Best ones?

    macavenger:
    Tell me about it...I never realized just how hard subtraction actually is until I tried to break it down to work on strings, character-by-character.

    This is mine:

    char* DoSub(char* op1,char* op2)
    {
     static char result[256];
     
     // Return zero if operands are the same
     if(IsGreater(op1,op2) == Undefined)
      return(zero);

     char buf1[256];
     char buf2[256];
     
     // Prepare buffers
     // Can't trust memset() here
     for(int i = 0;i < 256;i++)
     {
      buf1[i] = '0';
      buf2[i] = '0';
     }
     
     // Copy operands in buffers with right alignment
     for(int x = strlen(op1),y = 255;x >= 0;x--,y--)
      buf1[y] = op1[x];
     for(int x = strlen(op2),y = 255;x >= 0;x--,y--)
      buf2[y] = op2[x];
     
     //Find greater operand
     char *greater = NULL;
     char *lesser = NULL;
     
     if(IsGreater(op1,op2) == True)
     {
      greater = buf1;
      lesser = buf2;
     }
     else
     {
      greater = buf2;
      lesser = buf1;
     }
     
     // Prepare result
     result[255] = '\0';
     
     int borrow = 0; // Will be used to handle borrow

     // Standard right-to-left, subtract-with-borrow algorithm
     for(int i = 254;i >= 0;i--)
     {
      int c1 = (int) (greater[i] - '0');
      int c2 = (int) (lesser[i] - '0');

      int r = c1 - c2 - borrow;

      if(r >= 0)
      {
       result[i] = ((char) r) + '0';
       borrow = 0;
      }
      else
      {
       result[i] = ((char) r + 10) + '0';
       borrow = 1;
      }
     }
     
     // Insert leading minus sign if needed
     if(IsGreater(op2,op1) == True)
     {
      int i = 0;

      while(result[i] == '0')
       i++;
      
      result[i - 1] = '-';
     }

     // Remove leading zeroes
     while(result[0] == '0')
     {
      for(int i = 0;i < 255;i++)
       result[i] = result[i + 1];
     }

     // Return result
     return(result);
    }

  • 05-17-2007 11:18 AM In reply to

    • macavenger
    • Not Ranked
    • Joined on 05-15-2007
    • Fairbanks, AK
    • Posts 7

    Re: Best ones?

    TheFeshy:
    I handled them easily. I just pass the number through the string-to-float and float-to-string functions I wrote...

    That's cheating. For my case, at least, manipulating strings means manipulating ONLY strings...no converting to floats allowed, however self-written and WTF'y the conversion is :)
    Aluminum iMac 20" C2D 2.4 GHz/300 GB/3 GB
  • 05-17-2007 11:31 AM In reply to

    Re: Best ones?

    macavenger:
    For my case, at least, manipulating strings means manipulating ONLY strings...no converting to floats allowed, however self-written and WTF'y the conversion is :)

    You're absolutely right.

    I take them from the calculator's display, operate on them and print the result out without ever using any "true" number.

  • 05-17-2007 11:34 AM In reply to

    • macavenger
    • Not Ranked
    • Joined on 05-15-2007
    • Fairbanks, AK
    • Posts 7

    Re: Best ones?

    Massimo:

    macavenger:
    Tell me about it...I never realized just how hard subtraction actually is until I tried to break it down to work on strings, character-by-character.

    This is mine:

    [snip...]


    yeah, I have mine posted over at http://forums.worsethanfailure.com/forums/post/121242.aspx, or at least the guts of mine. That function is called from another that swaps the numbers if needed...at least for some cases :) Actually, for most subtractions returning a negative number, you'll get an incorrect result, but it does work on the test cases for this contest :)
    Aluminum iMac 20" C2D 2.4 GHz/300 GB/3 GB
  • 05-17-2007 1:27 PM In reply to

    Re: Best ones?

    Here is mine:

     

    char *DoSub(char *op1, char *op2)
    {
        //TODO return the difference between op1 and op2

        static char TheResult[BUFFERSIZE];
        Move(TheResult, &Zero);

        char Sign = Compare(op1, op2) == Less ? Subtraction : Addition;
        if (Compare(op1, op2) == Less)
            *(long*)&op1 ^= *(long*)&op2 ^= *(long*)&op1 ^= *(long*)&op2;

        char *PointerTo_op1 = EndOf(op1);
        char *PointerTo_op2 = EndOf(op2);
        char *PointerToTheResult = TheResult;
        bool BorrowTheOne = false;

        while (PointerTo_op1 >= op1)
        {
            char *RightOp = PointerTo_op2 >= op2 ? PointerTo_op2-- : &Zero;

            if (*PointerTo_op1 == Nine && *RightOp == *PointerTo_op1)
                *PointerToTheResult++ = BorrowTheOne == true ? *PointerTo_op1 : Zero;
            if (*PointerTo_op1 == Nine && *RightOp == Eight)
            {
                *PointerToTheResult++ = BorrowTheOne == true ? Zero : One;
                BorrowTheOne = false;
            }
            if (*PointerTo_op1 == Nine && *RightOp == Seven)
            {
                *PointerToTheResult++ = BorrowTheOne == true ? One : Two;
                BorrowTheOne = false;
            }
           

    ... Snipped a couple hundred lines of similiar code


            if (*PointerTo_op1 == Zero && *RightOp == Two)
            {
                *PointerToTheResult++ = BorrowTheOne == true ? Seven : Eight;
                BorrowTheOne = true;
            }
            if (*PointerTo_op1 == Zero && *RightOp == *PointerTo_op1)
                *PointerToTheResult++ = BorrowTheOne == true ? Nine : *PointerTo_op1;
            if (*PointerTo_op1-- == Zero && *RightOp == One)
            {
                *PointerToTheResult++ = BorrowTheOne == true ? Eight : Nine;
                BorrowTheOne = true;
            }
        }

        *PointerToTheResult = End;
        PointerToTheResult = Reverse(TheResult);
        while (*PointerToTheResult++ == Zero && *PointerToTheResult != End);
            --PointerToTheResult;
        if (Sign == Subtraction)
            *Move(PointerToTheResult + 1, PointerToTheResult) = Sign;

        return PointerToTheResult;
    }

  • 05-17-2007 1:33 PM In reply to

    Re: Best ones?

    I picked a faux client-server approach.  I drew a lot of inspiration from the front page WTFs on this fine website.  Here are the steps to calculating 1 + 1 in my calculator.

    1.  The Front End is a text widget that does not allow interaction (you can only talk to it via an input palette).  The Front End retains a string in memory instead of reading off of the text widget, so using the text box is a futile affair.  Entering "1+1=", at this point, causes the string "1+1" to be created.
    2. When the user presses '=', the Middle End (part 1) is forked off by the Front End.  The Front End then prints the string to a pipe, where the middle end (part 1) redirects stdin and stdout to files.  They would have been pipes, but that never worked.  So the middle end copies the pipe to a file, opens an output end, and executes bison parser #1.  The parser's only job is to transform "1+1" into something the Back End will understand: a string of the form 'it = "1"+"1"; print it;".  This is, of course, sent off on to a pipe to Middle End (part 2).
    3. The Middle End (part 2) used to be an experiment in piping to bison, but once it started working, I found it easier to interact with that than the Back End.  So its sole purpose in life is to talk to the Back End in a way it understands.  It does nothing but move what's printed on its pipe to a different file, and fork & exec the Back End.
    4. The Back End parses the string expressions, passing them to libGMP in a leaky and useless manner, and then prints to what it believes is stdout.
    5. Instead of trying to simulate a reply, I got lazy and used the Front End to open up the last file in the chain and read it, appending the contents to the text widget.
    Now, I thought that this was pretty bad, but my chances at that JPEG seem shot after seeing some nearly Lovecraftian horrors spawned from the deeps...
    Filed under:
  • 05-17-2007 1:34 PM In reply to

    • phaedrus
    • Top 500 Contributor
    • Joined on 03-20-2007
    • Seattle Ex-Pat living in the Bay Area
    • Posts 111

    Re: Best ones?

    Massimo:

    I've seen lots of wonderful and/or horrible things here, both on the main site and in this contest, and I think WTFs can be divided in two main categories, at least when talink about code: things that are just so utterly complicated and/or convoluted they could easily win an Obfuscated <Put Your Language Here> Contest, and things that are just simple, neat, to the point, and leave you screaming in horror and wanting to use some really heavy and/or really sharp tool on the programmer who created them.

    I personally prefer the latter ones, and all my entries follow this pattern; I think a Real WTF(TM) should slam you in the face with the uttermost violence, instead of making you look, search and try to understand what at all is it all about. Also, simple (but powerful) WTFs have two added benefits: they can easily be understood by someone who doesn't even know the language they're written in, and they can be quickly shared with your friends; something like "hey, this guy's deleting an object from inside it, WTF?!?" or in "patching in-memory ASM code at runtime, now *that*'s crazy!", or even "wow, the calculator is executed on a network server to which the GUI connects and submits operations using XML, what had the programmer smoked?"; as opposed to "what the heck's going on in this 500-lines function who returns the sum of two numbers? Let's see... oh, that's a bitshift... ok, recursion... damn, what was that variable for? Argh, headache!".

    What do you think about this? :-)

    I think you're right about the Ugly Code rule.  I think it's going to disqualify a significant number of entries.  I'm hoping mine is not one of those, although I went and abused the Ugly Code rule, as my entry is kind of a hybrid.  There's Ugly Code in there, but that's not the Real WTF.  The Real WTF is the clean code I wrote to make the Ugly Code work. 

    Hmm, I think I just gave everything away.  That little tidbit combined with the my other recent posts probably gives away what I did.  I'm still not going to be explicit. 

    All men are frauds. The only difference between them is that some admit it. I myself deny it.
    -- H. L. Mencken
  • 05-17-2007 1:38 PM In reply to

    Re: Best ones?

    Massimo:

    macavenger:
    For my case, at least, manipulating strings means manipulating ONLY strings...no converting to floats allowed, however self-written and WTF'y the conversion is :)

    You're absolutely right.

    I take them from the calculator's display, operate on them and print the result out without ever using any "true" number.

     

    But looking at your DoSub() code I noticed you are using ints in your for loops. In my code I do not use any numbers, not even for counting loops. It is all done with text strings.

  • 05-17-2007 2:18 PM In reply to

    Re: Best ones?

    In my code I do not use any numbers, not even for counting loops. It is all done with text strings.


    for (char i = 'a', i < 'a' + NUM_ITERATIONS; i++) ?  Or is it something worse?

  • 05-17-2007 2:23 PM In reply to

    Re: Best ones?

    Massimo:

    I've seen lots of wonderful and/or horrible things here, both on the main site and in this contest, and I think WTFs can be divided in two main categories, at least when talink about code: things that are just so utterly complicated and/or convoluted they could easily win an Obfuscated <Put Your Language Here> Contest, and things that are just simple, neat, to the point, and leave you screaming in horror and wanting to use some really heavy and/or really sharp tool on the programmer who created them.


    Two of my entries follow the second philosophy: they are simple, well-coded, and present a single, major algorithmic WTF in less than 200 lines of code.  The third is something else entirely.
  • 05-17-2007 2:28 PM In reply to

    Re: Best ones?

    burntfuse:

    In my code I do not use any numbers, not even for counting loops. It is all done with text strings.


    for (char i = 'a', i < 'a' + NUM_ITERATIONS; i++) ?  Or is it something worse?

    This is my DoMul() function. LoopCounter is the loop controller:

    char *DoMul(char *op1, char *op2)
    {
        //TODO return the product of op1 and op2

        static char TheResult[BUFFERSIZE];
        Move(TheResult, &Zero);

        char LoopCounter[BUFFERSIZE];
        Move(LoopCounter, &Zero);
        while (Compare(LoopCounter, op2) == Less)
        {
            Move(LoopCounter, DoAdd(LoopCounter, &One));
            Move(TheResult, DoAdd(TheResult, op1));
        }

        return TheResult;
    }

    I used only while loops in my code, there are no for loops at all.

     

  • 05-17-2007 4:26 PM In reply to

    • macavenger
    • Not Ranked
    • Joined on 05-15-2007
    • Fairbanks, AK
    • Posts 7

    Re: Best ones?

    Chicken Little:
    burntfuse:

    In my code I do not use any numbers, not even for counting loops. It is all done with text strings.


    for (char i = 'a', i < 'a' + NUM_ITERATIONS; i++) ?  Or is it something worse?

    This is my DoMul() function. LoopCounter is the loop controller:

    [snip..]

    I used only while loops in my code, there are no for loops at all.

     


    I used no loops-any looping I needed I implemented with a recursive function :) My "counters" are implemented similarly to the above example for numbers that I know will fit in a char - some of my recursions can end up being hundreds (or thousands) of levels deep, and for those I used a char string, which I incremented using a function I write that makes it act like a regular number (rolling over to the next digit when it reches '9' or '0'. I'll admit, however, that things got somewhat more boring once I discovered that a char is perfectly happy to work as a one-byte int, even without being explicitly cast as such.
    Aluminum iMac 20" C2D 2.4 GHz/300 GB/3 GB
  • 05-17-2007 6:40 PM In reply to

    Re: Best ones?

    macavenger:
    Massimo:
    My first entry shouts something along the lines of "you're not allowed to do this!" if you try to use decimal or negative numbers... it's just too much pain to handle those when your calculator is based on manipulating strings.

    Tell me about it...I never realized just how hard subtraction actually is until I tried to break it down to work on strings, character-by-character. In my code, I managed to eliminate ints entierly... makes for some fun lines like char buffer[`~']; :p

    But subtraction is so simple in ASCII BigEndian BCD as in O(n) for positive results and O(2n+1) for negative results:
    static void minus(node_t *l, node_t *r)
    {
            int n, i, b = 0;
            char *res;
            /* Recursive reduction of parsetree to values */
            reduce(l);
            reduce(r);
            /* Degenerate cases */
            if(l->e || r->e)
            {
                    l->e = 1;
                    zap(r);
                    return;
            }
            if(r->s)
            {
                    r->s = 0;
                    plus(l, r);
                    return;
            }
            n = fixsize(l, r);  /* Need same sized operands */
            res = (char *)xmalloc(n+2);
            for(i = 0; i < n; i++) /* Subtract */
            {
                    int ch = l->v[i] - r->v[i] + '0' - b;
                    b = 0;
                    if(ch < '0')
                    {
                            ch += 10;
                            b++;
                    }
                    res[i] = ch;
            }
            if(b) /* 2's complement if borrowed (negative) */
            {
                    node_t *o = (node_t *)xmalloc(sizeof(*o));
                    node_t *p = (node_t *)xmalloc(sizeof(*p));
                    node_t *q = (node_t *)xmalloc(sizeof(*q));
                    char *c = (char *)xmalloc(n+2);
                    memset(c, '0', n);
                    c[i] = '1';
                    p->v = c;
                    q->v = res;
                    minus(p, q);
                    res = p->v;
                    xfree(p);
            }
            else
                    while(i > 1 && res[i-1] == '0')
                            res[--i] = 0;
            l->s = b;
            zap(r);
            xfree(l->v);
            l->v = res;
    }
    
  • 05-17-2007 7:55 PM In reply to

    Re: Best ones?

    BsAtHome:

    But subtraction is so simple in ASCII BigEndian BCD as in O(n) for positive results and O(2n+1) for negative results:

    O(n) and O(2n+1) are the same thing. 


  • 05-17-2007 8:01 PM In reply to

    Re: Best ones?

    asuffield:
    O(n) and O(2n+1) are the same thing.

    They are, because their durations both depend linearly on N.

    At the same time, they are not, because O(2n) will always take two times the time of O(n).

  • 05-17-2007 11:53 PM In reply to

    Re: Best ones?

    Massimo:

    asuffield:
    O(n) and O(2n+1) are the same thing.

    They are, because their durations both depend linearly on N.

    At the same time, they are not, because O(2n) will always take two times the time of O(n).

    No, you have to understand what O() actually means. It's not just a rough measurement of the algorithm's performance, nor is it a measurement of how many steps the algorithm actually takes, it has a specific definition. Informally:

    An algorithm is O(f(x)) if and only if there exists two constant values C and x0 such that the time/steps/whatever taken to complete the algorithm is always less than C * f(x) for all x > x0. Note that this means