# Monotone sequence beatitude

Provided that the input is a monotone sequence of three or more integers:

• Output -2 if the sequence strictly decreases. Example: [7,4,3,2]

• Output -1 if the sequence monotone decreases but is neither strict nor constant. Example: [6,5,5]

• Output 0 if the sequence is constant. Example: [0,0,0]

• Output +1 if the sequence monotone increases but is neither strict nor constant. Example: [-1,2,2,2,4]

• Output +2 if the sequence strictly increases. Example: [0,1,2]

I/O format is flexible. Standard loopholes apply.

• Please add at least 1 worked example and some test cases. Commented Nov 14, 2023 at 9:18
• If the sequence is [-1,2,3,2,4], is it considered increasing ? Commented Nov 14, 2023 at 9:57
• @gobes It is not monotone. Commented Nov 14, 2023 at 9:58
• Related Commented Nov 14, 2023 at 10:55
• The addition of the word "constant" in the description confuses me. As an example, what should the return for [1,2,5] be? It is strictly increasing, but it is a constant interval. Commented Jan 4 at 5:24

# 05AB1E, 8 7 6 bytes

¥.±Z+W


Attempt This Online!

¥      deltas
.±     sign
Z      maximum without popping
W      minimum


# Jelly, 6 bytes

IṠQ.ịS


Try it online!

Port of Command Master's 05AB1E answer. A monadic link taking a list of integers and returning an integer.

## Explanation

I      | Increments
Ṡ     | Signs
Q    | Uniquify
.ị  | Last and first
S | Sum

• I think uniquify is not necessary Try it online! Commented Nov 14, 2023 at 7:05
• @pajonk it is if the input is something like [1,2,2,3] Commented Nov 14, 2023 at 7:34
• Ah, I get it now. It's "Last and first" (as described) not min and max. Commented Nov 14, 2023 at 8:25

# Uiua, 11 bytes

⊢+⇌.⊝±≡/-◫2


Try it!

Port of Command Master's 05AB1E answer.

⊢+⇌.⊝±≡/-◫2
≡/-◫2  # deltas
±       # sign
⊝        # deduplicate
.         # duplicate
⇌          # reverse
⊢            # first


# JavaScript (ES6), 47 bytes

a=>(a.reduce((p,v)=>(a|=p<v?5:p>v?-2:3,v)),a%3)


Try it online!

### Method

Because the input array a contains at least 3 elements, it is guaranteed to be evaluated to $$\0\$$ when coerced to an integer. So we can safely re-use it as a signed 32-bit mask.

For each pair of consecutive elements $$\(p,\:v)\$$ in the input array, we apply to a a bitwise OR with:

• $$\5\$$ if $$\p
• $$\-2\$$ if $$\p>v\$$
• $$\3\$$ if $$\p=v\$$

These values were chosen such that the expected output in $$\[-2\dots2]\$$ is obtained by reducing the final bitmask modulo $$\3\$$.

### List of cases

Because the sequence is monotone, there are only 5 possible cases:

$$\p $$\p>v\$$ $$\p=v\$$ operations final bitmask modulo 3
no no yes 0 | 3 3 0
no yes no 0 | -2 -2 -2
no yes yes 0 | -2 | 3 -1 -1
yes no no 0 | 5 5 2
yes no yes 0 | 5 | 3 7 1

# Scala 3, 71 63 bytes

Saved 8 bytes thanks to the comment of @corvus_192

x=>x zip x.tail map{case(a,b)=>b compare a}pipe(x=>x.min+x.max)


Attempt This Online!

• 63 bytes: x=>x zip x.tail map{case(a,b)=>b compare a}pipe(x=>x.min+x.max) Commented Nov 15, 2023 at 20:14

# Python, 55 bytes

lambda S,*s:min(x:={(S<t)-(S>(S:=t))for t in s})+max(x)


Attempt This Online!

# Python 2, 53 bytes

def f(s):t=map(cmp,s[1:],s[:-1]);return min(t)+max(t)


Attempt This Online!

# Nekomata, 5 bytes

∆±uÄµ


Attempt This Online!

∆±uÄµ
∆       Delta
±      Sign
u     Uniquify
Ä    Multiply by 2
µ   Mean


