text:
Detect heat waves
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]

Is the temperature guaranteed to be below 100 Celsius?

@FryAmTheEggman Well, in the Netherlands, yes :), but I don't want your answer to abuse this fact, so no.

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?

@HatWizard Yes, that’s okay. “Crash / don’t crash” is also fine, for example.

Us folks here in California could sure use this! ;)

Hey @Lynn this was a great challenge and still is :-)

@RolandSchmitz Thank you! I'm happily surprised by the creative answers that came out of it so late into the challenge's lifetime.

Recommended test case: [25, 30, 25, 60, 25]. Without this, the second : can be dropped from my regex, making it 37 bytes, and it still passes all the test cases. Also, Martin Ender's Retina answer fails this test case.

@Deadcode added!

C (gcc), 88 75 73 bytes

Saved two bytes thanks to ceilingcat.

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!

h,e,a;t - nice touch!

@ceilingcat Thank you.

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

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.

Welcome to PPCG! Very nice first answer complete with test case suite! Could you add an explanation so we understand the magic?

That's a really elegant solution, well done :)

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.

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!

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

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

@Shaggy I thought so too, but I couldn't find a shorter version either. Thanks a lot for the pointer!

Looks like we're winning this one at the moment :)

Do the non-ASCII characters not count as multiple bytes?

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

17 bytes with the -x¡ flag.

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

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!

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

try to use $args  instead param($a) and $a

-2 bytes ...{$a=-split$_;$a.count-ge5-and($a|?{$_-ge30}).count-ge3}

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

103 bytes $b=@();$args|%{if($_-ge25){$b+=$_}else{,$b;$b=@()}}-E{,$b}|?{$_.count-ge5-and($_|?{$_-ge30}).count-ge3}

What does -E do? I'm not familiar with that.

-E is short vertion of -End shitch. Powershell allows you to use a significant part of the parameter name. It work :)

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!

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 Thanks for spotting that, fixed

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

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.

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!

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

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

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

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

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

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 Many thanks. I updated the solution accordingly.

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.

Jelly, 21 bytes
L5r⁸ṡẎ<25Ẹ$Ðḟ29<S€2<Ẹ

Try it online!

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.

Very nice. You can shave off a few bytes with an each_cons approach - 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.

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

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!

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

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

This is fantastic! There is probably an even shorter way leveraging Jonathan Allan's math...

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

@RolandSchmitz very true!

*(j>29) => *!j<30 will save you a byte by dropping a parenthesis.

@Giuseppe nice trick!

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!

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.

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

Nice! Even one byte less compared to the Swift solution.

Very cool! I've got it down to 45 bytes.

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.

This is a great solution, especially the part with the spaceship and the negative array index.

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

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

-1 byte: ->a{b=1;a.any?{|r|1>b=[b*3,1,b*2][5<=>r/5]%72}}

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!

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.

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!

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

Try it online!

K (ngn/k), 38 32 30 bytes
{+/7<,/4_'*\'|:',\+/x>/:24 29}

Try it online!

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.

47 bytes: T->reduce((x,y)->y<25?x>0:(2+(y<30))x%72,1,T)<1 - unfortunately only one of the golfs I used in JavaScript and in C can be used in Julia.

Regex (ECMAScript+(?^=)RME), 34 bytes
((:x{25,}){5,})(?^1=(:.*x{30}){3})

Takes its input in unary, as a concatenation of strings of x characters whose lengths represent the numbers, separated and enclosed on both sides by : characters. Example: :xxx:x:xx: represents 3,1,2.
Try it on replit.com - ECMAScript+(?^=) (RegexMathEngine -xli)
(                # \1 = the following:
    (
        :x{25,}  # Match and consume a list element that's ≥ 25
    ){5,}        # Loop the above at least 5 times, as many times as possible
)
(?^1=            # Lookinto - match against the contents of \1
    (
        :.*      # Skip to any list element (completing the match of any
                 # previously partially-consumed list element), putting it in tail
                 # (can start in the middle of it and this is still fine, because
                 # we only need to assert that it's ≥ 30)
        x{30}    # Assert tail ≥ 30; tail -= 30
                 # No need to consume the rest of tail if it's > 30, because the
                 # ":.*" part will make sure that we finish matching at the end
                 # of this list element before skipping to a subsequent one.
    ){3}         # Loop the above 3 times
)

Regex (ECMAScript or better), 38 bytes
(?=(:x{25,}){5,}(.*))(:.*x{30}){3}.*\2

Try it online! - ECMAScript (SpiderMonkey)
Try it online! - ECMAScript 2018 (Node.js)
Try it online! - Perl
Try it online! - Java
Try it online! - Boost
Try it online! - Python
Try it online! - Ruby
Try it online! - PCRE
Try it online! - .NET
Try it on replit.com - ECMAScript (RegexMathEngine)
(?=
    (
        :x{25,}  # Match and consume a list element that's ≥ 25
    ){5,}        # Loop the above at least 5 times, as many times as possible
    (.*)         # \2 = the remainder of the string
)
(
    :.*          # Skip to any list element (completing the match of any
                 # previously partially-consumed list element), putting it in tail
                 # (can start in the middle of it and this is still fine, because
                 # we only need to assert that it's ≥ 30)
    x{30}        # Assert tail ≥ 30; tail -= 30
                 # No need to consume the rest of tail if it's > 30, because the
                 # ":.*" part will make sure that we finish matching at the end
                 # of this list element before skipping to a subsequent one.
){3}             # Loop the above 3 times
.*\2             # Assert that at some subsequent position, \2 can be matched,
                 # demonstrating that the 3 loop iterations above only matched
                 # list elements that occurred within the same range of the string
                 # as that matched by the 5 loop iterations at the beginning.

While golfing this, I found a bug in Ruby's regex engine triggered by 39 byte version: Try it online! / Attempt This Online! - it gives false negatives on all of the truthy test cases, while working fine in all the other regex engines.

JavaScript (ES6), 44 bytes
a=>a.reduce((b,c)=>c<25?!!b:b*(2^c<30)%72,1)

Try it online!
This is based on Udo Borkowski's JavaScript answer which is 49 bytes. The extra golfs are:

Change (c<30?2:6) to (c<30?2:3), because multiplying by both \$2\$ and \$3\$ simultaneously is redundant and doesn't keep track of any more information than if we just multiply by two different primes. Thus instead of 864, we can use 108 as our magic number, as the sum of the multiplicities of \$2\$ and \$3\$ is now equal to the previous multiplicity of \$2\$.
Change (c<30?2:3) to (c<30?3:2), thus getting 72 as our magic number instead of 108, saving 1 byte.
Change (c<30?3:2) to (2^c<30), taking advantage of bitwise ^ having a lower operator precedence than the < comparison operator. This saves another 2 bytes.
Move b>0 from the ternary condition, to its truthy argument. This saves another 2 bytes.

This is still "inverted logic", returning falsey for a "Contains a Heat Wave" and truthy for "No Heat Wave". But as a result of change #3, the return value for "Contains a Heat Wave" is sometimes 0 and sometimes false. This can be cleaned up by !, taking it to 45 bytes: Try it online!
The original explanation (edited to reflect the changes):
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 \$3\$. If a number \$≥ 30\$ is seen, the reduce is multiplied by \$2\$. If a number \$< 25\$ is seen the reduce starts again at \$1\$. If the reduce is divisible by \$72=2×2×2×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, 59 bytes
lambda a:reduce(lambda b,c:[b*(2+(c<30))%72,b>0][c<25],a,1)

Try it online!
A port of the above. 4 bytes shorter than Udo Borkowski's Python 2 answer which is 63 bytes.
Clean True/False output is 61 bytes: Try it online!
Python 3.8+, 62 59 bytes
lambda a,b=1:[b:=[b*(2+(c<30))%72,b>0][c<25]for c in a][-1]

Try it online! / Attempt This Online!
Unfortunately reduce was moved into the functools library in Python 3. So, this uses a list comprehension workaround to match the Python 2 version's length.
Clean True/False output is 61 bytes: Try it online! / Attempt This Online!
Python 2, 54 bytes
b=1
for c in input():b=[b*(2+(c<30))%72,b>0][c<25]
1/b

Try it online!
This full program outputs via its exit-code:

1 (the program raised a ZeroDivisionError) if the list contains a heat wave
0 (the program exited normally) if it does not

Python 3+, 60 bytes
Try it online! - Same as the Python 2 version above, but using eval(input()) in place of input().
Python 3.8+, 59 bytes
for c in eval(input())+[b:=1]:b=[b*(2+(c<30))%72,b/b][c<25]

