# 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$/extract_tex] 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. # Input A positive integer n with 3 or more digits, in any reasonable format, e.g. • Integer • String • List of digits # Test cases ### Truthy 1324 -> Truthy 9191 -> Truthy 12121 -> Truthy 121212 -> Truthy 1212121 -> Truthy 19898 -> Truthy  ### Falsy (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. • May we take input as a list of digits rather than an integer? Commented Feb 6, 2020 at 17:03 • @RobinRyder yes you may – RGS Commented Feb 6, 2020 at 17:10 • @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. Commented Feb 6, 2020 at 19:27 • @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! Commented Feb 6, 2020 at 19:52 • Related with a source restriction – Jo King Commented Feb 7, 2020 at 0:39 ## 25 Answers # 05AB1E, 6 bytes ¥ü*0‹P  Try it online! With truthy and falsy reversed, this would be 5 bytes: ¥ü*dZ  TIO • Good job! +1 Why would the truthy <> falsy reversal make it shorter? – RGS Commented Feb 6, 2020 at 17:38 • @RGS 05AB1E has a single-byte built-in for x >= 0, but not for its negation x < 0. Commented Feb 6, 2020 at 17:39 • I see, thanks for the tip. – RGS Commented Feb 6, 2020 at 17:40 • 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. Commented Feb 7, 2020 at 7:38 # R, 44 40 bytes crossed out 44 is still regular 44 -1 byte thanks to Giuseppe. function(x,d=diff)all(d(sign(d(x)))^2>3)  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. function(x)all(s<-sign(diff(x)),rle(s)l<2)  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. • Good job, I like the usage of the run length function! +1 – RGS Commented Feb 6, 2020 at 17:23 • 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. Commented Feb 6, 2020 at 19:22 • similarly, for your old version, you can do rle(s)l<2 since we know there aren't zero-length runs. Commented Feb 6, 2020 at 19:28 • +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... Commented May 20, 2020 at 10:08 # JavaScript (ES6), 35 33 bytes a=>!a.some(p=v=>a*(a=p-(p=v))>=0)  Try it online! ### Commented 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()  • +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? – RGS Commented Feb 6, 2020 at 19:07 • Also, could you explain a bit what is going on in x=p=v=>x*(x=p-(p=v))>=0 ? – RGS Commented Feb 6, 2020 at 19:07 • @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. Commented Feb 6, 2020 at 19:16 • @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. Commented Feb 6, 2020 at 19:22 • ah I get it! Thanks for the explanation! – RGS Commented Feb 6, 2020 at 19:22 # Jelly, 7 6 bytes A benchmarking solution. A monadic link taking as input the list of digits I×Ɲ<0Ạ  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 • 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? Commented Feb 6, 2020 at 17:31 • @79037662 yes it would! Thanks for the alert! – RGS Commented Feb 6, 2020 at 17:37 • 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. Commented Feb 6, 2020 at 18:54 • @NickKennedy oh sorry, will do so for the next challenges. Thanks for letting me know. – RGS Commented Feb 6, 2020 at 18:58 • @RGS no worries! And nice challenge. Commented Feb 6, 2020 at 19:20 # Japt-!, 7 bytes Takes input as a digit array. äÎä* dÄ  Try it • Don't flags usually add up to the byte count? – RGS Commented Feb 6, 2020 at 17:12 • Your code currently gives a truthy value for 122, which is not a mountain range number. – RGS Commented Feb 6, 2020 at 17:14 • @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...) Commented Feb 6, 2020 at 17:32 • @LuisMendo They can be used but they count as a different language. Commented Feb 6, 2020 at 20:01 • @RGS, fixed. And if you'd followed the link I very deliberately include with the flags in all my solutions ... Commented Feb 6, 2020 at 22:54 # Haskell, 57554744 42 bytes all(<0).z(*).z(-) z f(x:s)=zipWith(f)sx: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 >>=. • Good job on this one! I like Haskell :D +1 – RGS Commented Feb 6, 2020 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. • Ah wow, you guys keep surprising me every time! +1 – RGS Commented Feb 7, 2020 at 9:04 # APL+WIN, 171512 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: ×/0>2×/2-/⎕  Try it online! (Dyalog Classic) • Good job on this one! +1 – RGS Commented Feb 6, 2020 at 22:11 • Is there a point to assigning the input to n? – Jo King Commented Feb 7, 2020 at 9:47 • Jo. No! There is no point. It was left over from an earlier version. Old age :( Thanks for spotting it. Commented Feb 7, 2020 at 16:32 • I believe there's no point to the 1= either, unless APL+WIN has a different result for 0>. Oh, and the second × too! – Jo King Commented May 15, 2020 at 13:15 • @JoKing Thanks again. Same excuse I am afraid! Commented May 20, 2020 at 6:56 # Husk, 7 bytes Λ<0Ẋ*Ẋ-  Try it online! Algorithm taken from the APL answer. ## Explanation Λ<0Ẋ*Ẋ- Ẋ- 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 ¬). IṠIỊẸ¬  Try it online! • 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 – RGS Commented Feb 6, 2020 at 19:04 • 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). Commented Feb 7, 2020 at 7:27 # Haskell, 37 bytes all(<0).g(*).g(-) g=(=<<tail).zipWith  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 f(a:b:t)=t==[]||(a-b)*(b-t!!0)<0&&f(b:t)  Try it online! The idea is a bit clearer to see in the slightly less-golfed form: 42 bytes f(a:b:c:t)=(a-b)*(b-c)<0&&f(b:c:t) 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! • Good job, as per usual. +1 because I see functions I know used in weird ways – RGS Commented Feb 7, 2020 at 0:27 • Nice answer, I didn't know about =<<. Commented Feb 7, 2020 at 0:34 • @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. – xnor Commented Feb 7, 2020 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! • 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 ;) ) – RGS Commented Feb 7, 2020 at 9:03 # Brachylog, 9 bytes ¬{s₃.o↙Ḋ}  Try it online! Takes a list of digits as input. ### Explanation ¬{ } 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: ¬{…}. • 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 – RGS Commented Feb 7, 2020 at 14:00 # Excel (Insider build ver. 1912), 122 Bytes A1 'Input B1 =SEQUENCE(LEN(A1)) 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  Tests • Hey there, thanks for your Excel submission! Very unusual :D +1 – RGS Commented Feb 7, 2020 at 23:57 # 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. gsub(/./){&<=>'[0]} p~/^1?(-11)*(-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! • Really cool answer +1 ! – RGS Commented Feb 7, 2020 at 9:05 • Doesn't work for 212 – G B Commented Feb 7, 2020 at 9:48 • @GB found the regex error. Fixed for no byte count change. Commented Feb 7, 2020 at 23:54 # Bash, 147 144 bytes M(){ a={1:0:1} d=x i=1 while [ i -lt {#1} ] do b={1:i:1} case d((a-b)) in [ux]-*)d=d;;*0|u*|d-*)return 1;;*)d=u;;esac a=b let i++ done }  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 • +1 nice submission! – RGS Commented Feb 6, 2020 at 22:09 • @RGS I think it is a very nice touch that you are commenting on (and upvoting) each answer. Thank You. +1 Commented Feb 6, 2020 at 22:25 • Thanks David! I just want to acknowledge every submission ;) – RGS Commented Feb 6, 2020 at 22:39 • @S.S.Anne My output looks like my input because the trailer code deliberately matches the format from the original sample data. Commented Feb 9, 2020 at 19:38 • @S.S.Anne I tested it too, and must have done the same thing. Reverted back to 144. Ah well. Commented Feb 9, 2020 at 19:45 # J, 15 bytes [:*/0>2*/\2-/$


