# 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]

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

# C (gcc), 88 75 bytes

h,e,a;t(int*_){for(h=e=a=0;*_;h+=e>4&a>2)e+=*_>24||(e=a=0),a+=*_++>29;e=h;}


Try it online!

• h,e,a;t - nice touch! – user9549915 Apr 23 '18 at 19:45

# Jelly, 15 bytes

:5_5Ṡ‘ẆP«LƊ€>4Ṁ


A monadic link accepting a list of numbers which returns 1 if a heatwave was detected else 0.

Try it online! or see the test-suite.

### How?

The criteria is the existence of a run of more than four values greater than or equal to 25, of which more than two must be greater than or equal to 30.

If we divide through by five the criteria becomes the existence of a run of more than four values greater than or equal to five, of which more than two must be greater than or equal to six.

If we subtract five from these values the criteria becomes the existence of a run of more than four values greater than or equal to zero, of which more than two must be greater than or equal to one.

If we take the sign of these values (getting -1, 0, or 1) the criteria becomes the existence of a run of more than four values not equal to -1, of which more than two must be equal to one.

If we add one to these values (getting 0, 1, or 2) the criteria becomes the existence of a run of more than four values not equal to zero, of which more than two must be equal to two.

The product of a list containing any zeros is zero and the product of a list containing more than two twos (and the rest being ones) is more than four. This means that the criteria on this adjusted list becomes that the minimum of the product and the length is greater than 4.

:5_5Ṡ‘ẆP«LƊ€>4Ṁ - Link: list of numbers
:5              - integer divide by five (vectorises)
_5            - subtract five (vectorises)
Ṡ           - sign {negatives:-1, zero:0, positives:1} (vectorises)
‘          - increment (vectorises)
Ẇ         - all sublists
P        -   product
L      -   length
«       -   minimum
>4  - greater than four? (vectorises) -- 1 if so, else 0
Ṁ - maximum -- 1 if any are 1, else 0


any(\a->sum[1|x<-a,x>29,take 4a<a]>2).scanl(\a t->[0|t>24]>>t:a)[]


Thanks to @flawr and @Laikoni for two bytes each and @xnor for a byte!

Try it online!

Equal length:

any(\a->take 4a<a&&sum a>2).scanl(\a t->[0|t>24]>>sum[1|t>29]:a)[]


Try it online!

# C (clang), 64 bytes

h;o(*t){for(h=1;*t;++t)h=h&&*t<25?1:h*(*t<30?2:6)%864;return!h;}


The function o() returns 1 for a heatwave or 0 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!

• Welcome to PPCG. – Muhammad Salman Jun 8 '18 at 19:16
• Welcome to PPCG! Very nice first answer complete with test case suite! Could you add an explanation so we understand the magic? – JayCe Jun 8 '18 at 19:48
• That's a really elegant solution, well done :) – Lynn Jun 9 '18 at 14:48

# Python 3, 79 bytes

lambda T:any(len(s)>4<sum(s+s)for s in bytes(t>29or(t<25)*9for t in T).split())


Try it online!

# APL (Dyalog Classic), 21 20 bytes

1∊8≤4↓⍉×\25 30⍸↑,⍨\⎕


Try it online!

uses ⎕io←1

25 30⍸x is 0 if x<25, 1 if 25≤x<30, or 2 otherwise

we compute cumulative products of these starting from (or equivalently: ending at) all possible locations, discard the first 4 products, and detect the presence of products ≥8 (which is 23)

# Japt, 19 18 bytes

ô<25 d_Ê¨5©3§Zè¨30
ô                  // Partition the input at every item
<25               // where the value is less than 25.
d_            // Then, return whether any resulting subarray
Ê¨5         // is at least five items long
3§      // has at least three items
Zè¨30 // with a value of at least 30.


I hope I got all the discussions in the comments correctly.
Shaved off one byte thanks to Shaggy.

Try it online!

• Thought this'd work out shorter when I was reading through it but could only manage 18 bytes. – Shaggy Apr 23 '18 at 20:54
• @Shaggy I thought so too, but I couldn't find a shorter version either. Thanks a lot for the pointer! – Nit Apr 23 '18 at 21:02
• Looks like we're winning this one at the moment :) – Shaggy Apr 23 '18 at 21:04
• Do the non-ASCII characters not count as multiple bytes? – sudo Apr 24 '18 at 0:43
• @sudo Those symbols are all single-byte. For example, 漢 would be 3 bytes, but ¨ is one byte. The symbols used above have been picked for the golfing language exactly for the reason that they're all a single byte. – Nit Apr 24 '18 at 7:39

# PowerShell, 121 bytes

param($a)$b="";($a|%{if($_-ge25){$b+="$_ "}else{$b;$b=""}})+$b|?{(-split$_).count-ge5-and(-split$_|?{$_-ge30}).count-ge3}


