谁最高?


32

N个孩子按一定顺序排列,没有两个孩子分享他们的确切大小。每个人只能将身高与其近邻比较。当老师大喊“如果你最高,举手”时,如果他们比两个邻居都高,他们就会高声喊叫,并且他们会同时举高声。如果只有一个人举手,他将获胜。如果不止一个举手,则将他们全部从该行中淘汰(保留其余孩子的顺序),然​​后重复该过程。

编写一个程序,该程序采用一组不同的整数(可以假定它们严格为正),并输出此游戏的获胜者。这是代码高尔夫球,因此最短的代码获胜。

示例(显示了中间阶段):

5 3 9 8 7→3 8 7→8

1 2 9 4→9

9 3 8 7 4 12 5→3 7 4 5 →3 4 →4


现任领导人:

  1. 果冻:17个字节[作者:Dennis♦]
  2. MATL:20个字节[作者:Luis Mendo]
  3. APL:28个字节[voidhawk]
  4. k:40个字节[Paul Kerrigan撰写]

还有一场Python之战。仍在等待更多的高尔夫语言出现。

我目前接受Dennis♦的回答-如果有新的获奖者,我将更新选择。


2
听起来更像是“谁可能是最高的,或者不是?” -要真正找到“谁是最高的”,您就必须消除那些压低
Alnitak

4
我画了与儿童游戏的相似之处,其中一个人大喊一些签名短语,然后以该游戏命名。有趣的是,最高的人获胜的可能性最小(大幅提高)。渐近地,在N中!排列,只有在2 ^(N-1)种情况下他才能获胜。
Orion 2016年

Answers:


4

果冻,17个字节

j@N»3\=x@ḟ@ḢṖ?µ¬¿

输入是一个逗号分隔的整数字符串。

在线尝试!

致谢@ Xanderhall,@ Sherlock和@ErikGolfer奠定了基础。

怎么运行的

j@N»3\=x@ḟ@ḢṖ?µ¬¿ Main link: Argument: A (integer or list of integers)

               ¬¿ While the logical NOT of A (0 for a positive integer, a non-empty
                  array for a non-empty array) is truthy:
              µ     Execute the chain of links to the left.
  N                   Negative; multiply all integers in A by -1.
j@                    Join -A, separating by A. This prepends and appends a
                      negative to A and appends more integers that will be ignored.
   »3\                Compute the maxima of all overlapping slices of length 3.
      =               Compare the maxima with the elements of A, yielding 1 or 0.
       x@             Repeat the elements of A, 1 or 0 times.
                      This ignores Booleans without a counterpart in A.
            Ṗ?        If the popped result is truthy, i.e., if it has at least two
                      elements:
         ḟ@             Filter/remove those elements from A.
                      Else:
           Ḣ            Head; extract the (only) element of the return value.

10

JavaScript(ES6),78 76 72字节

感谢@ edc65 -4个字节

f=a=>a.map((c,i)=>(p>c|c<a[i+1]?q:r).push(p=c),p=q=[],r=[])&&r[1]?f(q):r

接受一个整数数组并输出一个仅包含获胜者的数组。

测试片段

这是使用.filter和数组推导的其他尝试:

f=a=>(q=a.filter((c,i)=>p>(p=c)|c<a[i+1]||0*r.push(c),p=r=[]))&&r[1]?f(q):r
f=a=>(r=a.filter((c,i)=>p<(p=c)&c>~~a[i+1]||0*r.push(c),p=q=[]))[1]?f(q):r
f=a=>[for(c of(i=p=q=[],r=[],a))(p>c|c<a[++i]?q:r).push(p=c)]&&r[1]?f(q):r
f=a=>(q=[for(c of(i=p=r=[],a))if(p>(p=c)|c<a[++i]||0*r.push(c))c])&&r[1]?f(q):r

或双重循环,非常长:

a=>eval("for(r=[,1];r[1]&&(p=i=q=[],r=[]);a=q)for(c of a)(p>c|c<a[++i]?q:r).push(p=c));r")

