release winning entries of IOCCC28 under the year 2024
Congratulations to: * 2024/anders - Prize in sound coding - layered music generator * 2024/burton - Prize in pentagrammatology - wordle hard mode solver * 2024/cable1 - Prize in bot talk - LLM inference engine * 2024/cable2 - Prize in murky waters - salmon recipe * 2024/carlini - Prize in perfect timing - Intel 4004 emulation * 2024/codemeow - Prize in tray planting - bonsai generator * 2024/endoh1 - Prize in patient pointillism - slow ray tracer in CPP * 2024/endoh2 - Prize in solid body physics - rotating rigid body simulation * 2024/ferguson1 - Prize in diabolical logistics - Oregon trail pact with the devil * 2024/ferguson2 - Prize in yil-tas - Navajo code talker translator * 2024/howe - Nice accent eh-ward - mini vi * 2024/kramer - Prize in linguistic arithmetic - natural language numerical calculator * 2024/kurdyukov1 - Prize in phased periodicity - phase of the Moon * 2024/kurdyukov2 - Prize in art restoration - JPEG artifact removal * 2024/kurdyukov3 - Prize in virtual quietus - gaming VM and doom * 2024/kurdyukov4 - Prize in embiggening - encode without literals * 2024/maffiodo - Prize in creative interpretation - Jav\*script interpreter * 2024/mills - Prize in ℤ₃ - Infocom v3 story interpreter * 2024/stedolan - Best one liner - icon from MD5 * 2024/straadt - Prize in imitative rebooting - OpenRISC CPU and Linux * 2024/tmarrec - Prize in cyclonic coding - 3D tornado simulation * 2024/tompng - Prize in quasi bijection - vortex encryptor decryptor * 2024/weaver - Sur prize - rickroll Ran `make update` to perform the above. new file: 2024/burton/.entry.json
This commit is contained in:
1 parent
10512e6c79
commit
09750f8899
443 files changed
+182938
-231
No files matched your search
@@ -0,0 +1,682 @@
|
||||
/*
|
||||
* although not strictly deobfuscated it is commented to try and explain it more
|
||||
*
|
||||
* Please note that I have tried to keep this consistent with the 'final
|
||||
* product' but I had to make fixes and so some of this might be out of date.
|
||||
* Still I am trying to redo it all; but some comments might not be strictly
|
||||
* correct. In which case I hope you can then fully appreciate just how twisted
|
||||
* this code is (and you probably will anyway)!
|
||||
*
|
||||
* Also it is true that some of the variables in the code (which are in the
|
||||
* submission itself, I believe but perhaps not) are not used. This was a
|
||||
* mistake but it's not worth the effort to try and find them all, especially as
|
||||
* it can also cause confusion to people. Trying to parse the code once let
|
||||
* alone several times (which I did) was not something I wanted to repeat again.
|
||||
*
|
||||
* And on that note: there indeed might be things wrongly stated. I tried but
|
||||
* failed to completely understand what I wrote years back. I have no idea how I
|
||||
* managed some of this and I don't know what I did in every case so any
|
||||
* incorrect statements are simply a sign of the obfuscation - a good thing!
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#ifndef DICT
|
||||
#define DICT "dict"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* English -> Navajo.
|
||||
*
|
||||
* I am sorry but I can't even begin to fathom TRYING to do this again for the
|
||||
* alt code (X=1), especially as a lot of it is the same but with some subtle
|
||||
* differences.
|
||||
*/
|
||||
#define X 0
|
||||
/*
|
||||
* the struct a is the holder of state but the state is, as will be seen soon,
|
||||
* mostly anonymous. Even the function pointers array has a different order per
|
||||
* function call! The only time (I think) that there is some form of consistency
|
||||
* is the *k and *c of the struct a which is the linked list of words for either
|
||||
* deciphering (alt version with -DX=1) or enciphering (with -DX=0)
|
||||
*/
|
||||
struct a {
|
||||
/*
|
||||
* some of these are consistent if they're only used in a single function. I
|
||||
* believe this applies in particular to:
|
||||
*
|
||||
* a - for Z(), which parses main() args and acts on them - it is that
|
||||
* part of main()'s body instead of in main(), this so I could make it
|
||||
* harder to keep follow with anonymous and inconsistent ordering and
|
||||
* variables.
|
||||
* N - first field in dictionary file.
|
||||
* S - second field in dictionary file.
|
||||
* A - temporary buffer when reading in dictionary file (which S and N use).
|
||||
*
|
||||
* Like I said the order of v changes depending on the function.
|
||||
*
|
||||
* However as for S and N it's not so simple because these char *'s are not
|
||||
* directly strdup()d! Instead the function that does this, called by F()
|
||||
* but not by those names (I will explain this later) set the 's' (below) in
|
||||
* an anonymous structure to either S or N in the call. The function being
|
||||
* called in all cases (even though it does not look like it) is the same in
|
||||
* every case even though it doesn't look like it; that function is w().
|
||||
*/
|
||||
char *w, *c, *s, *x, *t, *u, **h, *S, *N, *A,*(*v[9])(struct a *), *y;
|
||||
struct a *e, *a, *z, *k, *j;
|
||||
int l;
|
||||
} *f, *c;
|
||||
/* ^ the linked list pointers - f is the list and c each node as the list is
|
||||
* created. The ->e is the next node which is why this is consistent, at least
|
||||
* in f.
|
||||
*/
|
||||
|
||||
/*
|
||||
* this is the alphabet of the language and it's translated for exact matches in
|
||||
* the alt version especially (it might be used in the encipher - regular -
|
||||
* version but I'm no longer sure of this).
|
||||
*
|
||||
* As can be seen the first element, element 0, is the letter, and the second
|
||||
* element, element 1, is the translation. The word for C for instance is MOASI
|
||||
* and it translates to 'cat'. When prog.alt encounters this it will report
|
||||
* 'cat'. If however prog encounters it it will translate the letters as it's
|
||||
* not in the dictionary. As well if prog.alt encounters something not in the
|
||||
* dictionary, say IOCCC, it will spell out the letters.
|
||||
*
|
||||
* If one does something like:
|
||||
*
|
||||
* ./prog.alt $(./prog ioccc)
|
||||
*
|
||||
* then it should print out 'ioccc' (w/o quotes of course).
|
||||
*/
|
||||
|
||||
char *B[][2] = {
|
||||
{ "A", "WOL-LA-CHEE" } , { "B", "SHUSH" } , { "C", "MOASI" } , { "D", "CHINDI" } ,
|
||||
{ "E", "DZEH" } , { "F", "CHUO" } , { "G", "JEHA" } , { "H", "TSE-GAH" } ,
|
||||
{ "I", "YEH-HES" } , { "J", "AH-YA-TSINNE" } , { "K", "BA-AH-NE-DI-TININ" } , { "L", "NASH-DOIE-TSO" } ,
|
||||
{ "M", "BE-TAS-TNI" } , { "N", "TSAH" } , { "O", "A-KHA" } , { "P", "CLA-GI-AIH" } ,
|
||||
{ "Q", "CA-YEILTH" } , { "R", "DAH-NES-TSA" } , { "S", "KLESH" } , { "T", "D-AH" } ,
|
||||
{ "U", "NO-DA-IH" } , { "V", "A-KEH-DI-GLINI" } , { "W", "GLOE-IH" } ,
|
||||
{ "X", "AL-NA-AS-DZOH" } , { "Y", "TSAH-AS-ZIH" } , { "Z", "BESH-DO-TLIZ" } ,
|
||||
} , *Y(struct a *) ;
|
||||
int z, J, C, k, H, D, s, L; size_t n, o; FILE *g;
|
||||
/*
|
||||
* these variables would not fit in the structs as they are needed in multiple
|
||||
* functions. Besides the next node of the linked list we can use the other
|
||||
* members of the struct anonymously and differently depending on the function
|
||||
* (to make it extremely hard to keep track of what is what).
|
||||
*
|
||||
* Now it would be possible to have these in as different variables but that
|
||||
* would go well beyond the size limit of rule 2!
|
||||
*
|
||||
* I will tell what these are as we encounter them.
|
||||
*/
|
||||
|
||||
char *I(struct a *a)
|
||||
{
|
||||
/*
|
||||
* okay this is truly dreadful.
|
||||
*
|
||||
* What z is set to is actually 0. That's it.
|
||||
*
|
||||
* Remember that a->z is actually a->j which is f. Well okay you can't know
|
||||
* that yet but you will.
|
||||
*/
|
||||
for (a->a = a->z, z = 0**"1"; a->a; a->a = a->a->e)
|
||||
{
|
||||
/*
|
||||
* the function called (a->v[2] (and remember a is anonymous in this
|
||||
* function, created by the calling function at time of calling it) is
|
||||
* Y(). Y() also takes a struct a * but we create it as we call the
|
||||
* function itself, just like what happened when we were called. We set
|
||||
* .w to a->a->w (a->a is the current node in the linked list) and .c to
|
||||
* a->x. But what are these?
|
||||
*
|
||||
* Well a->w is assigned (will talk about this later) the first field OR
|
||||
* second field of the dictionary depending on if we are deciphering or
|
||||
* enciphering. Of course this file is enciphering but that only adds to
|
||||
* confusion! As I see it right now, if deciphering (X==1) (which again
|
||||
* does not happen here) then it is the second field (S in that struct);
|
||||
* else it is the first field (N in that struct).
|
||||
*
|
||||
* And what was 'x'? I am sorry but I can't figure that out but I can
|
||||
* say that Y() checks if two strings are equal but ignoring !isalpha().
|
||||
* What this implies is it is either the first or second string as Y()
|
||||
* acts on exact matches of letters as noted earlier.
|
||||
*
|
||||
* Okay doing an fprintf() suggests that it is the input. For instance
|
||||
* if I were to do ./prog.alt shush the a->x is shush itself.
|
||||
*/
|
||||
if (a->v[2](&(struct a){ .w=a->a->w, .c=a->x} ))
|
||||
{
|
||||
/*
|
||||
* just to make sure we print out the stuff before in case there is
|
||||
* a non-alpha character (or characters)
|
||||
*/
|
||||
while (!isalpha(*a->x) && *(a->x)) { L=putchar(*a->x); ++a->x; }
|
||||
/*
|
||||
* okay this is also really nasty. Remember that z starts out at 0
|
||||
* and a->c is (I think!) the first field if X==1 (which is false)
|
||||
* and the second field if X==0 (enciphering mode, true). Well okay
|
||||
* so this part is not the nasty part; it's the body of the loop.
|
||||
*/
|
||||
while ((z++)[a->a->c])
|
||||
/*
|
||||
* this is truly awful. First of all remember that z starts out
|
||||
* at 0 here and we want to set 's' to something terrible. But
|
||||
* what in the world is '-*"1"-*"1"- -97? It is -1. But why do I
|
||||
* want s to be -1? Well I don't. Remember that I'm adding it to
|
||||
* s which starts out at 0. Thus the first pass this will be
|
||||
* indeed -1, second pass 0 etc. But why start out at -1 when it
|
||||
* seems like we're indexing into a->c (a char *)? This is
|
||||
* extremely nasty too.
|
||||
*
|
||||
* Let us break this down a bit more. If s is -1 the !s (will
|
||||
* end up being?) false. That means the !isupper(a->x[0**"z"])
|
||||
* will not be called the first time (or perhaps it will, I
|
||||
* don't know now). Okay but we have to back up a bit. What is
|
||||
* 0**"z"? That is 1. So what is a->x[1]? This is also very
|
||||
* ugly. I believe (but I am no longer sure!) that the calling
|
||||
* code is:
|
||||
*
|
||||
* (((*a->h[--a->l]=='e'-':')&&(*a->v)(&(struct a){ .v[0]=I,
|
||||
* .s=((a->l)[a->h])+1} ) &&++a->l)||(a->v[1](&(struct a){
|
||||
* .v[2]=Y,.x=((a->l)[a->h])} ),++a->l)); if (g) puts(""); }
|
||||
*
|
||||
* Okay actually I'm sorry. I have absolutely no idea what this
|
||||
* is. But the numbers at least can be explained. Also we can
|
||||
* break the code down more though, just not determine all the
|
||||
* values. If !s and isupper(a->x[1]) we will index a->a->c[s].
|
||||
* But when it's not we will call tolower(a->a->c[s]). Now you
|
||||
* might ask how in the world a->a->c[s] is legal on the first
|
||||
* pass. I'm sorry but once again I have no clue I just know it
|
||||
* does not evaluate to invalid indexing. Even more baffling is
|
||||
* if the index starts out at 0 (i.e. - -98 instead of - - 97),
|
||||
* the code does not work! Of course it might not be baffling at
|
||||
* all but seems that way after trying to parse this nasty nasty
|
||||
* code.
|
||||
*/
|
||||
s=z+-*"1"-*"1"- -97,L=putchar(!s&&isupper(a->x[0**"z"])?a->a->c[s]:tolower(a->a->c[s]));
|
||||
goto n;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* if we get here it means that the word is not in the dictionary. And of
|
||||
* course this is also extremely nasty, the expressions. The 2/ *"z"
|
||||
* evaluates to 0 and the 1+0**"1" evaluates to 1.
|
||||
*
|
||||
* Okay and the number[pointer] indexing is used. As noted above I believe
|
||||
* K->x is the actual input. I'll try and parse the loop but no guarantees I
|
||||
* get everything! Much of this was written years ago.
|
||||
*/
|
||||
for (z = 2/ *"z", s=1+0**"1"; z[a->x]; ++z)
|
||||
{
|
||||
/*
|
||||
* okay the first part is simple enough. For each !isalpha() char in
|
||||
* a->x we simply print the char via putchar(). Again I'm unclear what
|
||||
* a->x is however.
|
||||
*/
|
||||
if (!isalpha(z[a->x]))
|
||||
L=putchar(z[a->x]);
|
||||
else
|
||||
{
|
||||
/*
|
||||
* so C is if the current char of the current input is lower case. I
|
||||
* am not sure if we actually need to save this or not but it's
|
||||
* quite possible we do. It might just be to save bytes (or it might
|
||||
* not save bytes).
|
||||
*/
|
||||
C = islower(z[a->x]);
|
||||
/*
|
||||
* This is even nastier than before I guess.
|
||||
*
|
||||
* The first one is easy: J is set to 0 and while J < 26 and ...
|
||||
* hold on, what are we checking against now?
|
||||
*
|
||||
* Well remember that B is the letter <-> Navajo word for that
|
||||
* letter array. So B[J][0] would be the letter itself and B[J][1]
|
||||
* will be the word itself. But now we have the other horrible
|
||||
* expressions! Remember that if X (it's always 1 in this file) is
|
||||
* non-zero it's deciphering and if it's 0 it's enciphering. But
|
||||
* what is:
|
||||
*
|
||||
* 1/ *"1"+s/
|
||||
* *"1"+1/ *"1"+s/ *"1"+1+(s-s)**"1"+(s*(s-s))**"1"
|
||||
*
|
||||
* ? Well first of all let's clarify that this is actually:
|
||||
*
|
||||
* 1/ *"1"+s/ *"1"+1/ *"1"+s/ *"1"+1+(s-s)**"1"+(s*(s-s))**"1"
|
||||
*
|
||||
* Observe too how a space removed in several places will turn it
|
||||
* into a comment!
|
||||
*
|
||||
* I can try and parse some of this but I'm not really sure of all
|
||||
* of it. For instance, how is (s*(s-s)) parsed? It would appear that
|
||||
* it's s * 0 and it might very well be. Assuming that s is 0 (for
|
||||
* example) it is 1; assuming it is 1 it is ... 1? So it seems. And
|
||||
* assuming it is 2 is .... 1 again? So it seems! So how in the
|
||||
* world does this work? Well remember what we're trying to get:
|
||||
* either the first element or the second, and in this place we
|
||||
* always need 1. Let's evaluate the other part (I'm sure you can
|
||||
* figure it out though after this first one): 0! Okay but there's
|
||||
* something really sneaky here (and above): ask yourself if 's' is
|
||||
* actually incremented. Got your answer? Okay good! In fact if you
|
||||
* were to update it you will get bad answers! For instance what
|
||||
* happens if it's 2? I got 5764801. And then what if it's 0?
|
||||
* -5764801.
|
||||
*/
|
||||
for (J = *"1"-*"1"; J < 26 && B[J][X?1/ *"1"+s/
|
||||
*"1"+1/ *"1"+s/ *"1"+1+(s-s)**"1"+(s*(s-s))**"1":((((s-1)**"1")**"1")**"1")**"1"]; ++J)
|
||||
{
|
||||
/*
|
||||
* oh dear did I do it again? Yup. I did. But in this case you
|
||||
* can probably figure it out. Even so I'll evaluate these for
|
||||
* you. Yes: 0+*"1"-*"1" is 0.
|
||||
*/
|
||||
if (*B[J][0+*"1"-*"1"] == toupper(z[a->x]))
|
||||
{
|
||||
/*
|
||||
* Not again! Okay to help out let's remember s is 1. So s *
|
||||
* 2 is 2. It's the other stuff that's a nightmare.
|
||||
*
|
||||
* (s*2)**"9"-171+*"9" == 0
|
||||
*
|
||||
* And you probably want to kill me but what is:
|
||||
*
|
||||
* *"1"-49 ?
|
||||
*
|
||||
* It is 0. And since you killed me you probably now want to
|
||||
* chop me up into tiny bits but before you do that I guess
|
||||
* you want to know what s/ *"1"+s/ *"1"+1/ *"1"+(s*s*s) is?
|
||||
* That evaluates to 1.
|
||||
*/
|
||||
for (k = (s*2)**"9"-171+*"9"; H=B[J][X?*"1"-49:s/ *"1"+s/ *"1"+1/ *"1"+(s*s*s)][k]; ++k)
|
||||
putchar(C?tolower(H):toupper(H));
|
||||
/*
|
||||
* this is putchar(' ')
|
||||
*/
|
||||
L=putchar(('\0'+'!'-1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* we jumped here if a word was in the dictionary and translated, as
|
||||
* explained earlier but we also get here if we don't (obviously)
|
||||
*/
|
||||
n:
|
||||
/*
|
||||
* if the last char we pushed on the stream is a space, don't add a space
|
||||
*/
|
||||
if (!isspace(L))
|
||||
putchar(' ');
|
||||
return a->s;
|
||||
}
|
||||
|
||||
/*
|
||||
* Z() used to be the parsing of args in main() and it's also truly dreadful, I
|
||||
* know. Unfortunately I am not sure if I can explain it all but I will try.
|
||||
*/
|
||||
char *Z(struct a *a)
|
||||
{
|
||||
/*
|
||||
* it would appear that a->l was argc of main() (c) and a->h is the argv
|
||||
* (a) so the condition of the loop is going through all the args. However
|
||||
* before we can continue we need to see how this function was called:
|
||||
*
|
||||
* Z(&(struct a){ .v = { t, I } ,.k=0, .l=c, .h=a, .j=f} );
|
||||
*
|
||||
* This means that a->v[0] == t() and a->v[1] == I and a (our struct)'s l is
|
||||
* c (argc in main()) and our a->l is argv in main(). Additionally a->j is
|
||||
* the linked list of words.
|
||||
*/
|
||||
while (a->h[a->l++])
|
||||
/*
|
||||
* I() :-) no longer can parse this completely (as in I don't know all
|
||||
* of what it does) but I'll still try breaking it down a bit. I make no
|
||||
* promises however. I will break the line up to help out, though it
|
||||
* might not do that much good.
|
||||
*/
|
||||
|
||||
/*
|
||||
* first notice how where the loop condition (postfix) increments argc
|
||||
* (a->l) the body of the loop immediately decrements (prefix decrement)
|
||||
* and compares the first char of the current arg to - what? The
|
||||
* expression 'e'-':' evaluates to '+'. This is checking for file as
|
||||
* input.
|
||||
*/
|
||||
(((*a->h[--a->l]=='e'-':')&&
|
||||
/*
|
||||
* Okay remember what I said above about x->v[0] being t() ? That means
|
||||
* that this is calling t().
|
||||
*/
|
||||
(*a->v)
|
||||
/*
|
||||
* ...and here we create the anonymous struct * for t(). As you can see
|
||||
* the first function pointer in the v[] array is I(). Observe how in
|
||||
* _this_ function v[0] is a different function! In this function v->[0]
|
||||
* is t() but in this next function (t() itself!) it will be I()! But how
|
||||
* do we construct it? Well...
|
||||
*
|
||||
* The &(struct a) is important because we can't do:
|
||||
*
|
||||
* (struct a *)
|
||||
*
|
||||
* because it is an error:
|
||||
*
|
||||
* prog.c:67:41: error: initialization of non-aggregate type 'struct a *'
|
||||
* with a designated initializer list.
|
||||
*
|
||||
* (Okay the line numbers are different but you get the idea.)
|
||||
* But since we need a pointer we can use & to get the address of the
|
||||
* anonymous struct.
|
||||
*/
|
||||
(&(struct a)
|
||||
/*
|
||||
* Now the fun part! The object we create is in the {}s (of course). Each
|
||||
* field, even pointers use '.' (which as shown above is required as we
|
||||
* can't do { ->s=... } as it's also illegal and this is why we make it a
|
||||
* struct that's not a pointer and take its address to get past that
|
||||
* problem).
|
||||
*
|
||||
* Here we are saying that in the anonymous struct we're passing to t()
|
||||
* the v[0] is I() and the s (a char *) is - what? Well this is awful. Do
|
||||
* you remember that a->l is argc and a->h is argv from main()? So
|
||||
*
|
||||
* ((a->l)[a->h])
|
||||
*
|
||||
* is argv[argc]. Now the usual C programmer would point out that that is
|
||||
* NULL. But something *extremely* nasty was done before we called this
|
||||
* function. I will explain it (or rather try to) in main() but it looks
|
||||
* like this:
|
||||
*
|
||||
* F((c=((~~!!~!9u|2**"9"-15u/ *"0"-2u)<<~~!~!~9u),c&=9u,&(struct a){ .l=1, .s=a[c],.v= { &w, &w } } ));
|
||||
*
|
||||
* Remember that c in main() (or our a->l) is argc. So this horrible call
|
||||
* resets c to some value, in particular 1 though that line does a lot
|
||||
* more.
|
||||
*
|
||||
* So what this part does is, again, set OUR v[0] to I() which we are now
|
||||
* calling, remember, and set OUR s (a char *) that is a->s to beyond
|
||||
* (argv[argc])+1 (starting out with argc == 1). This also sets .j to
|
||||
* a->k which is actually - what? This is sneaky. In main() when calling
|
||||
* Z() a->j is set to f (the linked list) but here we're setting a->j (in
|
||||
* the function call) to a->k. But in main() in calling Z() a->k is set
|
||||
* to NULL! Further down though we will do .z=a->j so this might (or
|
||||
* might not) be called a red herring.
|
||||
*
|
||||
* But of course we're not done!
|
||||
*/
|
||||
{ .v[0]=I, .j=a->k, .s=((a->l)[a->h])+1} )
|
||||
/*
|
||||
* I'm sure that some people are screaming by now, if they even got this
|
||||
* far, but here we are doing something sneaky (imagine that) too.
|
||||
*
|
||||
* Remember how the loop condition incremented argc but the loop body
|
||||
* immediately decremented it (since we needed to check the first char
|
||||
* of the first arg, not the next)? Well the problem is now that we have
|
||||
* checked that we nee to get x-> (argc) incremented again, but prefix.
|
||||
*/
|
||||
&&++a->l)||
|
||||
/*
|
||||
* But of course if these (what are these? Please go back up and check, I
|
||||
* too am getting tired of trying to parse all this and I have a lot more
|
||||
* to do!) did not succeed we still have more nastiness.
|
||||
*
|
||||
* a->v[1] is I() so now main() is (or rather we, Z(), are on behalf of
|
||||
* main()) calling t with - yup, ANOTHER anonymous struct a *!
|
||||
*/
|
||||
(a->v[1](&(struct a)
|
||||
/*
|
||||
* The good news at least is you know how the struct is constructed but
|
||||
* what are we doing here and why?
|
||||
*
|
||||
* Well here we are saying that in the call to I() that v[2] is Y() (not
|
||||
* again) and x (a char *, not like x here which is a struct a *) is set
|
||||
* to the current argv[argc].
|
||||
*
|
||||
*/
|
||||
{ .v[2]=Y,.x=((a->l)[a->h]),.z=a->j}
|
||||
/*
|
||||
* this is the end of the function call but we're not actually done just
|
||||
* yet.
|
||||
*
|
||||
* Observe how we are prefix incrementing a->l again (argc in main())!
|
||||
*/
|
||||
),++a->l));
|
||||
/*
|
||||
* Okay but you might ask yourself: how come we're using the comma
|
||||
* operator here? Well because at this point although we do need to
|
||||
* call I() we also need to increment argc (a->l) yet again!
|
||||
*
|
||||
* But...why? After all the body of the loop does this! Not quite. It
|
||||
* does do this but that was on the left hand side (lhs) of the body
|
||||
* of the loop and the beginning of the body of the loop decremented
|
||||
* it! So in order to get argc back to the next one we have to
|
||||
* increment it as a side effect!
|
||||
*/
|
||||
|
||||
/*
|
||||
* we only do this because we need to return a char *; a simple return
|
||||
* 0 would also work and so would a return NULL.
|
||||
*/
|
||||
return "";
|
||||
}
|
||||
/*
|
||||
* this function is simpler though there still are some potentially confusing
|
||||
* things going on here. Yes this looks kind of like a rot13 implementation but
|
||||
* the dictionary file actually has Z -> A, Y -> B, X -> C etc. But what was r
|
||||
* formed of? Actually this is extremely sneaky.
|
||||
*/
|
||||
char *w(struct a *a)
|
||||
{
|
||||
/*
|
||||
* Okay but you might notice I did something nasty again. Okay I did
|
||||
* multiple nasty things! You probably can figure these out at least though.
|
||||
* Anyway, 1/ *"s" is 0 and 'k'-'*' evaluates, as you might have guessed, to
|
||||
* 'A'.
|
||||
*
|
||||
* That means start out at 0, go through a->s - well you get the idea. But
|
||||
* what is a->s? Well that is the dictionary file of course but that'll be
|
||||
* discussed in the respective function.
|
||||
*/
|
||||
for (D = 1/ *"s"; a && a->s && D[a->s] && (a->s[D]) &&
|
||||
(a->s[D] = isupper(a->s[D])?("ZYXWVUTSRQPONMLKJIHGFEDCBA"
|
||||
)[(a->s[D] - ('k'-'*'))]:D[a->s]); ++D) ;
|
||||
|
||||
/*
|
||||
* at one point it was possible for a to be NULL so we checked here. It
|
||||
* shouldn't be needed now though.
|
||||
*/
|
||||
return a?a->s:"";
|
||||
}
|
||||
|
||||
/*
|
||||
* this is kind of like strcasecmp() except that it ignores !isalpha(). There is
|
||||
* only one thing that might not be immediately obvious so I'll only comment on
|
||||
* that. Well okay as you'll see a->w is the first string and a->c is the
|
||||
* second. But besides that it's pretty easy.
|
||||
*/
|
||||
char *Y(struct a *a)
|
||||
{
|
||||
if (*a->w && *a->c && a->w[1] && a->c[1])
|
||||
while (*a->w && *a->c)
|
||||
{
|
||||
while (!isalpha(*a->w) && *a->w++);
|
||||
while (!isalpha(*a->c) && *a->c++);
|
||||
if (!*a->c || !*a->w || tolower(*a->w) != tolower(*a->c))
|
||||
break;
|
||||
++a->w; ++a->c;
|
||||
}
|
||||
/*
|
||||
* remember that we need to return a char * so what this does is it
|
||||
* evaluates to either a 'true' value (non NULL string) or a NULL pointer.
|
||||
* This can be checked as if an int but matching the requirement that it
|
||||
* returns a char * (for the function pointer array).
|
||||
*/
|
||||
return !*a->w&&!*a->c?"":0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function reads in the dictionary file as the first line might suggest.
|
||||
*/
|
||||
char *F(struct a *a)
|
||||
{
|
||||
g = fopen(DICT, "r");
|
||||
if (g)
|
||||
{
|
||||
/*
|
||||
* We use getline(3) even though there is the bug I mentioned in the
|
||||
* remarks file because we can have it dynamically allocate memory. It
|
||||
* stores the newline but so does fgets() and we don't really care about
|
||||
* it. In fact we do not want to remove the newline!
|
||||
*/
|
||||
while (getline(&a->A, &n, g) != -1)
|
||||
/*
|
||||
* So we were called like this:
|
||||
*
|
||||
* F((c=((~~!!~!9u|2**"9"-15u/ *"0"-2u)<<~~!~!~9u),c&=9u,&(struct a){ .l=1, .s=a[c],.v= { &w, &w } } ));
|
||||
*
|
||||
* I am not going to explain the first part until main() but the
|
||||
* second part, which can only happen by the comma operator (like in
|
||||
* other places) and which we use as we need the other thing to be
|
||||
* done first, it sets up our struct a *a's .l to 0, v[0] to &w and
|
||||
* v[1] to &w. Why both? To mislead of course!
|
||||
*/
|
||||
|
||||
/*
|
||||
* this part is easy but note how we use a->A and a->S as the first
|
||||
* and second column. They are not really needed except to have them
|
||||
* also in the struct (and even if they were not NULL we assign them
|
||||
* first).
|
||||
*/
|
||||
if ((a->N = strtok(a->A, "\t")) && (a->S = strtok(0, "\t")))
|
||||
{
|
||||
/*
|
||||
* Oh no! Not another bonkers calculation! Well fortunately you can
|
||||
* probably put together what it is but if not it evaluates to 1.
|
||||
* Basically we're allocating a struct a *.
|
||||
*/
|
||||
c = calloc(1**"0"-47, sizeof *c);
|
||||
/*
|
||||
* more fun with anonymous structs here as we populate the struct a *
|
||||
* we just created. As I might have said elsewhere if X is non-zero
|
||||
* (never true here) it means decipher and otherwise it means encipher.
|
||||
* means. But observe how c->w can be one or the other just like
|
||||
* c->c. That's because the X check is done in other places too.
|
||||
*
|
||||
* Now about these structs being created. For c->w it is a strdup()d
|
||||
* copy of the result of calling w() on either a->S or a->N.
|
||||
* Similarly we are doing the same thing (but opposite order) for
|
||||
* c->c. But hold on a moment you might think. Why then are we
|
||||
* assigning multiple values? Well actually we're not. This is just
|
||||
* the copy but both are always assigned to the w()'s struct a *'s s
|
||||
* (a char *).
|
||||
*
|
||||
* As for the function calls:
|
||||
*
|
||||
* a->l is 0 and a->e is NULL but even if it wasn't it would
|
||||
* evaluate to 1 and so a->v[a->l], a->v[a->e==0] (as 1 or 0)
|
||||
* and a->v[1] all point to w()!
|
||||
*/
|
||||
c->w = strdup(X?a->v[a->l](&(struct a){ .s=a->S} ):a->v[a->e==0](&(struct a){ .s=a->N} ));
|
||||
c->c = strdup(X?a->v[1](&(struct a){ .s=a->N} ):a->v[a->l](&(struct a){ .s=a->S} ));
|
||||
c->e = f;
|
||||
f = c;
|
||||
}
|
||||
|
||||
free(a->A);
|
||||
a->A = 0;
|
||||
fclose(g);
|
||||
g = 0;
|
||||
}
|
||||
else puts("couldn't open dict");
|
||||
return "";
|
||||
}
|
||||
|
||||
/*
|
||||
* fortunately t() is a bit easier - although you might remember the call to it
|
||||
* is not.
|
||||
*/
|
||||
char *t(struct a *a)
|
||||
{
|
||||
/*
|
||||
* this assigns o with 0
|
||||
*/
|
||||
o = *"";
|
||||
g = fopen(a->s, "r");
|
||||
a->A = 0;
|
||||
while (g && getline(&a->A, &o, g) != -1)
|
||||
{
|
||||
/*
|
||||
* the usual suspect: we're using a->S as a temporary value for strtok()
|
||||
* to extract the first field (space or tab delimited)
|
||||
*/
|
||||
a->S = strtok(a->A, " \t");
|
||||
while (a->S)
|
||||
/*
|
||||
* strdup() is useful here
|
||||
*/
|
||||
if ((a->y=strdup(a->S))) {
|
||||
/*
|
||||
* if a token was found then we will call a->v[0] which is I don't
|
||||
* even know; I'm really tired doing this and I have more to parse
|
||||
* for you - sorry! Anyway in that function v[2] will be Y() and w
|
||||
* will be S (the token we extracted).
|
||||
*/
|
||||
(*a->v)(&(struct a){ .v[2]=Y, .x=a->y} );
|
||||
/*
|
||||
* get next token for this line
|
||||
*/
|
||||
a->S = strtok(0, " \t"); free(a->y); a->y=0;
|
||||
|
||||
/*
|
||||
* if the last char we pushed on the stream is a space
|
||||
* don't add a space
|
||||
*/
|
||||
if (L!='\n')putchar(' ');
|
||||
}
|
||||
}
|
||||
if(g) { clearerr(g); fclose(g); g = 0; free(a->A); a->A= 0; }
|
||||
return "";
|
||||
}
|
||||
|
||||
/*
|
||||
* Good news: we've reached the last function!
|
||||
*
|
||||
* Bad news: it's also dreadful, really dreadful!
|
||||
*/
|
||||
int main(int c, char **a)
|
||||
{
|
||||
/*
|
||||
* Do I have to try and parse this? Okay well I did explain in one function
|
||||
* (F() itself) the second half but I did not explain the first half so I'll
|
||||
* try here.
|
||||
*
|
||||
* Remember how I said (I think I said anyway) that argc is set to 1? Well
|
||||
* that is because:
|
||||
*
|
||||
* ((~~!!~!9u|2**"9"-15u/ *"0"-2u)<<~~!~!~9u)
|
||||
*
|
||||
* evaluates to 113 and 113 & 9 is 1. The other parts are just a
|
||||
* distraction.
|
||||
*
|
||||
* Notice the double {} there (that's not the only place this occurs though
|
||||
* I think).
|
||||
*/
|
||||
F((c=((~~!!~!9u|2**"9"-15u/ *"0"-2u)<<~~!~!~9u),c&=9u,&(struct a){ .l=1, .s=a[c],.v= { &w, &w } } ));
|
||||
/*
|
||||
* This was the one that processes the args. It is not a hard call to deal
|
||||
* with (the function Z() itself is of course): call Z() with an anonymous
|
||||
* struct a * with v[0] == t(), v[1] == I(), l == c (argc), a == a
|
||||
* (argv) and k == 0 (NULL) and j == f (linked list of words)
|
||||
*/
|
||||
Z(&(struct a){ .v = { t, I } ,.k=0, .l=c, .h=a, .j=f} );
|
||||
puts("");
|
||||
/*
|
||||
* Now go have some good chocolate or some great pie! You deserve it!
|
||||
*/
|
||||
}
|
||||
Reference in new issue
Block a user