Fake the forecast

The new weather predicting supercomputer has arrived, and it doesn't work.

In the meantime your boss wants you to buy the technicians some time by faking the daily wind maps.

Your task is to draw a grid of arrows representing wind direction.

The grid is:

• made up of 15px square tiles
• 8 tiles by 8 tiles
• 120px square total
• 000 background

Each grid tile has 8 potential orientations, representing wind direction:

1. North
2. Northeast
3. East
4. Southeast
5. South
6. Southwest
7. West
8. Northwest

Which must be depicted as follows:

N NE E SE S SW W NW

The maps must vary gradually, in order to be believable.

This means each tile may only differ from its neighbour by one step. Specifically:

• A tile can only differ by one increment or decrement from each of the 4 adjoining tiles. (or 3 for side tiles, 2 for corner tiles).
• e.g. a tile with neighbour E could be NE, E or SE (assuming it accords with its other neighbours).
• Orientations can loop back around, i.e. N -> NW and NW -> N.

To illustrate, the following map is valid :

NW  N NE NE NE NE NE NE
N NE NE NE NE NE NE  E
NE NE NE NE NE NE  E SE
E NE NE NE NE  E SE  S
SE  E  E  E  E SE  S SE
S SE SE SE SE  S SE  E
SW  S  S  S  S SE  E NE
SW SW  S  S SE  E NE  N


Maps must be unique, don't generate the same map for different inputs.