说明

它的工作方式非常简单:它构建一个相对较高r的数组()和一个不较高的数组(q),r如果仅包含一项,则返回;如果不是,它将自行运行q并返回结果。


小吃片段在哪里?
Kritixi Lithos

@KritixiLithos添加了:-)
ETHproductions '16

“ [1,2,5,8,9,12,3,4,10]输出:5”我认为这应该输出8,而不是5。首先,消除12和10,然后消除9和4,然后赢得8次。
Orion

1
@orion我不好,代码片段没有在将其参数发送给函数之前将其参数转换为数字。此问题已解决。
ETHproductions's

通过切换q和,可以在过滤器示例中节省4个字节r。您避免使用,&&r并且过滤器表达式也缩短了一个字节。
尼尔

8

MATL,20字节

`tTYadZSd0<~&)nq}x2M

输入是一个列向量,;用作分隔符。

在线尝试!验证所有测试用例

说明

这是挑战中描述的过程的直接实现。一do... while圈保持删除元素,直到只有一个已被删除; 那就是输出。

要删除的元素将通过先求和再求差来检测。给出负值的将被删除。

`        % Do...while
  t      %   Duplicate. Takes input (implicit) the first time
  TYa    %   Append and prepend a zero
  d      %   Consecutive differences
  ZS     %   Signum
  d      %   Consecutive differences
  0<~    %   Logical mask of non-negative values: these should be kept
  &)     %   Split array into two: those that should kept, then those removed
  nq     %   Size minus 1. This is used as loop condition. The loop will exit
         %   if this is 0, that is, if only one element was removed
}        % Finally (i.e. execute at the end of the loop)
  x      %   Delete array of remaining elements
  2M     %   Push last element that was removed
         % End (implicit)
         % Display (implicit)

4

Python3,265 260 248 243 203 121 117 112 111字节

def T(I):
 b=[0];q=[];J=b+I+b
 for i,x in enumerate(I):[q,b][J[i]<x>J[i+2]]+=x,
 return len(b)<3and b[1]or T(q)

谢谢@ ZacharyT,@ orion和@mathmandan节省了5 45个字节!


2

Haskell,85个字节

