毫不留情的数字


16

一个波状号码是一个号码,其中其数字之间交替向上向下像下面的编号:461902或708143,或甚至1010101,但不是123,因为2 <3。

写一个程序或功能,如果一个数是它返回一个truthy值起伏,否则一个falsy值。最短的代码获胜。

注意:一位数字是有效输入,但不视为udulant,因此isUndulant对于n <10 ,返回false。


数字输入为字符串,整数,浮点数...?
停止转动逆时针

1
目的是什么?代码高尔夫球(最短函数)?
亚历山德鲁

1
@JBernardo:我认为是真实的或未定义的行为,因为这将是递归的更好的基础案例。
乔伊·亚当斯

4
您对无用数字的定义与标准定义不符mathworld.wolfram.com/UndulatingNumber.html。这是故意的吗?
mellamokb

9
如果基本情况正确,我的解决方案可以小16%(恕我直言)。
eternalmatt 2011年

Answers:


6

J,45岁

*./(n>9),(}:(=-)}.)(}:*@-}.)n#:~10$~>.10^.n=.

样品使用:

   *./(n>9),(}:(=-)}.)(}:*@-}.)n#:~10$~>.10^.n=. 461902
1
   *./(n>9),(}:(=-)}.)(}:*@-}.)n#:~10$~>.10^.n=. 708143
1
   *./(n>9),(}:(=-)}.)(}:*@-}.)n#:~10$~>.10^.n=. 1010101
1
   *./(n>9),(}:(=-)}.)(}:*@-}.)n#:~10$~>.10^.n=. 123
0
   *./(n>9),(}:(=-)}.)(}:*@-}.)n#:~10$~>.10^.n=. 5
0

我敢肯定,有一种更好的方法可以扭曲Insert /来一次完成更多的工作,但是我已经几个月没有J了,我需要重新开始。


在这个问题上很难击败J。不错的解决方案!
leonardo

@leonardo谢谢!
JB

6

Ruby,72 70个字符

Q=10;k=->n,v{(n%Q-n/Q%Q)*v<0?k[n/Q,-v]:n<Q};u=->n{n>9&&k[n,-1]|k[n,1]}

用法和测试用例:

p u[10101]   # <= true
p u[708143]  # <= true
p u[2421]    # <= false
p u[1231]    # <= false
p u[873]     # <= false

一位数字为false

p u[5]       # <= false

连续的相同数字也返回false

p u[66]      # <= false
p u[1221]    # <= false

6

J,30个字节

