Хто найвищий?


32

П’ятеро дітей, де двоє не поділяють їх точний розмір, вишикуються в певному порядку. Кожен може порівняти висоту лише зі своїми безпосередніми сусідами. Коли вчитель кричить "підніміть руки, якщо ви найвищий", вони роблять це, якщо вони вищі за своїх сусідів, і вони роблять це одночасно. Якщо тільки один піднімає їх руку, він виграє. Якщо декілька піднімають руки, їх всі виключають з ряду (зберігаючи порядок решти дітей) і вони повторюють процес.

Напишіть програму, яка містить масив різних цілих чисел (можна припустити, що вони суворо позитивні) і виводить переможця цієї гри. Це код-гольф, тому виграє найкоротший код.

Приклади (показані проміжні стадії):

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 байт [від Денніса ♦]
  2. MATL: 20 байт [Луїс Мендо]
  3. APL: 28 байт [voidhawk]
  4. k: 40 байт [автор Пол Керріган]

Також триває битва на Пітонах. Ще чекаю, поки з’явиться більше мов для гри в гольф.

На даний момент я прийняв відповідь Деніса ♦ - якщо з’являться нові переможці, я оновлю вибір.


2
звучить більше як "хто може бути найвищим, а може і ні?" - насправді знайти «який є найвищим» ви повинні усунути ті , які тримають свої руки вниз
Альнитак

4
Я намалював подібність до дитячих ігор, де одна людина кричить якусь підписну фразу, після якої гра називається. Як не дивно, найвищий шанс виграти найвищий (з величезним відривом). Асимптотично, поза N! перестановки, лише в 2 ^ (N-1) випадках він виграє.
Оріон

Відповіді:


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

"[1,2,5,8,9,12,3,4,10] Вихід: 5" Я думаю, що це повинно вивести 8, а не 5. Спочатку виключаються 12 і 10, потім 9 і 4, потім 8 виграшів .
Оріон

1
@orion Моє погано, фрагмент не перетворив свої аргументи на номери перед тим, як відправити їх у функцію. Це було виправлено.
ETHproductions

Ви можете зберегти 4 байти на прикладі фільтра, перемикаючи qта 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: \\ імпорт все ще потребує. Btw, tailsтакож можна замінити на ...|a:b:c:_<-scanr(:)[]$0:x++[0],....
німі

О так, я цього не усвідомлював.
Згарб

2

Математика, 107 108 байт

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

Пояснення

Спочатку встановіть xі yдорівнюйте вводу List. Цикл продовжується до тих пір, поки Length@y==1. x~Split~Lessце перелік списків послідовних, зростаючих елементів, Split[x,#>#2&]це список списків послідовних, спадаючих елементів. Якщо взяти список Maxусіх списків у першому, це список дітей вищий за дитину праворуч (разом із самою правою дитиною). Якщо взяти перший аргумент ( #&) усіх списків у останньому, то список дітей вищий, ніж дитина, зліва (разом із самою лівою дитиною). Перетином цих двох буде список дітей, які підняли руку. Встановіть це рівним y. x=DeleteCases[x,#|##&@@y]видаляє з xбудь-яких елементів, що відповідають елементу y( #|##&еквівалентноAlternatives). Як тільки цикл закінчується, поверніться (+4 байти).y. Якщо вихід повинен бути цілим числом (а не списком, що містить одне ціле число), поверніться#&@@y

Дякую Мартіну Ендеру, що врятував 2 байти і змусив мене дотримуватися правил. Відкрити для пропозицій.


Я не думаю, що !Lessпрацює так, як ви очікували, оскільки це насправді не відповідає функції. Вам, ймовірно, доведеться користуватися Greater(або #>#2&) там. Ви можете використовувати x~Split~Lessдля першого, Splitхоча і >для Lengthумови.
Мартін Ендер

1
Що стосується необхідності оцінювати Clear@yміж викликами функцій, то, боюся, це не вірно . Вам або доведеться самостійно скинути його, розгорнути його краще, або перетворити це на повну програму з Inputта Print.
Мартін Ендер

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]

Використовує коротке замикання, як у відповіді Йодла (Закарі Т)


Ви можете зняти ще 3 байти, використовуючи: +=b,замість +=[b](зарахування до математики), t=[0]використовуючи tдля додавання до A, а потім, оскільки ми починаємо з 0 дюймів t, перевірка t[-2]<1є коротшою len(t)<2, а t[1]в такому випадку - як результат.
Оріон

Останній рядок стає return t[-2]and f(l)or t[1].
Оріон

0

Математика, 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], що обчислює масив (max-of-me-and-my-soses) s зі списку вхідних даних.a=Position[...-#,0]потім віднімає початковий список і повертається там, де є 0; це діти, що виховують руки.

If[Equal@@a, #[[Last@a]], #0@Fold[Drop@##&,#,Reverse@a]]&гілки залежно від того, чи всі елементи aрівні чи ні (у цьому випадку вони будуть лише, якщо aє одинаковими); якщо так, то ця дитина є переможцем, і ми виводимо її номер; якщо ні, то ми рекурсивно викликаємо цю функцію у списку з усіма елементами на позиціях у aвидалених.


0

Пітон 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]}

Пояснення:
$ - це інше.

Умова полягає в тому, чи є 1 сума B, яка визначається як мінімум з двох списків, згенерованих за допомогою перевірки, чи х більше, ніж попередні та пост-позиції (Труба зворотна).

Якщо це правда, ми повертаємо x там, де B - істина.
Інакше ми повторюємось без справжніх позицій.


0

129 байт Scala

Гольф

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 на зовнішній стороні, тож отримайте правильне число (якщо припустити, висота nobodys негативно!)


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, як vector, dequeіlist .

Створює два контейнери t і sтого ж типу і додає локальний найвищий tта інший до s. Якщо tнатомість є лише 1 елемент , інакше рекурсивний дзвінок із собою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])}

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.