Detect heat waves

48

4

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]

Lynn

Posted 2018-04-23T18:33:07.827

Reputation: 55 648

2Is the temperature guaranteed to be below 100 Celsius? – FryAmTheEggman – 2018-04-23T21:38:29.877

3@FryAmTheEggman Well, in the Netherlands, yes :), but I don't want your answer to abuse this fact, so no. – Lynn – 2018-04-24T06:42:41.127

What do you mean by decide? Your test cases imply this means output a truthy or falsy value, but there are other ways of performing decision, such as two consistent values; can we use those? – Post Rock Garf Hunter – 2018-06-11T14:27:20.250

1@HatWizard Yes, that’s okay. “Crash / don’t crash” is also fine, for example. – Lynn – 2018-06-11T14:43:38.393

Us folks here in California could sure use this! ;) – juniorRubyist – 2018-06-15T23:05:23.073

2Hey @Lynn this was a great challenge and still is :-) – Roland Schmitz – 2018-06-19T20:01:47.103

1@RolandSchmitz Thank you! I'm happily surprised by the creative answers that came out of it so late into the challenge's lifetime. – Lynn – 2018-06-20T08:25:56.160

Answers

31

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!

Jonathan Frech

Posted 2018-04-23T18:33:07.827

Reputation: 6 681

24h,e,a;t - nice touch! – user9549915 – 2018-04-23T19:45:24.757

19

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
          Ɗ€    - last three links as a monad for €ach:
       P        -   product
         L      -   length
        «       -   minimum
            >4  - greater than four? (vectorises) -- 1 if so, else 0
              Ṁ - maximum -- 1 if any are 1, else 0

Jonathan Allan

Posted 2018-04-23T18:33:07.827

Reputation: 67 804

9

Haskell, 73 72 71 69 67 66 bytes

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!

Angs

Posted 2018-04-23T18:33:07.827

Reputation: 4 825

9

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!

Roland Schmitz

Posted 2018-04-23T18:33:07.827

Reputation: 161

Welcome to PPCG. – Muhammad Salman – 2018-06-08T19:16:29.757

Welcome to PPCG! Very nice first answer complete with test case suite! Could you add an explanation so we understand the magic? – JayCe – 2018-06-08T19:48:25.690

That's a really elegant solution, well done :) – Lynn – 2018-06-09T14:48:28.463

7

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!

Dennis

Posted 2018-04-23T18:33:07.827

Reputation: 196 637

7

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)

ngn

Posted 2018-04-23T18:33:07.827

Reputation: 11 449

6

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
          ©        // and
           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!

Nit

Posted 2018-04-23T18:33:07.827

Reputation: 2 667

Thought this'd work out shorter when I was reading through it but could only manage 18 bytes.

– Shaggy – 2018-04-23T20:54:28.907

@Shaggy I thought so too, but I couldn't find a shorter version either. Thanks a lot for the pointer! – Nit – 2018-04-23T21:02:30.300

1Looks like we're winning this one at the moment :) – Shaggy – 2018-04-23T21:04:37.887

Do the non-ASCII characters not count as multiple bytes? – sudo – 2018-04-24T00:43:30.230

1@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 – 2018-04-24T07:39:25.413

17 bytes with the -x¡ flag. – Shaggy – 2019-02-12T17:28:38.100

@Shaggy I don't think that's really a win, the flags are longer than the single byte saved. Sure, it counts as a separate lang for scores, but then it isn't a Japt answer anymore. – Nit – 2019-02-12T19:55:59.210

5

PowerShell, 121 bytes

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

Try it online! or Verify all test cases

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

AdmBorkBork

Posted 2018-04-23T18:33:07.827

Reputation: 41 581

try to use $args instead param($a) and $a – mazzy – 2018-06-09T06:45:31.167

-2 bytes ...{$a=-split$_;$a.count-ge5-and($a|?{$_-ge30}).count-ge3} – mazzy – 2018-06-09T08:46:23.497

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 https://regex101.com/r/lXdvIs/2

– mazzy – 2018-06-09T10:57:29.840

