52
\$\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]
[25, 30, 25, 60, 25]
[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\$
9
  • 2
    \$\begingroup\$ Is the temperature guaranteed to be below 100 Celsius? \$\endgroup\$ Commented Apr 23, 2018 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
    Commented Apr 24, 2018 at 6:42
  • 1
    \$\begingroup\$ @HatWizard Yes, that’s okay. “Crash / don’t crash” is also fine, for example. \$\endgroup\$
    – lynn
    Commented Jun 11, 2018 at 14:43
  • 2
    \$\begingroup\$ Hey @Lynn this was a great challenge and still is :-) \$\endgroup\$ Commented Jun 19, 2018 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
    Commented Jun 20, 2018 at 8:25

46 Answers 46

31
\$\begingroup\$

C (gcc), 88 75 73 bytes

h,e,a;t(int*_){for(h=e=a=0;*_;h+=e>4&a>2)e=*_<25?a=0:++e,a+=*_++>29;e=h;}

Try it online!

\$\endgroup\$
2
  • 27
    \$\begingroup\$ h,e,a;t - nice touch! \$\endgroup\$
    – user79465
    Commented Apr 23, 2018 at 19:45
  • \$\begingroup\$ @ceilingcat Thank you. \$\endgroup\$ Commented Jun 19, 2020 at 23:40
20
\$\begingroup\$

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
\$\endgroup\$
10
\$\begingroup\$

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!

\$\endgroup\$
4
  • \$\begingroup\$ Welcome to PPCG. \$\endgroup\$ Commented Jun 8, 2018 at 19:16
  • \$\begingroup\$ Welcome to PPCG! Very nice first answer complete with test case suite! Could you add an explanation so we understand the magic? \$\endgroup\$
    – JayCe
    Commented Jun 8, 2018 at 19:48
  • \$\begingroup\$ That's a really elegant solution, well done :) \$\endgroup\$
    – lynn
    Commented Jun 9, 2018 at 14:48
  • \$\begingroup\$ 59 bytes: h;o(*t){for(h=1;*t;h=*t++<25?!!h:h%72)h*=2^*t<30;return!h;} - this uses some of the same golfs from my JavaScript answer, and a couple more. \$\endgroup\$
    – Deadcode
    Commented Mar 30, 2023 at 22:26
9
\$\begingroup\$

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!

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

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!

\$\endgroup\$
7
\$\begingroup\$

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)

\$\endgroup\$
6
\$\begingroup\$

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!

\$\endgroup\$
7
  • \$\begingroup\$ Thought this'd work out shorter when I was reading through it but could only manage 18 bytes. \$\endgroup\$
    – Shaggy
    Commented Apr 23, 2018 at 20:54
  • \$\begingroup\$ @Shaggy I thought so too, but I couldn't find a shorter version either. Thanks a lot for the pointer! \$\endgroup\$
    – Etheryte
    Commented Apr 23, 2018 at 21:02
  • 1
    \$\begingroup\$ Looks like we're winning this one at the moment :) \$\endgroup\$
    – Shaggy
    Commented Apr 23, 2018 at 21:04
  • \$\begingroup\$ Do the non-ASCII characters not count as multiple bytes? \$\endgroup\$
    – sudo
    Commented Apr 24, 2018 at 0:43
  • 1
    \$\begingroup\$ @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. \$\endgroup\$
    – Etheryte
    Commented Apr 24, 2018 at 7:39
5
\$\begingroup\$

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

\$\endgroup\$
6
  • \$\begingroup\$ try to use $args instead param($a) and $a \$\endgroup\$
    – mazzy
    Commented Jun 9, 2018 at 6:45
  • \$\begingroup\$ -2 bytes ...{$a=-split$_;$a.count-ge5-and($a|?{$_-ge30}).count-ge3} \$\endgroup\$
    – mazzy
    Commented Jun 9, 2018 at 8:46
  • \$\begingroup\$ 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 \$\endgroup\$
    – mazzy
    Commented Jun 9, 2018 at 10:57
  • \$\begingroup\$ 103 bytes $b=@();$args|%{if($_-ge25){$b+=$_}else{,$b;$b=@()}}-E{,$b}|?{$_.count-ge5-and($_|?{$_-ge30}).count-ge3} \$\endgroup\$
    – mazzy
    Commented Jun 9, 2018 at 11:13
  • \$\begingroup\$ What does -E do? I'm not familiar with that. \$\endgroup\$ Commented Jun 13, 2018 at 15:05
5
\$\begingroup\$

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!

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

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).
\$\endgroup\$
5
\$\begingroup\$

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!

\$\endgroup\$
4
\$\begingroup\$

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
\$\endgroup\$
4
\$\begingroup\$

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.

\$\endgroup\$
4
\$\begingroup\$

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.

\$\endgroup\$
4
\$\begingroup\$

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

\$\endgroup\$
4
\$\begingroup\$

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!

\$\endgroup\$
4
\$\begingroup\$

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

\$\endgroup\$
2
  • \$\begingroup\$ Your first test is commented unnecessarily - it works. \$\endgroup\$
    – ngn
    Commented Apr 24, 2018 at 14:28
  • \$\begingroup\$ @ngn Thanks for spotting that, fixed \$\endgroup\$
    – user41805
    Commented Apr 24, 2018 at 17:48
