48
\$\begingroup\$

Background

The Royal Netherlands Meteorological Institute defines a heat wave* as a series of at least 5 consecutive days of ≥25°C weather (“summery weather”), such that at least 3 of those days are ≥30°C (“tropical weather”).

The tropical weather doesn't have to be measured consecutively: for example: 30, 25, 30, 26, 27, 28, 32, 30 is a 8-day long heat wave with 4 days of tropical weather.

*(Well, by Dutch standards.)

Challenge

Given a non-empty list of positive integers representing Celsius temperature measurements from successive days, decide whether that list contains a heat wave (as per the above definition).

The shortest answer in bytes wins.

Test cases

Falsey:

[30]
[29, 29, 29, 47, 30]
[31, 29, 29, 28, 24, 23, 29, 29, 26, 27, 33, 20, 26, 26, 20, 30]
[23, 31, 29, 26, 30, 24, 29, 29, 25, 27, 24, 28, 22, 20, 34, 22, 32, 24, 33]
[23, 24, 25, 20, 24, 34, 28, 32, 22, 20, 24]
[24, 28, 21, 34, 34, 25, 24, 33, 23, 20, 32, 26, 29, 29, 25, 20, 30, 24, 23, 21, 27]
[26, 34, 21, 32, 32, 30, 32, 21, 34, 21, 34, 31, 23, 27, 26, 32]
[29, 24, 22, 27, 22, 25, 29, 26, 24, 24, 20, 25, 20, 20, 24, 20]
[23, 33, 22, 32, 30]
[28, 21, 22, 33, 22, 26, 30, 28, 26, 23, 31, 22, 31, 25, 27, 27, 25, 28]
[27, 23, 42, 23, 22, 28]
[25, 20, 30, 29, 32, 25, 22, 21, 31, 22, 23, 25, 22, 31, 23, 25, 33, 23]

Truthy:

[30, 29, 30, 29, 41]
[1, 1, 25, 30, 25, 30, 25, 25, 25, 25, 25, 25, 25, 25, 40, 1, 1]
[31, 34, 34, 20, 34, 28, 28, 23, 27, 31, 33, 34, 29, 24, 33, 32, 21, 34, 30, 21, 29, 22, 31, 23, 26, 32, 29, 32, 24, 27]
[26, 29, 22, 22, 31, 31, 27, 28, 32, 23, 33, 25, 31, 33, 34, 30, 23, 26, 21, 28, 32, 22, 30, 34, 26, 33, 20, 27, 33]
[20, 31, 20, 29, 29, 33, 34, 33, 20]
[25, 26, 34, 34, 41, 28, 32, 30, 34, 23, 26, 33, 30, 22, 30, 33, 24, 20, 27, 23, 30, 23, 34, 20, 23, 20, 33, 20, 28]
[34, 23, 31, 34, 34, 30, 29, 31, 29, 21, 25, 31, 30, 29, 29, 28, 21, 29, 33, 25, 24, 30]
[22, 31, 23, 23, 26, 21, 22, 20, 20, 28, 24, 28, 25, 31, 31, 26, 33, 31, 27, 29, 30, 30]
[26, 29, 25, 30, 32, 28, 26, 26, 33, 20, 21, 32, 28, 28, 20, 34, 34]
[34, 33, 29, 26, 34, 32, 27, 26, 22]
[30, 31, 23, 21, 30, 27, 32, 30, 34, 29, 21, 31, 31, 31, 32, 27, 30, 26, 21, 34, 29, 33, 24, 24, 32, 27, 32]
[25, 33, 33, 25, 24, 27, 34, 31, 29, 31, 27, 23]
\$\endgroup\$
  • 2
    \$\begingroup\$ Is the temperature guaranteed to be below 100 Celsius? \$\endgroup\$ – FryAmTheEggman Apr 23 '18 at 21:38
  • 3
    \$\begingroup\$ @FryAmTheEggman Well, in the Netherlands, yes :), but I don't want your answer to abuse this fact, so no. \$\endgroup\$ – Lynn Apr 24 '18 at 6:42
  • 1
    \$\begingroup\$ @HatWizard Yes, that’s okay. “Crash / don’t crash” is also fine, for example. \$\endgroup\$ – Lynn Jun 11 '18 at 14:43
  • 2
    \$\begingroup\$ Hey @Lynn this was a great challenge and still is :-) \$\endgroup\$ – Roland Schmitz Jun 19 '18 at 20:01
  • 1
    \$\begingroup\$ @RolandSchmitz Thank you! I'm happily surprised by the creative answers that came out of it so late into the challenge's lifetime. 🎉 \$\endgroup\$ – Lynn Jun 20 '18 at 8:25

