Mountain range number

A number is a mountain range number if the inequalities satisfied by their consecutive digits alternate. In a way, looking at the number's digits should exhibit a /\/\/\... or a \/\/\/... pattern.

More formally, if our number n has \$k\$ digits

$$n = d_1d_2d_3\cdots d_k$$

then n is a mountain range number if

$$\begin{cases}d_1 > d_2 \\ d_2 < d_3 \\ d_3 > d_4 \\ \cdots \end{cases} \vee \begin{cases}d_1 < d_2 \\ d_2 > d_3 \\ d_3 < d_4 \\ \cdots \end{cases}$$

Your task

Given an integer with 3 or more digits, output a Truthy value if the number is a mountain range number or Falsy otherwise.


A positive integer n with 3 or more digits, in any reasonable format, e.g.

  • Integer
  • String
  • List of digits

Test cases


1324 -> Truthy
9191 -> Truthy
12121 -> Truthy
121212 -> Truthy
1212121 -> Truthy
19898 -> Truthy


(Added another Falsy test case as per the comments, some answers might not cover the 4422 test case)

123 -> Falsy
321 -> Falsy
4103 -> Falsy
2232 -> Falsy
1919199 -> Falsy
4422 -> Falsy

This is so shortest answer in bytes wins! Standard loopholes are forbidden.

  • 1
    \$\begingroup\$ May we take input as a list of digits rather than an integer? \$\endgroup\$ – Robin Ryder Feb 6 '20 at 17:03
  • 2
    \$\begingroup\$ @RobinRyder yes you may \$\endgroup\$ – RGS Feb 6 '20 at 17:10
  • 2
    \$\begingroup\$ @AdmBorkBork this one has an input relaxation (k>=3); also the other challenge is so old that many of the answers there wouldn't be close to competitive on this one; I'd actually rather remove the old one as a dupe of this. \$\endgroup\$ – Giuseppe Feb 6 '20 at 19:27
  • 1
    \$\begingroup\$ @Giuseppe That's what I was leaning towards as well, hence why I didn't hammer it. I have now just hammered the old one. Thanks! \$\endgroup\$ – AdmBorkBork Feb 6 '20 at 19:52
  • 1
    \$\begingroup\$ Related with a source restriction \$\endgroup\$ – Jo King Feb 7 '20 at 0:39

25 Answers 25


05AB1E, 6 bytes


Try it online!

With truthy and falsy reversed, this would be 5 bytes:



  • \$\begingroup\$ Good job! +1 Why would the truthy <> falsy reversal make it shorter? \$\endgroup\$ – RGS Feb 6 '20 at 17:38
  • 4
    \$\begingroup\$ @RGS 05AB1E has a single-byte built-in for x >= 0, but not for its negation x < 0. \$\endgroup\$ – Grimmy Feb 6 '20 at 17:39
  • \$\begingroup\$ I see, thanks for the tip. \$\endgroup\$ – RGS Feb 6 '20 at 17:40
  • \$\begingroup\$ I've used your answer to golf my answer in the same challenge with source restriction. If you want to post it as your own answer there I will of course revert back to my 7-byter and allow you to. \$\endgroup\$ – Kevin Cruijssen Feb 7 '20 at 7:38

R, 44 40 bytes

crossed out 44 is still regular 44

-1 byte thanks to Giuseppe.


Try it online!

Computes the differences of the signs of the differences of the input. These must all be equal to 2 or -2, i.e. the square must equal 4; checking that the square is >3 is sufficient.

If two consecutive digits are equal, there will be a 0 in the signs of differences, leading to a difference of signs of differences equal to 1 or -1. If three consecutive digits are in ascending or descending order, then the corresponding differences will be of the same sign, leading to a difference of signs of differences equal to 0. If neither of these occurs, the number is a mountain range number.

Old version (included as it might be golfable):

R, 44 43 bytes

-1 byte thanks to Giuseppe.


Try it online!