Try it online! / Attempt This Online!
Alternative 59 bytes:
b=1
for c in eval(input()):b=[b:=b*(2+(c<30))%72,b/b][c<25]

Try it online! / Attempt This Online!

Perl 5 -pa, 52 bytes
map{$_<25?$w=$h=0:$w++;$h+=$_>29;$\|=$w>4&&$h>2}@F}{

Try it online!

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

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

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

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

You have an extra set of parens around $b+=($_-ge30)

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)

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

Why do you localise your variables? The program will certainly work without ;c;C;k;i;x

They are local v

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

So what? This is code golf. Code quality is of no importance at all.

@Adám yes formally correct and without possible Undefined Behaviour is a prerequisite of one function they came first than codegolf

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!

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!


text:
Help me redirecting
Your task is to automatically complete URLs like the address bar in most  browsers is doing. We will use the following (simplified) rules:

If the input string starts with http://, ftp:// or https://, return the string unchanged.
Otherwise, if the input string contains a dot ., e.g. in.put then the HTTP is assumed and http:// is prepended: http://in.put.
Otherwise ftp:// is prepended, e.g. ftp://input when the input string was input.

Input
Any string which must not necessarily be a valid URL.
Output
The string modified according to the above rules.
Test Cases
dan-pc -> ftp://dan-pc
https://localhost/ -> https://localhost/
ftp://foo -> ftp://foo
http://foo -> http://foo
f.oo -> http://f.oo
derp.me -> http://derp.me
another.one/ ->http://another.one/
// -> ftp:////
a://b -> ftp://a://b

This is code golf, shortest code wins. Good Luck!

Can the input be abcd://site? (generally if there is something before :// can we assume it's http, https or ftp?

nope. You do not have to take care of "invalid" input. Yes , your assumption is right @user202729

Then which inputs are valid?

If the input might be abcd://lol it results in ftp://abcd://lol
Having to check invalid input seemed like a overkill to me.

I'd suggest adding a test case for http://foo

Can the input be an arbitrary string? It looks like answers are assuming it's formatted like a URL.

the input is string, but if your language has a better solution go for it. It isn't clearly defined, so any in/output is allowed as long as the output matches the testcases. @xnor

@ChasBrown edited.

@HermanLauenstein Everything is valid, the constraints to construct the url should be clear, however here are your examples:
// -> ftp:////  a://b -> http://a://b

I find the explanation very confusing. It talks about a search bar, but doesn't appear to support searching. It talks about writing a browser which supports redirecting, but doesn't seem to actually fetch anything.

It seems also that the last test case is not following the rules, as a://b doesn't contain a . and so should be output as ftp://a://b

Additionally, the last test case does not agree with 0x45's earlier reply to @user202729.

Sorry, I was doing this parallel to actual work. Fixed it.

Suggested test case: "p://", which should map to "ftp://p://"

What about ftps://?

@Titus, read the previous comments and the description conscientious. Otherwise, if the input string contains a dot ., e.g. in.put then the HTTP is assumed and http:// is prepended: http://in.put. There is no dot, so it should be ftp://<input>

R, 98 bytes
x=scan()
cat(`if`(grepl("^(https?|ftp)://",x),"",`if`(grepl("\\.",x),"http://","ftp://")),x,sep="")

Try it online!

This won't quite work, for a couple of reasons: the regex . in the second grepl matches any single character, you need \\. instead. Additionally, the first grepl will match anything that has p:// or s:// as a substring; you need to use a regex like others have used, ^(https?|ftp)://

Whoops, you're right about the latter grepl, fixed that.  But the first one correctly matches all the test cases as they currently stand, I can update this if need be.  Or is that considered bad form?

The input is specified as Any string which must not necessarily be a valid URL. so I think you need that update. Which is annoying, to be sure. String challenges in R are seldom fun :(

Damn, you're right.  That'll learn me to read the instructions better.  Fixed, and thanks for reigning me in =)

not a problem, I've been burned so many times before...I must have ten or so answers I deleted for not meeting the specs that I never went back to. =P

Perl 5 -p, 38 bytes
m%://%||s%.*\.%http://$&%||s%^%ftp://%

Try it online!

Ruby, 63 56 55 bytes
->a{a[%r*(https?|ftp)://*]?a:"#{a[?.]?'ht':?f}tp://"+a}

Try it online!

Erm your code just works if you supply the result in your code...?

They were hardcoded tests, now it should be more dynamic

Swift, 147 133 bytes
Thanks to Herman L for saving 14 bytes.
Sadly, NSRegularExpression would've taken away lots of precious bytes.
import Foundation;let s=readLine()!,h=["http://","https://","ftp://"];print(h.contains{s.hasPrefix($0)} ?s:h[s.contains(".") ?0:2]+s)

Prettyfied:
import Foundation

let s = readLine()!, h = ["http://","https://","ftp://"]
print(h.contains{ s.hasPrefix($0) } ? s :h[s.contains(".") ? 0 : 2] + s)

Try it online!

I managed to remove a few bytes: TIO

@HermanL Wow, impressive! Thank you.

Python 2, 87 85 bytes
lambda s:re.match('(https?|ftp)://',s)and s or['f','ht']['.'in s]+'tp://'+s
import re

Try it online!
-2 bytes thx to Titus and wastl

Maybe re.match(r'://',s) should be enough

@tsh: It´s not. Look at the latest test case. But I´d personally say that ^(ht|f)tps?:// should be ok.

I don't think ftps is considered a valid protocol. But you can save two bytes by removing r and ^ (re.match does only apply the regex at the beginning)

JavaScript, 64 bytes
x=>x.match`^(https?|ftp)://`?x:`${/\./.test(x)?'ht':'f'}tp://`+x

JavaScript, 51 50 bytes, Real life assumption
x=>x.match`//`?x:`${/\./.test(x)?'ht':'f'}tp://`+x

Thank tsh for 1 byte

'htt':'ft'}p -> 'ht':'f'}tp

Won't this fail for abcd://site? Expected output is ftp://abcd://site.

@Shaggy That's why I say "Real life assumption". In comment such are invalid input

No, the comments were clarifying that those inputs were valid but inputs with an invalid protocol should be treated the same as inputs with no protocol. The test cases have been updated to reflect this.

JavaScript (Firefox 52), 41 bytes
s=>new URL(s,/\./.test(s)?'http:':'ftp:')

If a string is required for output, add 3 bytes +'' at the end. (Notice this solution may add a trailing / at the end of domain name since they are the same URL)

f=
s=>new URL(s,/\./.test(s)?'http:':'ftp:')

t=s=>console.log(`${s} -> ${f(s)}`)

t('example.com')
t('example')
t('http://example')
t('https://example')
t('ftp://example')
t('http://example.com')
t('https://example.com')
t('ftp://example.com')

It seems this only works on Firefox 52 ESR but not Firefox 60 or Chrome 65. So sad.

Java 8, 74 72 bytes
s->s.matches("(https?|ftp)://.*")?s:(s.contains(".")?"ht":"f")+"tp://"+s

-2 bytes thanks to @HermanLauenstein.
Try it online.
Explanation:
s->                   // Method with String as both parameter and return-type
  s.matches("(https?|ftp)://.*")?
                      //  If the input starts with one of
                      //  "http://", "https://", or "ftp://"
   s                  //   Return it as is
  :                   //  Else:
   (s.contains(".")?  //   If it contains a dot
     "ht"             //    Start with "ht"
    :                 //   Else:
     "f")             //    Start with "f"
   +"tp://"+s         //   And append "tp://" and the input-String

-2 bytes using s->s.matches("(https?|ftp)://.*")?s:(s.contains(".")?"ht":"f")+"tp://"+s

@HermanLauenstein Pretty obvious change now that I see it, but I hadn't thought of it at all, so thanks! :)

PHP, 59 bytes
<?=strpos($s=$argn,':')?$s:(strpos($s,'.')?ht:f)."tp://$s";

To run all the tests:
cat <<EOF | php -nF <filename>
dan-pc
https://localhost/
ftp://foo
http://foo
f.oo
derp.me
another.one/
EOF

(Put a newline before the <?= for formatting, not required for one line of input)
Or just one at a time:
echo '<input>' | php -nF <filename>

Or Try it online!

I think you have to use a regex; your current code fails for the a://b example.

@Titus Oh, I didn't see that new test case. Thanks for letting me know. Do you think it'd be acceptable to just do 'p:' instead of ':', since it fulfills the test cases, or would it be more "right" to use a regex?

I´d say it´d be fair to be precise, as all other submissions are so too: %^(ht|f)tps?://% should be ok though.

