Some fancy code

Impressive code sleuthing.

I really did not expect to EVER se that cracked, and you phVkN did it in a few hours!

You need not, ever again, refer to anyone else as a "real programmer" as if you weren't.
 
i might consider myself a "real programmer" if i can get the other ones.
ty for the complement tho :)

honestly, it's tough. i've never worked with c before. i cant figure out how to print to the screen....

i thought there was a cout in c :| if so what's teh header to include, and how is it different. if not, what's the cout equiv.in c?

Edit: nevermind, printf, huh. coming back a little bit, i've used funcs like printf before.
 
quick q for anyone still around..
what does 31[a] actually do? i took advantage of it, but that syntax means nothing to me.

Edit: for context, like this bit
_==*a?putchar(31[a])
'a' being a char*
 
he's using the pointer value as an index in to 31. remember, in C, an array reference is just a pointer. so 31 must be an address. some darke C knowledge. maybe the environment variable?
 
oh duh. it's an obfuscated way of adding 31 to a pointer address. cool. thx

i remember in the c++ tut. i read. int *a; a[5] == 5[a] == *(a+5);
 
yup, but instead of using a name (like "a") to be an address, he's just using the address, 31.

then the bastard uses an name, "a", to be the index into the array whos address is 31. since arrays evaluate to addresses, which are just numbers.
 
oh my god. all that pain. it's so simple...

