0
#include <stdio.h>
#include <stdlib.h>
main() {
    int j, u[23] = {0};
    while (!u[19]) {
        while (u[j = rand() % 23]++)
            ;
        putchar("uatChks rteJ r hon,\neca"[j]);
    }
}

Is an obfuscated piece of code meant to print

Just another C hacker,

It works in two different online compilers/interpreters I've tried (ideone.com and codepad.org) but not when I run it with GCC.

When I build it and run it using GCC, it prints:

,cthehasok tre anu

On my computer, I am building it with this command:

gcc C:\Programming\c\JACH.c -o JACH

I think the problem is to do with the rand() function, and maybe the RAND_MAX macro:

In my compiler, RAND_MAX is defined as 32767, whereas on ideone.com, it is 2147483647. I'm not sure if that actually has anything to do with it, but I'm convinced that rand() is the problem, after running tests such as this:

srand(0);
int i;
for (i=1;i<4;i++) {
    printf("%d: %d\n", i, rand() % 23);
}

This code produced very different results across compilers,

gcc:

1: 15
2: 14
3: 9

ideone.com:

1: 11
2: 0
3: 6

Does anyone know how I can force my compiler to provide the same results as ideone.com/online compilers?

theonlygusti
  • 11,032
  • 11
  • 64
  • 119
  • 4
    I'm not sure you can depend on `rand()` being the same implementation across systems. – JS1 Dec 02 '14 at 19:26
  • @JS1 OK, is there any way I can test that though? – theonlygusti Dec 02 '14 at 19:29
  • @JS1 Yes, I see your point, but how can I test/fix it? – theonlygusti Dec 02 '14 at 19:36
  • 1
    You can test it with a simple program that prints the first few `rand()` results. I know you always get the same sequence from `rand()` on one machine if you don't seed it (that's useful for testing), but remember - it's a random number generator. See this previous question http://stackoverflow.com/questions/1026327/what-common-algorithms-are-used-for-cs-rand – Weather Vane Dec 02 '14 at 20:09

1 Answers1

1

A linear congruential generator is a simple way of generating pseudorandom numbers, and can be implemented using very little code.

In fact, if you use one that generates a sequence of maximal length, then there's no need to check for values that have already been returned because it will generate each value once before repeating.

This code will work on any system, and since it doesn't rely on any library calls except for putchar(), it will always produce the same output. The while() loop will exit when j has returned to its original value of zero:

#include <stdio.h>
int main() {
  int j=0;
  while (putchar("\nae ,hhtr tseCouk nJcra"[j=(j*93+19)%23]) && j);
  return 0;
}

Update

The number sequence you provided (1804289383, 846930886, 1681692777, 1714636915) shows that ideone uses the GLIBC random number generator, which calculates random numbers from a pool of 34 integers initialized based on a seed value.

If you use the default seed value of 1 (not zero, which is actually disallowed and changed to 1 internally), then the initialization phase can be omitted altogether and you end up with this function:

int default_rand() {
  static unsigned int i=3, r[34] = { 0xf3bec5da, 0x991539b1, 0x16a5bce3, 0x6774a4cd,
             0x55928aca, 0xc34a51a2, 0x73b5def3, 0x3e01511e, 0x4e508aaa, 0x61048c05,
             0xf5500617, 0x846b7115, 0x6a19892c, 0x896a97af, 0xdb48f936, 0x14898454,
             0x37ffd106, 0xb58bff9c, 0x59e17104, 0xcf918a49, 0x09378c83, 0x52c7a471,
             0x8d293ea9, 0x1f4fc301, 0xc3db71be, 0x39b44e1c, 0xf8a44ef9, 0x4c8b80b1,
             0x19edc328, 0x87bf4bdd, 0xc9b240e5, 0xe9ee4b1b, 0x4382aee7, 0x535b6b41 };
  i = (i+1) % 34;
  return (r[i] = r[(i+3)%34] + r[(i+31)%34]) >> 1;
}

You can verify for yourself that this function generates exactly the same numbers as successive calls to rand() after calling srand(0) or srand(1) (ideone link).

Community
  • 1
  • 1
r3mainer
  • 23,981
  • 3
  • 51
  • 88
  • Can you create a linear congruential generator that generates these numbers in order: 1804289383, 846930886, 1681692777, 1714636915 when seeded with 0, in the same way `rand()` does on ideone.com? – theonlygusti Jan 10 '15 at 12:58
  • @theonlygusti Those numbers aren't generated by a linear congruential generator. [Use the code on this page instead.](http://www.mscs.dal.ca/~selinger/random/) – r3mainer Jan 10 '15 at 13:52
  • Could you add that link to your answer and provide an example of it, maybe as a function that can be used in the same way as rand()? – theonlygusti Jan 10 '15 at 13:55
  • Wow, thanks! I didn't know about the `srand` requirements either, but this works, just what I needed! – theonlygusti Jan 11 '15 at 10:05