*/0<(#,]*{.*1 _1$~#)2-/\a.i.":

与其他J答案不同的方法。

   * / 0 <(#,] * {。* 1 _1 $〜#)2-/ \ ai“:461902
1个
   * / 0 <(#,] * {。* 1 _1 $〜#)2-/ \ ai“:708143
1个
   * / 0 <(#,] * {。* 1 _1 $〜#)2-/ \ ai“:1010101
1个
   * / 0 <(#,] * {。* 1 _1 $〜#)2-/ \ ai“:123
0
   * / 0 <(#,] * {。* 1 _1 $〜#)(} .-} :) ai“:5
0

如果5个被认为是多余的,将短3个字符。


好吧,至少我可以以领导一个小时的想法来安慰自己。:-)
Gareth

5

(pdf)eTeX,129个字符

\def\a#1#2{\if#2?\ifx\r\s\def\s{1}\else
True\end\fi\fi\edef\t{\pdfstrcmp{#2}{#1}}\ifx\s\t
False\end\fi\let\s\t\a#2}\expandafter\a

编译时pdfetex filename.tex 1324?提供pdf输出。TeX主要是一种排版语言,而输出到stdout大约需要20个字符。同样,对一位数字的奇怪要求(错误而不是真实)要花我26个字符。


5

Haskell,88 77 73 65个字符

z=tail>>=zipWith compare
q[]=0>1
q s=all(/=EQ)$s++z s
u=q.z.show

这需要常用的语言编译(或-X标志)NoMonomorphismRestriction。如果您不同意,我们必须添加4个字符并定义z

z s=zipWith compare s$tail s

我很生气,您击败了我的104个字符的解决方案。u n=length s>1&&(a[GT,LT]||a[LT,GT])where s=show n;z=q compare s$tail s;w=q(==)z;q=zipWith;a=and.w.cycle有点优雅。zipWith一次与compare您一样,然后zipWith再次与(==)cycle[GT,LT]cycle[LT,GT]作为第二个参数。
eternalmatt 2011年

您可以内联w,因为tail>>=zipWith compare这会缩短几个字节。
自豪的haskeller 2014年

另外,我打了以下简短版本的qq[]=0<1;q(a:b:s)|a/=b,a/=EQ=q$b:s;q _=0>1
高尔夫球

实际上,这是一个更短的版本: q s=and$all(/=EQ)s:zipWith(/=)s(tail s)
骄傲的haskeller 2014年

@proudhaskeller-两个版本均未通过所有测试。他们都未能在3(应该是假的),和第一失败许多人,像32和101010101.
MtnViewMark

4

贤者,83 76字节

f=lambda x:uniq(cmp(*`x`[i-2:i][::(-1)^i])for i in[2..len(`x`)])in[[1],[-1]]

有了使用JBernardo的cmp(* [..])的想法。在Sage中,uniq(...)是的别名list(set(...))

编辑:只是注意到对于x <10,uniq(cmp(...)) == []不在上[[1],[-1]]。如果将x作为字符串而不是整数输入,我可以再输入4个字符!


我有个主意,要使用sum(uniq(...))^2,因为sum([1,-1]) = 0,单例[1]和[-1]的总和要等于1。不幸的是,它在三次重复的数字上失败;1011101.
展位,

真好 我应该学习贤哲。顺便说一句,我刚刚意识到L如果Python中的数字大于2 ** 32 ,反引号将附加一个,并且会影响结果。鼠尾草会发生这种情况吗?
JBernardo

是的,Sage使高尔夫运动变得更美好……例如,其荒谬的启动时间花费在导入巨大的模块树上。Sage Integer类无需理会,L因为Sage是用python编写的。1234->整数('1234')。您可以在这里直接使用Sage:sagenb.org
2011年

4

Python:101 100个字符

缩小之前:

undulate = (lambda n: n > 9
            and all(cmp(*digits) == (i % 2) * 2 - 1
                    for i, digits
                    in enumerate(zip(min(`n`,`n`[1:]), 
                                     max(`n`,`n`[1:])))))

缩小后:

a=lambda b:b>9and all(cmp(*c)==d%2*2-1 for d,c in enumerate(zip(min(`b`,`b`[1:]),max(`b`,`b`[1:]))))

3

Python,134129个字符

def f(x):d=[cmp(*i)for i in zip(`x`,`x`[1:])]if x>9 else[0];n=d[0]>0;return all(i<0 for i in d[n::2])&all(i>0 for i in d[n<1::2])

取消高尔夫:

def f(x):
    if x>9:
        d = [cmp(*i)for i in zip(`x`,`x`[1:])] #difference of x[i] and x[i+1]
    else:
        d = [0]       #trick to return False if x<10 using less chars
    n = d[0]>0        #First digit is -1 or 1?
    neg = d[n::2]     #negative numbers if x is Undulant
    pos = d[not n::2] #positive numbers if x is Undulant

    #check if all negs are -1 and all pos are 1 and return value
    return all(i<0 for i in neg) and all(i>0 for i in pos)

3

JavaScript,88个字符

function _(i){i+='';c=i[0];f=i[a=x=1];for(g=f<c;d=i[x++];c=d)g^=a&=g?d<c:d>c;return!f^a}

本质上,将数字转换为字符串并比较相邻的字符,将每个字符的期望值翻转。


2
在JavaScript中,一个函数不需要名称,并且问题明确要求一个函数,因此您可以保存两个字符。
Ry- 2011年

3

K,41个字节

{(x>9)&~max(=). 1_'-':'1_'(<':;>':)@\:$x}

例如

{(x>9)&~max(=). 1_'-':'1_'(<':;>':)@\:$x}1212130659
1b

3

CoffeeScript, 98 67 53个字节

(n)->0!in((n[i]>=c^(n[0]<n[1])+i)%2for c,i in n[1..])

测试:

[
    '01010101' # true
    '12345'    # false
    '1010101'  # true
    '887685'   # false
    '9120734'  # true
    '090909'   # true
]

未压缩:

undulant = (n) ->
    direction = n[0] < n[1]
    return n.split('').every (cur, i) ->
        prev = arr[i-1] or 10 * direction
        +(prev >= cur) is (direction+i)%2

3

J,44 39 36 31字节

*/2(0<#@],0>*/\)*2-/\".;' ',.":

用法与以前相同。

我没有注意到我的上一次编辑使得完全不需要使用0的不等式。:-)

先前的答案(+说明):

(0=+/2=/\u)*(1<#u)**/2~:/\2<:/\u=.".;' ',.":

用法:

    (0=+/2=/\u)*(1<#u)**/2~:/\2<:/\u=.".;' ',.":461902
1

答案分为四个部分:

  1. u=.".;' ',.": 这将数字读为字符串":,将其拆分为以空格' ',.开头的字符列表,将其缝合在一起;,将其转换回数字".,然后存储结果,u=.这基本上使461902变成了4 6 1 9 0 2用J处理

  2. */2~:/\2<:/\ 这对存储在u中的值进行运算。它获取每对字符,并检查左字符是否小于或等于右字符,2<:/\因此4 6 1 9 0 2变为1 0 1 01。然后获取此结果,并检查每对数字的不等式2~:/\所以1 0 1 0 1变成1 1 11。最后,将它们全部相乘得到0或1。*/这时如果不是两件事情,我们可以返回答案:当问题要求为0;和相等的数字被视为与“小于”相同,因此461900返回1而不是0。Bummer。走吧...

  3. (1<#u) 这将检查u中存储的项目数#u是否大于1,如果它只是一个数字,则返回false。

  4. (0=+/2=/\u) 这将获取存储在u中的每对数字并检查是否相等2=/\u。然后,它汇总答案并检查其是否为0。

然后,将数字2、3和4的结果相乘,以使数字满足问题中指定的要求(希望)为1。


做得好,能再次取得领先,但我只是向您借了一个窍门!
短暂

(话虽这么说,我认为您可以带我a.i.":剃掉几个字符。)
短暂的

不幸的是,我可能不得不把这种不平等检查回来-现在我的答案失败的11,22,33,44等
加雷

3

Haskell,82个字节

c=cycle[(<),(>)]
l!n=n>9&&and(zipWith3($)l(show n)$tail$show n)
u n=c!n||((>):c)!n

在线尝试!


在此解决方案中,我仅数83个字符。(也许您在Windows上?用unix行尾写文件,这是合法的Haskell。)
MtnViewMark 2011年

谢谢,我使用'wc'来计数Cygwin上的字符。我数了82个字符。我使用了以下代码,因为wc似乎输出了一个额外的字符。(Vim不会显示尾随的换行符,但记事本会显示...) readFile "Undulant.hs" >>= print . length . dropWhile (== '\n') . reverse . filter (/= '\r')
Thomas Eding

c=cycle[(<),(>)]可以缩短为c=(<):(>):c
莱科尼

1
zipWith3($)l(show n)$tail$show n可以zipWith3($)l=<<tail$show n并且((>):c)可以tail c。总共70个字节:在线尝试!
Laikoni '18

3

Python,119108字节

def u(x):l=[cmp(i,j)for i,j in zip(`x`,`x`[1:])];print x>9and all([i*j<0 for i,j in zip(l,l[1:])])and l!=[0]

2
Nice use of xor. You can cut quite a few characters out with ... for a,b in zip(t,t[1:]) rather than using ranges. Also, you don't need the brackets in all([...]) -- Python makes a generator when it finds (... for ...), even if the parentheses are for a function call.
boothby

非常感谢您的建议!他们非常有价值!-20个字符
Kirill

非常好的解决方案。少几个字符x>9 and all(i^j for i,j in zip(l,l[1:]))并删除if l else False
安特

1
它并非在所有情况下都有效。有两种情况是有问题的:只有2位数字(例如11),而最后2位数字相同且大于前一位(例如12155)。第一个问题是因为没有测试x <100。其次是因为“单向比较”。它可以通过修复cmp(i,j)i^j设置i*j<0,也可以进行测试and l[0]!=0。几个字符:-/
Ante

1
Hmmm... print saves one character over return, but is it legitimate? The spec does ask for a function that "returns".

2

Python, 155 chars

g=lambda a,b:all(x>y for x,y in zip(a,b))
u=lambda D:g(D[::2],D[1::2])&g(D[2::2],D[1::2])
def U(n):D=map(int,str(n));return(n>9)&(u(D)|u([-d for d in D]))

2

C++, 94 chars

bool u(int N){int K,P,Q,U=1,D=1;while(N>9)P=N%10,Q=(N/=10)%10,K=D,D=U&Q<P,U=K&Q>P;return U^D;}

same method as my Erlang awnser with a for loop rather than recursion.


2

Python 105 101 100 chars

c=lambda r,t:len(r)<2 or(cmp(*r[:2])==t and c(r[1:],-t))
u=lambda x:x>9and c(`x`,cmp(*`x`[:2])or 1)

Recursive solution. c(r,t) checks if first char of r is less (t==-1) or greater (t==1) of second char, and call opposite check on shortened string.


Nice. You can save a character in the first line by removing 0, and you can save three characters on the second line by writing u=lambda x:x>9 and c(`x`,cmp(*`x`[:2])or 1)

Tnx. I didn't like any() from the beginning :-)
Ante

You can save one more by writing x>9and.

2

Perl/re, 139 bytes

Doing everything in regex is kind of a bad idea.

/^(?:(.)(?{local$a=$1}))?(?:(?>((.)(?(?{$a lt$3})(?{local$a=$3})|(?!)))((.)(?(?{$a gt$5})(?{local$a=$5})|(?!))))*(?2)?)(?(?{pos>1})|(?!))$/

I'm using Perl 5.12 but I think this will work on Perl 5.10. Pretty sure 5.8 is out though.

for (qw(461902 708143 1010101 123 5)) {
    print "$_ is " . (/crazy regex goes here/ ? '' : 'not ') . "undulant\n";
}

461902 is undulant
708143 is undulant
1010101 is undulant
123 is not undulant
5 is not undulant

2

GolfScript, 48 bytes

[`..,(<\1>]zip{..$=\-1%.$=-}%(\{.@*0<*}/abs

Hoping to beat J, my first time using GolfScript. Didn't quite succeed.


2

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.


1

PowerShell, 88

Naïve and trivial. I will golf later.

filter u{-join([char[]]"$_"|%{if($n){[Math]::Sign($n-$_)+1}$n=$_})-notmatch'1|22|00|^$'}

My test cases.


1

JavaScript, 112

function(n,d,l,c,f){while(l=n%10,n=n/10|0)d=n%10,c?c>0?d>=l?(f=0):(c=-c):d<=l?(f=0):(c=-c):(c=d-l,f=1);return f}

You only need to pass it one argument. I could probably golf this further with a for loop.


(d>=l -> d>0) and (d<=l -> d<2) perhaps? I'm not looking closely, as perhaps d might contain fractional parts that might skew it.
Thomas Eding

@trinithis: That's a lowercase L, not a 1. Thanks though!
Ry-

Where's DejaVu Sans Mono or Bitstream Vera Sans Mono when you need it? Perhaps I need to customize stackoverflow with some custom css or a user script...
Thomas Eding

@trinithis: I agree, the font choice isn't that great. Bolding doesn't stand out enough...
Ry-

1

Erlang, 137 123 118 chars

u(N)->Q=N div 10,u(Q,N rem 10,Q>0,Q>0). u(0,_,D,U)->D or U;u(N,P,D,U)->Q=N rem 10,u(N div 10,Q,U and(Q<P),D and(Q>P)).

Won't this return True so long as there has been at least one up and one down transition anywhere? Won't it return True for, say 1234321?
MtnViewMark

@ MtnViewMark, yeah it did thanks, I misunderstood the question fixed now hopefully.
Scott Logan

1

CJam, 30 bytes

CJam is newer than this challenge, so this does not compete for the green checkmark, but it's not a winner anyway (although I'm sure this can actually be golfed quite a bit).

l"_1=\+{_@-\}*;]"_8'*t+~{W>},!

Test it here.

How it works

Firstly, I'm doing some string manipulation (followed by eval) to save 5 bytes on duplicate code:

"..."_8'*t+~
"..."        "Push this string.":
     _       "Duplicate.";
      8'*t   "Replace the 8th character (the -) with *.";
          +~ "Concatenate the strings and evaluate.";

So in effect my code is

l_1=\+{_@-\}*;]_1=\+{_@*\}*;]{W>},!

First, here is how I deal with the weird special case of a single digit. I copy the digit at index 1 and prepend it to the number. We need to distinguish 3 cases:

  • The first two digits are different, like 12..., then we get 212..., so the start is undulant, and won't affect whether the entire number is undulant.
  • The first two digits are the same, like 11..., then we get 111.... Now the start is not undulant, but the number wasn't undulant anyway, so this won't affect the result either.
  • If the number only has one digit, the digit at index 1 will be the first digit (because CJam's array indexing loops around the end), so this results in two identical digits, and the number is not undulant.

Now looking at the code in detail:

l_1=\+{_@-\}*;]_1=\+{_@*\}*;]{W>},!
l                                   "Read input.";
 _1=\+                              "Prepend second digit.";
      {_@-\}*                       "This fold gets the differences of consecutive elments.";
             ;]                     "Drop the final element and collect in an aray.";
               _1=\+                "Prepend second element.";
                    {_@*\}*         "This fold gets the products of consecutive elments.";
                           ;]       "Drop the final element and collect in an aray.";
                             {W>},  "Filter out non-negative numbers.";
                                  ! "Logical not.";

I'm sure there is a shorter way to actually check digits (of length greater 1) for whether they are undulant (in particular, without using two folds), but I couldn't find it yet.


1

Prolog 87 bytes

u(X) :- number_codes(X,C),f(C).
f([_,_]).
f([A,B,C|L]) :- (A<B,B>C;A>B,B<C),f([B,C|L]).

To run it, just save it as golf.pl, open a prolog interpreter (e.g. gprolog) in the same directory then do:

consult(golf).
u(101010).

It will give true if the number is undulant, otherwise just no.


1

Mathematica, 46 bytes

#!=Sort@#&&#!=Reverse@Sort@#&[IntegerDigits@n]

Examples (spaces are not required):

# != Sort@# && # != Reverse@Sort@# &[IntegerDigits@5]
# != Sort@# && # != Reverse@Sort@# &[IntegerDigits@123]
# != Sort@# && # != Reverse@Sort@# &[IntegerDigits@132]
# != Sort@# && # != Reverse@Sort@# &[IntegerDigits@321]

(*  out *)
False  False  True  False

1

Scala, 141 133 129 97 bytes

def u(n:Int):Boolean=n>9&&{
val a=n%10
val b=(n/10)%10
a!=b&&n<99||(a-b*b-(n/100)%10)<0&&u(n/10)}

With a = n % 10, b = (n/10) % 10, c = (n/100) % 10

if a > b and b < c or 
   a < b and b > c

Then a-b * b-c is either x*-y or -x*y with x and y as positive numbers, and the product is in both cases negative, but for -x*-y or x*y (a < b < c or a > b > c) the product is always positive.

The rest of the code is handling special cases: one digit, two digits, two identical digits.


1

Perl, 78 bytes

sub u{@_=split//,$_=shift;s/.(?=.)/($&cmp$_[$+[0]])+1/ge;chop;$#_&&!/00|1|22/}

1

Q, 71 bytes

{$[x>9;any all a=#[;(1 -1;-1 1)](#)a:1_signum(-':){"I"$x}each -3!x;0b]}

Sample usage:

q){$[x>9;any all a=#[;(1 -1;-1 1)](#)a:1_signum(-':){"I"$x}each -3!x;0b]} 5
0b
q){$[x>9;any all a=#[;(1 -1;-1 1)](#)a:1_signum(-':){"I"$x}each -3!x;0b]} 10101
1b
q){$[x>9;any all a=#[;(1 -1;-1 1)](#)a:1_signum(-':){"I"$x}each -3!x;0b]} 01010
1b
q){$[x>9;any all a=#[;(1 -1;-1 1)](#)a:1_signum(-':){"I"$x}each -3!x;0b]} 134679
0b
q){$[x>9;any all a=#[;(1 -1;-1 1)](#)a:1_signum(-':){"I"$x}each -3!x;0b]} 123456
0b
q){$[x>9;any all a=#[;(1 -1;-1 1)](#)a:1_signum(-':){"I"$x}each -3!x;0b]} 132436
1b

You can logic away the if {(x>9)&any all a=#[;(1 -1;-1 1)](#)a:1_signum(-':)("I"$')($)x} gives 62
skeevey

Never seen ($) syntax for string before and the logic is a nice touch.
tmartin

1

Julia 0.6, 62 bytes

f(x,a=sign.(diff(digits(x))))=x>9&&-a*a[1]==(-1).^(1:endof(a))

Takes in a number, returns true for Undulant, and false for not. Eg f(163) returns true.

f(x,a=sign.(diff(digits(x))))=x>9&&-a*a[1]==(-1).^(1:endof(a))
f(x,                        )                                   # function definition
    a=sign.(diff(digits(x)))                                    # default 2nd argument is array of differences of signs of digits
                              x>9&&                             # short circuiting and to catch cases under 10
                                   -a*a[1]                      # make the first element of a always -1
                                          ==(-1).^(1:endof(a))  # check that a is an array of alternating -1 and 1 of correct length

Try it online!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.