# What my entry is We all (most of us?) know about Pascal's triangle and my entry is focused on it but it creates a HTML file that generates a Pascal's triangle but on top of it is a Sierpinski triangle - and it can do much more than that. The base is Pascal's triangle but I have included a number of generated examples; one has the Sierpinski triangle on top of the Pascal's triangle. Another has the triangular numbers highlighted; another has both the Sierpinski triangle and the triangular numbers and there are various other things as well. The program itself allows for customisation even besides by way of jQuery support (but it's not restricted to jQuery - it's just the file it refers to that I included is jQuery; it can be replace with something else or simply removed) and stylesheets. There is a base stylesheet but since stylesheets can override previous stylesheets the user specified stylesheet can override whatever wanted. I have not made the default style Sierpinski because I feel that it's better to allow for it but also allow for other things without having to override it every time. Also you can certainly change the colouring scheme of the triangle as well as width and text and everything else possible with CSS and jQuery (or whatever library you choose). # Why I was looking through the summary of previous winning entries to find something that wasn't done and having not seen Pascal's triangle I thought it might be worth working on. It's not that I thought of Pascal's triangle whilst looking at the list so much as I was trying to find interesting things to do and I came across things like prime magic squares and prime arrays and prime triangle. Magic squares have been done before and although not prime specific it seemed in some way or another to me to be more limited. But then why not do Pascal's triangle instead? I found a very interesting essay on the properties of Pascal's triangle and started to like the idea even more. But at this time the design was still very limited; I hadn't thought of jQuery or even custom stylesheets just yet. Some of the things I found interesting about the Pascal's triangle from the [essay][] is that if you colour the even numbers differently from the odd numbers you get the Sierpinski triangle - a type of fractal that has not been, it seems, generated as part of another winning entry. And yet here it's the Pascal's triangle as well! But there are other properties some of which I give examples of and others I simply refer to or otherwise are seen if you go to the link(s) provided. Amongst some of the interesting properties are: * For the rows with prime numbers find the first prime and that prime number is a divisor of every number in the row. Anyone knows, too, that the IOCCC judges love primes (and I have much more to say on primes later on)! * If you add each row up in the triangle the sum is a power of 2; so for instance row 0 is 1 because 2 to the power of 0 == 1 (though it appears that in some cases `bc` disagrees it's wrong). On the subject of powers of 2 I might as well include an interesting 'trick' I discovered whilst talking (about something very different) with someone a couple years ago (as I was speaking in fact); I have this much further in this file. I make use of the fact that a number raised to the power of 0 is 1 in the obfuscation, also. * If you start with row 2 at the 1 the diagonal numbers are the triangular numbers. I have demonstrated this in the file `triangle-numbers.html` by use of one of the features I have implemented - optional jQuery scripts. It took a few minutes to figure out the pattern but once I did and once I learnt how to do what I was after in jQuery the triangular numbers are highlighted! I have also included a Sierpinski triangle that also highlights the triangular numbers. There are some other very fascinating properties. Regrettably I did not have time to implement more than the fractal and the triangular numbers but I still believe my entry is interesting and also unique; as far as I can tell nothing like this has won before at any rate. Another article exists that has more information on the 'secrets' of Pascal's triangle which can be found at [Top 10 Secrets of Pascal's Triangle][]. * Why/how this is interesting for an entry Although winning entries have generated fractals none have generated the Sierpinski triangle; furthermore no winning entry has generated Pascal's triangle. My entry does both: my entry by default generates Pascal's triangle but gives the functionality of creating the Sierpinski triangle as well (as I demonstrate). Furthermore with the many properties of Pascal's triangle as well as the customisability (stylesheet and jQuery - default library but can be replaced) it provides for a number of other possibilities just to do with Pascal's triangle but in fact there are others too (I mention some later). As I noted I also generate the triangular numbers. And although a winning entry has done something with the Fibonacci numbers these are also in Pascal's triangle as the article mentions. I feel that these alone are interesting and unique enough to consider worth entering but of course there's more. I'd have liked to implement some of the above secrets (or whatever) but I did a lot of work on some other entries and I have a very lot going on but I wanted to get something in at least; I'm pleased that I was able to get two mathematical things no previous winning entry has done (or maybe that's three now, now that I have the triangular numbers): one on top of another in this case. The fact we all love fractals and it's a fractal that's not won the contest yet along with another mathematical thing - Pascal's triangle - makes it more interesting. I also as I think I said generate the Sierpinski triangle with the triangular numbers on top of the Pascal triangle. # Obfuscation 1. Mostly global variables. 2. It certainly generates a HTML file but the best you can find of strings is a lot of gibberish. What is it all about? A spoiler might be that it's a variation of rot13. Several winning entries have used or focused on rot13 but my entry uses rot47. That's what the `char [13][72];` is: scrambled already. But what about the function that undoes the scrambling? 3. If you look at the function F() you won't likely know what it is at first glance but it's the function that works the rot47. As you can see I use octal, hexadecimal and decimal as I iterate through the `char *`. I modify the string in place which is why it's a `char [13][72];` (but some elements are accessed more than one time, see further down) but I do a number of other things too. I don't use any `#define`s because that makes for much easier reading. In '1 place' instead of using '2' I made it `pow(1,0)+1` (typecasted to an int) because as I noted previously (and I don't think nearly as many people know this) anything to the power of 0 is 1 so this means the above will evaluate to 2. In other places 1 is referred to literally. In most cases the numbers are non-decimal and instead of using ASCII literal constants I use the raw values (but since it's an algorithm specific to ASCII I see no problem with that at all). At least Clang complains about the cast to int of the function call to `pow()` (apparently it doesn't if I assign the value to another variable first) and that's why I have added the `-Wno-bad-function-cast` to the CFLAGS. But how is it called? 4. `F()` isn't called normally for sure. First observe that there are two macros: Z0 and Z1. Notice also there is a very simple function called `I`. One of the macros calls this function and the other does not. But how does it work? More correctly how is it used? It's maybe easy to see that it scans the strings and returns the index to the array of the right string where the string is passed into the function. But couldn't I just use the raw/literal index itself? I could but instead what is done is something like this: `I(K[((i))])>=0?F(K[I(K[((i))])]):""`. I.e. instead of just doing: `array[0]` for example I pass that element to the macro which calls the function that finds the index which the macro uses in the array (if not found - which shouldn't happen it'll be an empty string). One way of putting it might be that *the string I want to use is determined by the string itself!* But there are two elements in the strings array that should not be touched and in that case the Z1 macro is called. The Z1 macro is also called on any string needed again after it's been decrypted. 5. Ternary operator used in a number of places including the rot47 function; it looks like this: ` l = (*p + (int)(((0176-0x20) / (((int)pow(1,0)+1)))));`. I'll let that speak for itself :) There is also at least one nested ternary operator. 6. Swap the order of the names argc/argv in main(). Later on I thought of removing some `if`s but this was after formatting the source more than once and I didn't think it added much to the above techniques; all things considered changing something like `if (1) printf("..");` to `(1 && printf("..."));` is hardly significant to techniques #2, #3 and #4. Of course it would add to it but it got to the point I had to finish what I was doing. Even so I did change one instance of `if` to that was temporary. # Layout of the source In spirit of the maths as well as the fact the judges love primes I tried to make every 'section' a prime in some way or another. Notice the following features of the source layout: * The first `#include`s are 3 and they end at column 73. * The remaining `#include`s and the two `#define`s are 5 and they end at column 73. * The next block is 5 lines of code and also end each at column 73. * Then a block of 7 lines ending at column 73. * 11 lines and column 73. * 13 lines and column 73. * 43 lines total counting blank lines but those are part of the separation of the sections and so are part of the layout necessarily. * iocccsize is 1871. And...according to BSD `primes(6)`: $ primes 2 14 2 3 5 7 11 13 $ primes 43 44 43 $ primes 73 74 73 $ primes 1871 1872 1871 There's more though. The iocccsize is 1871, the line count is 43 and the maximum line length is 73. What is that added up? 1987. Okay and is 1987 also a prime? Yes: $ primes 1987 1988 1987 Also 3 is a prime and it's 3 different numbers added up. And if you take the `wc -l` and `wc -L` and add up the two columns as in: 43 + 73 You get (4 + 7) + (3 + 3) = 11 + 6 = 17, also a prime according to the primes program. And if you take the total above 1987, and then add to it the year, 2019, you get 4006 and then if you divide it by the year the IOCCC started, 1984, you get 2, also a prime. Finally there are 19 instances of 'prime' in this file. Certainly there are other ways to find them with these numbers but it's amazing how many primes you can find if you're creative enough even in such a small set of numbers isn't it? I do regret that the layout is not a triangle but if I think it would have made it messier unless it was rather blocky but I wanted it to not take up as much space and it also made it easier to have a primed layout. # Compiling I already mentioned one warning to disable but here are the flags I have used. Some of the warnings are only enabled by Clang -Weverything and I suspect that gcc doesn't have some of the warnings so the respective `-Wno-` options won't exist either. -Wall -Wno-missing-variable-declarations -Wno-missing-prototypes -Wno-conversion -Wno-bad-function-cast -Wno-comma -DN=26 -lm To get the -DN out of the way: it's simply a cap on rows. Can be changed but obviously large values will make for an ugly triangle and could cause other problems too. I do use `uintmax_t` but I only use `strtoul()` because I don't see why there is any need for a bigger value (Clang scan-check does not report any issues with this and I've not seen any issue nor has any warning triggered for size changes/overflows/etc.). Unfortunately there isn't an integer specific version so it's unsigned long. Also should be noted that the `strtou*()` functions silently convert negative numbers to their positive equivalent. I've not tested extremely large values so I suppose that there could be an issue with the comparison check of `n > N` but it might not be an issue since I have the type larger than the type of the conversion function. Obviously I don't expect `N` to be so huge as that'll only make the output look awful at the best of problems. As for disabling warnings: * The missing variable declarations and missing prototypes warnings are asinine as far as I am concerned; declaring them static I believe resolves the problem but I obviously don't use the variables without them being declared. And the functions are defined before their use so there's no problem there either. * The no conversion one is because of this (note that I might have had the source code in a different format or line count at the time of pasting this): prog.c:34:32: warning: implicit conversion loses integer precision: 'int' to 'char' [-Wconversion] *p=(int)l>0176?l-(int)0176-0x20:l; ~ ~~~~~~~~~~~^~~~~ prog.c:34:38: warning: implicit conversion loses integer precision: 'int' to 'char' [-Wconversion] *p=(int)l>0176?l-(int)0176-0x20:l; ~ ^ prog.c:36:14: warning: implicit conversion loses integer precision: 'int' to 'char' [-Wconversion] *p = l - (0176-0x21+1); ~ ~~^~~~~~~~~~~~~~~ prog.c:38:12: warning: implicit conversion loses integer precision: 'int' to 'char' [-Wconversion] *p = l; ~ ^ But that's because `char` is a small int; instead of using the literal constant values I'm using the raw values but as noted it's ASCII specific so there is no problem anyway. There is also a check for overflow in the function as well. * The `-Wno-bad-function-cast` is because of this: prog.c:33:44: warning: cast from function call of type 'double' to non-matching type 'int' [-Wbad-function-cast] l = (*p + (int)(((0176-0x20) / (((int)pow(1,0)+1))))); But as I already noted it seems to be because I don't use a variable first but in either case all it's doing is adding 1 + 1 for 2 only it's doing it in a way that more people do not know. Actually I have a lot of fun asking people the first few powers - making them think that they understand it - and then ask them what it would be to the power of 0. It's not what they expect but it amuses me greatly! * The `-Wno-comma` is interesting to me: I only got the warning for `-std=c90`; for C99 and C11 it didn't trigger anything (unless a different layout did maybe). Even so if it's misuse of the comma operator I'm curious what misuse of octal, hexadecimal and `pow()` looks like! :) * And the `-lm` is of course because I use the maths function `pow()`. # Portability * Requires ASCII systems. * I only have little endian machines but I don't believe there is any problem with endianness (I'm not claiming one way or another other than to say I know it works with little endian). * Built on Fedora with Clang; test it under Fedora and macOS. Works fine. # Lints Clang scan-check reports no problems at all. I won't even get into `splint` because it is far too strict and frankly defies the idea that it's perfectly valid to test if a pointer is NULL (says it's not boolean). It also detects a supposed memory leak; valgrind does not detect any at all and I don't see why it would either since I do release the memory allocated (maybe one exception: if a call to `calloc()` fails but there was already a successful allocation but then I simply return 1 from main at that point and the OS should release that memory - though I don't know how it's handled if there is a OOM situation). # Beautifiers I have tested `bcpp`, `astyle` and GNU `indent` and although they certainly break the code up so it's easier to see where you are that hardly helps with some of the techniques I have used. # Questions on output The following points come to mind on should there be any problems. The stylesheet is base.css and the following IDs and classes can be observed: First there is class `j`: if I am not mixing these up that is the column class whereas `i` is the row. Inside each `
`s (class `j`) there is one of two IDS: `odd` and `even`. These are used to mark the odd and even cells of the triangle. It only has the background colour but I can imagine that depending on the background it might be useful to have another colour for the font or there might be some other things you want depending on odd and even numbers. I have (for the Sierpinski stylesheet) the even background as lightblue and the odd background as red and it doesn't look too bad for my eyes on a white background but that too could be played with; for the base.css I don't touch the background/text colour at all. Going back to class `j`: at one point I had the width at `6em`; but when I had tested the output for 32 rows the output looked very odd. This was however before I added the viewport device-width specific stuff. I am not that good with CSS but I believe that that part should make it responsive - but I cannot confirm this with certainty. And for some time now N is less than 32. Next there is a feature in CSS that can colour the Nth item (I'm going to call it) of a list. With a little creativity I can imagine (see what I did?) that one could make all sorts of different 'art' (or whatever anyone might want to call it). Anyway it looks something like this: .j:nth-child(odd) { /* ... ; */ } .j:nth-child(even) { /* ... ; */ } The `` id is `pascal`. At one point I had added a `\n` (in the C I mean - so newline in the output) I believe it was after every element but I removed that because it added spaces in the triangle and this looked wrong to me. It seems to me that a bigger screen will allow for bigger triangles to look okay but in any case my test run I used was from 5 through the max which is now 26 (anything > 26 on my 13" laptop has an overflow problem at least with the current width specified though maybe part of that is also the browser, I don't know); note that does not mean I tested each and everyone so much as I tested a number of the numbers in the range) and as noted this is on my 13" laptop. This is my macOS system; my Fedora system has a 24" monitor but I've not used it in a long time other than for development (read I wrote the code etc. and do the invocations and I tested that on macOS too but only view them under macOS). I'm not sure if 26 is even okay with the width of each 'cell'; I cannot tell for certain with my vision I'm afraid. Either way `N` can be changed at compilation time but obviously the larger N is that fits on the screen the more you can see the beauty of the Sierpinski triangle on top of the Pascal's triangle (if you specify the stylesheet `sierpinski.css` or else do `cat sierpinski.css >> base.css`). Output looks okay on my end in Firefox, Chrome and Safari. On the other hand with N=32 depending on styles (the default base.css for example) the output sort of reminds me of a spaceship maybe even similar in the old game Asteroids (though admittedly it's been a very long time since I've played that ...). And that's another point: although it doesn't look like Pascal's triangle in full (as in not all rows) it's not to say that there aren't some interesting effects that different values of `N > 26` have on my 13" screen. One more thing: what happens if the stylesheet is missing? You get powers of 11! The first 5 rows is easy enough but for further rows you have to do some carrying to get the right number. Both documents I have cited talk about this. Anyway a 15 row triangle without any styling would look something like: 1 11 121 1331 14641 15101051 1615201561 172135352171 18285670562881 193684126126843691 1104512021025221012045101 1115516533046246233016555111 1126622049579292479249522066121 11378286715128717161716128771528678131 11491364100120023003343230032002100136491141 (And I know that that does not look like a triangle beyond first four rows but that's because it's not meant to be flat text. Even so it does demonstrate another trait of Pascal's triangle.) # Customising output But then wouldn't it be nice if there was just a base stylesheet that provided what I described but it was easy to specify not just a stylesheet that can be used to override the base.css file and in addition support JavaScript? And whilst at it why not make it jQuery capable? I thought these were very definitely worth adding: it makes it much more interesting and to those who know JavaScript and like it (I personally hate web design however ironic that might be with my entry ...) they can do even more. In order to do this I had to first de-obfuscate (in fact twice! Because I later made `