# K (ngn/k), 14 bytes

+/2#?0 1'1_-':


Try it online!

A slight variation on Nick Kennedy's Jelly answer. 0 1' is from coltim's comment on another K answer.

+/2#?0 1'1_-':
1_-':    differences
0 1'         binary search into 0 1; negative -> -1, 0 -> 0, positive -> 1
?             keep unique elements
2#              cycle the elements to length 2
+/                sum


# Python 2, 43 bytes

lambda s:cmp(s[::-1],s)<<len(set(s))/len(s)


Attempt This Online!

Logs:

• My original answer (49 bytes):
lambda s:cmp(s[-1],s[0])*(2-(len(set(s))<len(s)))

• Neil's suggestion: *(2-(len(set(s))<len(s))) -> -~(len(set(s))==len(s))
• xnor's suggestion: *(2-(len(set(s))<len(s))) -> <<(len(set(s))==len(s)) ; cmp(s[-1],s[0]) -> cmp(s[::-1],s)
• Albert.Lang's suggestion: *(2-(len(set(s))<len(s))) -> <<len(set(s))/len(s)

Thank for amazing suggestions!

• -~(len(set(s))==len(s)) is a byte shorter than (2-(len(set(s))<len(s))).
– Neil
Commented Nov 14, 2023 at 9:43
• Better yet, <<(len(set(s))==len(s)) without *. Also, cmp(s[::-1],s) saves a byte
– xnor
Commented Nov 14, 2023 at 10:02
• Even more betterer: lambda s:cmp(s[::-1],s)<<len(set(s))/len(s) Commented Nov 14, 2023 at 18:18
• Thanks for y'all amazing suggestions. Was busy so just checked cg now. Commented Nov 17, 2023 at 16:17

# R, 32 29 bytes

\(x)sum(range(sign(diff(x))))


Attempt This Online!

A function taking a vector and returning the relevant result. Based on Command Master's 05AB1E answer.

Thanks to @pajonk for saving three bytes!

• -3 bytes by porting your own Jelly answer :) Commented Nov 14, 2023 at 6:18
• I don't know R, but it doesn't look like you need the range. Commented Nov 14, 2023 at 9:23
• Thanks @Shaggy. You don’t for the examples used but would if the sequences were longer than 3 integers. Commented Nov 14, 2023 at 12:57

# K (ngn/k), 21 16 bytes

-5 thanks to @coltim

&/+/|/\0 1'1_-':


Try it online!

           1_-': deltas
0 1'      sign
&/               minimum

• I think you can use |/\  rather than 1|/\ , since the input is going to be a list (so the max-reduce-converges will end after a single iteration). There's also the golfy 0 1'intList sign version that saves several bytes. Commented Nov 14, 2023 at 15:29

# JavaScript (Node.js), 50 bytes

a=>~!a.some(p=x=>p==(p=x))*Math.sign(a[0]-a.pop())


Try it online!

Use begin and end to detect direction

# sclin, 23 bytes

_"-"2%map0<=>"|/"Q + &/


## Explanation

Prettified:

_ \- 2%map 0<=> \|/ Q + &/

• _ \- 2%map negated delta (via pairwise difference)
• 0<=> sign (i.e. compare to 0)
• \|/ Q dup and get max
• + &/ vectorized-add and get min

# Desmos, 33 bytes

f(L)=D.max+D.min
D=sgn(L[2...]-L)


Port of 05AB1E.

Try It On Desmos!

Try It On Desmos! - Prettified

# Retina, 57 51 bytes

\d+
*
Lv\b_+,_+
+_,_
,
O^
,,G
^_
-_
/[^-]+/__+


Try it online! Link includes test cases. Only accepts positive integer lists, but will output -2 to 2 as required. Explanation:

\d+
*


Convert to unary.

Lv\b_+,_+
+_,_
,


For each overlapping pair of integers, get a substring representing the delta: _+, for negative, , for 0 and ,_+ for positive.

O^


Group identical substrings together and sort _, first.

,,G


Keep only one of each group, but if there is only one group, keep two of it.

^_
-_


If there was a _, then prefix a - sign.

/[^-]+/__+


Count the runs of _s.