import Data.List
f x=(#)=<<(x\\)$[b|a:b:c:_<-tails$0:x++[0],b<a||b<c]
[s]#_=s
_#i=f i

用法示例:f [9,3,8,7,4,12,5]-> 4

怎么运行的:

f x =                            -- main function with parameter x
         [b|                  ]  -- make a list of all b
            a:b:c:_              -- where b is the second element of all lists with
                                 -- at least 3 elements
             <- tails $ 0:x++[0] -- drawn from the tails of x with a 0 pre- and
                                 -- appended (tails [1,2,3] -> [1,2,3],[2,3],[3],[])
               ,b<a||b<c         -- and b is not greater than its neighbors
   (#)=<<(x\\)                   -- feed the list difference of x and that list
                                 -- and the list itself to the function #

[s]#_s                           -- if the list difference is a singleton list,
                                 -- return the element
_#i=f i                          -- else start over with the list of b's

一个变体,也是85个字节:

import Data.List
f x|n<-[b|a:b:c:_<-tails$0:x++[0],b<a||b<c]=last$f n:[s|[s]<-[x\\n]]

b(见上文)的列表绑定到n,s如果x\\n是单例列表,f n则返回元素,否则返回。


您可以摆脱导入,并使用保存3个字节f x|y@(_:z)<-x++[0]=(#)=<<(x\\)$[b|(a,b,c)<-zip3(0:y)y z,b<a||b<c]
Zgarb '16

@Zgarb:\\ 仍然需要导入。顺便说一句,tails也可以用代替...|a:b:c:_<-scanr(:)[]$0:x++[0],...
nimi

哦,对,我没有意识到。
Zgarb '16

2

Mathematica,107字节

(For[x=y=#,Length@y>1,x=DeleteCases[x,#|##&@@y],y=Intersection[Max@@@x~Split~Less,#&@@@Split[x,#>#2&]]];y)&

说明

首先,设置xy等于input List。循环一直持续到Length@y==1x~Split~Less是连续的递增元素Split[x,#>#2&]列表的列表,是连续的递减元素列表的列表。取Max前者中的所有列表中的所有列表,将得出比其右边的孩子(以及最右边的孩子)高的孩子的列表。取#&后者中所有列表的第一个参数(),得出的孩子列表要比左侧孩子(以及最左边的孩子)高。这两个的交集将成为举手的孩子的列表。将此设置为yx=DeleteCases[x,#|##&@@y]从移除了x匹配的元件的任何元件y#|##&等效于Alternatives)。循环终止后,返回y。如果输出必须是整数(而不是包含单个整数的列表),则返回#&@@y(+4个字节)。

感谢Martin Ender节省了2个字节并使我遵守规则。公开征求意见。


我认为!Less这并不像您期望的那样有效,因为这实际上无法评估函数。您可能需要在此处使用Greater(或#>#2&)。您可以使用x~Split~Less在第一Split,但并>Length条件。
Martin Ender

1
至于必须Clear@y在函数调用之间进行评估,恐怕是无效的。您要么必须自己重设,更好地确定范围,要么使用Input和将其变成完整的程序Print
Martin Ender

1

Perl 6、111个字节

{(@_,{(($/=(0,|@$_,0).rotor(3=>-2).classify({+so .[1]>.[0,2].all})){1}>1??$/{0}!!$/{1})».[1]}...*==1)[*-1][0]}

展开:

{  # bare block lambda with implicit parameter list 「@_」

  (                                    # generate a sequence
    @_,                                # starting with the input

    {   # code block used to get the next value in the sequence
        # which has implicit parameter 「$_」

        (
          (


            $/ =   # store in 「$/」 for later use

            ( 0, |@$_, 0 )             # the input with 0s before and after
            .rotor( 3 => -2 )          # take 3 at a time, back up 2, repeat
            .classify({
              +                        # Numify the following:
              so                       # simplify the following Junction
              .[1] > .[ 0, 2 ].all     # is the middle larger than its neighbors
            })



          ){1}                         # look at the values where it is true
          > 1                          # is there more than 1?

        ??                             # if so
          $/{ 0 }                      # look at the false ones instead

        !!                             # otherwise
          $/{ 1 }                      # look at the true ones

      )».[1]                           # undo the transformation from 「.rotor」
    }

    ...                                # keep doing that until

    * == 1                             # there is only one value
  )\
  [ * - 1 ]                            # the last value of the sequence
  [ 0 ]                                # make it a singular value ( not a list )

}

1

Python 2中,100个 98字节

def f(A):
 t=[0];l=[];a=b=0
 for c in A+[0]:[l,t][a<b>c]+=[b];a,b=b,c
 return t[-2]and f(l)or t[1]

按照Yodle的答案使用短路回路(由Zachary T撰写)


您可以通过以下方法再减去3个字节:使用+=b,代替+=[b](贷给mathmandan),t=[0]使用t用来添加到A,然后,由于我们现在从0开始t,所以检查t[-2]<1比短len(t)<2,并且t[1]在这种情况下用作结果。
Orion

最后一行成为return t[-2]and f(l)or t[1]
Orion 2016年

0

Mathematica,101个字节

If[Equal@@(a=Position[Max/@Partition[#,3,1,{2,2},0]-#,0]),#[[Last@a]],#0@Fold[Drop@##&,#,Reverse@a]]&

未命名的递归函数,将一个数字列表作为输入,并返回一个具有单个数字(获胜者)的列表作为输出。

该算法的核心是Max/@Partition[#,3,1,{2,2},0],它从输入列表中计算(最大我和我的邻居)的数组。a=Position[...-#,0]然后减去原始列表并返回0。这些是举手的孩子。

If[Equal@@a, #[[Last@a]], #0@Fold[Drop@##&,#,Reverse@a]]&根据的所有元素a是否相等进行分支(在这种情况下,仅当a是单例时才是);如果是这样,那么这个孩子就是赢家,我们输出她的号码;如果没有,那么我们将在列表上递归调用此函数,并a删除所有位于位置的元素。


0

Python 2,99字节

def f(l):k=[x[0]for x in zip(l,[0]+l,l[1:]+[0])if(max(x),)>x];return(len(k)+2>len(l))*max(l)or f(k)

0

PHP,131字节

$r=$a=$argv;for(;$r[1];$a=array_values(array_diff($a,$r))){$r=[];foreach($a as$i=>$x)if($x>$a[$i-1]&$x>$a[$i+1])$r[]=$x;}echo$r[0];

从命令行参数获取数字。如果文件名以正数开头则失败。

分解

// import (and init $r[1])
$r=$a=$argv;
// while more than 1 raised hand, remove them from data
for(;$r[1];$a=array_values(array_diff($a,$r)))
{
    // reset hands
    $r=[];
    // raise hands
    foreach($a as$i=>$x)
        if($x>$a[$i-1]&$x>$a[$i+1])$r[]=$x;
}
// output
echo$r[0];

0

k,40个字节

{$[1=+/B:(|>':|x)&>':x;x@&B;.z.s x@&~B]}

说明:
$是if-else。

条件是1是否为B的总和,B的总和定义为通过检查x是否大于前后位置(管道反向)生成的两个列表中的最小值。

如果为真,则返回x,其中B为真。
否则,我们将在没有真实立场的情况下进行递归。


0

Scala 129字节

打高尔夫球

def x(a:List[Int]):Int={val (y,n)=(0+:a:+0).sliding(3).toList.partition(l=>l.max==l(1));if(y.length>1)x(n.map(_(1)))else y(0)(1)}

不打高尔夫球

def whoIsTallest(a: List[Int]): Int = {
  val (handUp, handDown) = (0 +: a :+ 0).sliding(3).toList.partition {
    case x :: y :: z :: Nil => y > x && y > z
  }
  if (handUp.length > 1)
    whoIsTallest(handDown.map(_(1)))
  else
    handUp.head(1)
}

通过在列表的左侧和右侧填充0,然后可以将其分成3组,并为手向上的那些对象划分列表,左侧和右侧的大多数元素在外侧与0相比,因此得到正确的数字(假设没有人身高是负面的!)


0

C ++ 14,182字节

#define P .push_back(c[i]);
int f(auto c){decltype(c)t,s;int i=0;(c[0]>c[1]?t:s)P for(;++i<c.size()-1;)(c[i-1]<c[i]&&c[i]>c[i+1]?t:s)P(c[i-1]<c[i]?t:s)P return t.size()<2?t[0]:f(s);}

了解到三元运算符可以与C ++对象一起使用。要求的输入是带有随机存取容器push_back,如vectordequelist

创建两个相同类型的容器ts并将本地最高的容器附加到t,其余的附加到s。如果只有1个元素t返回该元素,否则递归调用自身s

取消高尔夫:

int f(auto c){
  decltype(c)t,s;
  int i=0;
  (c[0]>c[1] ? t : s).push_back(c[i]);
  for(;++i<c.size()-1;)
    (c[i-1]<c[i]&&c[i]>c[i+1] ? t : s).push_back(c[i]);
  (c[i-1]<c[i] ? t : s).push_back(c[i]);
  return t.size()<2 ? t[0] : f(s);
}

0

R,83个字节

两种不同的版本:

这个取向量N:

while(T){Z=diff(sign(diff(c(0,N,0))))<0;if(sum(Z)>1)N=N[!Z]else{print(N[Z]);break}}

这创建了一个递归定义的函数F:

F=function(N){Z=diff(sign(diff(c(0,N,0))))<0;if(sum(Z)>1)F(N[!Z])else return(N[Z])}

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.