Try it online!

-7 bytes thanks to RGS's technique

• Nice submission :) what does RGS's technique mean? +1
– RGS
Commented Feb 6, 2020 at 22:11
• Meaning the logic is essentially the same as yours, translated into J, and was shorter than the initial approach i tried Commented Feb 6, 2020 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.

• Interesting submission! +1
– RGS
Commented Feb 6, 2020 at 22:10

# Burlesque, 22 bytes

XX2COqcm^m2COPD{0.<}al


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

• Nice answer. It looks kind of funny +1 can't you save some bytes by taking a list of digits as input?
– RGS
Commented Feb 6, 2020 at 23:49
• 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. Commented Feb 6, 2020 at 23:51

# K (ngn/k), 14 bytes

&/0>2_*':-':$:  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?

• The TIO link has 16 bytes? Is it 'cuz you assign your function to f? +1 for the good work :D
– RGS
Commented Feb 7, 2020 at 0:29
• @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.
– ngn
Commented Feb 7, 2020 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!

• Interesting submission! +1
– RGS
Commented Feb 6, 2020 at 23:40
• 94 bytes Commented Feb 7, 2020 at 1:17
• @ChasBrown Nice one zip auto truncates the larger - thanks! :-) Commented Feb 7, 2020 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!

• @ceilingcat Thanks! Commented Feb 9, 2020 at 20:13
• +1 for the cool submission, but can you help me understand how the return here works?
– RGS
Commented Feb 9, 2020 at 20:13
• @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. Commented Feb 9, 2020 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!!

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

# R, 34 bytes

all((d=diff(scan()))[1]*d*.5:-1>0)


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

_.sliding(3).forall(t=>t(0)<t(1)&t(1)>t(2)|t(0)>t(1)&t(1)<t(2))


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!