Retina, 64 bytes
^(?!(https?|ftp)://)(?=.*\.)
http://
^(?!(https?|ftp)://)
ftp://

Try it online!

GolfScript, 58 55 bytes
.'://':a/.,(\0=['https'.4<'ftp']:l?)*{}{.'.'?)!)l=a@}if

Try it online!
This is my first GolfScript program, so I expect there is a lot room for golfing.
Explanation:
.'://':a/.,(\0=['https'.4<'ftp']:l?)*{}{.'.'?)!)l=a@}if Full program, implicit input
.                                                       Copy input
 '://':a                                                Push '://', and assign it to a
        /.                                              Split input at '://' and copy
          ,(                                            Push length of the result - 1 (<==> '://' in input)
            \0=                                         Pull up the array and get the first element
               ['https'.4<'ftp']:l                      Push [ 'https', 'http', 'ftp' ] and assign it to l
                                  ?)                    Test if first element is in that array
                                    *{}{            }if If at least one of those values is false
                                        .'.'?)          Push whether the input contains a dot
                                              !)        Logical not and increment:
                                                              '.' in input -> 1
                                                           no '.' in input -> 2
                                                l=      Get that element of l ([ 'https', 'http', 'ftp' ])
                                                  a@    Append a ('://') and input
                                                        Implicit output

Pyth, 58 bytesSBCS
J"://"I:Q."(|e<UGÐÌ@ãy!'"ZQ.?I}\.Q++"http"JQ.?++"ftp"J

Test suite
Code contains unprintable characters, and as such does not display properly on Stack Exchange. The link provided contains these characters and is the correct version of the program.

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
The Third Flak!
This challenge was posted as part of the April 2018 LotM challenge

Brain-Flak is a turing-tarpit language which has gained quite a lot of fame here on PPCG. The memory of the language is composed by two stacks, but a "hidden" third stack was discovered by Wheat Wizard, leading to some interesting new ways of thinking Brain-Flak programs.
So, what about giving that poor hidden third stack more visibility? Let's create a language where the third stack has the recognition it deserves! Here I present you Third-Flak.
The language
In Third-Flak there is only one stack, called the third stack. Operators work on the third stack in the same way they do in Brain-Flak, but here there are no [],{},<> nilads and no {...} monad (so the only admissible characters in a Third-Flak program are ()[]<>). Here is what each operator does (examples will be given representing the third stack with a list where the last element is the top of the stack):

() is the only two-characters operator in Third-Flak. It increases the top of the third stack by 1. Example: [1,2,3]→[1,2,4]
(,[,<: all opening parentheses that are not covered by the previous case push a 0 to the third stack. Example: [1,2,3]→[1,2,3,0]
) pops two elements from the third stack and pushes back their sum. Example: [1,2,3]→[1,5]
] pops two elements from the third stack and pushes back the result of subtracting the first from the second. Example: [1,2,3]→[1,-1]
> pops an element from the third stack. Example [1,2,3]→[1,2]

And here are the other rules of the language:

At the beginning of execution the third stack contains only a single 0.
It is forbidden to have empty [] or <> inside a program (they would be noops anyway if following the semantics of Third-Flak, but they actually have a different meaning in Brain-Flak that is not possible to recreate here).
Parentheses always need to be balanced, except for the fact that trailing closing parentheses at the end of the program can be missing. As an example, [()<(() is a valid Third-Flak program (and the third stack at the end of the program would be [1,0,1]).
A program can only contain the six allowed characters ()[]<>. Programs are guaranteed to be non-empty.

Note: it is implied by the previous rules that you won't have to deal with situations where you need to pop from an empty stack.
The challenge
Simple, write an interpreter for Third-Flak. Your program must take as input a Third-Flak program and return as output the state of the third stack at the end of the program.
Your output format is flexible as long as it is possible to unambiguously read from it the state of the third stack and the same number is always encoded in the same way (This is just a way of saying that any output format that's not a blatant way to try to cheat is fine).
Your output choice may restrict the range of numbers you can manage as long as this does not trivialize the challenge (since this would be a default loophole).
Test cases
For each test case the first line is the input, and the second line the output stack represented as a space separated list of numbers where the top of the stack is the last element.
[()<(()
0 1 0 1

[((((()()()()()))
0 0 0 5

((([()][()][()])))
-3

[<<(((()()()())(((((
0 0 0 0 0 4 0 0 0 0 0

[()]<(([()])><[()]
-1 0 -1

(())(()()())(())(())(()()())(())(())(()()())(())(()()()()())(()())(()()()()())(())(()()())(())(()()()()())(())(())(())(())(()()()()())(())(())(()()())(())(())(()()())(())(()()()()())(()())(()()()()())(())(()()())(())(()()()()())(())(())(())(())(())(())(()())(())(())(())(()())(()()()())(())(()()()()())(()())(()())(()())(()()())(())(()())(())(()()()()())(()())(()()()()())(())(())(())(())(())(()())(())(())(())(()()()()())(())(())(()()()()())(())(())(()()()()())(())(())(()())(())(()())(())(()())(())(()())(())(()())(()())(()())(()())(()())(()())(()())(()())(())(()()()()())(())(())(()()())(())(())(()()())(())(()()()()())(()())(()()()()())(())(()()())(())(())(()()())(()())(())(()()()()())(())(())(()()())(())(())(()()())(())(()()()()())(()())(()()()()())(())(())(())(()()())(())(())(()()())(())(())(()()())(())(()()()()())(()())(()()()()())(()()())(())(()()())(())(())(())(()())(()()())(()())(())(()()()()())(()())(())(()()())(())(()()()()())(())(())(())(()()())(())(())(())(()())(())(()())(()()()())(())(())(()()()()())(()())(()())(())(()()())(())(())(())(())(()()())(()())(())(())(()()()()())(())(())(()()()()())(())(())(()()()()())(())(())(()())(())(()())(())(()())(())(()())(()())(()())(()())(())(()()()()())(()())(())(()()())(())(()()()()())(()()()()())(())(()()())(())(())(()())(())(()()()()())(())(()()()()())(())(())(())(()()()()())(())(())(()())(())(()())(())(()())(())(()())(())(()())(()())(()())(()())(())(()()()()())(()())(())(()()())(())(())(()())(())(()()()()())(()())(()()()()())(())(()()())(())(())(()()()()())(())(()()()()())(())(())(())(()())(())(()()()()())(())(())(()())(())(()())(())(()())(()())(()())(()())(())(()()()()())(()())(())(()()()()())(())(()()())(())(())(()())(())(()()()()())(()())(()()()()())(())(()()())(())(())(())(()())(()()()())(())(())(()())(())(()()()()())(())(())(()()()()())(())(())(()()()()())(())(())(()())(())(()())(())(()())(())(()())(())(()())(()())(()())(()())(()())(()())(())(()()())(())(())(()())(())(()()()()())(()())(()()()()())(()()())(())(())(()())(())(())(()()()()())(()()()())(()())(()())(()()())(())(()())(())(()()()()())(()())(()()()()())(())(())(())(()()()())(()()()())(()()
718 2

Is the stack initialised with a 0? Otherwise [()] breaks the rule that we don't need to worry about popping from an empty stack

@JoKing Yep: "At the beginning of execution the third stack contains only a single 0". Maybe I should highlight that part a bit, I was afraid it would have been too easy to miss.

Oops, I don't know how I missed that

Crossed out e is still e.

If anyone can't see that, the crossed out e is here.

Is an empty stack acceptable output for an empty program? The stack should be a single zero by this spec. Or are we to expect a non-empty Third-Flak program?

@Giuseppe let's say that the program is not empty, and do whatever is golfiest for you :)

Brain-Flak, 276 bytes
{({}<>)<>}<>{(((()()()()()){})((({}){})())(({})({}{}([{}])(<>))))((()()(){[()]<{}>}{}){()<{{}}>}{}<<>({}({})())>{()(<{}>)}{}<>)<>}<>{(([{}]()<>)){{}({}())((){[()](<({}())((){[()](<({}())((){[()](<{}([{}]{})>)}{}){(<{}{}>)}{}>)}{}){(<{}({}{})>)}{}>)}{}){(<{}{}({}())>)}}{}<>}<>

Try it online!
You had to know this was coming.

Python 3, 145 144 132 122 116 109 104 bytes
-7 bytes thanks to Leo!
And - 5 thanks to Lynn!
s=[0]
for i in input().replace('()',' '):s+=i in']>) 'and(i<'!'or(2-ord(i)%5)*s.pop())+s.pop(),
print(s)

Try it online!
Pretty standard implementation. Not so readable now though. I'm disappointed I couldn't figure out a shorter way to check between start and end brackets though.
Some attempts at one-liners:

124 bytes (anonymous function):
lambda c:[s.append(i in']>) 'and(i<'!'or~-']>)'.index(i)*s.pop())+s.pop())or s for s in[[0]]for i in c.replace('()',' ')][0]

115 bytes (full program):
s=[0];[s.append(i in']>) 'and(i<'!'or~-']>)'.index(i)*s.pop())+s.pop())for i in input().replace('()',' ')];print(s)

Append is annoyingly longer than plain assignment

~-']>)'.index(i) can be (2-ord(i)%5) to save 4 bytes.

Retina 0.8.2, 64 48 46 bytes
\(\)
_
[([<]
¶
+1`¶(.*)\)|(.*)¶\2]|¶.*>
$1
%`_

Try it online! Outputs the stack from bottom to top. Only works with non-negative integers, and the last test case is too slow, so the link only includes three test cases. Explanation: The stack implicitly precedes the program, so it starts off as the empty string, which represents a single zero. The () nilad is turned into a _ which is used to count in unary, while the other open brackets are turned into newlines which push a zero on to the stack as they are encountered. The close brackets are then processed one at a time so that the stack will be correct; the ) deletes the previous newline, adding the top two elements together, the ] deletes the top element and matches it from the previous element on the stack thus subtracting it, and the > just deletes the top element. Finally the stack is converted to decimal. Edit: Saved 2 bytes thanks to @Leo.

What's the $3 for? (great answer, anyway!)

@Leo That's a left-over from a previous golf. Thanks for spotting it!

Ruby, 98 91 bytes
->s{a=[i=0];s.chars{|c|a<<("([<"[c]?s[i,2]["()"]?1:0:a.pop*~-"]>)".index(c)+a.pop);i+=1};a}

Try it online!
My initial code worked similarly in spirit to Jo King's Python answer, so that before looping through the source chars we replaced all () substrings by another character, as a distinct operator.
However, at least in Ruby, it turned out golfier not to do this, but rather go for a slightly more cumbersome approach. Here, we maintain an additional indexer i keeping track of our position in the source string, and whenever an opening bracket is encountered, we do a lookahead checking if our current+next chars s[i,2] form the () operator. In that case we push 1 instead of 0 on top of the stack, and let the closing ) do its job in the next step.

R, 182 177 bytes
function(P){for(k in utf8ToInt(gsub("\\(\\)",7,P))%%8){if(k%in%0:4)F=c(0,F)
if(k==7)F[1]=F[1]+1
if(k==1)F=c(F[2]+F[3],F[-3:0])
if(k==5)F=c(F[2]-F[1],F[-2:0])
if(k==6)F=F[-1]}
F}

Try it online!
Returns the stack, where the top of the stack is first and the bottom of the stack is last.
Swaps () with 7 and then computes the code points mod 8 to get distinct
numeric values, which are easier and golfier to work with than strings.
It's golfier to work with the beginning of a vector in R, so we construct the stack that way.
Then it sees a ), or when k==1, it adds an extra zero to the top of the stack since it's golfier to add it and remove it.

05AB1E, 25 bytes
Î„()1:v"0+0\0->"žuykè.V})

Try it online!
Explanation
Î                           # initialize the stack with 0 and the input
 „()1:                      # replace any occurrence of "()" in the input with 1
      v                }    # for each char y in this string
                žuyk        # get its index in the string "()[]<>{}"
       "0+0\0->"    è       # use this to index into the string "0+0\0->"
                     .V     # eval
                        )   # wrap the stack in a list

SOGL V0.12, 34 bytes
0,Ƨ() Iŗ{"(<[”č0ŗΖ)+ŗ ] -ŗΖ>Xŗ!!}⁰

Try it Here!

CJam, 29 bytes
0q")]>([<""+-;U"er"U+"/')*~]p

Try it online!
0q                              Push 0, input
  ")]>([<""+-;U"er              Translate )]>([< to +-;UUU
                  "U+"/')*      Replace U+ by )
                          ~     Eval as CJam code
                           ]p   Wrap and pretty-print stack

Ceylon, 285 266 bytes
function f(variable String c){variable Integer[]s=[0];value o=>[s[0]else nothing,s=s.rest][0];void u(Integer i)=>s=[i,*s];while(c!=""){if(c[0:2]=="()"){u(1);c=c.rest;}switch(c[0])case(')'){u(o+o);}case(']'){u(-o+o);}case('>'){noop(o);}else{u(0);}c=c.rest;}return s;}

Try it online!
(Saved 19 bytes due to a suggestion by Leo.)
Formatted and commented:
// Interpreter for ThirdFlak
// Question:    https://codegolf.stackexchange.com/q/163242/2338
// This answer: https://codegolf.stackexchange.com/a/163403/2338
//
// This function takes the code as a string, and returns the value
// of the stack as a sequence of Integers.
function f(variable String c) {
    // stack, in the beginning just a single 0.
    // Top element of the stack is the first, because push + pop is easier this way.
    variable Integer[] s = [0];
    // pop – used like an Integer variable (not a function – this saves the `()`), but has side effects.
    value o =>
        // `s[0]` is the first element of the stack. We tell the compiler
        // that it is non-null (otherwise we'll get an error at run time)
        // using the `else nothing`. `s.rest` is `s` without its first element.
        // Both together are wrapped into a 2-tuple, of which we then take just
        // the first element, to have both together in an expression instead
        // the longer way using an accessor block with a temporary variable and a return.
        // value o {
        //   value r = s[0] else nothing;
        //   s = s.rest;
        //   return r;
        // }
        [s[0] else nothing, s = s.rest][0];
    // push
    void u(Integer i) =>
        // a tuple enumeration, using the spread argument.
        s = [i, *s];
    // the main loop
    while (c != "") {
        if (c[0:2] == "()") {
            // »`()` is the only two-characters operator in Third-Flak. It increases the top of the third stack by 1.«
            // As `)` alone adds the two top elements together, we can just push a one here, and let the handling for `)` do the rest.
            u(1);
            c = c.rest;
        }
        switch (c[0])
        case (')') {
            // »`)` pops two elements from the third stack and pushes back their sum.«
            u(o + o);
        }
        case (']') {
            // »`]` pops two elements from the third stack and pushes back the result of subtracting the first from the second.«
            // As the o written first is the first one, we can't write this as a subtraction.
            u(-o + o);
        }
        case ('>') {
            // »`>` pops an element from the third stack.«
            // `o;` alone is not a valid statement, so we pass it to the `noop` function.
            noop(o);
        }
        else {
            // all other valid code characters are `(`, `[`, `<`, which all just push a 0.
            u(0);
        }
        c = c.rest;
    }
    return s;
}

Try it online!

I don't really know Ceylon, but maybe you could remove the first case of the switch and use the else part to manage all opening brackets :)

Hmm, I guess that could work ... it would change the behavior for invalid input, but that is not a problem.

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/


text:
Matrix in "slash" order
Given two positive numbers N >= 2 and N <= 100 create a matrix which follows the following rules:

First Number starts at position [0,0]
Second Number starts at position [0,1]
Third number goes below First Number (position [1,0])
Following numbers goes in "slash" direction
Range of numbers used is [1, N1 * N2]. So, numbers goes from starting 1 to the result of the multiplication of both inputs.

Input

Two numbers N >= 2 and N <= 100. First number is the amount of rows, Second number the amount of columns.

Output

Matrix. (Can be outputted as a multidimensional array or a string with line breaks)

Example:
Given numbers 3 and 5 output:
1   2   4   7   10
3   5   8   11  13
6   9   12  14  15

Given numbers 2 and 2
1   2
3   4

Given Numbers 5 and 5
1   2   4   7   11
3   5   8   12  16
6   9   13  17  20
10  14  18  21  23
15  19  22  24  25

The shortest code in bytes wins.

Btw, is there a better name for this challenge? I dont know how to call it.

Can we use 0 indexing for any of the numbers?

@JoKing No. Must start at 1.

Very closely related.

@LuisfelipeDejesusMunoz Perhaps a better term for the order is "diagonals"? Personally, I'd call it a "zig-zag", because it reminds me of Cantor's Zig-Zag proof, but that might confusing.

@LuisfelipeDejesusMunoz anti-diagonal is the term for the other diagonal.

Jelly, 6 5 bytes
pSÞỤs

Try it online!
How it works
pSÞỤs  Main link. Left argument: n. Right argument: k

p      Take the Cartesian product of [1, ..., n] and [1, ..., k], yielding
       [[1, 1], [1, 2], ..., [n, k-1], [n, k]].
 SÞ    Sort the pairs by their sums.
       Note that index sums are constant on antidiagonals.
   Ụ   Grade up, sorting the indices of the sorted array of pairs by their values.
    s  Split the result into chunks of length k.

Damn. Mine is 200+ bytes. Can you add some explanation pls?

I've edited my answer.

God damn it, Dennis. Also, good job.

@LuisfelipeDejesusMunoz Looks like you're not using Jelly. Some languages are verbose by default, don't worry about that.

Wow, it is too "closely related". That's identical to the first link in miles' answer. Consider upvoting both. :)

I think it might be possible to do this with <atom><atom>¥þ but I can't find the right combination. oþ++þ is close but doesn't quite get there

Seems like this answer won.

I'm a little confused on what Ụ does. So up to that point for say a matrix dim(2,3) you would have [[1, 1], [1, 2], [1, 3], [2, 1], [2, 2], [2, 3]] which you sort by the sum of their pairs. I assume that the sort 1.is low to high 2. tie leaves first appearance first giving [[1, 1], [1, 2], [2, 1], [1, 3], [2, 2], [2, 3]]. Am I right up to here? What happens after this step?

@akozi So far, so good. The indices of the sorted array are [1, 2, 3, 4, 5, 6]. Ụ sorts this array, using the key that maps 1 to [1, 1], 2 to [1, 2], 3 to [2, 1], etc. Essentially, this finds the index of each pair from the sorted-by-sums array in the sorted-lexicographically array

So you map the numbers 1-n*k to the unsorted list based on the sorted list then split the unsorted list back into rows of length k?

@akozi Basically, yes.

Python 3, 91 bytes
def f(n,k):M=[(t//k+t%k,t)for t in range(n*k)];return zip(*k*[map([M,*sorted(M)].index,M)])

Try it online!

R, 101 60 54 bytes
function(M,N)matrix(rank(outer(1:M,1:N,"+"),,"l"),M,N)

Try it online!
Thanks to @nwellnhof for the suggestion of rank
Ports Dennis' Jelly answer.
Old answer, 101 bytes:
function(M,N)matrix(unsplit(lapply(split(1:(M*N),unlist(split(x,x))),rev),x<-outer(1:M,1:N,"+")),M,N)

Try it online!
split is doing most of the work here; possibly there's a golfier algorithm but this definitely works.
Explanation:
function(M,N){
x <- outer(1:M,1:N,"+")			# create matrix with distinct indices for the antidiagonals
idx <- split(x,x)			# split into factor groups
items <- split(1:(M*N),unlist(idx))	# now split 1:(M*N) into factor groups using the groupings from idx
items <- lapply(items,rev)		# except that the factor groups are
					# $`2`:1, $`3`:2,3, (etc.) but we need
                                        # $`2`:1, $`3`:3,2, so we reverse each sublist
matrix(unsplit(items,x),M,N)		# now unsplit to rearrange the vector to the right order
					# and construct a matrix, returning the value
}

Try it online! -- you can use wrap a print around any of the right-hand sides of the assignments <- to see the intermediate results without changing the final outcome, as print returns its input.

Can you add some explanation pls?

@LuisfelipeDejesusMunoz added. If there's anything unclear, let me know and I'll try and clarify.

rank(x,1,"f") is 2 bytes shorter than order(order(x)).

@nwellnhof oh, very nice, but using rank(x,,"l") will get rid of the t as well.

Java 10, 121 120 109 105 bytes
m->n->{var R=new int[m][n];for(int i=0,j,v=0;i<m+n;)for(j=++i<n?0:i-n;j<i&j<m;)R[j][i-++j]=++v;return R;}

-11 bytes thanks to @OlivierGrégoire.
-4 bytes thanks to @ceilingcat.
Try it online.
Explanation:
m->n->{                // Method with two integer parameters and integer-matrix return-type
  var R=new int[m][n]; //  Result-matrix of size `m` by `n`
  for(int i=0,j,       //  Index integers, starting at 0
          v=0;         //  Count integer, starting at 0
      i<m+n;)          //  Loop as long as `i` is smaller than `m+n`
    for(j=++i<n?0      //   Set `j` to 0 if `i+1` is smaller than `n`
               :i-n;   //   or to the difference between `i` and `n` otherwise
        j<i&j<m;)      //   Inner loop `j` until it's equal to either `i` or `m`,
                       //   so basically check if it's still within bounds:
      R[j][i-++j]=++v; //    Add the current number to cell `j, i-(j+1)`
  return R;}           //  Return the result-matrix

I realized this takes columns first and then rows.

@Luis I think it's convention to take coordinates as x,y/width,height

109 bytes

J, 15 bytes
$1(+/:@;)</.@i.

-4 more bytes for this solution by miles. Thanks!
Try it online!
J, 22 19 bytes
-3 bytes thanks to FrownyFrog!
,$[:>:@/:@/:@,+/&i.

Try it online!
An implementation of Dennis' fantastic Jelly solution in J.
Explanation:
Dyadic verb, takes left and right argument (m f n)
+/&i. creates lists 0..m-1 and 0..n-1 and makes an addition table for them:
   3 +/&i. 5
0 1 2 3 4
1 2 3 4 5
2 3 4 5 6

[:>:@/:@/:@, flattens the table and grades the list twice and adds 1 to it:
   3 ([:>:@/:@/:@,+/&i.) 5
1 2 4 7 10 3 5 8 11 13 6 9 12 14 15

,$ reshapes the list back into mxn table:
   3 (-@],\[:>:@/:@/:@,+/&i.) 5
1 2  4  7 10
3 5  8 11 13
6 9 12 14 15

-@],\ → ,$ for −3 bytes.

@FrownyFrog - Of course, I feel stupid, it's so obvous now. Thank you!

15 bytes $1(+/:@;)</.@i. with input as an array [r, c]

@miles: Very cool, thanks! I tried /. but could't achieve your result :)

APL+WIN, 38 or 22 bytes
Prompts for integer input column then row:
m[⍋+⌿1+(r,c)⊤m-1]←m←⍳(c←⎕)×r←⎕⋄(r,c)⍴m

or:
(r,c)⍴⍋⍋,(⍳r←⎕)∘.+⍳c←⎕

based on Dennis's double application of grade up. Missed that :(

Sorry for the question but is there somewhere I can test it?

@Luis felipe De jesus Munoz No problem. APL+WIN is not available on line but you can test it on the Dyalog website at http://tryapl.org/ if you replace the ⎕ characters with the integers of your choice.

APL (Dyalog Unicode), 14 12 bytes
{⍵⍴⍋⍋∊+/↑⍳⍵}

Try it online!
-2 thanks to ngn, due to his clever usage of ↑⍳.
Based off of Dennis's 5-byte Jelly solution.

∘.+⌿⍳¨⍵ -> +/↑⍳⍵

@ngn Wow, that's a clever usage of ⍳ combined with ↑.

Wolfram Language (Mathematica), 73 67 bytes
Count elements in rows above: Min[j+k,#2]~Sum~{k,i-1}
Count elements on the current row and below: Max[j-k+i-1,0]~Sum~{k,i,#}
Put into a table and add 1. Voila:
1+Table[Min[j+k,#2]~Sum~{k,i-1}+Max[j-k+i-1,0]~Sum~{k,i,#},{i,#},{j,#2}]&

Update: I realized there is a shorter way to count all the positions ahead of a normally specified position in the matrix with just one sum over two dimensions:
Table[1+Sum[Boole[s-i<j-t||s-i==j-t<0],{s,#},{t,#2}],{i,#},{j,#2}]&

Try it online!
Try it online!

05AB1E, 23 bytes
*L<DΣ¹LILâOsè}UΣXsè}Á>ô

Try it online!

Python 3, 164 bytes
from numpy import*
r=range
def h(x,y):
 a,i,k,j=-array([i//y+i%y for i in r(x*y)]),1,2,0
 while j<x+y:a[a==-j],i,k,j=r(i,k),k,k+sum(a==~j),j+1
 a.shape=x,y;return a

Try it online!
This is definitely not the shortest solution, but I thought it was a fun one.

from numpy import* and dropping both n. is slightly shorter. Also, you can drop the space at ) for. And changing to Python 2 allows you to change return a to print a (in Python 3 it would be the same byte-count print(a)).

Thanks! I should have thought of import*. I'll never beat Dennis' answer, so I'll stick to Python 3.

TI-Basic, 76 bytes
Prompt A,B
{A,Bdim([A]
1X
For(E,1,B+A
For(D,1,E
If D≤A and E-D<B
Then
X[A](D,E-D+1
X+1X
End
End
End
[A]

Prompts for user input and returns the matrix in Ans and prints it.
TI-Basic is a tokenized language; all tokens used here are one byte, other than [A] which is 2 bytes.
Note: TI-Basic (at least on the TI-84 Plus CE) only supports matrices up to 99x99, and so does this program.
Explanation:
Prompt A,B        # 5 bytes, prompt for user input
{A,Bdim([A]      # 9 bytes, make the matrix the right size
1X               # 4 bytes, counter variable starts at 1
For(E,1,B+A       # 9 bytes, Diagonal counter, 1 to A+B-1, but we can over-estimate since we have to check later anyway.
For(D,1,E         # 7 bytes, Row counter, 1 to diagonal count
If D≤A and E-D<B  # 10 bytes, Check if we are currently on a valid point in the matrix
Then              # 2 bytes, If so,
X[A](D,E-D+1     # 13 bytes, Store the current number in the current point in the matrix
X+1X             # 6 bytes, Increment counter
End               # 2 bytes, End dimension check if statement
End               # 2 bytes, End row for loop
End               # 2 bytes, End dimension for loop
[A]               # 2 bytes, Implicitly return the matrix in Ans and print it

Python 2, 93 bytes
def f(b,a):i=1;o=[];exec"if b:o+=[],;b-=1\nfor l in o:k=len(l)<a;l+=[i]*k;i+=k\n"*a*b;print o

Try it online!
Semi-Ungolfed version:
def f(b,a):
    i=1
    o=[]
    for _ in range(a*b)
        if b:
            o+=[[]]
            b-=1

        for l in o:
            if len(l)<a:
                l+=[i]
                i+=1
    print o

Japt, 25 24 bytes
Hardly elegant, but gets the job done. Working with 2D data in Japt is tricky.
;N×Ç<U©Ap[] A®Ê<V©Zp°T
A

;                      // Set alternative default vars where A is an empty array.
 N×Ç                   // Multiply the inputs and map the range [0..U*V).
    <U                 // If the current item is less than the second input,
      ©Ap[]            // add a new empty subarray into A.
            A®         // Then, for each item in A,
              Ê<V      // if its length is less than the first input,
                 ©Zp°T // Add the next number in the sequence to it.
A                      // Output the results, stored in A.

I added the -Q flag in TIO for easier visualization of the results, it doesn't affect the solution.
Bit off one byte thanks to Oliver.
Try it online!

Speaking of ×, you can replace *V  with N×.

@Oliver And here I was, thinking that shortcut is handy, but not a common use case. Thanks a lot!

JavaScript (Node.js), 103 bytes
(a,b,e=[...Array(b)].map(_=>[]))=>f=(x=0,y=i=0)=>(x<a&y<b&&(e[y][x]=++i),x?f(--x,++y):y>a+b?e:f(++y,0))

Try it online!

Perl 6, 61 59 bytes
{($!={sort($_ Z=>1..*)>>.{*}})($!([X+] ^<<$_)).rotor(.[1])}

Try it online!
Another port of Dennis' Jelly solution.

Java (JDK 10), 142 131 bytes
X->Y->{var A=new int[X][Y];int E=1;for(int y=0;y<Y+X-1;y++)for(int x=0;x<X;x++){if(y-x<0|y-x>Y-1)continue;A[x][y-x]=E++;}return A;}

Try it online!
Explanation:

X->Y->{                            // Method with two integer parameters and integer-matrix return-type
    var A=new int[X][Y];           // The Matrix with the size of X and Y
    int E=1;                       // It's a counter
        for(int y=0;y<Y+X-1;y++)   // For each column plus the number of rows minus one so it will run as long as the bottom right corner will be reached
            for(int x=0;x<X;x++){  // For each row
                if(y-x<0|y-x>Y-1)  // If the cell does not exist becouse it's out of range
                    continue;      // Skip this loop cycle
                A[x][y-x]=E++;     // Set the cell to the counter plus 1
            }
    return A;                      // Return the filled Array
}

Big thank to Kevin Cruijssen because I didn't know how to run my code on tio.Some code like the header and footer are stolen from him. -> His answer

119 bytes: https://tio.run/##jVA9b4MwFNz7K143W4CVj2apAYkhlTp0ygJCHlwCkVNikDEpVprfTh3iKqnUoZL15Hv37Lt7e37kwX77MRY17zp440KeHgA6zbUoYG9Z0mtRk6qXhRaNJC/uEr5KXe5K5f9vSEids5zFMRQQwZgGcRbEpyNXkESy/Jz4lOUZo1WjkEWwjua@iWbUhJmXBnNqPA//cIPtD2FKB9sTFXpEJhjC2Zet9ts5xkk@sNwiFq09j6pS90pCQs8jtdnsafv32sZzKY@N2MLBJkcbrYTc5YzjyxIAdNlptPSfML3Blb@8hwt/8ZtdTfB8FbpXmPiL@8y/1NRpuExW9LkgvG1rgzLsLinG0wzAxnS6PJCm16S1HnUt0W3viVLcdEQ3V/@IY2fpj1fO3Xn8Bg

105 bytes

Husk, 9 bytes
ṠCoηÖ¤×,ḣ

Try it online! Most of the heavy lifting is done by ×, which creates pairs in the desired order so that it can support infinite lists.
Explanation
CηÖ×,ḣ²ḣ⁰⁰  (Expanded; let N and K denote the arguments.)
 ηÖ          Take the list of indices of the sorted values of
   ×,         the list of all pairs taken from
     ḣ²        the range from 1 to N and
       ḣ⁰      the range from 1 to K, and
C        ⁰  cut it into lengths of K.

PHP, 115 bytes
a pretty lazy approach; probably not the shortest possible.
function($w,$h){for(;$i++<$h*$w;$r[+$y][+$x]=$i,$x--&&++$y<$h||$x=++$d+$y=0)while($x>=$w|$y<0)$y+=!!$x--;return$r;}

anonymous function, takes width and height as parameters, returns 2d matrix
try it online

JavaScript (Node.js), 108 105 101 100 bytes
n=>(l=>{for(r=[];i<n*n;n*~-n/2+2>i?l++:l--*y++)for(T=y,t=l;t--;)r[T]=[...r[T++]||[],++i]})(y=i=0)||r

Try it online!

Attache, 45 bytes
{Chop[Grade//2<|Flat!Table[`+,1:_2,1:_],_]+1}

Try it online!
Anonymous lambda, where paramaters are switched. This can be fixed for +1 byte, by prepending ~ to the program. The test suite does this already.
Explanation
This approach is similar to the J answer and the Jelly answer.
The first idea is to generate a table of values:
Table[`+,1:_2,1:_]

This generates an addition table using ranges of both input parameters. For input [5, 3], this gives:
A> Table[`+,1:3,1:5]
 2 3 4 5 6
 3 4 5 6 7
 4 5 6 7 8

Then, we flatten this with Flat!:
A> Flat!Table[`+,1:3,1:5]
[2, 3, 4, 5, 6, 3, 4, 5, 6, 7, 4, 5, 6, 7, 8]

Using the approach in the J answer, we can grade the array (that is, return indices of sorted values) twice, with Grade//2:
A> Grade//2<|Flat!Table[`+,1:3,1:5]
[0, 1, 3, 6, 9, 2, 4, 7, 10, 12, 5, 8, 11, 13, 14]

Then, we need to chop the values up correctly, as in the Jelly answer. We can cut every _ elements to do this:
A> Chop[Grade//2<|Flat!Table[`+,1:3,1:5],5]
 0 1  3  6  9
 2 4  7 10 12
 5 8 11 13 14

Then, we just need to compensate for the 0-indexing of Attache with +1:
A> Chop[Grade//2<|Flat!Table[`+,1:3,1:5],5]+1
 1 2  4  7 10
 3 5  8 11 13
 6 9 12 14 15

And thus we have the result.

Python 3, 259 bytes
So I did this a weird way. I noticed that there were two patterns in the way the array forms.
The first is how the top rows pattern has the difference between each term increasing from 1 -> h where h is the height and l is the length. So I construct the top row based on that pattern
For a matrix of dim(3,4) giving a max RoC = 3 We will see the top row of the form
1, (1+1), (2+2), (4+3) = 1, 2, 4, 7

Suppose instead that the dim(3,9) giving a max RoC = 3 we will instead see a top row of
`1, (1+1), (2+2), (4+3), (7+3), (10+3), (13+3), (16+3), (19+3) = 1, 2, 4, 7, 10, 13, 16, 19, 22

The second pattern is how the rows change from one another. If we consider the matrix:
1   2   4   7   11
3   5   8   12  16
6   9   13  17  20
10  14  18  21  23
15  19  22  24  25

and subtract each row from the row below (ignoring the extra row) we get
2 3 4 5 5
3 4 5 5 4
4 5 5 4 3
5 5 4 3 2

Upon seeing this matrix we can notice this matrix is the sequence 2 3 4 5 5 4 3 2 where by each row is 5 terms of this pattern shifted by 1 for each row. See below for visual.
         |2 3 4 5 5| 4 3 2
       2 |3 4 5 5 4| 3 2
     2 3 |4 5 5 4 3| 2
   2 3 4 |5 5 4 3 2|

So to get the final matrix we take our first row we created and output that row added with the 5 needed terms of this pattern.
This pattern will always have the characteristics of beginning 2-> max value and ending max value -> 2 where the max value = min(h+1, l) and the number of times that the max value will appear is appearances of max = h + l -2*c -2 where c = min(h+1, l) - 2
So in whole my method of creating new rows looks like
1  2  3  7  11 +      |2 3 4 5 5|4 3 2  = 3  5  8  12 16

3  5  8  12 16 +     2|3 4 5 5 4|3 4 2  = 6  9  13 17 20

6  9  13 17 20 +   2 3|4 5 5 4 3|4 2    = 10 14 18 21 23

10 14 18 21 23 + 2 3 4|5 5 4 3 2|       = 15 19 22 24 25

Relevant code below. It didn't end up being short but I still like the method.
o,r=len,range
def m(l,h):
 a,t=[1+sum(([0]+[x for x in r(1,h)]+[h]*(l-h))[:x+1]) for x in r(l)],min(l,h+1);s,c=[x for x in r(2,t)],[a[:]]
 for i in r(h-1):
  for j in r(o(a)):
   a[j]+=(s+[t]*(l+h-2*(t-2)-2)+s[::-1])[0+i:l+i][j]
  c+=[a[:]]
 for l in c:print(l)

Try it online!

Japt, 20 bytes
õ ïVõ)ñx
£bYgUñ¹ÄÃòV

Try it

Haskell, 92 bytes
r=[1..]
(#)=take
n!k=[[sum$lookup(i,j)$zip[(i,j)|s<-r,i<-n#r,j<-k#r,i+j==s]r|j<-k#r]|i<-n#r]

Try it online!


text:
Area enclosed by perimeter loop
Find the area of a region of unit cells given its perimeter loop as a sequence of 90-degree turns.
For example, take the three-cell region
XX
X

whose perimeter loop we draw
L<S<L
v   ^
S R>L
v ^
L>L

Each turn is marked as left (L), straight (S), or right (R). Starting from the R, the turns are RLLSLSLL. So, given input RLLSLSLL, we should output 3 for the area.
The input sequence is guaranteed to trace out a loop enclosing a single region on its left.

The path ends back at the start point, facing the initial direction, forming a loop.
The loop does not cross or touch itself.
The loop goes counterclockwise around a region.

I/O
You can take input as a list or string of characters LSR, or as  numbers -1, 0, 1 for left, straight, right. Output is a positive integer. Floats are OK.
Test cases
The inputs are given in both formats followed by their respective outputs.
RLLSLSLL
LLLL
SLLSLL
LSRRSLLSSLSSLSSL
SSSSSLSSSSSLSSSSSLSSSSSL

[1, -1, -1, 0, -1, 0, -1, -1]
[-1, -1, -1, -1]
[0, -1, -1, 0, -1, -1]
[-1, 0, 1, 1, 0, -1, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1]
[0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1]

3
1
2
7
36

Brain-Flak, 112 bytes
(([]){[{}]<{({}()){{}<>([{}]<([{}])>)(<>)}<>(({}[({})])[({}{})])<>}{}<>>({}<({}())>)<>([])}{})({()<({}()())>}{})

Try it online!
This program uses Green's theorem to compute the area
The current location is stored on the right stack, in a format that depends on the direction faced.
Direction  top  second
north       -x       y
west        -y      -x
south        x      -y
east         y       x

In all instances, the second value on the stack will increase by 1, and the line integral for the area decreases by half the value on the top of the stack.  To compensate, the end of the program divides the running total by -2.
# For each number in input
(([]){[{}]

  # Evaluate turn-handling to zero
  <

    # If turn:
    {

      # If right turn:
      ({}()){{}

        # Negate both values on other stack (reverse direction)
        <>([{}]<([{}])>)

      (<>)}

      # Swap the two stack elements and negate the new top of stack
      # This performs a left turn.
      <>(({}[({})])[({}{})])<>

    }{}

  <>>

  # Evaluate as top of stack and...
  ({}<

    # increment the number below it
    ({}())

  >)<>

([])}{})

# Divide total by -2
({()<({}()())>}{})

APL (Dyalog Classic), 30 28 19 bytes
-2 thanks to @Adám
(+/9∘○×11○+\)0j1*+\

Try it online!
uses tricks with complex numbers to compute the coordinates
the area is ½Σ(xi-xi+1)(yi+yi+1) or equivalently Σ(xi-xi+1)yi as the lines are only horizontal or vertical

Save to by converting to tradfn body.

@Adám right, I was hoping for a train and somehow forgot to do that...

@Adám ah! I found the train :)

JavaScript (ES6), 52 50 bytes
Saved 2 bytes thanks to @Neil
Expects the second input format.
a=>a.map(k=>r+=(2-(a=a+k&3))%2*(y+=~-a%2),r=y=0)|r

Try it online!
How?
This description applies to the previous version: x and y have since been inverted.
This is based on the formula already mentioned by @ngn: A = Σ(xi - xi+1)yi, which can also be written as Σdxiyi where dxi is either -1, 0 or 1.
We start with r = y = 0.
We keep track of the current direction in a:
          | a = 0 | a = 1 | a = 2 | a = 3
----------+-------+-------+-------+-------
direction | East  | South | West  | North
       dx |  +1   |   0   |  -1   |   0     <--  -(~-a % 2)
       dy |   0   |  +1   |   0   |  -1     <--  (2 - a) % 2

It is updated with a = a + k & 3, where k is the current element of the input array.
Because a initially contains the input array, a + k is coerced to NaN on the first iteration and then to 0 when the bitwise AND is applied. This means that the first direction change is actually ignored and we always start heading to East. It doesn't matter because the area remains the same, no matter the orientation of the final shape.
Then, we update y with y += (2 - a) % 2.
Finally, we compute -dx with ~-a % 2 and subtract y * -dx from r, which -- at the end of the process -- is our final result.

a=>a.map(k=>r+=(2-(a=a+k&3))%2*(y+=~-a%2),r=y=0)|r saves 2 bytes.

Python 2, 64 bytes
f=lambda c,d=1,x=0:c>[]and f(c[1:],d*1j**c[0],x+d.real)-x*d.imag

Try it online!
Computes ∑xΔy using complex numbers.

Haskell, 71 70 69 bytes
a 0 0
a x d(t:r)|k<-t+d=x*g k+a(x+g(k-1))k r
a _ _ _=0
g a=sin$a*pi/2

Explanation:
Green's Theorem gives the formula for the area : A = ½∑(xk+1+xk)(yk+1-yk), which simplifies to A = ½∑Δx=02xkΔy + ½∑Δy=0(xk+1+xk)*0 = ∑xΔy when turns are 90 degrees along the axes. We have the following pseudocode for a recursive turn-globbing function that keeps track of the x position and direction:
A x dir (turn:turns) = ΔA + A (x+Δx) (dir+turn) turns

where the new direction, ΔA and Δx can be seen from the following tables. We can see a sinusoidal periodicity of length four in both ΔA and Δx along the diagonal axis, dir+turn, which is implemented using sin instead of modular arithmetic.
  ↔|L S R ΔA| L  S  R  Δx| L  S  R
←   ↓ ← ↑    -x  0  x      0 -1  0
↑   ← ↑ →     0  x  0     -1  0  1
→   ↑ → ↓     x  0 -x      0  1  0
↓   → ↓ ←     0 -x  0      1  0 -1

Try it online!

Wolfram Language (Mathematica), 36 30 bytes
Area@Polygon@AnglePath[.5Pi#]&

If you have an older version of Mathematica (~v10) you'll need Most@ in front of AnglePath to avoid closing the polygon. (Thanks to @user202729 for the tips).
original:
Try it online!
updated:
Try it online!

#.5Pi seems to work.

It looks like that it's possible to drop the Most too.

Jelly, 15 11 bytes
Thanks to @xnor for pointing out a useless step, saving 2 bytes
Thanks to @dylnan for saving another byte
Expects the second input format. Returns a float.
+\ı*Ḟ_\×ƊĊS

Try it online! or run all test cases
Commented
+\ı*Ḟ_\×ƊĊS  - main link, taking the input list   e.g. [1, -1, -1, 0, -1, 0, -1, -1]
+\           - cumulative sum                     -->  [1, 0, -1, -1, -2, -2, -3, -4]
  ı*         - compute 1j ** d,                   -->  [(0+1j), (1+0j), (0-1j), (0-1j),
               which gives a list of (-dy + dx*j)       (-1+0j), (-1+0j), (0+1j), (1+0j)]
         Ċ   - isolate the imaginary part (dx)    -->  [1, 0, -1, -1, 0, 0, 1, 0] (floats)
        Ɗ    - invoke the last 3 links as a monad
    Ḟ        - isolate the real part (-dy)        -->  [0, 1, 0, 0, -1, -1, 0, 1] (floats)
     _\      - negated cumulative sum (gives y)   -->  [0, -1, -1, -1, 0, 1, 1, 0]
       ×     - compute dx * y                     -->  [0, 0, 1, 1, 0, 0, 1, 0]
          S  - sum                                -->  3

Is keeping only the least 2 significant bits necessary?

+\ı*Ḟ_\×ƊĊS saves a byte

@xnor and dylnan Thank you for helping me golfing this submission. And extra thanks to xnor for the bounty!

Python 2, 62 bytes
f=lambda l,p=0,s=1:l>[]and(p/s).imag/2+f(l[1:],p+s,s*1j**l[0])

Try it online!
Similar to Lynn's solution, but using some complex arithmetic to extract the right component of the complex number in one go.

Pyth, 25 bytes
Uses the -1, 0, 1 input format.
s*Vm_sd._sMKm^.j)sd._QeMK

Try it here!

Pyth, 14 bytes
_smec^.j)sd2.:

Test suite
_smec^.j)sd2.:
              Q     implicit input
            .:      take all non-empty contiguous sublists
  m                map this operation onto each one:
   ec^.j)sd2
         s           the sum of the sublist
     ^.j)            raise it to the complex unit 1j to that power
    c      2         halve it
   e                take the imaginary part
_s                take the negated sum of the result

This expresses the area as the sum of -1/2 * g(sum(l)) over all contiguous sublists l over the input, where g does modular indexing into [0,1,0,-1]. The code implements g as g(x)=imag(1j**x). There may be a shorter method with direct modular indexing, using sin, or an arithmetic function on x%4.


text:
Checkers Checker
The goal of this challenge is to determine if a move is a legal English Checkers move.
This challenge will use an 8x8 board. A moved piece should be treated as a man (not a king) that can only move diagonally forward. The board will have 0 or more black pieces and 1 or more white piece. One white piece will be currently moving. The white piece can "jump" over one black piece diagonally in front of it if the square directly behind it is empty. It is possible to take a further jump from that position if there is another black piece in either direction diagonally in front of it. Capture is mandatory, so it is illegal to not take a jump that is available. However, it is not mandatory to take a path that maximizes the number of jumps. Basically, this means that if you make a jump and there is another possible jump from the ending position then that move is illegal. Piece positions use the following numbering scheme:

Rules
Inputs:

A list of numbers that represent black pieces.
A list of numbers that represent white pieces.
A starting position for the white piece
The ending position for the white piece

Output:

A truthy value if the move is valid, otherwise a falsey value

You can assume a white piece will always occupy the starting position.
If convenient, you can assume that the first white piece in the white piece list will contain the starting position instead of accepting input 3.
Standard code golf rules. Fewest bytes wins.

Test Cases
To illustrate, O is the starting position, X is the ending position, B are black pieces, and W are white pieces
Black pieces: []
White pieces: [5]
Move: (5, 1)
Output: True

Single move no jump
 X _ _ _
O _ _ _

B: [6]
W: [9]
M: (9, 2)
O: True

Single jump
 _ X _ _
_ B _ _
 O _ _ _

B: [2, 6]
M: (9, 2)
O: False

Illegal ending position on top of black piece
 _ X _ _
_ B _ _
 O _ _ _

B: [7, 14]
W: [17]
M: (17, 3)
O: True

Double jump
 _ _ X _
_ _ B _
 _ _ _ _
_ B _ _
 O _ _ _

B: [7, 14]
M: (17, 10)
O: False

Illegal jump, must take the next jump as well
 _ _ _ _
_ _ B _
 _ X _ _
_ B _ _
 O _ _ _

B: [4]
W: [8]
M: (8, 3)
O: False

Illegal jump across the board
 _ _ _ X
B _ _ _
 O _ _ _

B: [6, 7]
W: [6]
M: (10, 1)
O: True

Split decision p1
 X _ _ _
_ B B _
 _ O _ _

B: [6, 7]
M: (10, 3)
O: True

Split decision p2
 _ _ X _
_ B B _
 _ O _ _

B: [2]
W: [1]
M: (1, 3)
O: False

Sideways Jump
 O B X _

B: [6]
W: [1]
M: (1, 10)
O: False

Backwards Jump
 O _ _ _
_ B _ _
 _ X _ _

B: [6]
W: [9, 2]
M: (9, 2)
O: False

Illegal ending position on top of white piece
 _ X _ _
_ B _ _
 O _ _ _

B: []
W: [9, 6]
M: (9, 2)
O: False

Illegal jump over white piece
 _ X _ _
_ W _ _
 O _ _ _

B: [8, 15, 23, 24]
W: [27]
M: (27, 4)
O: True

Split decision long path
 _ _ _ X
_ _ _ B
 _ _ _ _
_ _ B _
 _ _ _ _
_ _ B B
 _ _ W _

B: [8, 15, 23, 24]
W: [27]
M: (27, 20)
O: True

Split decision short path
 _ _ _ _
_ _ _ B
 _ _ _ _
_ _ B _
 _ _ _ X
_ _ B B
 _ _ W _

I suggest a test-case like B=[8,15,23,24];W=[27] with each of M=[27,4] and M=[27,20] 1. it will give a change of direction. 2 it will answer a question I have: are both valid or must the longer be taken? ("Capture is mandatory, so it is illegal to not take a jump that is available" kind of suggests both are valid, although I don't know why you make it illegal not to capture if possible, so maybe you mean to take as many pieces as possible?)

Sorry I do not know how to play (English) checkers. Would you mind to adding some more details about what is a legal move.

Here is a summary of the test cases in STDIN-friendly format.

Capture is mandatory, so it is illegal to not take a jump that is available. what does "take a jump" mean?

@JonathanAllan
I think I addressed your question in the explanation and added the test cases.

@EriktheOutgolfer In checkers, if you can capture an enemy piece, you have to do so until it is not possible to capture any more pieces. In this context "take a jump" means "capture a piece", as far as I can tell.

just hard to understand

@Nit Well, challenges have to be self-contained (this has been added since when I commented).

What is the expected answer to [8, 15, 16, 23, 24], [27], (27, 11), [7, 15, 16, 23, 24], [27], (27, 11), [7, 8, 15, 16, 23, 24], [27], (27, 11)?

@tsh All of these should be false because it is possible to take a jump from the ending square (11). I will edit the question a bit to clarify. Basically, if there is a possible jump from the ending square then that move is not legal.

What about [10, 3], [14], 14, 7? Should it be truthy?

@tsh Should be truthy because it's not legal to jump off the board.

B: [4]
W: [8]
M: (8, 3)
should return true, wont it?

@DanielIndie that's right.

"Basically, this means that if there is a possible jump from an ending position then that move is illegal." Yes, but that's understating the situation. It's also illegal to move without jumping, even if that move ends where no jump is possible, if a jump is possible now.

That was challenging :)
* fixed bugs (added bytes)
JavaScript (Node.js), 197 193 191 185 181 186 bytes
f=(B,W,S,E,F=1)=>g(S).filter((x,i)=>B[I="includes"](x)&!B[I](t=g(x)[i])&!W[I](t)&&t>0?F+=f(B,W,t,E):0)[0]?F>1:g(S)[I](E)
g=S=>[S--,!(y=~-(e=S-3)/4%2|0)||S%4^3?y?e+1:e:0,S%4||y?y?e:e-1:0]

Try it online!

I think you can use >>2&1 instead of /4%2|0.

Testcase: [10, 3], [14], 14, 7 failed.

@tsh fixed :), if more test cases failed let me know

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/