PowerShell doesn't have the equivalent of a .some or .every or the like, so this is rolled by hand.

We take input $a as an array of integers. Set helper variable $b to the empty string. Then, loop through every integer in $a. Inside the loop, if the integer is -greaterthanorequal to 25, add it to our potential string $b, otherwise put $b on the pipeline and set it to the empty string. Once outside the loop, array-concatenate the pipeline results with $b, and put those through a Where-Object clause |?{...}. This pulls out those strings that have an element length of -ge5 (based on splitting on whitespace) and a count of temps greater than 30 being -ge3. Those strings are left on the pipeline, so a truthy value is non-empty (see the "verify all test cases" link for truthy/falsey distinction).

• try to use $args  instead param($a) and $a – mazzy Jun 9 '18 at 6:45 • -2 bytes ...{$a=-split$_;$a.count-ge5-and($a|?{$_-ge30}).count-ge3} – mazzy Jun 9 '18 at 8:46
• 109 bytes with arrays. save $args|%{if($_-ge25){$b+=$_}else{,$b;$b=@()}}-E{,$b}-B{,($b=@())}|?{$_.count-ge5-and($_|?{$_-ge30}).count-ge3} as get-heatWave.ps1. Test script regex101.com/r/lXdvIs/2 – mazzy Jun 9 '18 at 10:57 • 103 bytes $b=@();$args|%{if($_-ge25){$b+=$_}else{,$b;$b=@()}}-E{,$b}|?{$_.count-ge5-and($_|?{$_-ge30}).count-ge3} – mazzy Jun 9 '18 at 11:13
• What does -E do? I'm not familiar with that. – AdmBorkBork Jun 13 '18 at 15:05

# Jelly, 17 16 bytes

:5_5Ṡṣ-ḤS«LƊ€Ṁ>4


Try it online!

### How it works

:5_5Ṡṣ-ḤS«LƊ€Ṁ>4  Main link. Argument: T (array of temperatures)

:5                Divide each item of T by 5 (integer division).
_5              Subtract 5 from each quotient.
Ṡ             Take the signs.
This maps (-oo,25) to -1, [25,30) to 0, and [30,+oo) to 1.
ṣ-           Split at occurrences of -1.
Ḥ          Double, replacing 1's with 2's.
Ɗ€     Map the three links to the left over each chunk.
S             Take the sum.
L           Take the length.
«            Take the minimum of the results.
Ṁ    Take the maximum.
>4  Test if it's larger than 4.
Note that the sum is larger than 4 if and only if there are more
than two 2's, which correspond to temperatures in [30,+oo).


# Python 2, 86 bytes

lambda l:any(2<s.count('2')*(len(s)>14)for s in[(t>24)+(t>29)for t in l].split('0'))


Try it online!

# JavaScript (ES6), 63 51 bytes

Returns a boolean.

a=>a.some(n=>(n>24?y+=++x&&n>29:x=y=0)>2&x>4,x=y=0)


Try it online!

# 05AB1E, 20 bytes

Œʒ24›DPsO4›*}29›O2›Z


Try it online!

Explanation

Œ                     # push sublists of input
ʒ          }         # filter, keep the lists where:
*          # the product of:
DP               # the product and
sO4›           # the sum compared using greater-than to 4
24›                 # for the elements greater than 24
# is true
# the result is:
Z  # the maximum from the remaining lists where
O     # the sum of
29›      # the elements greater than 29
2›   # is greater than 2


## Batch, 119 bytes

@set h=0
@for %%t in (0 %*)do @if %%t lss 25 (set/as=5,t=3)else set/a"t+=!!t*(29-%%t)>>9,s-=!!s,h+=!(s+t+h)
@echo %h%


Takes input as command-line arguments and outputs 1 for a heatwave otherwise 0.

# Python, 67 bytes

f=lambda l:l>l[:4]and(min(l)>24<sorted(l)[~2]-5)|f(l[1:])|f(l[:-1])


Try it online!

Times out on the longer test cases due to exponential growth. Finds contiguous sublists by repeatedly chopping the first or last element. That 3 days are ≥30°C is checked by looking at the third-largest value sorted(l)[~2]. The base cases could perhaps be shorter by taking advantage of truthy/falsey or terminating with error.

# JavaScript (Node.js), 48 bytes

a=>a.some(x=>x>24?++A>4&(B+=x>29)>2:A=B=0,A=B=0)


Try it online!

