13
\$\begingroup\$

Write the shortest program to forecast the weather for the next 7 days

The input (from stdin) is the weekday and the season

The output (to stdout) is seven lines weekday and the temperature in centigrade

The weekdays begin on the input weekday

The temperatures are random numbers with the range depending on the season

Spring 10 - 30 degrees  
Summer 20 - 40 degrees  
Autumn  5 - 25 degrees  (Fall is a synonym for autumn)
Winter -5 - 15 degrees

Sample Input

Thursday Winter

Sample Output

Thursday -1
Friday 3
Saturday 8
Sunday 7
Monday 10
Tuesday 10
Wednesday -1

Your program must not have identical output every time it is run with the same input

\$\endgroup\$
5
  • \$\begingroup\$ Is it sufficient that only one day has random temperatures? This way, the output won't be identical for each run. \$\endgroup\$
    – hallvabo
    Feb 3, 2011 at 14:22
  • 1
    \$\begingroup\$ Ive been thinking about tagging issues and would suggest that this a simulation of a whether forecast. \$\endgroup\$ Feb 4, 2011 at 20:51
  • \$\begingroup\$ @hallvabo, I don't intend to add any extra conditions to the question, it is what it is :) \$\endgroup\$
    – gnibbler
    Feb 5, 2011 at 6:12
  • \$\begingroup\$ FWIW: At least from the standpoint of my solution it's far easier to just generate random temperatures for each day than just for a single one. Handling all days the same is far easier and better to golf. \$\endgroup\$
    – Joey
    Feb 11, 2011 at 20:06
  • \$\begingroup\$ Is this a joke? \$\endgroup\$ Aug 5, 2011 at 2:18

10 Answers 10

8
\$\begingroup\$

Ruby 1.8, 95 characters

#!ruby -nrdate
7.times{|i|puts (Date.parse($_)+i).strftime"%A #{"\023\004\016\016\035"[$_[-3]%5]-9+rand(21)}"}

The character escapes inside the string should be replaced by the character literals they represent.

  • Found a shorter way to pack the data, Ruby 1.9 would be 4 characters longer now (add .ord after $_[-3]).
  • 112 -> 105 by stealing Joey's idea of not splitting the input.
  • 105 -> 101. Note that the first line is actually parsed by the Ruby interpreter itself, so it even works when running the solution like echo "Thursday Winter" | ruby1.8 forecast.rb
  • 101 -> 96. Stole Joey's idea again to just embed the temperatures into a string instead of an array.
  • Whoops, just noticed it should be rand(21), not rand(20).
  • 96 -> 95. Removed unnecessary whitespace.
\$\endgroup\$
4
\$\begingroup\$

Windows PowerShell, 104