Edit: Saved 6 bytes by porting my answer to Retina 0.8.2 for 61 bytes and then backporting the golfs:

\d+
$* M!&\b1+,1+ +1,1 , O^ +¶.+¶ ¶ ^1 -1 ((1+)|,|¶)+$#2


Try it online! Link includes test cases. Only accepts positive integer lists, but will output -2 to 2 as required. Explanation: Retina 0.8.2 uses $* (which produces 1s) instead of * (which produces _s) for unary, needs to use M!& instead of Lv, and doesn't have an equivalent of ,,G or _ (as a command), so I had to emulate those. # Vyxalg, 29 bitsv2, 3.625 bytes ¯±:G+  Try it Online! Bitstring: 11001100111100010001111111001  Port of the 05ab1e answer # Charcoal, 23 bytes ≔ＥΦθκ⁻›ι§θκ‹ι§θκθＩ⁺⌊θ⌈θ  Try it online! Link is to verbose version of code. Explanation: Port of @Albert.Lang's Python answer. ≔ＥΦθκ⁻›ι§θκ‹ι§θκθ  Get the signs of the deltas. Ｉ⁺⌊θ⌈θ  Add the minimum and maximum of them. # JavaScript (Node.js), 54 bytes a=>a.map(n=p=o=v=>[n|=a>v,p|=a<v,o|=a==v,a=v])|p-n<<!o  Try it online! # C (gcc), 63 bytes Port of my JS answer. m,p;f(a,n)int*a;{for(m=0;p=*a++,--n;)m|=p<*a?5:p>*a?-2:3;m%=3;}  Try it online! # APL+WIN, 52 bytes Prompts for vector: +/2 1 0×(×n)×(s=⍴v),((s<⍴v)^s>0),0=s←1+|n←+/×-2-/v←⎕  Try it online! Thanks to Dyalog Classic # Go, 193 183 bytes Saved 10 bytes thanks to the comment of @corvus_192 Golfed version. Attempt this online! func c(a,b int)int{if a<b{return 1};if a>b{return -1};return 0} func f(n[]int)int{z:=math.MaxInt64;Z:=^z;for i:=0;i<len(n)-1;i++{r:=c(n[i],n[i+1]);if r<z{z=r};if r>Z{Z=r}};return z+Z}  Ungolfed version. Attempt This Online! package main import ( "fmt" "math" ) func compare(a, b int) int { if a < b { return 1 } if a > b { return -1 } return 0 } func f(nums []int) int { min, max := math.MaxInt64, math.MinInt64 for i := 0; i < len(nums)-1; i++ { result := compare(nums[i], nums[i+1]) if result < min { min = result } if result > max { max = result } } return min + max } func main() { fmt.Println(f([]int{1, 2, 3, 5, 9})) fmt.Println(f([]int{1, 2, 3, 5, 5})) fmt.Println(f([]int{1, 1, 1, 1, 1})) fmt.Println(f([]int{1, 1, -3, -5, -9})) fmt.Println(f([]int{-1, -2, -3, -5, -9})) }  • -9 bytes: z:=math.MaxInt64;Z:=-~z; Commented Nov 15, 2023 at 20:27 # Swift, 175 bytes Short version: func m(_ n:[Int])->Int{var r=0,s=0>1;for i in 0..<n.count-1{let(y,x)=(n[i+1],n[i]);if y>x{r=r>0 && !s ?2:1}else if y<x{r=r<0 && !s ? -2:-1}else{r=r.signum();s=0<1}};return r}  Verbose version: Basically update the return value to be 2 or -2 as long as the elements differ from each other and "clamp" it to -1,0,+1 as soon as two same elements are found. func m(_ n:[Int])->Int{ var r=0, s=0>1 for i in 0..<n.count-1{ let(y,x)=(n[i+1],n[i]); if y>x{ r=r>0 && !s ?2:1 }else if y<x{ r=r<0 && !s ? -2:-1 }else{ r=r.signum(); s=0<1 } }; return r }  # Perl 5-p, 53 bytes s/\S+/$'&&$'-$&/ge;$_=2*(/^(\S+ )\1+$/?\$1<=>0:.5-/-/)


Try it online!