• (cs)

    Goodness me. I think some bits of my brain just fell out of my ears.

  • DAve (unregistered)

    But...It Works???

    Fist!

  • Tom Ritchford (unregistered)

    Ahhh, C++ template abuse! Template metaprogramming is a classic sign of too much caffeine and intelligence.

    Overall, I'm astonished by the exceptionally low quality of these submissions (low quality == good). I have no idea how you're going to judge them....

  • Tom Ritchford (unregistered)

    Ahhh, C++ template abuse! Template metaprogramming is a classic sign of too much caffeine and intelligence.

    Overall, I'm astonished by the exceptionally low quality of these submissions (low quality == good). I have no idea how you're going to judge them....

  • CBlue (unregistered)

    I have to say the garbage collection on this is absolute pure unadulterated genius

  • Houdini (unregistered)

    I would hope that "357 becomes ((3 * 10) + 5) * 10) + 7" would be "357 becomes ((3 * (2 * 5)) + 5) * (2 * 5)) + 7".

    Because, you know, that makes it easier to... something.

  • gabba (unregistered)

    How is this a WTF? It's just another ostentatiously clever nerdy programming exercise. Like the OCR one.

  • (cs)
    In the process I found an obscure bug which calc.exe has but which my program does NOT! Yes, the Windows calculator is buggier than a WTF entry. You heard it from me first.

    You can't just say that and nothing more! What is this bug? :-)

  • w00t (unregistered) in reply to Houdini
    Houdini:
    I would hope that "357 becomes ((3 * 10) + 5) * 10) + 7" would be "357 becomes ((3 * (2 * 5)) + 5) * (2 * 5)) + 7".

    Because, you know, that makes it easier to... something.

    Shouldn't that expression be in some sort of prefix notation? Just because?

  • MikeCD (unregistered)

    I think this is the best one yet.

  • Barron (unregistered)

    But what was the bug???

  • (cs)

    I love the GreedyGarbageCollector which (a) has to be run manually, (b) deletes any subclass of Object that you haven't marked as non-garbage by calling hey_thats_not_garbage, and (c) provides no way of marking an Object as garbage once you've called hey_thats_not_garbage on it.

  • Someone (unregistered)

    This guy can not program C++; he doesn't even know the basics.

        template <typename T>
            void ChangeState() { if (state) delete state; state = new State<T>(); }
    

    is way too complex. It could and should just be

        template <typename T>
            void ChangeState() { delete state; state = new State<T>(); }
    

    Remember: cycles are expensive.

  • Pasotaman (unregistered)

    I love this entry because of the factor tree, but let's face it: C++ template abuse is just too simple. Combining it with memory operator overloading, any grandma with a C++ tutorial can write the biggest WTF in history if put to it.

    P.S.: what we are all wanting to know now is: what's the bug in the windows calculator?

  • Ken (unregistered)

    I love it. There may be two more of these yet to go, but I have a winner!

  • Dennis Ferron (unregistered) in reply to vecctor
    vecctor:
    In the process I found an obscure bug which calc.exe has but which my program does NOT! Yes, the Windows calculator is buggier than a WTF entry. You heard it from me first.

    You can't just say that and nothing more! What is this bug? :-)

    OK so you guys are never going to believe this but... I discovered it, and forgot to write down how to reproduce it. Now I can't remember it. I considered not mentioning it because of this, but then I decided it would be more fun to flummox everyone by mentioning its existence but not what it is. Kind of like Fermat's last theorem (paraphrased): "I've discovered a proof to this vexing famous problem of mathematics, but the margin of this paper isn't big enough to hold the solution."

    I can tell you the general nature of the bug, though. It has to do with making the calc.exe program confuse itself when dealing with its accumulator versus its memory. The basic idea is that you have a memory, and an accumulator, and when you do your operation, the operation is performed on the two, and the result is stored in memory. Because the calculator supports many forms of operation, such as "+=" or "n + n + n" series of operations, it gets really confusing at some points whether we should use the memory, or the accumulator, for the next operation, or combine them. This is why I implemeted a state machine for my calculator, to keep track of all this. There is a series of operations you can perform on the Windows calculator, by combining the different types of operations (repeated additions, repeated equals presses, +=, then changing your mind about which operation you want) which tricks Windows Calc into making the wrong choice (between memory or accumulator) as to which value to use in the next operation. The next answer it gives, while justifiable as a reasonable way to interpret the keypresses, is different from the way the calculator would have acted without the build up to it. Since my calculator builds up the equations as a tree of numbers and operations in memory, and doesn't try to collapse them to a number until it needs to be displayed, it isn't susceptible to getting confused by prematurely calculating an answer.

  • Garcia (unregistered)

    A Z80 does not have 265k of RAM. Among other things, a Z80 is just a chipset which was used in the early 8-bit "microcomputers", such as the ZX Spectrum and derivatives, which had 48k of memory (32k RAM + 16k ROM).

  • whicker (unregistered) in reply to Garcia
    Garcia:
    A Z80 does not have 265k of RAM. Among other things, a Z80 is just a chipset which was used in the early 8-bit "microcomputers", such as the ZX Spectrum and derivatives, which had 48k of memory (32k RAM + 16k ROM).
    Quite pedantic, the sentence reads "His first computer was an old 8-bit Z80 (256K of RAM) that could only run CP/M."

    Subject is computer. Think back to your sentence diagrams in 6th grade.

  • dkf (unregistered) in reply to Garcia
    Garcia:
    A Z80 does not have 265k of RAM. Among other things, a Z80 is just a chipset which was used in the early 8-bit "microcomputers", such as the ZX Spectrum and derivatives, which had 48k of memory (32k RAM + 16k ROM).
    Many later Z80-based systems had bank-switched memory systems so that they could address more than the width of a 16-bit bus would lead you to believe. Heck, even the early ZX Spectrum did that sort of thing (for ROMs) with Interface 1...
  • M.G. (unregistered) in reply to Garcia
    Garcia:
    A Z80 does not have 265k of RAM. Among other things, a Z80 is just a chipset which was used in the early 8-bit "microcomputers", such as the ZX Spectrum and derivatives, which had 48k of memory (32k RAM + 16k ROM).

    No. A Z80 is an 8-bit microprocessor (not a "chipset" any more than an Intel Pentium is a "chipset"). It doesn't have any memory at all, actually, except for the registers. It has an 8-bit data bus and 16-bit address bus. The original post was stating that the submitter had a Z80-based machine (of which there were many) that had 256K of RAM. You know, like I'd say my current system is an AMD Athlon (2 GB RAM).

    He's a pinball (captcha) wizard...

  • dkf (unregistered)

    Ooh, another gem of a comment from Operators.cpp:

    Thank you, Stroustroup, for working so hard to ensure C++ fully supports all WTF's.

  • Kinglink (unregistered) in reply to Dennis Ferron
    Dennis Ferron:
    OK so you guys are never going to believe this but... I discovered it, and forgot to write down how to reproduce it. Now I can't remember it. I considered not mentioning it because of this, but then I decided it would be more fun to flummox everyone by mentioning its existence but not what it is. Kind of like Fermat's last theorem (paraphrased): "I've discovered a proof to this vexing famous problem of mathematics, but the margin of this paper isn't big enough to hold the solution."

    I can tell you the general nature of the bug, though. It has to do with making the calc.exe program confuse itself when dealing with its accumulator versus its memory. The basic idea is that you have a memory, and an accumulator, and when you do your operation, the operation is performed on the two, and the result is stored in memory. Because the calculator supports many forms of operation, such as "+=" or "n + n + n" series of operations, it gets really confusing at some points whether we should use the memory, or the accumulator, for the next operation, or combine them. This is why I implemeted a state machine for my calculator, to keep track of all this. There is a series of operations you can perform on the Windows calculator, by combining the different types of operations (repeated additions, repeated equals presses, +=, then changing your mind about which operation you want) which tricks Windows Calc into making the wrong choice (between memory or accumulator) as to which value to use in the next operation. The next answer it gives, while justifiable as a reasonable way to interpret the keypresses, is different from the way the calculator would have acted without the build up to it. Since my calculator builds up the equations as a tree of numbers and operations in memory, and doesn't try to collapse them to a number until it needs to be displayed, it isn't susceptible to getting confused by prematurely calculating an answer.

    Bad code monkey, it's more of a WTF to say there's a bug and not explain it!! Stop ruining the natural mystique you acquired.

  • Mankynd (unregistered) in reply to Kinglink
    Kinglink:
    Dennis Ferron:
    OK so you guys are never going to believe this but... <snip>

    I can tell you the general nature of the bug, though. <snip>

    Bad code monkey, it's more of a WTF to say there's a bug and not explain it!! Stop ruining the natural mystique you acquired.

    Hmm. I have a feeling calc.exe is going to get more unit testing in the next couple of days than in the entire lifecycle of windows development.

    Captcha: pirates <insert obligatory "Arrrr">

  • Mike (unregistered)

    Did you do any testing that involved the number 95? I foresee some problems there.

    • Mike
  • Anonymous (unregistered) in reply to Mike

    Why? Because "nineteen" is spelled as "ninteen"? That's consistent throughout.

  • vDave (unregistered) in reply to CBlue
    CBlue:
    I have to say the garbage collection on this is absolute pure unadulterated genius

    I love the use of a vector instead of a list for this. Especially when telling the garbage collector that an object really is important.

    Although i have to say that the biggest WTFerys of all here are:

    know_thyself() - completely unneeded if 'better designed' (== less of a wtf)

    allocation of an object to represent current state, for use as a template parameter to do name-based base class function resolution - again with 'better design' (still == less wtf) and some clever typdef-ing this can be completely avoided.

    Overall, a nice example. More clever than WTF, but i think this (and most of the other examples) just goes to show that you can't force the genius of slow, natural decay.

  • Dennis Ferron (unregistered) in reply to vDave
    vDave:
    know_thyself() - completely unneeded if 'better designed'

    Oh, no kidding. That was a horrible way to band-aid over a problem I could have avoided. I kept getting bitten by the "slicing problem" because I was trying to store derived-class instances into vector slots only big enough for base class sized objects. The extra bits of the derived class just get sliced off - yes it's as painful as it sounds. So I thought, ah the heck with it, I'll just make the sliced base instances able to keep a pointer to the real original object. Sufficiently screwy for a WTF contest, why not? Later I realized I could have stopped the madness by using vectors of pointers, instead of vectors of actual objects. I decided to leave it in "just in case", since I suspect the operator overload functions could've been slicing my objects too.

    (BTW, you noticed I use vector<> a lot. It's because I don't fully trust list<> with my data. All that mucking about with pointers to "heads" and "tails" under the covers; gives me the creeps.)

  • (cs)

    He's cheating his own spec:

        virtual float Value() const
    

    ...when it actually comes to the calculations, he defaults to those boring traditional number classes.

    Naughty, naughty.

  • iMalc (unregistered)

    I imagine that a GCD or LCM function if added to this calculator would be rather um... special.

  • Mats Gefvert (unregistered)

    My eyes... my eyes....

  • Sarkie (unregistered)

    Well I don't know if it's a bug, but a few

    Number + # + # + # (Loop until calc.exe issues 100% CPU)

    Seems it likes to kill the gui, when waiting for the answer, not a seperate thread.

    Microsoft ftw!

    captcha: CRAAZY ( i know, isn't it)

  • (cs)

    Wow. I was sure there's nothing C++ templates can't do, but this extends the borders of conceivable.

  • (cs) in reply to IMil
    IMil:
    Wow. I was sure there's nothing C++ templates can't do, but this extends the borders of conceivable.

    Are C++ templates turing complete? Maybe we can do some calculations at compile time :)

  • J Random Hacker (unregistered) in reply to Mcoder
    Mcoder:
    Are C++ templates turing complete? Maybe we can do some calculations at compile time :)

    Yes, they are. Apparently a demonstrator program was once posted to an C++ standard committee list, and there were a few 'OMG what have we done' replies.

    http://ubiety.uwaterloo.ca/~tveldhui/papers/2003/turing.pdf

  • (cs) in reply to Mcoder
    Mcoder:
    IMil:
    Wow. I was sure there's nothing C++ templates can't do, but this extends the borders of conceivable.

    Are C++ templates turing complete? Maybe we can do some calculations at compile time :)

    There is code floating around that calculates the Fibonacci sequence as compiler error messages through C++ templates.

    Of course modern compilers die after the first few errors, but you can still see it.

    Yes, templates are turing complete.

  • (cs) in reply to Someone
    Someone:
    This guy can not program C++; he doesn't even know the basics.
        template <typename T>
            void ChangeState() { if (state) delete state; state = new State<T>(); }
    

    is way too complex. It could and should just be

        template <typename T>
            void ChangeState() { delete state; state = new State<T>(); }
    

    Remember: cycles are expensive.

    Congratulations! You have entirely missed the point of this contest!

  • opello (unregistered) in reply to bob the dingo
    bob the dingo:
    Someone:
    This guy can not program C++; he doesn't even know the basics.
        template <typename T>
            void ChangeState() { if (state) delete state; state = new State<T>(); }
    

    is way too complex. It could and should just be

        template <typename T>
            void ChangeState() { delete state; state = new State<T>(); }
    

    Remember: cycles are expensive.

    Congratulations! You have entirely missed the point of this contest!

    Yeah, where's the SafeDelete function to handle only deleting when not NULL?!

  • SomeCoder (unregistered) in reply to JamesKilton
    JamesKilton:
    Mcoder:
    IMil:
    Wow. I was sure there's nothing C++ templates can't do, but this extends the borders of conceivable.

    Are C++ templates turing complete? Maybe we can do some calculations at compile time :)

    There is code floating around that calculates the Fibonacci sequence as compiler error messages through C++ templates.

    Of course modern compilers die after the first few errors, but you can still see it.

    Yes, templates are turing complete.

    Yes, I've seen that code. It's... ahem, interesting...

    That's at least one thing about C++; it lets you do whatever the hell you want. That's generally a good thing but it also means if you want to brutally commit suicide with it, you're allowed to...

  • (cs) in reply to SomeCoder
    SomeCoder:
    JamesKilton:
    Mcoder:
    IMil:
    Wow. I was sure there's nothing C++ templates can't do, but this extends the borders of conceivable.

    Are C++ templates turing complete? Maybe we can do some calculations at compile time :)

    There is code floating around that calculates the Fibonacci sequence as compiler error messages through C++ templates.

    Of course modern compilers die after the first few errors, but you can still see it.

    Yes, templates are turing complete.

    Yes, I've seen that code. It's... ahem, interesting...

    That's at least one thing about C++; it lets you do whatever the hell you want. That's generally a good thing but it also means if you want to brutally commit suicide with it, you're allowed to...

    Also known as:

    "C lets you shoot yourself in the foot, but C++ lets you reuse the bullet"

  • Waf (unregistered)

    This calc is intelligent!

    If i press "2+2=0" (equealing any calculation to 0) it recognises there's a problem and excuses for the inconvenience! There's also an obscure text of sending to Microsoft my license...

  • IV (unregistered)

    I hay have found the Windows bug!

    Enter the characters 3 + 3 + 3 + = and the result is 18. I never would have thought to do + = except for the comment (which I asume was actually supposed to mean just hitting the equals sign again.)

    It is completely reproduceable, and I think it might actually be done to specs. + = adds the number to itself, and - = subtracts it to itself.

    The real WTF is that if you do 5 + 5, then hit the + sign again, then realize you didn't want to add another number and hit =, something I can see happening to many people, you get 20. This could just be an example of bad specs.

    captcha: pirates.

  • What are they teaching kids in school these days? (unregistered)

    IV: You have not found a bug. This is how calculators WORK.

    Enter number Enter operation Enter new number, or press = to use currently displayed number.

    You'll be hard-pressed to find a calculator (outside this competition anyway) that doesn't do this.

  • Aaron (unregistered) in reply to JamesKilton

    So are C macros--there was an IOCCC winner once that did a primes test or something like that, entirely in cpp.

  • Single Male (unregistered) in reply to What are they teaching kids in school these days?
    What are they teaching kids in school these days?:
    IV: You have not found a bug. This is how calculators WORK.

    Enter number Enter operation Enter new number, or press = to use currently displayed number.

    You'll be hard-pressed to find a calculator (outside this competition anyway) that doesn't do this.

    Actually real calculator implementations vary widely in behavior. Today most cheap calculators are built using one of a small number of chips--the only difference between them being the display and key size and shape, and whether the power source is a battery or a solar cell. A decade or two ago...there was more variety.

    I remember years ago, when I carried around a briefcase + one or more calculators with me instead of a laptop case + laptop, and when there were actually a lot of calculator vendors and there was a lot of competition between them, being annoyed because there was no standardization for various behaviors between calculators, sometimes even between calculators made from the same vendor.

    It was an exciting time. It was the era when calculator vendors competed based on the number of supported functions, but stopped short of actually being programmable ("Our calculator has 2560 functions if you multiply the number of actual mathematical operators by the number of possible states of the SHIFT, CONTROL, and MODE keys and the number of display precision options! The wussy Sharp calculator only has 2359 features!!! And ours has an address book built in with space for 32 names, addresses, and phone numbers, each one no more than 27 bytes long! Buy our 1337 (a1(u1a40r, |7 r0xX0r5!!!!!!!!!!!!!!").

    Some calculators simply blink at you if you press = multiple times or without entering a number: 3 + 5 = = = gives 3, 3, 5, 8, 8, 8. 3 + 5 + = gives 3, 3, 5, 8, Err0r. These were boring calculators that sometimes also required you to press C or CE before you could start a new calculation, instead of implicitly clearing the result when you enter a number after pressing =. With this genus of calculator, you'd never have a wrong result if one of the keys started firing multiple times when you press them, a common mechanical problem that plagues all pocket calculators to some degree.

    Others repeat the last {operator, operand} tuple: 3 + 5 = = = gives 3, 3, 5, 8, 13, 18. This is quite useful if you need a series of values at some interval, or if you are multiplying instead of adding you can get a series of exponential growth calculations, like compound interest. It's a bit annoying when dust gets under the = key and you keep having to double check every result: when 3 + 5 = 18, it's time to get a new "=" key.

    Some use various special key combinations or sequences, e.g. if you wanted numbers at regular intervals, you could get the series 3, 3, 5, 8, 8, 13, 18 from the key sequence 3 + 5 = + = =. That solves the dusty key problem and allows series calculations, but I had to read the instruction manual to discover the existence of that key sequence. Intuitively I would expect the results 3, 3, 5, 8, 8, 16, {16 or 24} from that sequence.

    Another variant: 3 + 5 + + + gives the sequence 3, 3, 5, 8, 13, 18.

    Accountants and point-of-sale people had (have?) their own special kinds of calculator. Some required you to enter "3 + 5 + =" to get 8 as the final result. Others have special "+=" keys which allow you to chain together several additions (but not other operations). These don't allow sequences like "3 * 5 * 7 =" at all, you'd need to enter "3 * 5 = * 7 =", or even "3 * 5 = 15 * 7 =" (i.e. you can't use a result as an operand).

    A bit off topic, but there are RPN calculators, where 3 + 5 = = = results in the sequence 3 STACK-ERROR 5 STACK-ERROR STACK-ERROR STACK-ERROR.

    Back on topic, some calculators I've used give you an error if you don't enter a number when expected: 3 + 5 + = gives 3, 3, 5, 5, Err0r.

    I owned one calculator where it was possible to put the "=" key into at least two configurable modes. One mode repeats the last {operator, operand} pair, the other doesn't. Ho hum.

    Another would repeat the last operator with the current result as operand: 3 + 5 = = = gives 3, 3, 5, 8, 16, 32. I don't know what this could possibly be useful for--I've only seen it on one calculator. I suspect this calculator was built using some kind of hand-optimized gate array, because it only gave correct results for basic calculator functions and went into invalid states at the drop of a hat, e.g. if you pressed the 4 and 9 keys simultaneously it had to be power-cycled before it would work again. That calculator also drew something like 15 mA of power at 9V, so it could (and probably did, since that calculator died an early death) damage its own circuitry if you left it too long in an invalid state.

    In general it's not safe to make assumptions about the behavior of a calculator once you depart from a strict "clear number operator number equals" sequence.

  • Single Male (unregistered) in reply to bob the dingo
    bob the dingo:
    Someone:
    This guy can not program C++; he doesn't even know the basics.
        template <typename T>
            void ChangeState() { if (state) delete state; state = new State<T>(); }
    

    is way too complex. It could and should just be

        template <typename T>
            void ChangeState() { delete state; state = new State<T>(); }
    

    Remember: cycles are expensive.

    Congratulations! You have entirely missed the point of this contest!

    Indeed, that should have been:

        template <typename T>
            void ChangeState() { if (state) delete state; else if (state != NULL) delete state; else if (state != 0) delete state; else; state = new State<T>(); }
    
  • Chris (unregistered) in reply to Single Male
    Single Male:
    bob the dingo:
    Someone:
    This guy can not program C++; he doesn't even know the basics.
        template <typename T>
            void ChangeState() { if (state) delete state; state = new State<T>(); }
    

    is way too complex. It could and should just be

        template <typename T>
            void ChangeState() { delete state; state = new State<T>(); }
    

    Remember: cycles are expensive.

    Congratulations! You have entirely missed the point of this contest!

    Indeed, that should have been:

        template <typename T>
            void ChangeState() { if (state) delete state; else if (state != NULL) delete state; else if (state != 0) delete state; else; state = new State<T>(); }
    

    Why not

        template <typename T>
            void ChangeState() { state = new State<T>(); delete state;}
    

    You know you need a new state, and this way you don't have to see if it's allocated since you will have had at least one defined already at that point.

    I'm optimizing out the need for any safety decisions at all, but remembering to delete stuff! Can't have memory leaks =-)

  • dislyxec (unregistered)

    Anybody understand the prime factorization of this line?

    class NinetySix : public Factors<Two, Two, Factors<Two, Two, Seven> >, public After<NinetyFive> {};

  • rslite (unregistered)

    I love the Guns N'Roses reference :) Reminds me of my youthful youth.

Leave a comment on “OMGWTF Finalist #10: FerronCalc”

Log In or post as a guest

Replying to comment #:

« Return to Article