[dayofweek]$d,$s=-split$input
(0..6*2)[+$d..(6+$d)]|%{''+[dayofweek]$_,((random 20)-5+'☼

↓'[$s[3]%5])}

The strings in there are a bit icky, so a hex view for your convenience:

000: 5B 64 61 79 6F 66 77 65 │ 65 6B 5D 24 64 2C 24 73  [dayofweek]$d,$s
010: 3D 2D 73 70 6C 69 74 24 │ 69 6E 70 75 74 0A 28 30  =-split$input◙(0
020: 2E 2E 36 2A 32 29 5B 2B │ 24 64 2E 2E 28 36 2B 24  ..6*2)[+$d..(6+$
030: 64 29 5D 7C 25 7B 27 27 │ 2B 5B 64 61 79 6F 66 77  d)]|%{''+[dayofw
040: 65 65 6B 5D 24 5F 2C 28 │ 28 72 61 6E 64 6F 6D 20  eek]$_,((random
050: 32 30 29 2D 35 2B 27 0F │ 00 0A 0A 19 27 5B 24 73  20)-5+'☼ ◙◙↓'[$s
060: 5B 33 5D 25 35 5D 29 7D │                          [3]%5])}

History:

  • 2011-02-04 00:16 (179) – First, straightforward attempt.
  • 2011-02-04 00:20 (155) – Why match whole season names when you can get away with individual characters and a regex match? Won't deal nicely with invalid input but that's always to be expected in Golfing.
  • 2011-02-06 13:12 (149) – Got rid of $t which only lengthened things.
  • 2011-02-10 22:50 (142) – Day name generation made simpler. I just generate a week twice, index in the correct position and pull out seven items.
  • 2011-02-10 22:52 (138) – Moving the initial cast to the declaration of $d saves a few bytes as well – and gets rid of $x.
  • 2011-02-10 23:03 (135) – Moving the cast further down the pipeline to avoid an array cast (which needs additional []). Also changed output to casting a list of objects to string which implicitly inserts a space ($OFS default).
  • 2011-02-11 20:54 (132) – Replaced the regex match by a list of character codes and indexing into a hashmap with the third character from the season.
  • 2011-02-11 21:00 (122) – Replaced the hash map by an array.
  • 2011-02-11 21:12 (117) – More array-y goodness. And shorter to boot. Modulo 8 packs the array a bit shorter.
  • 2011-02-11 21:16 (116) – Extracted a factor of five to replace 0,0,2 by 0..2 which is shorter.
  • 2011-02-11 21:22 (114) – Used a slightly different calculation. It still maps autumn and fall to the same index and has the advantage of only requiring five values. Very nice. The negative index into the string also plays very well with »Fall« being shorter than the rest.
  • 2011-02-11 21:45 (112) – Stolen Ventero's way of determining the season's temperature range which is two bytes shorter.
  • 2011-02-12 03:16 (105) – Back to 105 after a different attempt just printed a single line.
  • 2011-02-12 13:23 (104) – Back to 104 again, using a positive index into the season since I split again.

Test script (as long as it outputs nothing the result is ok):

foreach ($d in 'Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday') {
    foreach ($s in 'Winter','Summer','Spring','Autumn','Fall') {
        $o=-split("$d $s"|./weather_foo.ps1)
        if ($o.Count -ne 14) { "Wrong output length" }
        $days = $o -notmatch '\d'
        $temps = $o -match '\d'
        if ($days[0]-ne$d) { "Found "+ $days[0] + " instead of $d" }
        $m = $temps | measure -min -max
        switch ($s) {
            'Summer'{ $min = 20 }
            'Spring'{ $min = 10 }
            'Fall'  { $min = 5  }
            'Autumn'{ $min = 5  }
            'Winter'{ $min = -5 }
        }

        if ($m.Minimum -lt $min) { "Minimum temperature $($m.Minimum) didn't match for $s" }
        if ($m.Maximum -gt $min + 20) { "Maximum temperature $($m.Maximum) didn't match for $s" }
    }
}
\$\endgroup\$
3
\$\begingroup\$

Golfscript - 110 chars

' ':^/){*}*43845%7&5*:|;){*}*333121%7&:$;7,{($+'Sun Mon Tues Wednes Thurs Fri Satur'^/.+='day '+20rand|+5-+n}/
  • Fully support all the temperature ranges, seasons and also support "Fall" as synonym for "Autumn" too.
  • I think there is some rooms for improvement, but my current golfscript knowledge is limited so far.

Here is the tests, 2 passes each to confirm randomness

$ echo -n Thursday Spring | gs codegolf-404.gs
Thursday 23
Friday 28
Saturday 25
Sunday 22
Monday 19
Tuesday 14
Wednesday 25

$ echo -n Thursday Spring | gs codegolf-404.gs
Thursday 27
Friday 12
Saturday 26
Sunday 12
Monday 27
Tuesday 17
Wednesday 21


$ echo -n Friday Autumn | gs codegolf-404.gs
Friday 10
Saturday 5
Sunday 17
Monday 24
Tuesday 24
Wednesday 12
Thursday 18

$ echo -n Friday Autumn | gs codegolf-404.gs
Friday 13
Saturday 7
Sunday 14
Monday 6
Tuesday 14
Wednesday 21
Thursday 5


$ echo -n Sunday Summer | gs codegolf-404.gs
Sunday 39
Monday 31
Tuesday 35
Wednesday 34
Thursday 21
Friday 36
Saturday 28

$ echo -n Sunday Summer | gs codegolf-404.gs
Sunday 34
Monday 20
Tuesday 30
Wednesday 39
Thursday 30
Friday 31
Saturday 37


$ echo -n Monday Fall | gs codegolf-404.gs
Monday 6
Tuesday 7
Wednesday 18
Thursday 13
Friday 7
Saturday 5
Sunday 14

$ echo -n Monday Fall | gs codegolf-404.gs
Monday 16
Tuesday 22
Wednesday 19
Thursday 23
Friday 21
Saturday 9
Sunday 17


$ echo -n Saturday Winter | gs codegolf-404.gs
Saturday 0
Sunday -5
Monday 10
Tuesday -3
Wednesday -5
Thursday 13
Friday -1

$ echo -n Saturday Winter | gs codegolf-404.gs
Saturday -4
Sunday 13
Monday 11
Tuesday 0
Wednesday 0
Thursday -5
Friday 9


$ echo -n Tuesday Summer | gs codegolf-404.gs
Tuesday 38
Wednesday 29
Thursday 25
Friday 29
Saturday 34
Sunday 20
Monday 39

$ echo -n Tuesday Summer | gs codegolf-404.gs
Tuesday 33
Wednesday 26
Thursday 31
Friday 37
Saturday 39
Sunday 24
Monday 28


$ echo -n Wednesday Winter | gs codegolf-404.gs
W    ednesday 7
Thursday 12
Friday 0
Saturday -3
Sunday 11
Monday 14
Tuesday 8

$ echo -n Wednesday Winter | gs codegolf-404.gs
Wednesday 0
Thursday -1
Friday 7
Saturday 12
Sunday -5
Monday -3
Tuesday 2
\$\endgroup\$
0
2
\$\begingroup\$

D: 436 Characters

import std.algorithm, std.random, std.range, std.stdio, std.typecons;

void main(string[] g)
{
    alias canFind w;
    alias tuple t;

    auto s = g[2];
    auto e = w(s, "g") ? t(10, 30) : w(s, "Su") ? t(20, 40) : w(s, "W") ? t(-5, 15) : t(5, 25) ;
    auto r = rndGen();

    int v()
    {
        r.popFront();
        return e[0] + cast(int)(r.front % (e[1] - e[0]));
    }

    auto x = findSplitBefore(["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], [g[1]]);

    foreach(q; chain(x[1], x[0]))
        writefln("%s %s", q, v());
}

Version with extraneous whitespace removed (which is how it comes to 436 characters):

import std.algorithm,std.random,std.range,std.stdio,std.typecons;void main(string[] g){alias canFind w;alias tuple t;auto s=g[2];auto e=w(s,"g")?t(10,30):w(s,"Su")?t(20,40):w(s,"W")?t(-5,15):t(5,25);auto r=rndGen();int v(){r.popFront();return e[0]+cast(int)(r.front%(e[1]-e[0]));}auto x=findSplitBefore(["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],[g[1]]);foreach(q;chain(x[1],x[0]))writefln("%s %s",q,v());}
\$\endgroup\$
2
  • \$\begingroup\$ Surely, you can save a lot of characters just by squeezing all the newlines and indentation, and most of the other spaces, out? ;-) \$\endgroup\$ Feb 3, 2011 at 12:58
  • \$\begingroup\$ I counted the characters with all of the extra whitespace removed. It's just so hard to read that way that it seemed silly to post it that way. \$\endgroup\$ Feb 3, 2011 at 13:04
2
\$\begingroup\$

PHP, 353 319 305 304 288 characters

<?$i=split(" ",fgets(STDIN));$d=$i[0][0].$i[0][1];$s=$i[1][2];$r=json_decode('{"i":[10,30],"m":[20,40],"t":[5,25],"n":[-5,15]}',true);$n=array(Sun,Mon,Tues,Wednes,Thurs,Fri,Satur);$z=$x=0;while($z<7)if($n[++$x][0].$n[$x][1]==$d||$z){$z++;echo$n[$x%7]."day ".rand($r[$s][0],$r[$s][1])."
";}

Ungolfed

<?php
    $input = fgets(STDIN);
    $info = split(" ", $input);
    $day = substr($info[0], 0, 2);
    $season = $info[1][2];
    $range[i][] = 10;
    $range[i][] = 30;
    $range[m][] = 20;
    $range[m][] = 40;
    $range[t][] = 5;
    $range[t][] = 25;
    $range[n][] = -5;
    $range[n][] = 15;
    $days[0] = "Sun";
    $days[1] = "Mon";
    $days[2] = "Tues";
    $days[3] = "Wednes";
    $days[4] = "Thurs";
    $days[5] = "Fri";
    $days[6] = "Satur";

    $i = $d = 0;

    while($i<7)
        if(substr($days[++$d], 0, 2)==$day||$i){
            $i++;
            echo $days[$d%7]."day ".rand($range[$season][0], $range[$season][1])."\n";
        }
?>

305 -> 304: Switched the newline
304 -> 288: Uses JSON arrays instead of PHP arrays

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Does not accept Fall as a synonym for Autumn as specified in the task description. \$\endgroup\$
    – Joey
    Feb 11, 2011 at 16:56
1
\$\begingroup\$

C# 350 Characters

There must be a more efficient way than this. But here's what I've got so far:

using System;class P{static void Main(string[]x){var r=new Random();var s=x[1][2];int l=s=='r'?10:s=='m'?20:s=='n'?-5:5,u=s=='r'?31:s=='m'?41:s=='n'?16:26,i=0,z=(int)Enum.Parse(typeof(DayOfWeek),x[0]);for(;i<7;i++){var d=z<1?"Sun":z<2?"Mon":z<3?"Tues":z<4?"Wednes":z<5?"Thurs":z<6?"Fri":"Satur";Console.WriteLine(d+"day "+r.Next(l,u));z=z>5?0:z+1;}}}

Or in a more readable format, with a couple of comments:

using System;
class P 
{
    static void Main(string[] x) 
    {
        var r = new Random();
        var s = x[1][2]; //3rd char of season, first where all have unique letter

   // lower & upper limits for random, based on season
        int l = s == 'r' ? 10 : s == 'm' ? 20 : s == 'n' ? -5 : 5, 
            u = s == 'r' ? 31 : s == 'm' ? 41 : s == 'n' ? 16 : 26, 
            i = 0,
   // this line makes me cringe, but converting to an int and back seems
   // the easiest way to loop through days
            z = (int)Enum.Parse(typeof(DayOfWeek), x[0]); 

        for (; i < 7; i++) 
        { 
            var d = z < 1 ? "Sun" : z < 2 ? "Mon" : z < 3 ? "Tues" : z < 4 ? "Wednes" : z < 5 ? "Thurs" : z < 6 ? "Fri" : "Satur";
            Console.WriteLine(d + "day " + r.Next(l, u)); 
            z = z > 5 ? 0 : z + 1; // increments day, resets to 0 after saturday
        }
    }
}
\$\endgroup\$
1
  • \$\begingroup\$ C# usually needs all the help it can get, so you can replace the contents of your for loop with this (I think): Console.WriteLine(Enum.GetName(typeof(DayOfWeek), z++ % 7) + " " + r.Next(l, u)); \$\endgroup\$
    – Steve
    Feb 12, 2011 at 1:10
1
\$\begingroup\$

Javascript - 251 chars

d=['Mon','Tues','Wednes','Thurs','Fri','Satur','Sun'],g=function(c){return Math.random()*21+c|0},p=prompt();for(i=0,j=7,t=true;i<j;i++){t=t&&p.indexOf(d[i])!=0;t?j++:console.log(d[i>6?i-7:i]+'day '+g(/mm/.test(p)?20:/g/.test(p)?10:/te/.test(p)?-5:5))}

Unfortunately the script does not meet the stdin/stdout requirement but it accepts Fall as a synonym for Autumn.

Whitespaced:

  d = [
    'Mon'
  , 'Tues'
  , 'Wednes'
  , 'Thurs'
  , 'Fri'
  , 'Satur'
  , 'Sun'
  ]
, g = function(c) {
    return Math.random()*21+c|0
  }
, p = prompt()

  ;

  for(i = 0, j = 7, t = true; i < j; i++) {
    t = t && p.indexOf(d[i]) != 0; 
    t ? 
      j++ : 
      console.log(d[i > 6 ? i - 7 : i] + 'day ' + g(/mm/.test(p) ? 
                                                      20 : 
                                                    /g/.test(p) ? 
                                                      10 : 
                                                    /te/.test(p) ? 
                                                      -5 : 
                                                      5
                                                    )
                  )
  }
\$\endgroup\$
1
\$\begingroup\$

PHP - 150 Characters

<?$t=array("m"=>15,"r"=>5,"n"=>-10);for($a=split(" ",fgets(STDIN));$i<7;$i++)echo date("l ",strtotime($a[0]."+$i day")),rand(5,25)+$t[$a[1][2]],"\n";

I figured I'd write my own PHP solution after the current one doesn't even fully satisfy the challenge conditions.

It relies on strtotime to parse the day, and date to echo it back. To determine the season, it follows the third letter of the season name, which is unique (as given).

To run properly, it requires notices to be disabled and short tags to be enabled.

\$\endgroup\$
1
\$\begingroup\$

Python 2, 220 characters

A little large but (almost) readable.

import random
c,e=raw_input().split()
a=[d+'day'for d in'Mon Tues Wednes Thurs Fri Satur Sun'.split()]*2
x='rmtn'.index(e[2])*2
g=(10,30,20,40,5,25,-5,15)[x:x+2]
f=a.index(c)
for b in a[f:f+7]:
 print b,random.randint(*g)

Output

# echo "Monday Summer" | python forecast.py 
Monday 33
Tuesday 29
Wednesday 33
Thursday 28
Friday 25
Saturday 21
Sunday 30
\$\endgroup\$
0
\$\begingroup\$

Mathematica 218

s_~g~d_ := 
Grid@RotateLeft[r = Thread@{DateString[{2012, 1, #}, {"DayName"}] & /@ Range@7, 
  RandomInteger[Cases[{{"Spring", {10, 30}}, {"Summer", {20, 40}}, {"Autumn", {5, 25}}, 
  {"Winter", {-5, 15}}}, {s, _}][[1, 2]], 7]}, Position[r, d][[1, 1]] - 1]

Usage

g["Winter", "Sunday"]

enter image description here

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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