44 Answers 44

2
\$\begingroup\$

K (ngn/k), 38 32 30 bytes

{+/7<,/4_'*\'|:',\+/x>/:24 29}

Try it online!

\$\endgroup\$
2
\$\begingroup\$

[JavaScript (ES6)], 49 bytes

a=>a.reduce((b,c)=>b>0&c<25?1:b*(c<30?2:6)%864,1)

Try it online!

The arrow function returns 0 for a heatwave or >0 else.

(Port of the Swift solution to JavaScript)

How does if work? Each sequence of numbers is iterated with a reduce operation starting at the reduce value 1. If a number >= 25 is seen the reduce is multiplied by 2. If a number >= 30 is seen the reduce is multiplied by 2 and by 3 = 6. If a number < 25 is seen the reduce starts again at 1. If the reduce is divisible by 864=2*2*2*2*2*3*3*3 then a heatwave is found, and the result of the modulo operation is 0 which results in a reduce value of 0. Only when a heat wave was found the reduce can become 0. Once the reduce value is 0 it will be 0 for all future reduces, i.e. also for the end result.

\$\endgroup\$
  • \$\begingroup\$ Nice! Even one byte less compared to the Swift solution. \$\endgroup\$ – Roland Schmitz Jun 11 '18 at 18:40
2
\$\begingroup\$

Java (JDK 10), 60 bytes

h->h.stream().reduce(1,(r,v)->r*25>r*v?1:r*(v<30?2:6)%864)<1

(-1 byte thanks Lynn: replaced r>0&&v<25 with r*25>r*v)

h->h.stream().reduce(1,(r,v)->r>0&&v<25?1:r*(v<30?2:6)%864)<1

The lambda expression returns true for a heatwave or false else.

Thanks to the magic number 864 and to Udo Borkowski and Mathis for their ideas.

How does if work? Each sequence of numbers is iterated with a reduce operation starting at the reduce value 1. If a number >= 25 is seen the reduce is multiplied by 2. If a number >= 30 is seen the reduce is multiplied by 2 and by 3 = 6. If a number < 25 is seen the reduce starts again at 1. If the reduce is divisible by 864=2*2*2*2*2*3*3*3 then a heatwave is found, and the result of the modulo operation is 0 which results in a reduce value of 0 and in a return value of true.

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Ruby, 50 48 bytes

->a{b=1;a.any?{|r|1>b=[b*2,1,b*6][5<=>r/5]%864}}

Try it online!

Thanks to Roland Schmitz and Udo Borkowski for the idea and the magic number 864. And again to Roland for saving 2 bytes.

\$\endgroup\$
  • \$\begingroup\$ This is a great solution, especially the part with the spaceship and the negative array index. \$\endgroup\$ – Roland Schmitz Jun 15 '18 at 5:34
  • \$\begingroup\$ You could save 2 more bytes by rearranging and combining the expressions of the inner lambda: ->a{b=1;a.any?{|r|1>b=[b*2,1,b*6][5<=>r/5]%864}} \$\endgroup\$ – Roland Schmitz Jun 15 '18 at 6:14
  • \$\begingroup\$ Thanks for the idea with the any{} operation, which gave me -16 Bytes in the Kotlin solution \$\endgroup\$ – Roland Schmitz Jun 15 '18 at 22:06
1
\$\begingroup\$

Perl 5 -pa, 52 bytes