f l=or$drop 4l>>[sum[1|x<-l,x>29,all(>24)l]>2,f$tail l,f$init l]  Try it online! # APL (Dyalog Unicode), 29 bytes ∨/(5≤≢¨a)∧3≤+/30≤↑a←e⊆⍨25≤e←⎕  Try it online! ∨/ are there any elements such that (5≤≢¨a) 5 < the tally ≢ of days in each series (a has all the possible series of days) ∧ and 3≤+/30≤ 3 ≤ the total +/ number of elements that are ≥ 30 in ↑a← the matrix formed by e⊆⍨25≤e←⎕ the series of consecutive elements that are ≥ 25 • Your first test is commented unnecessarily - it works. – ngn Apr 24 '18 at 14:28 • @ngn Thanks for spotting that, fixed – Cows quack Apr 24 '18 at 17:48 # Kotlin, 57 bytes {var r=1;it.any{r*=2;if(it>29)r*=3;if(it<25)r=1;r%864<1}}  (-1 Byte by replacing the explicit Parameter v-> with the implicit parameter it) {var r=1;it.any{v->r*=2;if(v>29)r*=3;if(v<25)r=1;r%864<1}}  (-16 bytes using the any{} operation as seen in the Ruby Solution by G B) {it.stream().reduce(1){r,v->if(r*25>r*v)1 else(r*if(v<30)2 else 6)%864}<1}  (-1 byte thanks Lynn: replaced r>0&&v<25 with r*25>r*v) {it.stream().reduce(1){r,v->if(r>0&&v<25)1 else(r*if(v<30)2 else 6)%864}<1}  This lambda expression takes a List and 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 an any{} operation starting at the reduce value 1. The reduce is multiplied by 2 and multiplied with 3 (2*3=6) if the number is greater or equal 30. 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 true return value in the inner lambda called from the any{} operation which then stops iterating and returns value of true. Try it online! • Nice explanation :) – JayCe Jun 8 '18 at 22:37 • I think your byte count should reflect the entire function declaration, not just the function's body. As it is right now, it seems to me to be a snippet. – Jonathan Frech Jun 8 '18 at 23:31 • @jonathan-frech, I changed the function body to a slightly longer lambda expression including the braces which are not optional like they are in Java. Is this fair? – Roland Schmitz Jun 10 '18 at 12:30 • @RolandSchmitz Looking at other Kotlin submissions and Java lambda function submissions, I guess not including the function declaration byte count is accepted; meaning that your original submission is most likely valid. Sorry for my comment, it just seemed odd to me as I find it looks very snippet-esk, since it is not a valid language construct without the type declaration. – Jonathan Frech Jun 10 '18 at 13:25 # Wonder, 34 bytes (/>@(& <2!> '<29#0)*> '<24#0).cns5  Usage example: ((/>@(& <2!> '<29#0)*> '<24#0).cns5) [25 33 33 25 24 27 34 31 29 31 27 23]  # Explanation Verbose version: (some x\\(and <2 (fltr <29) x) (every <24) x) . (cns 5)  Take overlapping sequences of 5 consecutive items, then check if any of the sequences have all items > 25 and more than 2 items > 30. • Hey, this is unrelated, but the facebook link on your website is dead. – mbomb007 Apr 24 '18 at 13:45 # Jelly, 21 bytes L5r⁸ṡẎ<25Ẹ$Ðḟ29<S€2<Ẹ


Try it online!

# Stax, 23 bytes

Æ7)║▄░Ä╟═╙hⁿ╧\ßY8÷K▌µ½x


Run and debug it at staxlang.xyz! This takes a long time to run, so I disabled auto-run.

### Unpacked (28 bytes) and explanation