• Input is an integer corresponding to the days between now and your forecast (e.g. 1 is tomorrow's forecast, 365 is a year's time).
• Output is the map as an image.
• Output should be reproducible, the same input will always give the same output
• You must give unique maps for at least 8 years - i.e. no identical output for any input between 1 and 2920 (I'm ignoring leap years).
• There is no defined output for any input greater than 2920.

The winning submission will produce valid maps (up to day 2920) with the fewest bytes of source code.

• What is the maximum input that needs to be handled? Is there any restriction on, e.g., the forecasts of two consecutive ways having to only differ by a maximum amount as well? Sep 24, 2014 at 9:50
• The maximum input that needs to be handled is 2920. There is no restriction on consecutive forecasts (except that they must be unique)
– jsh
Sep 24, 2014 at 9:54
• Oh, sorry, I must've overlooked the last bullet point. :) Sep 24, 2014 at 10:11
• Slightly off topic: Just showed this to a friend who is weather forecaster and he told me that some of those weather apps you can get aren't much better than what we are doing here, since they apparently just take the free weather data from the big airports and interpolate them, more often than not those interpolations just suck. Sep 24, 2014 at 13:16
• "The new weather predicting supercomputer has arrived, and it doesn't work." Submit it to the International Journal of Climate Science. It'll be par for the course. :P
– COTO
Sep 24, 2014 at 15:16

Matlab (182*)

It is assumed that the input is stored in n. hen looking at the algorithm, it is not sure that the results will be unique, but I checked for n=1 upto 3000 that they are unique and satisfy the rules. I basically just use complex numbers of the unit circle and 'smoothen' them by conv2 with a gaussian filter. After that they get 'rounded' to the 8 possible directions.

*I know no way how to scale the output to a certain number of pixels, so that has to be done manually=/

EDIT: I just discovered that there are cases where my checking program didn't recognise wrong solutions (changes by more than 1 step), but I am trying to find another solution.

Input:

n = 1


Code:

rand('seed',0);
for x=1:n
b = exp(1i*rand(8)*2*pi);
end
for k=1:12
b = conv2(b,[1,2,1]'*[1,2,1],'same');b=b./abs(b);
end
c = exp(1i*round(angle(b)*4/pi)*pi/4)/3;
quiver(real(c),imag(c));


• What do you mean by "scale the output to a certain number of pixels," scale the arrows, or the image? Sep 25, 2014 at 13:29
• @krs013 I mean scaling the whole image, I didn't found out yet how to do that such that it has e.g. a width of exactly 8*16 pixels. Sep 25, 2014 at 14:55

Mathematica, 116 115 bytes

f@n_:=Graphics[Array[(d=n~BitGet~#;Arrow@{1+{w=15#~Mod~8+6.5d,h=15Floor[#/8]},14+{w-13d,h}})&,64,0],ImageSize->120]


I suppose a good horse never jumps higher than it has to. 2920 different grids are very easily achieved with using only two directions (I'm using N and NE), which makes satisfying the continuity rule trivial. I'm simply choosing between N and NE based on the bits of n, so this will actually produce 264 different wind maps.

Here are the first ten maps:

PS: My original idea was to enumerate all 84 combinations for the 4 corners and "linearly" interpolation the rest of the grid. That probably would have resulted in nicer maps, but this is code golf after all, so I went with the what fulfils the minimum requirements.

• I should haved asked for 2^64+1 grids. :)
– jsh
Sep 24, 2014 at 10:49
• @jsh I'd got 8 choices for two adjacent directions. It would have made the code somewhat longer, but it would still have been similarly easy, and would allow for 2^67 unique grids. But don't worry, I think it's still a nice code golf - doing graphical output golf is hard (due to the required objectivity) and I think you've done a fairly good job with it. Sep 24, 2014 at 10:51
• I like the idea of the interpolation, but how would you have interpolated when each of the four corners would point to the center? Sep 24, 2014 at 12:58
• @MartinBüttner: Although this technically meets the spec, it does seem to be contrary to the spirit of the challenge, which is to make the map believable. Just an observation.
– COTO
Sep 24, 2014 at 15:24
• @COTO Very true, but its also code golf and not a popularity contest, and "believability" is not an objective validity criterion. Sep 24, 2014 at 15:28

PHP 5.4, 549 bytes

Somewhat hindered by the need to define arrows as graphics, here is my PHP code:

<? $i=$argv[1];$p="R0lGODdhBQAFAIAAAP///wAAACwAAAAABQAFAAAC";$a=[$p."BwRiicGsDwoAOw",$p."CEQeoLfmlhQoADs",$p."CARiF8hnmGABADs",$p."CIwDBouYvGIoADs",$p."BwRil8Gs+QoAOw",$p."CIQRYcqrnkABADs",$p."CARihscYn1YBADs",$p."CAx+Bmq6HWIBADs"];$c=[$i&7,$i>>3&7,$i>>6&7,$i>>9];$m=imagecreate(120,120);imagecolorallocate($m,255,255,255);foreach($a as$_)$z[]=imagecreatefromstring(base64_decode($_));for($y=0;$y<8;$y++)for($x=0;$x<8;$x++)imagecopy($m,$z[($c[0]*(7-$x)*(7-$y)+$c[1]*$x*(7-$y)+$c[2]*(7-$x)*$y+$c[3]*$x*$y)/49%8],$x*15+5,$y*15+5,0,0,5,5);imagepng($m);


Takes its argument from the command line, such as:

php windmap.php 123

This solution will use the input as the definition of the four corners. The rest of the map will be smoothly interpolated between values. It has defined results for all values from 0 to 4095, a grand total of ~11.25 years of fake forecast, which should be more than enough time to fix the weather software!

Here's a GIF of all the results:

(Small note: My domain recently expired because I wasn't paying attention. I've renewed it, but the above image and link may not work until the DNS updates)

Unsquishified:

<?php
$input =$argv[1];
$prefix = "R0lGODdhBQAFAIAAAP///wAAACwAAAAABQAFAAAC";$arrows = [
$prefix."BwRiicGsDwoAOw", // E$prefix."CEQeoLfmlhQoADs", // NE
$prefix."CARiF8hnmGABADs", // N$prefix."CIwDBouYvGIoADs", // NW
$prefix."BwRil8Gs+QoAOw", // W$prefix."CIQRYcqrnkABADs", // SW
$prefix."CARihscYn1YBADs", // S$prefix."CAx+Bmq6HWIBADs", // SE
];
$points = [$input & 7,
$input >> 3 & 7,$input >> 6 & 7,
$input >> 9 // input beyond 0o7777 (4095) will be undefined due to lack of & 7 here ];$img = imagecreate(120,120);
imagecolorallocate($img,255,255,255);$arrowimgs = [];
foreach($arrows as$src) {
$arrowimgs[] = imagecreatefromstring(base64_decode($src));
}
for($y=0;$y<8; $y++) { for($x=0; $x<8;$x++) {
$point = ($points[0] * (7-$x)/7 * (7-$y)/7
+ $points[1] *$x  /7 * (7-$y)/7 +$points[2] * (7-$x)/7 *$y  /7
+ $points[3] *$x  /7 *   $y /7 ) % 8; imagecopy($img,$arrowimgs[$point],$x*15+5,$y*15+5,0,0,5,5);
}
}
imagepng(\$img,"out.png");

• How does the interpolation work? Sep 25, 2014 at 11:42
• @flawr It takes an approximation of the distance to each corner and uses that as a weight for how much that corner's value should affect the current point's value. Sep 25, 2014 at 11:45
• But in this case every arrow should point to the middle in frame 1647? tinyurl.com/o7z9grl Sep 25, 2014 at 15:26
• @flawr Look down the leftmost column to see how it's "interpolating" from 7 (SE) to 1 (NE) by going through all the values 6, 5, 4, 3, 2... as opposed to the shorter "7, 0, 1" that you might expect. The algorithm isn't sophisticated enough to interpolate with rotation like that. Sep 25, 2014 at 15:31
• Ah thats how you solved it! This is really a nice, since the interpoation with '7,0,1' would have resulted in an invalid arrow field=) +1 for the arrow graphics! Sep 25, 2014 at 15:35

BBC Basic, 83 ASCII characters, tokenised filesize 72

  INPUTn:VDU23,48,516;543;4;0;23,49,783;5,9;0;0:WIDTH8FORi=1TO64PRINT;1ANDn;:n/=2NEXT


This is basically a port of Martin's concept, but the implementation in BBC basic is very different. I reprogram the font for the numbers 0 and 1 then output the binary digits of n in reverse order.

Ungolfed code is below. In BBC basic you can print individual ASCII characters using the VDU command, but the language has a series of machine-specific codes similar to escape sequences but starting with unprintable characters. For reprogramming the font, we start with ASCII 23. Normally 8-bit values are taken, but if you use a semicolon as a separator instead of a comma, it takes 16-bit little endian values (as used in the golfed version.)

  INPUTn
VDU23,48,4,2,31,2,4,0,0,0         :REM redefine font for "0" as an east facing arrow, with an 8x8 bitmap
VDU23,49,15,3,5,9,0,0,0,0         :REM redefine font for "1" as a northeast facing arrow, with an 8x8 bitmap
WIDTH8                            :REM set print width to 8 characters
FORi=1TO64PRINT;1ANDn;:n/=2:NEXT  :REM print the binary digits of n in reverse order from least significant to most significant.


Output

For the numbers 0 to 7. Note that the font is not reset at the end of the program, hence the numbers 0 and 1 appear as arrows in the first two examples.

• Nice idea! :) But are the tiles 15x15? Sep 24, 2014 at 22:21
• @MartinBüttner BBC basic allows you to redefine a font on an 8x8 grid. To keep numbers small, I did the smallest recognisable east arrow (5x5 squeezed into the top right corner of the grid) and made the most similar looking northeast arrow. In the screenmode used here, the definition has a 1:1 correspondence with pixels (and leaves an ample gap between rows) but I doubled the grid size in Windows Paint to get a better size image on SE. Some of the other screen modes in BBC basic have more than 1 pixel per grid element, and user defined characters are noticeably more grainier than regular font. Sep 24, 2014 at 22:36