map{$_<25?$w=$h=0:$w++;$h+=$_>29;$\|=$w>4&&$h>2}@F}{

Try it online!

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

Java 8, 91 bytes

h->{int e=0,a=0,t=0;for(int i:h)t=(e=i<25?0:e+1)>4&(a=i<25?0:i<30?a:a+1)>2?1:t;return t>0;}

Hopefully we'll have a heat wave here in The Netherlands soon, since it's currently 13 °C again (even though it was 24 °C this weekend..)

Try it online.

Explanation:

h->{              // Method with integer-array parameter and boolean return-type
  int e=0,        //  Amount of subsequent 25+ days, starting at 0
      a=0,        //  Amount of 30+ days in the current 'heat wave', starting at 0
      t=0;        //  Result-flag, starting at 0
  for(int i:h)    //  Loop over the input-array
    t=            //   Change the flag to:
      (e=i<25?    //    If the current temperature is below 25 °C
          0       //     Reset `e` to 0
         :        //    Else (temperature is 25+ °C):
          e+1)    //     Increase `e` by 1
       >4         //    Validate if `e` is at least 5 now
      &(a=i<25?   //    If the current temperature is below 25 °C
           0      //     Reset `a` to 0
          :i<30?  //    Else if the current temperature is [25,29] °C
           a      //     Leave `a` the same
          :       //    Else (temperature is 30+ °C):
           a+1)   //     Increase `a` by 1
       >2?        //    Validate if `a` is at least 3 now:
                  //    If there is a 'heat wave':
        1         //     Change the flag `t` to 1 
       :          //    Else:
        t;        //     Leave the flag `t` unchanged
  return t>0;}    //  Return whether the flag `t` is 1 now
\$\endgroup\$
1
\$\begingroup\$

J, 35 bytes

1#.(1,2~:/\24<])(2<1#.29<]*4<#);.1]

Try it online!

Returns 0 for Falsy and positive integer for Truthy

I feel it's too descriptive, so it's certainly golfable.

Explanation:

I split x u;.1 ythe input list of values into sublists that are smaller or greater/equal to 25. x is a binary mask denoting the intervals, y is the input list

(1,2~:/\24<]) finds if each item is greater or equal to 25; then marks the boundaries of the intervals and prepends 1 to the list for the start.

    (1,2~:/\24<]) 1 1 25 30 25 30 25 25 25 25 25 25 25 25 40 1 1
1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0

    ((1,2~:/\24<])<;.1]) 1 1 25 30 25 30 25 25 25 25 25 25 25 25 40 1 1
┌───┬──────────────────────────────────────┬───┐
│1 1│25 30 25 30 25 25 25 25 25 25 25 25 40│1 1│
└───┴──────────────────────────────────────┴───┘

(2<1#.29<]*4<#) Checks if the length # of the sublist is at least 5 and sets all items to 0 if not by multiplying the list by the result of the check; then checks if there are 3 or more items that are greater or equal to 30.

   ((1,2~:/\24<])(2<1#.29<]*4<#);.1]) 1 1 25 30 25 30 25 25 25 25 25 25 25 25 40 1 1
0 1 0

1#. adds up the partial results

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

><>, 64 bytes

00>l3(?^$:1+{:64*)?v~~~~
  ^<v?)4:+1$~$?)+fe<
)?v^>$:@2
;n<   0<

Keeps track of the current number of summer days and tropical days, resets when a regular day is encountered. For every summer day it checks if the requirements for a heat wave is met.

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

Julia 0.6, 49 bytes

T->reduce((x,y)->y>24?(2+4(y>29))x%864:x>0,1,T)<1

Try it online!

The popular reduce solution from Udo Borkowski. The final <1 limits the output to true/false. We can remove it for 47 bytes, but the output will then be either false or 0 (varying) for, well, false, and a non-zero number for true.

Alternate version (equivalent) based on G B's Ruby implementation (1 byte longer):

T->(x=1;any(y->(x=y>24?(2+4(y>29))x%864:x>0)<1,T))

Try it online!

Explanation for either version:

function u_explained(temps)
  x = 1
  for y in temps
    if y > 24
      val = 2 + (y > 29 ? 4 : 0) #2 for 25 to 29, 6 for 30 and above
      x = val * x 
      #If we've reached 5 "summery" days (2^5) of which at least 3 are
      # "tropical" (3^3), then x will be a multiple of 2^5*3^3
      # If we've reached there, make x 0. Else, keep as is.
      x = x % 864
    else
      #found non-summery day, reset non-zero values into 1 (true), but keep 0 as 0 (false)
      x = x > 0
    end
  end
  return x == 0
end

Older solution:

75 bytes

T->(l=endof(T))>4&&any(prod(1+sign(T[i:j]÷5-5))>7 for i=1:l-4 for j=i+4:l)

Try it online!

(+13 bytes to fix buggy behaviour for test cases 2 and 9)