4
\$\begingroup\$

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)
\$\endgroup\$
4
  • \$\begingroup\$ You have to include the import statement too :) \$\endgroup\$ Commented Jun 12, 2018 at 10:22
  • 1
    \$\begingroup\$ You actually don’t need to import reduce from functools, it's a built-in in Python 2! \$\endgroup\$
    – lynn
    Commented Jun 12, 2018 at 10:34
  • 1
    \$\begingroup\$ 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 :) \$\endgroup\$
    – lynn
    Commented Jun 12, 2018 at 10:38
  • \$\begingroup\$ @Lynn Many thanks. I updated the solution accordingly. \$\endgroup\$ Commented Jun 12, 2018 at 12:31
4
\$\begingroup\$

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!

\$\endgroup\$
4
  • \$\begingroup\$ Nice explanation :) \$\endgroup\$
    – JayCe
    Commented Jun 8, 2018 at 22:37
  • \$\begingroup\$ 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. \$\endgroup\$ Commented Jun 8, 2018 at 23:31
  • \$\begingroup\$ @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? \$\endgroup\$ Commented Jun 10, 2018 at 12:30
  • \$\begingroup\$ @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. \$\endgroup\$ Commented Jun 10, 2018 at 13:25
3
\$\begingroup\$

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.

\$\endgroup\$
1
  • \$\begingroup\$ Hey, this is unrelated, but the facebook link on your website is dead. \$\endgroup\$
    – mbomb007
    Commented Apr 24, 2018 at 13:45
3
\$\begingroup\$

Jelly, 21 bytes

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

Try it online!

\$\endgroup\$
3
\$\begingroup\$

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.

\$\endgroup\$
3
\$\begingroup\$

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!

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

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
\$\endgroup\$
3
\$\begingroup\$

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!

\$\endgroup\$
7
  • \$\begingroup\$ 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... \$\endgroup\$
    – Giuseppe
    Commented May 22, 2018 at 16:24
  • \$\begingroup\$ ^ 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... \$\endgroup\$
    – Giuseppe
    Commented May 22, 2018 at 16:26
  • \$\begingroup\$ This is fantastic! There is probably an even shorter way leveraging Jonathan Allan's math... \$\endgroup\$
    – JayCe
    Commented May 22, 2018 at 16:30
  • \$\begingroup\$ 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))) \$\endgroup\$ Commented Jun 9, 2018 at 12:25
  • \$\begingroup\$ @RolandSchmitz very true! \$\endgroup\$
    – JayCe
    Commented Jun 9, 2018 at 13:30
3
\$\begingroup\$

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.

\$\endgroup\$
3
\$\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\$
2
  • \$\begingroup\$ Nice! Even one byte less compared to the Swift solution. \$\endgroup\$ Commented Jun 11, 2018 at 18:40
  • \$\begingroup\$ Very cool! I've got it down to 45 bytes. \$\endgroup\$
    – Deadcode
    Commented Mar 30, 2023 at 20:55
3
\$\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\$
3
\$\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\$
4
  • \$\begingroup\$ This is a great solution, especially the part with the spaceship and the negative array index. \$\endgroup\$ Commented Jun 15, 2018 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\$ Commented Jun 15, 2018 at 6:14
  • \$\begingroup\$ Thanks for the idea with the any{} operation, which gave me -16 Bytes in the Kotlin solution \$\endgroup\$ Commented Jun 15, 2018 at 22:06
  • \$\begingroup\$ -1 byte: ->a{b=1;a.any?{|r|1>b=[b*3,1,b*2][5<=>r/5]%72}} \$\endgroup\$
    – Deadcode
    Commented Mar 30, 2023 at 23:30
3
\$\begingroup\$

Haskell, 60 bytes

f q|(a,~(_:t))<-span(>24)q=sum[1|x<-a,x>29,take 4a<a]>2||f t

Try it online!

This combines some ideas from previous Haskell answers in a new form along with exit by error code to come out ahead.

How?

(a,~(_:t))<-span(>24)q puts the prefix of the list which is entirely >24 into a, and then tries to match the remainder of the list to the pattern h:t (dropping one value <= 24 and putting the remaining suffix into t). This pattern match might fail even on truthy inputs, if the heat wave is at the end of the list, which is where the ~ comes in: it forces Haskell to match the rest of the pattern even if _:t can't be matched (an "irrefutable pattern"), in which case t is undefined (i.e. set to _|_) and will error out if we ever try to use it.

Since Haskell has the usual short circuiting on ||, we will only try to evaluate f t on undefined t if there was no heat wave in the list, in which case we exit high. If there was a heat wave, we'll find it and short circuit out, returning True and exiting low.

The irrefutable pattern saves one byte compared to tail, which will similarly fail if called on an empty list:

Haskell, 61 bytes

f q|(a,b)<-span(>24)q=sum[1|x<-a,x>29,take 4a<a]>2||f(tail b)

Try it online!

\$\endgroup\$

Your Answer

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

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