103 bytes $b=@();$args|%{if($_-ge25){$b+=$_}else{,$b;$b=@()}}-E{,$b}|?{$_.count-ge5-and($_|?{$_-ge30}).count-ge3} – mazzy – 2018-06-09T11:13:25.733

What does -E do? I'm not familiar with that. – AdmBorkBork – 2018-06-13T15:05:58.537

-E is short vertion of -End shitch. Powershell allows you to use a significant part of the parameter name. It work :) – mazzy – 2018-06-13T15:14:54.700

5

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

Dennis

Posted 2018-04-23T18:33:07.827

Reputation: 196 637

5

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!

Rod

Posted 2018-04-23T18:33:07.827

Reputation: 17 588

4

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

user41805

Posted 2018-04-23T18:33:07.827

Reputation: 16 320

Your first test is commented unnecessarily - it works. – ngn – 2018-04-24T14:28:00.577

@ngn Thanks for spotting that, fixed – user41805 – 2018-04-24T17:48:29.203

4

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!

quite bad one

l4m2

Posted 2018-04-23T18:33:07.827

Reputation: 5 985

4

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!

Arnauld

Posted 2018-04-23T18:33:07.827

Reputation: 111 334

4

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

Emigna

Posted 2018-04-23T18:33:07.827

Reputation: 50 798

4

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.

Neil

Posted 2018-04-23T18:33:07.827

Reputation: 95 035

4

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.

xnor

Posted 2018-04-23T18:33:07.827

Reputation: 115 687

4

Haskell, 64 bytes

f l=or$drop 4l>>[sum[1|x<-l,x>29,all(>24)l]>2,f$tail l,f$init l]

Try it online!

xnor

Posted 2018-04-23T18:33:07.827

Reputation: 115 687

4

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!

Roland Schmitz

Posted 2018-04-23T18:33:07.827

Reputation: 161

Nice explanation :) – JayCe – 2018-06-08T22:37:32.603

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 – 2018-06-08T23:31:27.367

@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 – 2018-06-10T12:30:42.807

@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 – 2018-06-10T13:25:46.057

3

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.

Mama Fun Roll

Posted 2018-04-23T18:33:07.827

Reputation: 7 234

Hey, this is unrelated, but the facebook link on your website is dead. – mbomb007 – 2018-04-24T13:45:55.130

3

Jelly, 21 bytes

L5r⁸ṡẎ<25Ẹ$Ðḟ29<S€2<Ẹ

Try it online!

Erik the Outgolfer

Posted 2018-04-23T18:33:07.827

Reputation: 38 134

3

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!

lfvt

Posted 2018-04-23T18:33:07.827

Reputation: 121

I believe it fails because in the second truthy case, the +30 days are not all within five days. – Stewie Griffin – 2018-04-23T19:52:18.390

Very nice. You can shave off a few bytes with an each_cons approach - Try it online!

– benj2240 – 2018-04-25T03:44:11.307

3

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.

Khuldraeseth na'Barya

Posted 2018-04-23T18:33:07.827

Reputation: 2 608

3

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

ბიმო

Posted 2018-04-23T18:33:07.827

Reputation: 15 345

3

Retina, 31 bytes

G4`_+
/\b_{1,24}\b/%)C2`_{30}
1

Try it online!

Martin Ender

Posted 2018-04-23T18:33:07.827

Reputation: 184 808

3

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.

TIO links to functional version.

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

JayCe

Posted 2018-04-23T18:33:07.827

Reputation: 2 655

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 – 2018-05-22T16:24:27.873

^ 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 – 2018-05-22T16:26:04.577

This is fantastic! There is probably an even shorter way leveraging Jonathan Allan's math... – JayCe – 2018-05-22T16:30:41.117

Nice, you could even save some more bytes, if you simplify the inner part from (i2(1+(2(j>29)))) to (i(2+4*(j>29))) – Roland Schmitz – 2018-06-09T12:25:41.473

@RolandSchmitz very true! – JayCe – 2018-06-09T13:30:22.777

*(j>29) => *!j<30 will save you a byte by dropping a parenthesis. – Giuseppe – 2018-06-09T14:25:18.777