Julia port of Jonathan Allan's brilliant Jelly solution. Probably not optimal, I just found the method used so neat that I had to try it.

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

APL(NARS), 100 char, 200 bytes

∇r←f w;c;C;k;i;x
r←i←c←C←0⋄k←≢w
→0×⍳k<i+←1⋄→3×⍳∼25>x←i⊃w⋄c←C←0⋄→2
c+←1⋄C+←x≥30⋄→2×⍳∼(c≥5)∧C≥3
r←1
∇

I find useful traslate program construct if() with "→LineNumber×⍳∼" test:

  f¨(,30)(29,29,29,47,30)(31,29,29,28,24,23,29,29,26,27,33,20,26,26,20,30)(23,31,29,26,30,24,29,29,25,27,24,28,22,20,34,22,32,24,33)(23,24,25,20,24,34,28,32,22,20,24)(24,28,21,34,34,25,24,33,23,20,32,26,29,29,25,20,30,24,23,21,27)(26,34,21,32,32,30,32,21,34,21,34,31,23,27,26,32)(29,24,22,27,22,25,29,26,24,24,20,25,20,20,24,20)(23,33,22,32,30)(28,21,22,33,22,26,30,28,26,23,31,22,31,25,27,27,25,28)(27,23,42,23,22,28)(25,20,30,29,32,25,22,21,31,22,23,25,22,31,23,25,33,23)
0 0 0 0 0 0 0 0 0 0 0 0 
  f¨(30,29,30,29,41)(1,1,25,30,25,30,25,25,25,25,25,25,25,25,40,1,1)(31,34,34,20,34,28,28,23,27,31,33,34,29,24,33,32,21,34,30,21,29,22,31,23,26,32,29,32,24,27)(26,29,22,22,31,31,27,28,32,23,33,25,31,33,34,30,23,26,21,28,32,22,30,34,26,33,20,27,33)(20,31,20,29,29,33,34,33,20)(25,26,34,34,41,28,32,30,34,23,26,33,30,22,30,33,24,20,27,23,30,23,34,20,23,20,33,20,28)(34,23,31,34,34,30,29,31,29,21,25,31,30,29,29,28,21,29,33,25,24,30)(22,31,23,23,26,21,22,20,20,28,24,28,25,31,31,26,33,31,27,29,30,30)(26,29,25,30,32,28,26,26,33,20,21,32,28,28,20,34,34)(34,33,29,26,34,32,27,26,22)(30,31,23,21,30,27,32,30,34,29,21,31,31,31,32,27,30,26,21,34,29,33,24,24,32,27,32)(25,33,33,25,24,27,34,31,29,31,27,23)
1 1 1 1 1 1 1 1 1 1 1 1 

If it is better I write less test space someone say that to me...

\$\endgroup\$
  • \$\begingroup\$ Why do you localise your variables? The program will certainly work without ;c;C;k;i;x \$\endgroup\$ – Adám Feb 17 at 17:20
  • \$\begingroup\$ They are local v \$\endgroup\$ – RosLuP Feb 18 at 22:57
  • \$\begingroup\$ @Adám They are local variables, if they are defined out that function, and are not declared local in the function, I suppose they could change what not have to change (a variable out the function) \$\endgroup\$ – RosLuP Feb 18 at 23:05
  • \$\begingroup\$ So what? This is code golf. Code quality is of no importance at all. \$\endgroup\$ – Adám Feb 18 at 23:15
  • \$\begingroup\$ @Adám yes formally correct and without possible Undefined Behaviour is a prerequisite of one function they came first than codegolf \$\endgroup\$ – RosLuP Feb 18 at 23:35
1
\$\begingroup\$

Powershell, 75 73 bytes.

-2 bytes thanks to Veskah.

based on Javascript by @Arnauld

$a=$b=0;$args|?{if($_-ge25){++$a-ge5-band($b+=$_-ge30)-ge3}else{$a=$b=0}}

returns an array or $null. Save as get-heatWave.ps1 and test with script https://regex101.com/r/lXdvIs/2

