AnswerBun.com

Mountain range numbers

Code Golf Asked by RGS on December 15, 2020

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

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.

25 Answers

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

Answered by Razetime on December 15, 2020

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!

Answered by cubic lettuce on December 15, 2020

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.

Answered by Dominic van Essen on December 15, 2020

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!

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

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

enter image description here

Answered by begolf123 on December 15, 2020

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

Answered by simonalexander2005 on December 15, 2020

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

Answered by Fatalize on December 15, 2020

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!

Answered by Value Ink on December 15, 2020

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.

Answered by xnor on December 15, 2020

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!

Answered by Chas Brown on December 15, 2020

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?

Answered by ngn on December 15, 2020

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!

Answered by xnor on December 15, 2020

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

Answered by DeathIncarnate on December 15, 2020

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!

Answered by Noodle9 on December 15, 2020

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:

×/0>2×/2-/⎕

Try it online! (Dyalog Classic)

Answered by Graham on December 15, 2020

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

Answered by David G. on December 15, 2020

Charcoal, 29 27 bytes

UMθ⁻ι§θ⊕κUMθ×ι§θ⊕κ›⁰⌈…θ⁻Lθ²

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:

UMθ⁻ι§θ⊕κ

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

UMθ×ι§θ⊕κ

Take consecutive products (again, cyclic).

›⁰⌈…θ⁻Lθ²

All results bar the last two must be negative.

Answered by Neil on December 15, 2020

J, 15 bytes

[:*/0>2*/2-/]

Try it online!

-7 bytes thanks to RGS's technique

Answered by Jonah on December 15, 2020

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

Answered by Arnauld on December 15, 2020

Jelly, (5?) 6 bytes

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

IṠIỊẸ¬

Try it online!

Answered by Jonathan Allan on December 15, 2020

05AB1E, 6 bytes

¥ü*0‹P

Try it online!

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

¥ü*dZ

TIO

Answered by Grimmy on December 15, 2020

Haskell, 57 55 47 44 42 bytes

all(<0).z(*).z(-)
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 >>=.

Answered by 79037662 on December 15, 2020

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.

Answered by Robin Ryder on December 15, 2020

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

Answered by RGS on December 15, 2020

Japt -!, 7 bytes

Takes input as a digit array.

äÎä* dÄ

Try it

Answered by Shaggy on December 15, 2020

Add your own answers!

Related Questions

What’s my PPCG ID?

8  Asked on December 3, 2020 by musicman523

     

The bouncing sequence

8  Asked on November 28, 2020 by wheat-wizard

       

Zero sum covers

16  Asked on November 10, 2020 by zgarb

     

Swapping “Good” and “Bad”

74  Asked on October 15, 2020 by ishaq-khan

     

Pi to the power y, for small y’s

22  Asked on October 4, 2020 by user9207

     

The Third String

36  Asked on September 5, 2020 by stephen

   

Compress your code in an image

11  Asked on August 17, 2020 by blint

     

Ask a Question

Get help from others!

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