Кто самый высокий?


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 байт [Деннис ♦]
  2. MATL: 20 байт [Луис Мендо]
  3. APL: 28 байт.
  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: \\ все еще нуждается в импорте. Кстати, tailsтакже может быть заменен на ...|a:b:c:_<-scanr(:)[]$0:x++[0],....
Ними

О, да, я этого не осознавал.
Zgarb

2

Mathematica, 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). Как только цикл завершится, вернитесь y. Если выходные данные должны быть целыми числами (а не списком, содержащим одно целое число), вернуть #&@@y(+4 байта).

Спасибо Мартину Эндеру за то, что он сэкономил 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]}

Expanded:

{  # 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

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], которое вычисляет массив (-max-of-me-and-my-соседей) из входного списка. 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

к, 40 байт

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

Объяснение:
$ - это if-else.

Условием является то, является ли 1 суммой B, которая определяется как минимум двух списков, сгенерированных путем проверки, больше ли x, чем предыдущая и последующая позиции (труба обратная).

Если это правда, мы возвращаем x, где B верно.
В противном случае мы вернемся без истинных позиций.


0

Scala 129 байт

Golfed

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)}

Ungolfed

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)
}

Заполняя список влево и вправо нулями, можно затем сгруппировать в наборы по 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. Если есть только 1 элемент tвзамен этого, в противном случае рекурсивный вызов сам с s.

Ungolfed:

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.