Computes the signs of the differences of consecutive digits. Then verifies that

  • none of the signs are 0s (would correspond to 2 equal consecutive digits);
  • the runs of the signs are all equal to 1, i.e. no 2 consecutive signs are equal.
  • 1
    \$\begingroup\$ Good job, I like the usage of the run length function! +1 \$\endgroup\$ – RGS Feb 6 '20 at 17:23
  • \$\begingroup\$ all(.^2>3) is a bit shorter, since we know that the absolute value of the diff of the signs is bounded between -2 and 2. \$\endgroup\$ – Giuseppe Feb 6 '20 at 19:22
  • \$\begingroup\$ similarly, for your old version, you can do rle(s)$l<2 since we know there aren't zero-length runs. \$\endgroup\$ – Giuseppe Feb 6 '20 at 19:28
  • \$\begingroup\$ @Giuseppe Thanks! \$\endgroup\$ – Robin Ryder Feb 6 '20 at 20:14
  • \$\begingroup\$ +1 for the clever squaring approach. You could have saved another 6 by using scan for input, but (as I acknowledged in my own answer) this doesn't seem particularly clever, and seems more like a sneaky trick... \$\endgroup\$ – Dominic van Essen May 20 '20 at 10:08

JavaScript (ES6),  35  33 bytes


Try it online!


a =>                // a[] = input list of digits,
                    //       re-used to store the last difference 
  !a.some(          //
    p =             // initialize p to a non-numeric value
    v =>            // for each v in a[]:
      a * (         //   multiply a by
        a =         //     the new value of a defined as
          p -       //       the difference between p and
          (p = v)   //       the new value of p, which is v
      )             //
      >= 0          //   the test fails if this is non-negative
  )                 // end of some()
  • \$\begingroup\$ +1 for your weird expression used. I haven't been around for a long time but I keep noticing you like to post JS answers! JS does incredibly well at golfing, does it not? \$\endgroup\$ – RGS Feb 6 '20 at 19:07
  • \$\begingroup\$ Also, could you explain a bit what is going on in x=p=v=>x*(x=p-(p=v))>=0 ? \$\endgroup\$ – RGS Feb 6 '20 at 19:07
  • 1
    \$\begingroup\$ @RGS We assign the arrow function v=>... to both x and p. Because this is non-numeric, the arithmetic operations in which these values are involved will result in NaN which is neither >=0 or <0. So the first 2 iterations will always be falsy, which is the expected behavior. \$\endgroup\$ – Arnauld Feb 6 '20 at 19:16
  • 2
    \$\begingroup\$ @RGS Initializing variables this way in the callback of a loop is a rather common trick in JS (err... I mean golfed JS, obviously). This also works if we want them to be zero'ish in some bitwise operations. \$\endgroup\$ – Arnauld Feb 6 '20 at 19:22
  • \$\begingroup\$ ah I get it! Thanks for the explanation! \$\endgroup\$ – RGS Feb 6 '20 at 19:22

Jelly, 7 6 bytes

A benchmarking solution.

A monadic link taking as input the list of digits


You can try it online or verify all test cases.

I         Take the forward differences
  Ɲ       and for each pair,
 ×        multiply them together.
   <0     Check if those are below 0.
      Ạ   Check if this array of booleans only contains Truthy values.

-1 byte thanks to @79037662

  • 3
    \$\begingroup\$ I don't know Jelly, but could it be shorter to simply check for negativity, instead of taking the sign and then checking it's equal to -1? \$\endgroup\$ – 79037662 Feb 6 '20 at 17:31
  • \$\begingroup\$ @79037662 yes it would! Thanks for the alert! \$\endgroup\$ – RGS Feb 6 '20 at 17:37
  • 1
    \$\begingroup\$ Nice answer. However, in general I’d consider holding back from answering your own question for a few days; as far as I understand that’s the general etiquette here. \$\endgroup\$ – Nick Kennedy Feb 6 '20 at 18:54
  • \$\begingroup\$ @NickKennedy oh sorry, will do so for the next challenges. Thanks for letting me know. \$\endgroup\$ – RGS Feb 6 '20 at 18:58
  • \$\begingroup\$ @RGS no worries! And nice challenge. \$\endgroup\$ – Nick Kennedy Feb 6 '20 at 19:20

Japt -!, 7 bytes

Takes input as a digit array.

äÎä* dÄ