:efc%4>nc{24>f=a{29>f%2>|&|&
:e                              Set of all contiguous subarrays
f                             Filter, using the rest of the program as a predicate:
c                              Copy subarray on the stack
%4>                           Five or more elements?
|&        AND
nc                         Copy subarray twice to top
{   f                    Filter:
24>                       Greater than 24?
=                   Equals the original subarray?
|&      AND
a                  Move subarray to top
{   f             Filter:
29>                Greater than 30?
%2>          Length greater than two?
Implicit print if all three conditions are met


This'll print all subarrays that can be counted as heat waves, which will be falsy if and only if none exist.

# Ruby, 89 bytes

->a{(0..a.size).map{|i|(b=a[i..-1].take_while{|t|t>24}).size>4&&b.count{|t|t>29}>2}.any?}


Try it online!

• I believe it fails because in the second truthy case, the +30 days are not all within five days. – Stewie Griffin Apr 23 '18 at 19:52
• Very nice. You can shave off a few bytes with an each_cons approach - Try it online! – benj2240 Apr 25 '18 at 3:44

# Husk, 19 bytes

Vo≥3#≥30fo≥5Lġ(±≥25


Try it online!

Using filter (f) is one byte shorter than using checking with a logical and (&), also it would be really nice to get rid of the ± - costing 2 bytes :(

### Explanation

V(≥3#≥30)f(≥5L)ġ(±≥25)  -- example input: [12,25,26,27,28,29,18,24,32]
ġ(    )  -- group by
( ≥25)  -- | greater or equal to 25: [0,1,2,3,4,5,6,0,0,8]
(±   )  -- | sign: [0,1,1,1,1,1,1,0,0,1]
-- : [[12],[25,26,27,28,29,30],[18,24],[32]]
f(   )         -- filter by
(  L)         -- | length: [1,6,2,1]
(≥5 )         -- | greater or equal to 5: [0,2,0,0]
-- : [[25,26,27,28,29,30]]
V(      )               -- does any element satisfy
(  #   )               -- | count occurences where
(   ≥30)               -- | | elements greater or equal to 30
(      )               -- | : [1]
(≥3    )               -- | greater or equal to 3: [0]
-- : 0


## Retina, 31 bytes

G4_+
/\b_{1,24}\b/%)C2_{30}
1


Try it online!

# R, 111 93 71 67 66 bytes

!Reduce(function(i,j)"if"(j<25,!!i,(i*(2+4*!j<30))%%864),scan(),1)


Try it online!

Shameless port of Roland Schmitz's answers. -4 bytes thanks to Roland and -1 thanks to Giuseppe.

Previous version extracted consecutive days>25 using rle and saved a whopping 18 bytes thanks to Giuseppe!

• if you use F instead of T, you can do F=F|"if"(cond,(expr),0) and then return F to save 6-ish bytes. You also have an unnecessary pair of parentheses around (1-z[i]):0 but I think that could just be 1-z[i]:1 anyway to save another couple bytes... – Giuseppe May 22 '18 at 16:24
• ^ I was about to submit the above comment when another idea occurred to me, and I managed to find a sub-100 byte solution! It's function(x,z=rle(x>24)$l){for(i in 1:sum(z|1))F=F|z[i]>4&sum(x[sum(z[1:i])+1-z[i]:1]>29)>2;F} but be careful pasting from PPCG into TIO because sometimes unprintables creep in... – Giuseppe May 22 '18 at 16:26 • This is fantastic! There is probably an even shorter way leveraging Jonathan Allan's math... – JayCe May 22 '18 at 16:30 • Nice, you could even save some more bytes, if you simplify the inner part from (i*2*(1+(2*(j>29)))) to (i*(2+4*(j>29))) – Roland Schmitz Jun 9 '18 at 12:25 • @RolandSchmitz very true! – JayCe Jun 9 '18 at 13:30 # Swift 4, 50 bytes {$0.reduce(1){$0>0&&$1<25 ?1:$0*($1<30 ?2:6)%864}}


Try it online!

The closure expression returns 0 for a heatwave or >0 else.

Created in collaboration with Roland Schmitz and Mathis.

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.

# Python 2, 66 63 bytes

lambda a:reduce(lambda b,c:(b*(6,2)[c<30]%864,1)[b*25>b*c],a,1)


Try it online!

-3 bytes thanks to Lynn

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.

A more readable, but longer version looks like this:

lambda a:reduce((lambda b,c: 1 if b>0 and c<25 else b*(2 if c<30 else 6)%864), a, 1)


Removing extra spaces/parenthesis and replacing x if cond else y by (y,x)[cond] gives

lambda a:reduce(lambda b,c:(b*(6,2)[c<30]%864,1)[b>0and c<25],a,1)


Lynn suggested to shorten the condition b>0and c<25:

b>0and c<25 --> b*25>0 and b*c<b*25 --> b*25>0 and b*25>b*c --> b*25>b*c

resulting in

lambda a:reduce(lambda b,c:(b*(6,2)[c<30]%864,1)[b*25>b*c],a,1)

• You have to include the import statement too :) – Muhammad Salman Jun 12 '18 at 10:22
• You actually don’t need to import reduce from functools, it's a built-in in Python 2! – Lynn Jun 12 '18 at 10:34
• You can check if b*25>b*c and save 3 bytes; this might apply to many of the solutions taking this approach in different languages :) – Lynn Jun 12 '18 at 10:38
• @Lynn Many thanks. I updated the solution accordingly. – Udo Borkowski Jun 12 '18 at 12:31

# Pyth, 23 bytes

f&glT5&>T]25gePPT30SM.:


Try it here

f&glT5&>T]25gePPT30SM.:
f                  SM.:Q   Get the sorted subsequences of the (implicit) input...
&qlT5                     ... with at least 5 elements...
&>T]25               ... all at least 25...
gePPT30        ... where the third to last is at least 30.


]&:46*#;_$v\+1\; +1\_;#+fe;#<\v ^_v#!4:\_;#2:<;\ >0>.@  Try it online! # Perl 6, 54 52 bytes {$_>5&.grep(*>29)>2}o{any kv classify $+=25>*,0,|$_}


Try it online!

• I'd love to read an explanation of this code! – Lynn Apr 24 '18 at 12:47