Code Golf Asked by RGS on December 15, 2020

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

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

```
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 code-golf so shortest answer in bytes wins! Standard loopholes are forbidden.

```
Λ<0Ẋ*Ẋ-
```

Algorithm taken from the APL answer.

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

Answered by Razetime on December 15, 2020

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

Answered by cubic lettuce on December 15, 2020

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

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.

Answered by Dominic van Essen on December 15, 2020

```
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!*

Answered by S.S. Anne on December 15, 2020

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

Answered by begolf123 on December 15, 2020

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

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

Answered by simonalexander2005 on December 15, 2020

```
¬{s₃.o↙Ḋ}
```

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: `¬{…}`

.

Answered by Fatalize on December 15, 2020

`-nl`

, 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)?$/
```

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/
```

Answered by Value Ink on December 15, 2020

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

Takes input splatted like `f(1,2,3,4)`

. Same idea as my second Haskell answer.

Answered by xnor on December 15, 2020

Answered by Chas Brown on December 15, 2020

```
&/0>2_*':-':$:
```

`$:`

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?

Answered by ngn on December 15, 2020

```
all(<0).g(*).g(-)
g=(=<<tail).zipWith
```

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.

```
f(a:b:t)=t==[]||(a-b)*(b-t!!0)<0&&f(b:t)
```

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

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]
```

Answered by xnor on December 15, 2020

```
XX2COqcm^m2COPD{0.<}al
```

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

Answered by DeathIncarnate on December 15, 2020

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

Answered by Noodle9 on December 15, 2020

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)

Answered by Graham on December 15, 2020

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

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

Answered by David G. on December 15, 2020

```
ＵＭθ⁻ι§θ⊕κＵＭθ×ι§θ⊕κ›⁰⌈…θ⁻Ｌθ²
```

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.

Answered by Neil on December 15, 2020

Answered by Jonah on December 15, 2020

```
a=>!a.some(p=v=>a*(a=p-(p=v))>=0)
```

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

Answered by Arnauld on December 15, 2020

Answered by Jonathan Allan on December 15, 2020

Answered by Grimmy on December 15, 2020

```
all(<0).z(*).z(-)
z f(x:s)=zipWith(f)s$x:s
```

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)

Answered by 79037662 on December 15, 2020

_{ crossed out 44 is still regular 44}

-1 byte thanks to Giuseppe.

```
function(x,d=diff)all(d(sign(d(x)))^2>3)
```

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

-1 byte thanks to Giuseppe.

```
function(x)all(s<-sign(diff(x)),rle(s)$l<2)
```

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.

Answered by Robin Ryder on December 15, 2020

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

Answered by RGS on December 15, 2020

22 Asked on October 4, 2020 by user9207

Get help from others!

Recent Answers

- haakon.io on Why fry rice before boiling?
- Lex on Does Google Analytics track 404 page responses as valid page views?
- Joshua Engel on Why fry rice before boiling?
- Peter Machado on Why fry rice before boiling?
- Jon Church on Why fry rice before boiling?

© 2022 AnswerBun.com. All rights reserved. Sites we Love: PCI Database, MenuIva, UKBizDB, Menu Kuliner, Sharing RPP, SolveDir