Try it

  • \$\begingroup\$ Don't flags usually add up to the byte count? \$\endgroup\$ – RGS Feb 6 '20 at 17:12
  • 2
    \$\begingroup\$ Your code currently gives a truthy value for 122, which is not a mountain range number. \$\endgroup\$ – RGS Feb 6 '20 at 17:14
  • 1
    \$\begingroup\$ @RGS Flags used to be part of the byte count indeed, but now there's consensus that they can be used for free (Personally I don't like that, but...) \$\endgroup\$ – Luis Mendo Feb 6 '20 at 17:32
  • \$\begingroup\$ @LuisMendo They can be used but they count as a different language. \$\endgroup\$ – S.S. Anne Feb 6 '20 at 20:01
  • \$\begingroup\$ @RGS, fixed. And if you'd followed the link I very deliberately include with the flags in all my solutions ... \$\endgroup\$ – Shaggy Feb 6 '20 at 22:54

Haskell, 57 55 47 44 42 bytes

z f(x:s)=zipWith(f)s$x:s

Try it online!

Takes input as a list of digits.

  • -2 by swapping the order of s and x:s

  • -8 by using a different helper function

  • -3 by using partial application and pointfree code

  • -2 by excluding f= from the submission (which I didn't realize was allowed :P)

xnor improved my answer using >>=.

  • 2
    \$\begingroup\$ Good job on this one! I like Haskell :D +1 \$\endgroup\$ – RGS Feb 6 '20 at 17:39

Python, 47 bytes

f=lambda a,b,*l:l==()or(a-b)*(b-l[0])*f(b,*l)<0

Try it online!

Takes input splatted like f(1,2,3,4). Same idea as my second Haskell answer.

  • \$\begingroup\$ Ah wow, you guys keep surprising me every time! +1 \$\endgroup\$ – RGS Feb 7 '20 at 9:04

Excel (Insider build ver. 1912), 122 Bytes

A1 'Input
C1 =MID(A1,B1#,1)
D1 =SIGN(IF(NOT(B1#-1),C1-C2,C1#-INDEX(C1#,B1#-1)))
E1 =(SUM(D1#)=D1*ISODD(LEN(A1)))*PRODUCT(D1#) 'Output

Returns ±1 (truthy) or 0 (falsy)

Explanation (can add more detail if people are interested)

B1 =SEQUENCE(LEN(A1)) ' Generates a spill array from 1 to the length of the input
C1 =MID(A1,B1#,1) ' Splits characters into rows. Using each value in the spill array B1#
                  ' as a charcter index
D1 =SIGN(IF(NOT(B1#-1), ' Choose different value on the first cell
           C1-C2, ' Use the opposite of the first difference between digits
           C1#-INDEX(C1#,B1#-1))) ' get the difference between each digit and the previous
E1 =(SUM(D1#)=D1*ISODD(LEN(A1))) ' Sum the digit differences, if the 
                                 ' input length is even check if 0, else check if equal to
                                 ' thefirst row of the differences
       *PRODUCT(D1#))            ' ensure there aren't any repeated digits


enter image description here

  • \$\begingroup\$ Hey there, thanks for your Excel submission! Very unusual :D +1 \$\endgroup\$ – RGS Feb 7 '20 at 23:57
  • \$\begingroup\$ Excel lent work! (sorry, I couldn't help myself) \$\endgroup\$ – cschultz2048 Oct 4 '20 at 2:40

APL+WIN, 17 15 12 11 bytes

5 bytes saved thanks to Jo King & 1 byte thanks to Bubbler. Turning into a real team effort!

Prompts for list of digits:


Try it online! (Dyalog Classic)

  • \$\begingroup\$ Good job on this one! +1 \$\endgroup\$ – RGS Feb 6 '20 at 22:11
  • \$\begingroup\$ Is there a point to assigning the input to n? \$\endgroup\$ – Jo King Feb 7 '20 at 9:47
  • \$\begingroup\$ Jo. No! There is no point. It was left over from an earlier version. Old age :( Thanks for spotting it. \$\endgroup\$ – Graham Feb 7 '20 at 16:32
  • \$\begingroup\$ I believe there's no point to the 1= either, unless APL+WIN has a different result for 0>. Oh, and the second × too! \$\endgroup\$ – Jo King May 15 '20 at 13:15
  • \$\begingroup\$ @JoKing Thanks again. Same excuse I am afraid! \$\endgroup\$ – Graham May 20 '20 at 6:56

Husk, 7 bytes


Try it online!

Algorithm taken from the APL answer.


     Ẋ- subtract pairs of consecutive elements
   Ẋ*   multiply pairs of consecutive elements
Λ       return truthy value if all elements are:
 <0     lesser than 0

Jelly, (5?) 6 bytes

5 if we may invert the truthy/falsey output (strip the trailing ¬).


Try it online!

  • \$\begingroup\$ Really clever solution! +1 it took me a bit to understand why you wanted to use the after the second I but then I realized you were building the opposite result \$\endgroup\$ – RGS Feb 6 '20 at 19:04
  • \$\begingroup\$ Fun fact, the codepoints of this answer themselves (in Jelly encoding) are also a mountain/dale (same as this answer on the source-restriction challenge). \$\endgroup\$ – Kevin Cruijssen Feb 7 '20 at 7:27

Haskell, 37 bytes


Try it online!

Takes the zipWith-based answer of 79037662 and generalizes out the pattern of

g(?) = \s->zipWith(?)(tail s)s

that applies the operator (?) to pairs of adjacent elements. This is shortened to the pointfree g=(=<<tail).zipWith.

We first apply g(-) to the input to take differences of consecutive elements, then g(*) to take products of those consecutive differences. Then, we check that these products are all negative, which means that consecutive differences must be opposite in sign.

Haskell, 40 bytes


Try it online!

The idea is a bit clearer to see in the slightly less-golfed form:

42 bytes

f _=1>0

Try it online!

We check that the first three digits (a,b,c) have the a->b steps and b->c steps going opposite directions by checking that the differences a-b and b-c have opposite signs, that is, their product is negative. Then we recurse to the list without its first element until the list has fewer than 3 elements, where it's vacuously true.

An alternative to check suffixes directly turned out longer:

43 bytes

f l=and[(a-b)*(b-c)<0|a:b:c:t<-scanr(:)[]l]

Try it online!

  • \$\begingroup\$ Good job, as per usual. +1 because I see functions I know used in weird ways \$\endgroup\$ – RGS Feb 7 '20 at 0:27
  • \$\begingroup\$ Nice answer, I didn't know about =<<. \$\endgroup\$ – 79037662 Feb 7 '20 at 0:34
  • \$\begingroup\$ @79037662 And nice method from you! It looks like you converged to basically that same answer. I didn't think of doing this problem mostly pointfree -- I thought it would be long compared to the explicit recursion. \$\endgroup\$ – xnor Feb 7 '20 at 0:41

Python 2, 65 58 bytes

lambda A:all((x-y)*(y-z)<0for x,y,z in zip(A,A[1:],A[2:]))

Try it online!

  • \$\begingroup\$ Nice solution with the zip function +1 and this one handles gracefully the 1 and 2 digit cases (probably not the only answer here doing that, but this one I can easily spot ;) ) \$\endgroup\$ – RGS Feb 7 '20 at 9:03

Brachylog, 9 bytes


Try it online!

Takes a list of digits as input.


¬{      }       It is impossible…
  s₃            …to find a subsequence of 3 elements…
    .o↙Ḋ        …which is already ordered

Slight subtility: o↙Ḋ is used to check whether the digits are increasing or decreasing. By default, o (which is the same as o₀) is for increasing order, and o₁ is for decreasing order. By using o↙Ḋ ( being an integer between 0 and 9), we check that the whole predicate is impossible for o₀, or o₁, or o₂, …, o₉. o₂ to o₉ are not implemented and thus will fail, which doesn’t impact the program as a whole.

If true. is an acceptable falsy value, and false. an acceptable truthy value (which I don’t think it should be), then you should be able to remove these 3 bytes: ¬{…}.

  • 1
    \$\begingroup\$ Thanks for your submission! And I agree with you, using "false" as a Truthy value and vice versa is questionable :p it looks like a lot of answers would've benefited from that, though. +1 \$\endgroup\$ – RGS Feb 7 '20 at 14:00

Ruby -nl, 57 41 bytes

Replaces each character in the input string with the cmp comparison (<=> in Ruby) between it and the next character $'[0] (if there is no next character, remove the character instead). Then, check if the resulting string consists entirely of alternating 1 and -1.


Try it online!

Old Solution, 57 bytes

Check for duplicate consecutive numbers first by checking if the input string matches /(.)\1/ and inverting it. If no such pairs are found, replace each character with true or false based on whether its cmp style comparisons (<=>) to the character before it $`[-1] and after it $'[0] are not equal. (If there is no character before or after it, the <=> returns nil, which is definitely not equal to whatever the other character comparison returns.) Finally, it checks if the result does not contain an f (meaning no falses were returned).

p ! ~/(.)\1/&&gsub(/./){($`[-1]<=>$&)!=($&<=>$'[0])}!~/f/

Try it online!

  • \$\begingroup\$ Really cool answer +1 ! \$\endgroup\$ – RGS Feb 7 '20 at 9:05
  • \$\begingroup\$ Doesn't work for 212 \$\endgroup\$ – G B Feb 7 '20 at 9:48
  • \$\begingroup\$ @GB found the regex error. Fixed for no byte count change. \$\endgroup\$ – Value Ink Feb 7 '20 at 23:54

Bash, 147 144 bytes

while [ $i -lt ${#1} ]
case $d$((a-b)) in
[ux]-*)d=d;;*0|u*|d-*)return 1;;*)d=u;;esac
let i++

Try it online!

I seem to like trying shell submissions, and learned some bash-isms in golfing this one.

$((a-b)) is equivalent to $(( $a - $b )) -- apparently you don't need the $ inside a $(( )) construct.

There is a ++ operator, works in $(( )) and in let

Subtracting letters is accepted, strangely. One of my samples in the TIO reads "xy", and apparently $((a-b)) evaluates a to x, and then variable x to an empty string and the empty string as numeric zero, and comparable for b and y. If I set x and y in the environment, those values are used.

Edit: -3 bytes by not putting whitespace after ;;, thanks to S.S.Anne

  • \$\begingroup\$ +1 nice submission! \$\endgroup\$ – RGS Feb 6 '20 at 22:09
  • 1
    \$\begingroup\$ @RGS I think it is a very nice touch that you are commenting on (and upvoting) each answer. Thank You. +1 \$\endgroup\$ – David G. Feb 6 '20 at 22:25
  • \$\begingroup\$ Thanks David! I just want to acknowledge every submission ;) \$\endgroup\$ – RGS Feb 6 '20 at 22:39
  • 1
    \$\begingroup\$ @S.S.Anne My output looks like my input because the trailer code deliberately matches the format from the original sample data. \$\endgroup\$ – David G. Feb 9 '20 at 19:38
  • 1
    \$\begingroup\$ @S.S.Anne I tested it too, and must have done the same thing. Reverted back to 144. Ah well. \$\endgroup\$ – David G. Feb 9 '20 at 19:45

J, 15 bytes


Try it online!

-7 bytes thanks to RGS's technique

  • \$\begingroup\$ Nice submission :) what does RGS's technique mean? +1 \$\endgroup\$ – RGS Feb 6 '20 at 22:11
  • 1
    \$\begingroup\$ Meaning the logic is essentially the same as yours, translated into J, and was shorter than the initial approach i tried \$\endgroup\$ – Jonah Feb 6 '20 at 23:01

Charcoal, 29 27 bytes


Try it online! Link is to verbose version of code. Takes input as a list of digits and outputs as a Charcoal boolean (- for a mountain range number, otherwise no output). Explanation:


Take consecutive differences (cyclic, so includes difference between last and first digit).


Take consecutive products (again, cyclic).


All results bar the last two must be negative.

  • \$\begingroup\$ Interesting submission! +1 \$\endgroup\$ – RGS Feb 6 '20 at 22:10

Burlesque, 22 bytes


Try it online!

XX      # Explode into digits
2CO     # 2-grams ("abc"->{"ab" "bc"})
qcm^m   # Compare each via UFO operator
2CO     # 2-grams
PD      # Product
{0.<}al # All less than 0
  • \$\begingroup\$ Nice answer. It looks kind of funny +1 can't you save some bytes by taking a list of digits as input? \$\endgroup\$ – RGS Feb 6 '20 at 23:49
  • 1
    \$\begingroup\$ It makes very little difference, as I'd need to parse them with ps or pe anyway. This sneakily operates on strings and relies on ASCII comparison. \$\endgroup\$ – DeathIncarnate Feb 6 '20 at 23:51

K (ngn/k), 14 bytes


Try it online!

$: as string

-': subtract (as ascii codes) each prior; implicit 0 before first

*': multiply by each prior; implicit 1 before first

2_ drop first 2 elements

&/0> all negative?

  • \$\begingroup\$ The TIO link has 16 bytes? Is it 'cuz you assign your function to f? +1 for the good work :D \$\endgroup\$ – RGS Feb 7 '20 at 0:29
  • 1
    \$\begingroup\$ @RGS thanks. yes, by convention function naming is not counted unless it's used for (non-anonymous) recursion. here i use the name f only for testing. \$\endgroup\$ – ngn Feb 7 '20 at 0:33

Python 3, 101 \$\cdots\$ 103 94 bytes

Added 13 bytes to fix error kindly pointed out by @ChasBrown.
Saved 9 bytes thanks to @ChasBrown!!!

def f(l):x=[a<b for a,b in zip(l[1:],l)];return all(a!=b for a,b in zip(x[1:]+l[1:],x[:-1]+l))

Try it online!

  • \$\begingroup\$ Interesting submission! +1 \$\endgroup\$ – RGS Feb 6 '20 at 23:40
  • \$\begingroup\$ 94 bytes \$\endgroup\$ – Chas Brown Feb 7 '20 at 1:17
  • \$\begingroup\$ @ChasBrown Nice one zip auto truncates the larger - thanks! :-) \$\endgroup\$ – Noodle9 Feb 7 '20 at 1:27

C (gcc), 59 bytes

d;m(int*s){for(d=*s/s[1];s[1]&&s[1]/ *s-d;d^=1)s++;s=s[1];}

Takes as input a wide string of digits and returns zero if that number is a mountain range number.

-12 bytes thanks to ceilingcat!

Try it online!

  • \$\begingroup\$ @ceilingcat Thanks! \$\endgroup\$ – S.S. Anne Feb 9 '20 at 20:13
  • \$\begingroup\$ +1 for the cool submission, but can you help me understand how the return here works? \$\endgroup\$ – RGS Feb 9 '20 at 20:13
  • \$\begingroup\$ @RGS Closest I can find is codegolf.stackexchange.com/a/106067/89298. It exploits GCC's behavior when compiling without optimization in which temporary results are stored in the return register. \$\endgroup\$ – S.S. Anne Feb 9 '20 at 20:15

Java (JDK), 95 83 bytes

p->{int i=0,j=1;for(;p.length>-~++i;)j=(p[i-1]-p[i])*(p[i]-p[i+1])<0?j:0;return j;}

Try it online!

Thanks to all in the comments for improvements - especially bit-shifting which I never would have thought of!!

  • \$\begingroup\$ Thanks for your submission! +1 for you. You can save 7 bytes by using 0/1 as Falsy/Truthy values! \$\endgroup\$ – RGS Feb 7 '20 at 15:28
  • \$\begingroup\$ Thanks! I hadn't thought to do that \$\endgroup\$ – simonalexander2005 Feb 7 '20 at 15:33
  • \$\begingroup\$ you may be able to shave 2 more bytes by returning nothing for Falsy. I think that is still reasonable. \$\endgroup\$ – RGS Feb 7 '20 at 15:42
  • \$\begingroup\$ An index shift could possibly save three further bytes. \$\endgroup\$ – Jonathan Frech Feb 7 '20 at 16:18

R, 34 bytes


Try it online!

Alternately reverses signs of all differences, and then multiplies them all by first difference: mountain range sequences will all be positive

Would be 40 bytes if defined as a function instead, so apologies to Robin with whom this would tie without the scan for input.


Scala, 63 bytes


Checks whether for all sliding triplets the center is strictly larger (or strictly smaller) than the previous element and the next element.

Try it online!


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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