I told you before: it was true. the slashes are control characters. the large string contains a series of codes that, through some method i haven't quite figured, call the second string of characters which contain the letters that actually print. Most likely from a memory offset value that's been encoded semi-randomly. Get down to it.
Code:
"!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry"
this string contains all the characters used to make the words. putchar(31[a]) references them. calling putchar(31[a+1[) would refer to the preceding character in the string, since this is not an array in as much, just values stored in memory, which means reverse order.
The next part is cool.
Code:
"@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l,+,
"On the /first/second/third/fourth/fifth/sixth/seventh/eighth
notice anything? they line up perfectly and match one-to-one. want another character? add one in. or take one out. or replace it...
still a ways from being able to change the word placement or execution, but it's probably not all that hard.
whoever thought this up is nuts...

night, folks. :D
 
WOW gj man

I want too I want too :D I'm gonna try to see if I can figure something out ..

P.S. wow .. I always knew that a[5] = *(a+5) .. but never realized it also = 5[a]
 
looks like the '/'s may be delemiters.

and hasan is joking about 5[a]... i hope
 
hmm ..
I think main gets called 69856 times .. O_O

Code:
int rlc;	/*recrusive loop count */

main(t,_,a)
char *a;
{
	rlc++;
	printf("%d \n", rlc);

I'm not sure if that would correctly count how many times main gets called .. but .. it's an attempt :p

and notice something strange .. every 20 or so steps in the list I get something like
i69577
.69852

etc ..

what could they mean? hmm .. could they be related to the
the second string of characters which contain the letters that actually print.

hmm .. I just tracked the ones that appear on the screen ..

they form the word:
"in a pea tree."

hmmm ..

P.S.
what is this char *a right after the main declaration and right before the curly bracket?! what rule does it follow?
 
kurly said:
and hasan is joking about 5[a]... i hope
actually .. no .. :bonce:

man .. I just realized that "in a pea tree" is the last thing in the string!!!!!!!!!!!1111oneone
but why the hell did it get inserted into my counter?!

anyway ..
from what I read .. the code checks for null, if it find a non-null, it prints it (I didn't track it in the code, I just figured it out from the discussion here ..)
so .. the encoding dictionary scatters the letters all over the place?! in an ordered manner, so that you can gather the string by working through the memory checking if there is a letter, if so prints it.

or anyway .. something like that.

hmmm .. :rolling:
 
i thought i was gonna sleep but i guess not :rolleyes:
kurly said:
and hasan is joking about 5[a]... i hope
hasan said:
actually .. no ..
no, he's right. using the bracket notation is just a way of performing pointer arithmetic, so a = b[a] = *(a+b)

heres the complete string
Code:
"@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l,+,/n{n+,/+#n+,/#;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){nl]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c ;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/"
"On the /first/second/third/fourth/fifth/sixth/seventh/eighth/ninth/tenth/eleventh/twelvth/ day of Christmas my true love gave to me\/twelve drummers drumming, /eleven pipers piping, /ten lords a-leaping,\/nine ladies dancing, /eight maids a-milking, /seven swans a-swimming,\/six geese a-laying, /five gold rings;\/four calling birds. /three french hens, /two turtle doves\and /a partridge in a pear tree.\\/"
and heres the decrypter string, with a newline to line it up
Code:
"!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:
\nuwloca-O;m .vpbks,fxntdCeghiry"
in one of the recursive calls, a is directed to the decrypter string, _ is directed to the other, and a is incremented until the characters in the two line up. then a recursive call (with the proper parameters to get it to the right part of the code) executes the putchar(31[a]) bit. 31 cells right of the code character is the character that gets printed...

still working on how the logic cycle get's it all in the right order. several of the 1-_ and 1+a type parameters can be changed to screw up the order..

Edit: char *a, if you are new to pointers, is a, well.. pointer.
specifically, a pointer toa char, named a. a pointer is a variable that holds a memory address. the compiler needs to know the type of data being pointed at, that's the 'char' part. if you've used arrays in java/c++, they're pointers, they just cant be directed at any other address than the one they are initialized with.
 
ok I'm stupid .. the letters there are not stored in the same memory places as my numbers .. they are just printed becuse the code is printing them :/

no, he's right. using the bracket notation is just a way of performing pointer arithmetic, so a = b[a] = *(a+b)

I know .. I'm just saying I didn't realize that b[a] == a before

:: edit ::
Edit: char *a, if you are new to pointers, is a, well.. pointer.
specifically, a pointer toa char, named a. a pointer is a variable that holds a memory address. the compiler needs to know the type of data being pointed at, that's the 'char' part. if you've used arrays in java/c++, they're pointers, they just cant be directed at any other address than the one they are initialized with.
I'm not that stupid .. :eek:

I'm saying what's char*a doing before the { ?
 
sorry, i was correcting him, not you, hasan...

jeeze. i edit like, every post. several times.
Edit: We should def. have some sort of coding competition or puzzles or something. this is fun.

Edit 2: Sorry again. I dunno what you know tho, you know? It's a global definition if it's outside a function body. maybe so the recursive functions can directly access it? i dunno.
 
heheh no prob.

I thought being between main() and { had a special meaning ..

like .. normally a global would be like this:
char *a;
main()
{

}
but he did it like this:
main() char*a
{
.
.

why did he insert th char *a between the declaration of main and its body?
 
Putting char*a between main() and its opening brace does NOT make it a global variable.

Putting char*a between main() and its opening brace does however have a special meaning. It is defining the TYPE of the parameter 'a'. If it did not do this 'a' would be given a default type (read: integer).

Observe that the following, changes, will produce the exact same output:
Code:
main(int t,int _,char*a)
//char *a;
{
The reason that he put char * after main( ), aside from adding obscuritiy, is that you can not define the types of only some of the variables in the parameter list -> its either all or none ( main(t,_, char*a) will cause an error).
 
oh duh. i thought it was outside the body. i wasn't paying attention. i just tried to put another variable decl. there and just realized i must have been talking out of my a$$. lolz.
thanks for clearin things up akrin. i had no idea anyway... :rolleyes:
 
could it be a C thing becuase well, in C you can't do this:
for(int i = 0; ......
but in C++ you can.

I noticed something ..
a is the memory position of the encrypted character ..
31[a] is the location of the dycrepted character ..

some changes based on some of my observations ...
Code:
#include<stdio.h>
#include<windows.h>

int rlc;	/*recrusive loop count */

main(t,_,a)
char *a;
{

/* sample letters and numbers taken from my loop counter thing */
/* e69838 */
/* .69852 */
/* g25463 */
/* a25328 */
/* d1726  */
/* h10847 */
	rlc++;
//	printf("%d \n", rlc); 

/* notie I substract 1 from the numbers when checking */
	

	if (rlc == 69837 || rlc == 69851 || rlc == 25462 || rlc == 25381 || rlc == 1725 || rlc == 10846)
	{
		printf("\n %d  %c  %c \n", a, *a, 31[a]);
		system("PAUSE");
	}
and the result: (arranged like this
a *a 31[a]
):
4333619 r d
4333623 , h
4333626 : y
4333622 l g
4333621 # e
4333608 ( .
:: EDIT ::
nvm you already figured that out .. :imu:
 
ok. i compiled it with env[31], and it produced identicle output.
I just didn't get the syntax. :eek:
 
hey .. there is a stupid thingy there ...

you can walk thru it step by step (sorta) by just removing the "return" .. bummer!
but I think you'll have to hit ctrl-f10 (run to cursor) rather than f10 cuz it will go assembly


:: EDIT ::

hmm .. so I'm doing this right now, and I think here is how it works:
you have two main strings: the one which has all the encrypted words, and the decrypter string. I don't know how it keeps track of their adresses .. but it does.

first: assign a to the words string .. some how it determines which word it's gonna print, takes the first letter of this word in its encrypted format, assigns a the adress of the dycrypter, find the letter in there, decrypt it by going 31 steps forward.
back to the words, get the next letter, decrypt it .. and so on and so forth.

:: EDIT ::
_ is used to store the (ascii?) or something of the current character that needs to be decrypted.
lol, actually _ is just a char.
 
i replaced the "? : " crap with if / else constructs: ezr to read and gives same output.
also serialized some of the nested main calls.
---
#include<stdio.h>

main( int argc,
int argv,
char* env ) {
char string1[512] = "@n'+,#'/*s{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l+,/n\
{n+,/+#n+,/# ;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!\
/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){nl]!\
/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' iwk{KK{nl]!/\
w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c ;;{nl'-{}rw]'/+,}##'*}\
#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/";
char string2[32] = "%s %d%d\n";
char string3[16] = "%s";
char string4[255] = "!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry";
int rc = 0;

// printf( "%d, %d, %d\n", argc, argv, env);
//for (rc=0; rc<strlen(string1); rc++)
// putchar(31[(char*)rc]);

if (argc > 1) { // 1
if (argc < 3) { // 2
rc = main( -86,
0,
env + 1
) + env;
rc = main( -87,
1 - argv,
rc );
rc = main( -79,
-13,
env + rc );
} // if 2
else { // 2
rc = 1;
} // else 2
if (argc < argv) { // 3
rc = main( argc + 1,
argv,
env );
}
else // 3
rc = 1;
rc = main(-94,
-27 + argc,
env);
if (rc &&
argc == 2) { // if 4
if (argv < 13) { // 5
rc = main( 2,
argv + 1,
string2 );
} // if 5
else // 5
rc = 9;
} // if 4
else // 4
rc = 16;
} // if 1
else { // 1
if (argc < 0) { // 2
if (argc < -72) { // 3
rc = main( argv,
argc,
string1 );
} // if 3
else { // 3
if (argc < -50) { // 4
if (argv == *env) { // 5
putchar(env[31]);
}
else { // 5
rc = main( -65,
argv,
env + 1 );
} // else 5
} // if 4
else { // 4
rc = main( (*env == '/') + argc,
argv,
env + 1 );
} // else 4
} // else 3
} // if 2
else { // 2
if (argc > 0) { // 3
rc = main( 2,
2,
string3 );
} // if 3
else { // 3
rc = *env == '/' ||
main( 0,
main( -61,
*env,
string4 ),
env + 1 );
} // else 3
} // else 2
} // else 1

return rc;
} // end main() Ha! Main! Right!


if someone can tell me how to save the indentation in a post, i'll invite them to my bar-mitzfa
---
 
the [ code ] [/ code ] tages ..

P.S. gj on the rewrite :thumbs:
 
hasan said:
lol, actually _ is just a char.

'_' can not be a char -> it is a 4 byte variable

(just put printf("%d", sizeof(_)); at the beginning of main);
 
maybe not, but I said at first that it stores the ascii code .. then I realized this is what chars do.
 
Just an interresting note if you haven't already realized:

in the piece of code (from kurly's version)
Code:
 if (argv < 13)

Replace 13 with 'X'.

This program will print out X - 1 days.
(ie. if you replace 13 with 2, it will only do the first day of the output)
 
There is some superfluous code and constants that have no reason to be at their current value.

After making the changes that concern this problem, kurly's code is refined to: (the output is the same as the original code)
Code:
#include<stdio.h>

main( int argc,int argv,char* env ) 
{
char string1[512] = "@n'+,#'/*s{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l+,/n\
{n+,/+#n+,/# ;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!\
/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){nl]!\
/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' iwk{KK{nl]!/\
w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c ;;{nl'-{}rw]'/+,}##'*}\
#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/";
char string2[32] = "%s %d%d\n";
char string3[16] = "%s";
char string4[255] = "!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry";
int rc = 0;


	if (argc > 1) 
	{
		if (argc == 2) 
		{
			rc = main( -26,0,env + 1) + env;
			rc = main( -26,	1 - argv, rc );
			rc = main( -26, -13,env + rc );
		} 

		if (argc < argv)  
			rc = main( argc + 1,argv,env );

		rc = main(-26,-27 + argc,env);

		if (argc == 2 && argv < 13) 
			rc = main( 2,argv + 1,string2 );
	} 
	else 
	{ 
		if (argc < 0) 
		{
			if (argc == -26)
				rc = main( argv,argc,string1);
			else 
			{ 
				if (argc == -27)
				{
					if (argv == *env)
						putchar(env[31]);
					else 
						rc = main( -27,argv,env + 1 );
				} 
				else
					rc = main( (*env == '/') + argc,argv,env + 1 );
			}
		} 
		else
		{
			if (argc == 1) 
				rc = main( 2,2,string3 );
			else //argc == 0
				rc = *env == '/' || main( 0, main( -27, *env, string4 ),env + 1 );
		}
	}

	return rc;
}
 
and another nested main() reduction (and practice with code tags)

here, i started trying to suggest variable names. don't think im right, but im hoping you guys can jump in and make some sense of them.
in particular, what are the magic numbers -26, and -27? text offsets?
what are the functinos of argc, argv, and env, and therefor, their propper names?

You can start to see how the flow is devided by the sign of argc.

---
Code:
#include<stdio.h>

main( int argc,int argv,char* env ) {
        char text[512]              = "@n'+,#'/*s{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l+,/n\
{n+,/+#n+,/# ;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!\
/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){nl]!\
/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' iwk{KK{nl]!/\
w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c ;;{nl'-{}rw]'/+,}##'*}\
#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/";
        char format1[16]            = "%s %d%d\n";
        char format2[4]             = "%s";
        char key[64]                = "!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry";
        int  rc                     =   0;
        const int numDays           =  13;
        const int mysteriousOffset  =  31;
        const int recursionControl  = -26; // being -2*numDays can't be coincidence
        const int recursionControl2 = recursionControl - 1; 

        if (argc > 1) 	{
		if (argc == 2) 		{
			rc = main( recursionControl,   0,        env + 1) + (int) env;
			rc = main( recursionControl,   1 - argv, (char*) rc );
			rc = main( recursionControl, -numDays,   env + rc );
                        } 
	        if (argc < argv)  
	                rc = main( argc + 1, argv, env );
	        rc = main( recursionControl, recursionControl2 + argc, env );
	        if (argc == 2 && argv < numDays) 
		        rc = main( 2, argv + 1, format1 );
                } 
        else 	{ 
	        if (argc < 0) {
			if (argc == recursionControl)
				rc = main( argv, argc, text);
			else { 
				if (argc == recursionControl2) {
					if (argv == *env)
						putchar(env[mysteriousOffset]);
					else 
						rc = main( recursionControl2, argv, env + 1 );
                                        } 
				else
					rc = main( (*env == '/') + argc, argv, env + 1 );
                                }
                        } 
		else {
			if (argc == 1) 
				rc = main( 2, 2, format2 );
                        else {
                                if (*env != '/') {
                                        rc = main( recursionControl2, *env, key );
                                        rc = main( 0,   rc,   env + 1 );
                                        }
                                }
                        }
                }

	return rc;
        }

I wont post anymore full programs... i fear i spam
 
i don't think anyone would mind. this is a coding forum, we're posting code.

besides, hardly anyone knows this forum exists, i think.

Edit: what's so mysterious about 'mysterious output'? it's just the offset from encrypted to decrypted chacter in the key. or, if it's just a name. nm...

if anyone wants, this is a decoded version of the text string:
Code:
"On the /first/second/third/fourth/fifth/sixth/seventh/eighth/n\
inth/tenth/eleventh/twelfth/ day of Christmas my true love gave to me!\
/twelve drummers drumming, /eleven pipers piping, /ten lords a-leaping,!\
/nine ladies dancing, /eight maids a-milking, /seven swans a-swimming,!/\
six geese a-laying, /five gold rings;!/four calling birds, /three fr\
ench hens, /two turtle doves!and /a partridge in a pear tree.!!/"

cypher:

"!uwloca-O;m .vpbks,fxntdCeghiry\nuwloca-O;m .vpbks,fxntdCeghiry"
i haven't tested this, i'm having some problem with my code... so thers a slight chance it wont work. it looks good though.
 
The value you have for recursiveControl and recurisveControl2 can be any value >= -26 provided that they are not equal to eachother.

In the original code, values you have associated with recursiveControl took any value less then -72, and values associated with recursiveControl2 took any value between -72 and -50.
 
do you mean <= -26?

and in my last post, where i said 'mysterious output' i meant 'mysteriousOffset' oopsie
 
Sorry, I did mean <= -26.... thnx for pointing it out phisionary.
 
Okay, another refinement of the code -> flattened out the logic a little more and noticed that the return value is always 0 so removed those pieces of the code. Here it is:

Code:
#include<stdio.h>

main( int argc,int argv,char* env ) {
char text[512]              = "@n'+,#'/*s{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l+,/n\
{n+,/+#n+,/# ;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!\
/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){nl]!\
/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' iwk{KK{nl]!/\
w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c ;;{nl'-{}rw]'/+,}##'*}\
#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/";

	char format1[16]            = "%s %d%d\n";
	char format2[4]             = "%s";
	char key[64]                = "!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry";
	const int numDays           =  13;
	const int mysteriousOffset  =  31;
	const int recursionControl  = -26; // being -2*numDays can't be coincidence
	const int recursionControl2 = recursionControl - 1; 


	if (argc == 2) 		
	{
		main( recursionControl,   0,        env + 1);
		main( recursionControl,   1 - argv, (char*) 0);
		main( recursionControl, -numDays,   env);
	} 

	if(argc > 1 && argc <= numDays)
	{
		if (argc < argv)  
			main( argc + 1, argv, env );
		
		main( recursionControl, recursionControl2 + argc, env );
	}

	if (argc == 2 && argv < numDays) 
		main( 2, argv + 1, format1 );

	if (argc == 1) 
		main( 2, 2, format2 );

	if (argc ==0) 
		if (*env != '/')
		{
			main( recursionControl2, *env, key );
			main( 0,   0,   env + 1 );
		}


	if (argc == recursionControl)
		main( argv, argc, text);

	if (argc == recursionControl2) 
	{
		if (argv == *env)
			putchar(env[mysteriousOffset]);
		else 
			main( recursionControl2, argv, env + 1 );
	} 
	if (argc < 0 && argc != recursionControl && argc != recursionControl2) 
		main( (*env == '/') + argc, argv, env + 1 );

	return 0;
}
 
so if you can decrypt the text string, can you fix the spelling error and reencrypt it? then my original challenge is met in day,

im not believing this.

i thaw this forum would be full of script kiddies. you guys are good
 
Phisionary said:
if anyone wants, this is a decoded version of the text string:
Code:
"On the /first/second/third/fourth/fifth/sixth/seventh/eighth/n\
inth/tenth/eleventh/twelfth/ day of Christmas my true love gave to me!\
/twelve drummers drumming, /eleven pipers piping, /ten lords a-leaping,!\
/nine ladies dancing, /eight maids a-milking, /seven swans a-swimming,!/\
six geese a-laying, /five gold rings;!/four calling birds, /three fr\
ench hens, /two turtle doves!and /a partridge in a pear tree.!!/"

Just one part your didn't decode -> '!' becomes '\n'.
 
Okay, here's the next level of refinement.
I've reduced a lot of the paramters to their absolute minimum.
I've collasped multi-stage recursion (that always executed in the same way) down to a single step.
I've collapsed recursively implemented loops into iterative (while) loops.
I've remove, now, unneeded variables.
I've remove the encryption step (it was trivial and not a big part of the program's logic)

Here's the code:
Code:
#include<stdio.h>

main( int argc,int argv,char* env ) {
char text[512]              = "On the /first/second/third/fourth/fifth/sixth/seventh/eighth/n\
inth/tenth/eleventh/twelfth/ day of Christmas my true love gave to me\n\
/twelve drummers drumming, /eleven pipers piping, /ten lords a-leaping,\n\
/nine ladies dancing, /eight maids a-milking, /seven swans a-swimming,\n/\
six geese a-laying, /five gold rings;\n/four calling birds, /three fr\
ench hens, /two turtle doves\nand /a partridge in a pear tree.\n\n/";

	const int numDays           =  13;
	const int recursionControl2 = -27;//recursionControl - 1; 

	//this replaces the first recusrive call -> which only serves the purpose
	// of setting argc = argv = 2 (argc was only equal to 1 on the first pass through)
	if(argc == 1)
		argc = argv =2;

	if (argc == 2) 		
	{
		main( 0, 0, text);
		main( 1-argv, 0, text);
		main( -numDays, 0, text);
	} 

	if(argc > 1 && argc <= numDays)
	{
		if (argc < argv)  
			main( argc + 1, argv, env );
		
		main(recursionControl2 + argc, 0, text );
	}

	if (argc == 2 && argv < numDays) 
		main( 2, argv + 1, 0 );

	
	//this was  formerly done by a recursively implemented loop
	while (argc < 0)
	{
		while(*env++ != '/');
		argc++;
	}
	
	//argc == 0 is the base (exit) condition for recursion
	if (argc ==0) 
		while(*env != '/')
			putchar(*env++);
	//this was formerly done by a recursively implemented loop

	return 0;
}

BTW, removing the extra recursive calls drop the total number of calls from about 69000 to 192.
 
super. the recursion was the biggest obfuscation of the whole thing.

so runing it with command line args botches the output.

LOL and you went ahead and corrected his spelling!
 
Here's a trace (from my last refinement) through all 192 recursive calls with values of argc, argv & the corresponding output (if any).
 
Another small refinement -> compressing one control block:
Code:
#include<stdio.h>
int count = 0;
main( int argc,int argv,char* env ) {
char text[512]              = "On the /first/second/third/fourth/fifth/sixth/seventh/eighth/n\
inth/tenth/eleventh/twelfth/ day of Christmas my true love gave to me\n\
/twelve drummers drumming, /eleven pipers piping, /ten lords a-leaping,\n\
/nine ladies dancing, /eight maids a-milking, /seven swans a-swimming,\n/\
six geese a-laying, /five gold rings;\n/four calling birds, /three fr\
ench hens, /two turtle doves\nand /a partridge in a pear tree.\n\n/";

	const int numDays           =  13;
	const int recursionControl2 = -27;//recursionControl - 1; 
	int x = 0;
	//this replaces the first recusrive call -> which only serves the purpose
	// of setting argc = argv = 2 (argc was only equal to 1 on the first pass through)
	if(argc == 1)
		argc = argv =2;

	if (argc == 2) 		
	{
		main( 0, 0, text);
		main( 1-argv, 0, text);
		main( -numDays, 0, text);
	} 

	if(argc > 1 && argc <= numDays)
		for(x = argv; x >= argc; x--)
			main(recursionControl2 + x, 0, text );

	if (argc == 2 && argv < numDays) 
		main( 2, argv + 1, 0 );

	
	//this was  formerly done by a recursively implemented loop
	while (argc < 0)
	{
		while(*env++ != '/');
			argc++;
	}
	
	//argc == 0 is the base (exit) condition for recursion
	if (argc ==0) 
		while(*env != '/')
			putchar(*env++);
	//this was formerly done by a recursively implemented loop

	return 0;
}

-------------------------------------------------------------------------
And now for how it works.

Okay the first time main is run the value of argc is 1 (refering to the number of command line parameters).

This is results in argc=argv = 2, argc IS NEVER 1 again.
------------------------------------------------------------
Okay, whenever the value of argc is, strictly, less than 0 the only piece of code:
Code:
	while (argc < 0)
	{
		while(*env++ != '/');
			argc++;
	}
is executed which counts |argc| '/'s in the text string.

When argc becomes 0,
Code:
 	if (argc ==0) 
		while(*env != '/')
			putchar(*env++);
prints whatever is between the last '/' encountered from above and the next one.
--------------------------------------------------------------------------

Next issue -> a control path of recursive calls exists for argc == 2.
Argc == 2 exactly 12 times.

Each time time argc == 2, two things happen:

1) the code
Code:
	if (argc == 2) 		
	{
		main( 0, 0, text);
		main( 1-argv, 0, text);
		main( -numDays, 0, text);
	}
is executed which prints out "On the <x> day of christmas..." where <x> corresponds to the current day to print out (specified by argv <= important).

2) the code
Code:
	if (argc == 2 && argv < numDays) 
		main( 2, argv + 1, 0 );
sets up the next call in the control path by keepin argc 2 and incrementing argv to the next day. (the current day is argv-1).

These two pieces of code form the control sequence for the entire program.
------------------------------------------------

The code
Code:
	if(argc > 1 && argc <= numDays)
		for(x = argv; x >= argc; x--)
			main(recursionControl2 + x, 0, text );

Creates argv-argc+1 calls where argc will be < 0, which results in a print statement. The calls will be sequenced such that the call with the highest value of argc is called first (so the third day would have sequence them -23,-24,-25).

This prints out all the items for each day.

----------------------------------------------------
That's everything.
 
you don't need to re-encrypt to fix the spelling error. once you know the way it's stored, you could do it in the original.
Code:
#include<stdio.h>
main(t,_,a)
char *a;
{
return!0<t?t<3?
main(-79,-13,a+main(-87,1-_,main(-86,0,a+1)+a)):1,t<_?main(t+1,_,a)
:3,main(-94,-27+t,a)&&t==2?_<13?main(2,_+1,"%s %d%d\n"):9:16:t<0?t<-72?
main(_,t,"@n'+,#'/*[color=red]([/color]s[color=red])[/color]{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l[color=blue]([/color],[color=blue])[/color]+,/n\
{n+,/+#n+,/#[color=red]([/color] [color=red])[/color];#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!\
/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){nl]!\
/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' iwk{KK{nl]!/\
w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c ;;{nl'-{}rw]'/+,}##'*}\
#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/")
:t<-50?_==*a?putchar(31[a]):
main(-65,_,a+1):
main((*a=='/')+t,_,a+1):
0<t?main(2,2,"%s")
:*a=='/'||main(0,main(-61,*a,
"!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry"
),a+1);
}
remove what's between the red, add what's between the blue.
(obviously the parenthesis are only there for effect).

Akrin, kurly, hasan... super job, guys. it's amazing how this thing has been transformed. very nice reformat/rewrite job. :cheers:
 
Back
Top