15
\$\begingroup\$

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 N NE NE E E SE SE S S SW SW W W NW 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.

\$\endgroup\$
  • \$\begingroup\$ 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? \$\endgroup\$ – Ingo Bürk Sep 24 '14 at 9:50
  • \$\begingroup\$ The maximum input that needs to be handled is 2920. There is no restriction on consecutive forecasts (except that they must be unique) \$\endgroup\$ – jsh Sep 24 '14 at 9:54
  • \$\begingroup\$ Oh, sorry, I must've overlooked the last bullet point. :) \$\endgroup\$ – Ingo Bürk Sep 24 '14 at 10:11
  • 8
    \$\begingroup\$ 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. \$\endgroup\$ – flawr Sep 24 '14 at 13:16
  • 2
    \$\begingroup\$ "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 \$\endgroup\$ – COTO Sep 24 '14 at 15:16
4
\$\begingroup\$

BBC Basic, 83 ASCII characters, tokenised filesize 72

Download emulator at http://www.bbcbasic.co.uk/bbcwin/bbcwin.html

  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. enter image description here

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ Nice idea! :) But are the tiles 15x15? \$\endgroup\$ – Martin Ender Sep 24 '14 at 22:21
  • \$\begingroup\$ @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. \$\endgroup\$ – Level River St Sep 24 '14 at 22:36
23
\$\begingroup\$

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));

vector field

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ What do you mean by "scale the output to a certain number of pixels," scale the arrows, or the image? \$\endgroup\$ – krs013 Sep 25 '14 at 13:29
  • \$\begingroup\$ @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. \$\endgroup\$ – flawr Sep 25 '14 at 14:55
15
\$\begingroup\$

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:

enter image description here

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.

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ I should haved asked for 2^64+1 grids. :) \$\endgroup\$ – jsh Sep 24 '14 at 10:49
  • \$\begingroup\$ @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. \$\endgroup\$ – Martin Ender Sep 24 '14 at 10:51
  • \$\begingroup\$ I like the idea of the interpolation, but how would you have interpolated when each of the four corners would point to the center? \$\endgroup\$ – flawr Sep 24 '14 at 12:58
  • 4
    \$\begingroup\$ @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. \$\endgroup\$ – COTO Sep 24 '14 at 15:24
  • 2
    \$\begingroup\$ @COTO Very true, but its also code golf and not a popularity contest, and "believability" is not an objective validity criterion. \$\endgroup\$ – Martin Ender Sep 24 '14 at 15:28
5
\$\begingroup\$

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:

Hot air!

And a ZIP containing each map can be downloaded here

(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");
|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ How does the interpolation work? \$\endgroup\$ – flawr Sep 25 '14 at 11:42
  • \$\begingroup\$ @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. \$\endgroup\$ – Niet the Dark Absol Sep 25 '14 at 11:45
  • \$\begingroup\$ But in this case every arrow should point to the middle in frame 1647? tinyurl.com/o7z9grl \$\endgroup\$ – flawr Sep 25 '14 at 15:26
  • 1
    \$\begingroup\$ @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. \$\endgroup\$ – Niet the Dark Absol Sep 25 '14 at 15:31
  • \$\begingroup\$ 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! \$\endgroup\$ – flawr Sep 25 '14 at 15:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.