JavaScript, 66 65 62 60 bytes
Takes input as a string, returns true
for undulant numbers, an empty string (falsey) for single digit numbers and false
otherwise.
([s,...a])=>a+a&&a.every(x=>eval(s+"<>"[++y%2]+x,s=x),y=s<a)
Try it
Run the Snippet below to test 0-9
and 25 random numbers <10,000,000
.
f=
([s,...a])=>a+a&&a.every(x=>eval(s+"<>"[++y%2]+x,s=x),y=s<a)
tests=new Set([...Array(10).keys()])
while(tests.add(Math.random()*1e7|0).size<35);
o.innerText=[...tests].map(x=>(x=x+``).padStart(7)+` = `+JSON.stringify(f(x))).join`\n`
<pre id=o></pre>
Explanation
A few fun little tricks in this one so I think it warrants a rare explanation to a JS solution from me.
()=>
We start, simply, with an anonymous function which takes the integer string as an argument when called.
[s,...a]
That argument is immediately destructured into 2 parameters: s
being the first character in the string and a
being an array containing the remaining characters (e.g. "461902"
becomes s="4"
and a=["6","1","9","0","2"]
).
a+a&&
First, we concatenate a
with itself, which casts both occurrences to strings. If the input is a single digit number then a
will be empty and, therefore, become and empty string; an empty string plus an empty string is still an empty string and, because that's falsey in JS, we stop processing at the logical AND and output our empty string. In all other cases a+a
will be truthy and so we continue on to the next part of the function.
a.every(x=>)
We'll be checking if every element x
in a
returns true
when passed through a function.
y=s<a
This determines what our first comparison will be (<
or >
) and then we'll alternate from there. We check if the string s
is less than the array a
, which gets cast to a string in the process so, if s
is less than the first character in a
, y
will be true
or false
if it's not.
s+"<>"[++y%2]+x
We build a string with the current value of s
at the beginning and x
at the end. In between, we index into the string "<>"
by incrementing y
, casting its initial boolean value to an integer, and modulo by 2, giving us 0
or 1
.
eval()
Eval that string.
s=x
Finally, we pass a second argument to eval
, which it ignores, and use it to set the value of s
to the current value of x
for the next iteration.