"Trig" or Treat

One brisk October morn' I chanced upon a discussion on feenode ##C about the The International Obfuscated C Code Contest (IOCCC) and thought it would be cool if I could carve out a pumpkin in obfuscated C. My goal was to make the program as small and simple as I could, so that I could use it as a teaching tool later on, if only to teach myself. (Teaching helps us learn). Although obfuscated code is not fit for production and otherwise atrocious it does give us some insight into the capabilities and versatility of the language.

This C program demonstrates some basic trig functions. That's why it's called, "Trig or Treat," but it's been so long I forgot what the trick is. Let's save it to a file called halloween.c and find out. To compile it, use any "C" compiler, such as the free gcc:

//gcc halloween.c -o halloween -lm

#include <math.h>
int main(i,r,c){
for(r=0;r<24;r++){
c=(int)(sinf(acosf(r/12.0-1))*24);
if(r==23)printf("Happy Halloween");else
for(i=0;i<24-c;i++)printf(" ");
for(i=0;i<2*c;i++)printf("%c",
((r>4&&r<8&&(i>6&&i<12||i>26&&i<32))||
(r>12&&r<21&&i>7&&i<2*c-8))?' ':'@');
printf("\n");}}

http:ideone.com/gKIGTr <-- click to run online

The program can also be run right off the page using a little-known trick with xsel and the Tiny C Compiler, a compiler project that I have actively contributed to over the years. I learned this trick while developing the Anchor pseudocode compiler. Simply highlight the code and type:

xsel|tcc -run -lm -

The program, when executed, produces this chillingly sinister smiley. (This guy looks like he would smile at the death of his own mother. He definitely has psychopathic tendencies).


               @@@@@@@@@@@@@@@@@@
           @@@@@@@@@@@@@@@@@@@@@@@@@@
         @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
       @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     @@@@@@@     @@@@@@@@@@@@@@@     @@@@@@
    @@@@@@@     @@@@@@@@@@@@@@@     @@@@@@@@
   @@@@@@@     @@@@@@@@@@@@@@@     @@@@@@@@@@
  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 @@@@@@@@                              @@@@@@@@
 @@@@@@@@                              @@@@@@@@
 @@@@@@@@                              @@@@@@@@
  @@@@@@@@                            @@@@@@@@
   @@@@@@@@                          @@@@@@@@
    @@@@@@@@                        @@@@@@@@
     @@@@@@@@                      @@@@@@@@
       @@@@@@@@                  @@@@@@@@
         @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
           @@@@@@@@@@@@@@@@@@@@@@@@@@
Happy Halloween@@@@@@@@@@@@@@@@@@

So, how does it work? I don't know. Like I said, I forgot, but we can analyze this by taking it apart and de-obfuscating it a little bit. The obfuscation is not that bad. I only removed extra spaces and comments. I see one trick right away. Putting i,r,c inside of main() automatically declares them as int, (but I would of course discourage the practice outside of tiny snippets for ones own use, and for the sake of discussions like these).

#include <math.h>
int main(i,r,c){
    /* for row=0 to 24 */
    for(r=0;r<24;r++){
        /* c is I guess the number of @'s */
        c=(int)(sinf(acosf(r/12.0-1))*24);
        
        /* print Halloween message */
        if(r==23)printf("Happy Halloween");
        /* number of spaces is 24-c */
        else for(i=0;i<24-c;i++) printf(" ");
        
        /* print either @ or ' ' depending on some logic */
        for(i=0;i<2*c;i++)printf("%c",
        ((r>4&&r<8&&(i>6&&i<12||i>26&&i<32))||
        (r>12&&r<21&&i>7&&i<2*c-8))?' ':'@');

        printf("\n"); /* done */
    }
}

There it is! Embedded in this code is a useful formula that I worked out years ago and wanted to save for future reference. The sinf(acosf(r/12.0-1))*24 takes the way we were taught to draw circles using sine and cosine and solves for x, so we can draw it one line at a time. The arc cosine is an inverse trigonometric function. It turns distances into angles. If we did it the other way using angles we would have had to plot it to memory first before printing it out and that would have made the program longer. Remember, I was trying to make it as small and simple as possible! Another way to plot this without using sine/cosine is to use the formula for a circle and solve. Plug it in and see. I will leave that as an exercise.

The bulk of the carving is done using one big ternary operator.


CCBY Copyright © 2016 Henry Kroll III, thenerdshow.com This web page is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.