top | item 2322913

Stack Overflow: Printing 1 to 1000 in C

284 points| numeromancer | 15 years ago |stackoverflow.com

97 comments

order
[+] RiderOfGiraffes|15 years ago|reply
... without conditionals.

Cute puzzle, nice to see some inventive torturing of C, and various dialects that people believe are C.

[+] chops|15 years ago|reply
and various dialects that people believe are C.

To be fair, the SO question specifies "using C or C++", not just C.

[+] ctdonath|15 years ago|reply
"nice to see some inventive torturing of C"

What ever happened to the IOCCC? (International Obfuscated C Coding Contest, ioccc.org)

[+] artmageddon|15 years ago|reply
My favorite response:

The real answer is "don't work there".

[+] silentbicycle|15 years ago|reply
A comment on the question says: "Why do interview questions always want you to write code that you shouldn't realistically write in application?"

To prepare you for the code they shouldn't realistically have in production. Oh.

[+] HelloBeautiful|15 years ago|reply
>> The real answer is "don't work there

, if you have to ask this question ;-)"

[+] lysium|15 years ago|reply
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.

[+] seiji|15 years ago|reply
though C compilers usually do not implement 'proper' tail calls

With optimizations turned on, gcc turns a tail recursive function into the equivalent of a for loop.

[+] silvajoao|15 years ago|reply

  #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;
  }
[+] ajays|15 years ago|reply
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.
[+] BobKabob|15 years ago|reply
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."
[+] gurraman|15 years ago|reply
An Erlang solution:

    f() -> f(1).
    f(1001) -> ok;
    f(N) -> io:fwrite("~p~n", [N]), f(N + 1).
[+] xentronium|15 years ago|reply
Will this count for solution? :)

    MAX = 1000

    def execute_if_not_equals(value, other, &block)
      noop = lambda {}
      [block, noop][value / other].call
    end

    def print(i)
      execute_if_not_equals(i, MAX) do
        puts(i + 1)
        print(i + 1)
      end
    end

    print(0)

[edit]: updated to not use != operator which is probably a cheat.
[+] Tomek_|15 years ago|reply
Javascript, validity depends on how exactly do you define conditions and loops:

  var items = [];
  var rec = function(item) {
      var func = [];
      func[true] = function(item) { items.push(item); [item-1].map(rec); };
      func[false] = function(item) {};
      return func[Boolean(item)](item);
  };
  var item = [1000];
  item.map(rec);
  console.log(items.reverse().join(','));
Won't do in browsers due to recurssion limit but change [1000] to [10] and you'll see it works.
[+] rararational|15 years ago|reply
Does this fit the criteria for python:

    print str(range(1,1001)).strip('[]').replace(', ','\n')
Edit: added missing [ as pointed out below
[+] BobKabob|15 years ago|reply
How about this Python solution:

    z="0123456789"
    print map(lambda x:int("".join(x))+1,zip(sorted(zip(*z)[0]*100),
              sorted(zip(*z)[0]*10)*10,
              zip(*z)[0]*100))
Only downside is that it prints as a list (so it has the format of [1,2,3..])
[+] die_sekte|15 years ago|reply
Haskell:

    mapM_ (putStrLn . show) [1..1000]
[+] scrabbles|15 years ago|reply
Is there a better way than this for scheme (racket)?

  (map (lambda (n)
       (displayln n))
     (cdr (build-list 1001 values)))
[+] jsmcgd|15 years ago|reply
Clojure: (map println (range 1 1001))
[+] 3pt14159|15 years ago|reply
1.upto 1000 {|n| puts n} # ruby ftw
[+] wbhart|15 years ago|reply
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.

[+] vilya|15 years ago|reply
Just because I haven't seen it mentioned yet, here's a solution using gcc's computed goto feature:

  #include <cstdio>
  int main(int argc, char** argv) {
    void* labels[2] = { &&doing, &&done };
    int i = 1;
  doing:
    printf("%d\n", i++);
    goto *labels[i / 1001];
  done:
    return 0;
  }
Still consider goto harmful? (Well yeah, so do I generally. But hey...)
[+] unknown|15 years ago|reply

[deleted]

[+] jedbrown|15 years ago|reply
In what sense do these lack conditionals?
[+] lysium|15 years ago|reply
IMHO, `&&` and `try` are conditionals, even if they lack the word `if`. :-)
[+] unknown|15 years ago|reply

[deleted]

[+] lysium|15 years ago|reply
How is 'goto repeat' not a loop? You've just 'spelled out' a for-loop, I think. :-)
[+] efnx|15 years ago|reply
I just learned a little more about C thanks to this. Compiling does cause a warning, though:

gcc printy.c printy.c: In function ‘main’: printy.c:4: warning: return type of ‘main’ is not ‘int’

[+] oakenshield|15 years ago|reply
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.
[+] singular|15 years ago|reply
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.

The function pointer solution is genius...

[+] orblivion|15 years ago|reply
I'd say:

#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
My favorite is: system("/usr/bin/seq 1000");

Only thing is, the interviewer would ask, "How would this work in Windows?"

[+] pbhjpbhj|15 years ago|reply
>the interviewer would ask, "How would this work in Windows?"

Cygwin?

[+] blazer|15 years ago|reply
Well, what do you think about

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
Obvious, but passing arguments to this will cause it to break.

One other mod: (j/1000) could be replaced with (j>999) which is still non conditional, but faster.

[+] dchest|15 years ago|reply
Well, just move the logic into its own function.

        #include <stdio.h>
        #include <stdlib.h>

        void pr(int j) {
                printf("%d\n", j);
                (pr + (exit - pr)*(j/1000))(j+1);
        }

        int main(int argc, char** argv) {
                pr(1);
                return 0;
        }