@Giuseppe nice trick! – JayCe – 2018-06-09T23:00:54.667

3

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.

Udo Borkowski

Posted 2018-04-23T18:33:07.827

Reputation: 181

3

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)

Udo Borkowski

Posted 2018-04-23T18:33:07.827

Reputation: 181

You have to include the import statement too :) – Muhammad Salman – 2018-06-12T10:22:25.800

1

You actually don’t need to import reduce from functools, it's a built-in in Python 2!

– Lynn – 2018-06-12T10:34:24.763

1You 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 – 2018-06-12T10:38:16.117

@Lynn Many thanks. I updated the solution accordingly. – Udo Borkowski – 2018-06-12T12:31:33.553

2

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.

user48543

Posted 2018-04-23T18:33:07.827

Reputation:

2

Perl 6, 54 52 bytes

{$_>5&.grep(*>29)>2}o{any kv classify $+=25>*,0,|$_}

Try it online!

nwellnhof

Posted 2018-04-23T18:33:07.827

Reputation: 10 037

2I'd love to read an explanation of this code! – Lynn – 2018-04-24T12:47:09.613

2

Befunge-98, 61 bytes

]&:46*`#;_$$$v\+1\;
 +1\_;#`+fe;#<\v
^_v#!`4:\_;#`2:<;\
>0>.@

Try it online!

Vincent

Posted 2018-04-23T18:33:07.827

Reputation: 601

2

K (ngn/k), 38 32 30 bytes

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

Try it online!

ngn

Posted 2018-04-23T18:33:07.827

Reputation: 11 449

2

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!

Roland Schmitz

Posted 2018-04-23T18:33:07.827

Reputation: 161

2

[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.

Udo Borkowski

Posted 2018-04-23T18:33:07.827

Reputation: 181

Nice! Even one byte less compared to the Swift solution. – Roland Schmitz – 2018-06-11T18:40:33.807

2

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.

G B

Posted 2018-04-23T18:33:07.827

Reputation: 11 099

This is a great solution, especially the part with the spaceship and the negative array index. – Roland Schmitz – 2018-06-15T05:34:46.817

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}} – Roland Schmitz – 2018-06-15T06:14:18.947

Thanks for the idea with the any{} operation, which gave me -16 Bytes in the Kotlin solution

– Roland Schmitz – 2018-06-15T22:06:43.927

1

Perl 5 -pa, 52 bytes

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

Try it online!

Xcali

Posted 2018-04-23T18:33:07.827

Reputation: 7 671

1

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

Galen Ivanov

Posted 2018-04-23T18:33:07.827

Reputation: 13 815

1

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

Kevin Cruijssen

Posted 2018-04-23T18:33:07.827

Reputation: 67 575

1

><>, 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.

SE - stop firing the good guys

Posted 2018-04-23T18:33:07.827

Reputation: 529

1

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 @_)
}

mazzy

Posted 2018-04-23T18:33:07.827

Reputation: 4 832

1You have an extra set of parens around $b+=($_-ge30) – Veskah – 2019-02-19T03:09:40.587

1

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.

sundar - Reinstate Monica

Posted 2018-04-23T18:33:07.827

Reputation: 5 296

1

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...

RosLuP

Posted 2018-04-23T18:33:07.827

Reputation: 3 036

Why do you localise your variables? The program will certainly work without ;c;C;k;i;x – Adám – 2019-02-17T17:20:22.890

They are local v – RosLuP – 2019-02-18T22:57:00.093

@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) – RosLuP – 2019-02-18T23:05:27.883

So what? This is code golf. Code quality is of no importance at all. – Adám – 2019-02-18T23:15:13.347

@Adám yes formally correct and without possible Undefined Behaviour is a prerequisite of one function they came first than codegolf – RosLuP – 2019-02-18T23:35:05.233

0

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!

Hyarus

Posted 2018-04-23T18:33:07.827

Reputation: 251

0

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)

Kevin Cruijssen

Posted 2018-04-23T18:33:07.827

Reputation: 67 575

0

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!

Destroigo

Posted 2018-04-23T18:33:07.827

Reputation: 401