$t = @(
    @(30, 29, 30, 29, 41),
    @(1, 1, 25, 30, 25, 30, 25, 25, 25, 25, 25, 25, 25, 25, 40, 1, 1),
    @(31, 34, 34, 20, 34, 28, 28, 23, 27, 31, 33, 34, 29, 24, 33, 32, 21, 34, 30, 21, 29, 22, 31, 23, 26, 32, 29, 32, 24, 27),
    @(26, 29, 22, 22, 31, 31, 27, 28, 32, 23, 33, 25, 31, 33, 34, 30, 23, 26, 21, 28, 32, 22, 30, 34, 26, 33, 20, 27, 33),
    @(20, 31, 20, 29, 29, 33, 34, 33, 20),
    @(25, 26, 34, 34, 41, 28, 32, 30, 34, 23, 26, 33, 30, 22, 30, 33, 24, 20, 27, 23, 30, 23, 34, 20, 23, 20, 33, 20, 28),
    @(34, 23, 31, 34, 34, 30, 29, 31, 29, 21, 25, 31, 30, 29, 29, 28, 21, 29, 33, 25, 24, 30),
    @(22, 31, 23, 23, 26, 21, 22, 20, 20, 28, 24, 28, 25, 31, 31, 26, 33, 31, 27, 29, 30, 30),
    @(26, 29, 25, 30, 32, 28, 26, 26, 33, 20, 21, 32, 28, 28, 20, 34, 34),
    @(34, 33, 29, 26, 34, 32, 27, 26, 22),
    @(30, 31, 23, 21, 30, 27, 32, 30, 34, 29, 21, 31, 31, 31, 32, 27, 30, 26, 21, 34, 29, 33, 24, 24, 32, 27, 32),
    @(25, 33, 33, 25, 24, 27, 34, 31, 29, 31, 27, 23)
)

$f = @(
    @(30),
    @(31, 29, 29, 28, 24, 23, 29, 29, 26, 27, 33, 20, 26, 26, 20, 30),
    @(29, 29, 29, 47, 30),
    @(23, 31, 29, 26, 30, 24, 29, 29, 25, 27, 24, 28, 22, 20, 34, 22, 32, 24, 33),
    @(23, 24, 25, 20, 24, 34, 28, 32, 22, 20, 24),
    @(24, 28, 21, 34, 34, 25, 24, 33, 23, 20, 32, 26, 29, 29, 25, 20, 30, 24, 23, 21, 27),
    @(26, 34, 21, 32, 32, 30, 32, 21, 34, 21, 34, 31, 23, 27, 26, 32),
    @(29, 24, 22, 27, 22, 25, 29, 26, 24, 24, 20, 25, 20, 20, 24, 20),
    @(23, 33, 22, 32, 30),
    @(28, 21, 22, 33, 22, 26, 30, 28, 26, 23, 31, 22, 31, 25, 27, 27, 25, 28),
    @(27, 23, 42, 23, 22, 28),
    @(25, 20, 30, 29, 32, 25, 22, 21, 31, 22, 23, 25, 22, 31, 23, 25, 33, 23)
)

"Should be $true"
$t | % {
    [bool](.\get-heatWave.ps1 @_)
}

"Should be $false"
$f | % {
    [bool](.\get-heatWave.ps1 @_)
}
\$\endgroup\$
0
\$\begingroup\$

C# (Visual C# Compiler), 114 bytes

using System.Linq;s=>s.Select((a,b)=>s.Skip(b).TakeWhile(c=>c>24)).Any(a=>a.Count()>4&&a.Where(b=>b>29).Count()>2)

Try it online!

\$\endgroup\$
0
\$\begingroup\$

05AB1E, 18 bytes

.γ25@}ʒg5@}30@O3@à

Try it online or verify all test cases.

Explanation:

.γ   }              # Group the (implicit) input-list by sections of:
  25@               #  >= 25
      ʒ   }         # Then only leave groups of:
       g5@          #  At least 5 items
           30@      # Check for each remaining value if its >= 30 (1 if truthy; 0 if falsey)
              O     # And get the amount of truthy values per group by taking the sum
               3@   # Check if that amount is >= 3 for each
                 à  # And check if any are truthy by taking the maximum
                    # (which is output implicitly as result)
\$\endgroup\$
0
\$\begingroup\$

C# (.NET Core), 81 bytes

Without LINQ.

a=>{int b=0;foreach(int i in a){b+=i<25?-b:i>29?11:1;if(b>34)return 1;}return 0;}

Try it online!

\$\endgroup\$

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.