The original question is unclear. What is a 'loop' and what is a 'conditional'?
Tail-recursive calls (like the linked solution uses, though C compilers usually do not implement 'proper' tail calls) or short-cut conditionals might not look like but are still loops or conditionals.
So, why the answer is funny it does not answer the original question.
#include <stdio.h>
#define print printf("%d\n", n++);
#define times2(x) x x
#define times5(x) x x x x x
#define pow3(x,f) x(x(x(f)))
int main() {
int n = 1;
pow3(times2, pow3(times5, print));
return 0;
}
How would you do the same in other languages? It would be interesting to see the same question answered in Python, Perl, Java, etc. etc. Just as a fun thought exercise, and not to get into language flamewars.
Here's a solution in Python, using pretty much the same logic as the top vote-getter on Stack Overflow:
def f(a):
print a
print a+1
{999: int}.get(a,f)(a+2)
f(1)
Note, I had to count by twos, because when I counted by ones, I got a "maximum recursion limit exceeded" error.
Basically, the concept is to call f recursively, until you get to 999 (and had printed 999 and 1000), at which time you call some non-recursive function (I call "int").
At 999, the inner-called f function terminates, leading to the unwinding of the stack (each previous f function terminating), and then the program ends.
This statement is the hard one to understand:
{999: int}.get(a,f)(a+2)
Basically, it's saying "Look up 'a' in this hard-coded dictionary that only has one value in it - for 999. If 'a' isn't found (as it won't be most of the time), set the look-up value to the function called 'f'. Otherwise, set the look-up value to the function called 'int'. In either case, call that looked-up value, passing the parameter of a+2."
Wow, HN must have a pretty large readership. Note that before this got posted on HN today my SO score from the solution was pretty static, for weeks. All of a sudden it's sprung up 300 points.
If I learned one thing from the experience it is that often the popularity of something is not a measure of how "correct" it is. It's often a measure of the compromises you are prepared to make, and also how "appealing" it is.
FWIW, thanks HN. I actually read about the question right here in the first place!
By the way, the "correct" version was added by someone else. Posts to whoever added it.
It's an abuse of the standard (c90 and c99). main is supposed to return int and take either no arg or two args, but I think a lot of legacy code violates this, so most compilers let you off with a warning. That said, "-Wall -Werror" are two useful things to always add to your gcc invokation.
It's things like this which convince me that I am never going to pass an interview at a decent tech place. When I attempt to write solutions to things like this I make a million mistakes and can never quite get there.
My idea was to create a buffer of 1000 bytes and recursively call a function while each byte is dereferenced until it finally hits a byte which causes a segfault... but I just can't get it working.
[+] [-] RiderOfGiraffes|15 years ago|reply
Cute puzzle, nice to see some inventive torturing of C, and various dialects that people believe are C.
[+] [-] chops|15 years ago|reply
To be fair, the SO question specifies "using C or C++", not just C.
[+] [-] ctdonath|15 years ago|reply
What ever happened to the IOCCC? (International Obfuscated C Coding Contest, ioccc.org)
[+] [-] artmageddon|15 years ago|reply
The real answer is "don't work there".
[+] [-] silentbicycle|15 years ago|reply
To prepare you for the code they shouldn't realistically have in production. Oh.
[+] [-] HelloBeautiful|15 years ago|reply
, if you have to ask this question ;-)"
[+] [-] ahlatimer|15 years ago|reply
[+] [-] RodgerTheGreat|15 years ago|reply
[+] [-] zem|15 years ago|reply
[+] [-] lysium|15 years ago|reply
Tail-recursive calls (like the linked solution uses, though C compilers usually do not implement 'proper' tail calls) or short-cut conditionals might not look like but are still loops or conditionals.
So, why the answer is funny it does not answer the original question.
[+] [-] seiji|15 years ago|reply
With optimizations turned on, gcc turns a tail recursive function into the equivalent of a for loop.
[+] [-] silvajoao|15 years ago|reply
[+] [-] ajays|15 years ago|reply
[+] [-] BobKabob|15 years ago|reply
Basically, the concept is to call f recursively, until you get to 999 (and had printed 999 and 1000), at which time you call some non-recursive function (I call "int").
At 999, the inner-called f function terminates, leading to the unwinding of the stack (each previous f function terminating), and then the program ends.
This statement is the hard one to understand:
Basically, it's saying "Look up 'a' in this hard-coded dictionary that only has one value in it - for 999. If 'a' isn't found (as it won't be most of the time), set the look-up value to the function called 'f'. Otherwise, set the look-up value to the function called 'int'. In either case, call that looked-up value, passing the parameter of a+2."[+] [-] gurraman|15 years ago|reply
[+] [-] xentronium|15 years ago|reply
[+] [-] Tomek_|15 years ago|reply
[+] [-] rararational|15 years ago|reply
[+] [-] BobKabob|15 years ago|reply
[+] [-] jodrellblank|15 years ago|reply
[+] [-] die_sekte|15 years ago|reply
[+] [-] scrabbles|15 years ago|reply
[+] [-] jsmcgd|15 years ago|reply
[+] [-] 3pt14159|15 years ago|reply
[+] [-] unknown|15 years ago|reply
[deleted]
[+] [-] silentbicycle|15 years ago|reply
No stinking loops!
[+] [-] unknown|15 years ago|reply
[deleted]
[+] [-] wbhart|15 years ago|reply
If I learned one thing from the experience it is that often the popularity of something is not a measure of how "correct" it is. It's often a measure of the compromises you are prepared to make, and also how "appealing" it is.
FWIW, thanks HN. I actually read about the question right here in the first place!
By the way, the "correct" version was added by someone else. Posts to whoever added it.
[+] [-] vilya|15 years ago|reply
[+] [-] unknown|15 years ago|reply
[deleted]
[+] [-] jedbrown|15 years ago|reply
[+] [-] lysium|15 years ago|reply
[+] [-] unknown|15 years ago|reply
[deleted]
[+] [-] lysium|15 years ago|reply
[+] [-] efnx|15 years ago|reply
gcc printy.c printy.c: In function ‘main’: printy.c:4: warning: return type of ‘main’ is not ‘int’
[+] [-] oakenshield|15 years ago|reply
[+] [-] unknown|15 years ago|reply
[deleted]
[+] [-] singular|15 years ago|reply
My idea was to create a buffer of 1000 bytes and recursively call a function while each byte is dereferenced until it finally hits a byte which causes a segfault... but I just can't get it working.
The function pointer solution is genius...
[+] [-] orblivion|15 years ago|reply
#include<stdio.h>
void output(x) { int y; printf("%i\n", x); y = 1 / (1000 - x); output(x + 1); }
int main() { output(1); }
With gcc on Linux it has the added bonus of "Floating Point Exception", don't know if that disqualifies it.
EDIT: Nevermind, I got it:
#include<stdio.h>
int output(x) { printf("%i\n", x); (x >= 1000 ) || output(x + 1); return 1; }
int main() { output(1); }
[+] [-] amitraman1|15 years ago|reply
Only thing is, the interviewer would ask, "How would this work in Windows?"
[+] [-] pbhjpbhj|15 years ago|reply
Cygwin?
[+] [-] spirit23|15 years ago|reply
(function(max){ new Array(max + 1).join(' ').replace(/\s/g, function(c, i){ console.log(i + 1); }) })(1000)
[+] [-] blazer|15 years ago|reply
int main(void) { printf(" 1 2 3 4 5 6 7 8"); return 0; }
I bet that 1000 was in binary and he was obviously checking the guy's CQ ( compSci Quotient)
[+] [-] afhof|15 years ago|reply
One other mod: (j/1000) could be replaced with (j>999) which is still non conditional, but faster.
[+] [-] dchest|15 years ago|reply
[+] [-] imechura|15 years ago|reply