Quem é o mais alto?

32

N crianças, sem duas que compartilhem seu tamanho exato, estão alinhadas em alguma ordem. Cada um só pode comparar alturas com seus vizinhos imediatos. Quando o professor grita "levante a mão se você for o mais alto", ele o fará se for mais alto que os vizinhos e o fará simultaneamente. Se apenas um deles levanta a mão, ele vence. Se mais de uma pessoa levantar a mão, todas elas são eliminadas da linha (preservando a ordem do restante das crianças) e repetem o processo.

Escreva um programa, que utilize uma matriz de números inteiros distintos (você pode assumir que eles são estritamente positivos) e produza o vencedor deste jogo. Isso é código-golfe, então o código mais curto vence.

Exemplos (com estágios intermediários mostrados):

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


Líderes atuais:

  1. Geléia: 17 bytes [de Dennis ♦]
  2. MATL: 20 bytes [de Luis Mendo]
  3. APL: 28 bytes [voidhawk]
  4. k: 40 bytes [de Paul Kerrigan]

Há também uma batalha de Pythons em andamento. Ainda estou esperando mais idiomas de golfe aparecerem.

No momento, aceitei a resposta de Dennis - se houver novos vencedores, atualizarei a seleção.

orion
fonte
2
soa mais como "quem pode ser o mais alto ou não?" - para realmente encontrar "que é o mais alto" você teria que eliminar os únicos que mantêm as mãos para baixo
Alnitak
4
Desenhei semelhança com os jogos infantis, onde uma pessoa grita alguma frase de assinatura após a qual o jogo é nomeado. Curiosamente, o mais alto tem menos chances de ganhar (por uma margem enorme). Assintoticamente, fora de N! permutações, apenas em 2 ^ (N-1) casos, ele vence.
orion

Respostas:

4

Geléia , 17 bytes

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

Entrada é uma sequência de números inteiros separados por vírgula.

Experimente online!

Os créditos vão para @Xanderhall, @Sherlock e @ErikGolfer por lançar as bases.

Como funciona

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.
Dennis
fonte
10

JavaScript (ES6), 78 76 72 bytes

Obrigado a @ edc65 por -4 bytes

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

Recebe uma matriz de números inteiros e gera uma matriz contendo apenas o vencedor.

Snippet de teste

Aqui estão algumas outras tentativas, usando .filtere comprehensions de matriz:

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

Ou um loop for duplo, terrivelmente longo:

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

Explicação

A maneira como isso funciona é bem simples: constrói uma matriz daqueles que são relativamente mais altos ( r) e uma matriz daqueles que não são ( q), depois retorna rse tiver apenas um item; caso contrário, ele executa automaticamente qe retorna o resultado disso.

ETHproductions
fonte
Onde está o trecho do lanche?
Kritixi Lithos
@KritixiLithos Adicionado :-)
ETHproductions
"[1,2,5,8,9,12,3,4,10] Resultado: 5" Acho que isso deve gerar 8, não 5. Primeiro, 12 e 10 são eliminados, depois 9 e 4, depois 8 vitórias .
orion
11
@orion Meu problema, o trecho não estava convertendo seus argumentos em números antes de enviá-los para a função. Isso foi corrigido.
ETHproductions
Você pode salvar 4 bytes no seu exemplo de filtro alternando qe r. Você evita que a &&rexpressão e do filtro também seja um byte mais curto.
Neil
8

MATL , 20 bytes

`tTYadZSd0<~&)nq}x2M

Entrada é um vetor de coluna, usando ;como separador.

Experimente online! Ou verifique todos os casos de teste .

Explicação

Esta é uma implementação direta do procedimento descrito no desafio. Um loop do... whilecontinua removendo elementos até que apenas um seja removido; e esse é o resultado.

Os elementos a serem removidos são detectados através da tomada de diferenças, signum e diferenças novamente. Aqueles que dão um valor negativo são os que devem ser removidos.

`        % 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)
Luis Mendo
fonte
4

Python3, 265 260 248 243 203 121 117 112 111 bytes

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)

Obrigado @ZacharyT, @orion e @mathmandan para salvar 5 45 um monte de bytes!

Yodle
fonte
2

Haskell, 85 bytes

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

Exemplo de uso: f [9,3,8,7,4,12,5]-> 4.

Como funciona:

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

Uma variante, também 85 bytes:

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]]

Ligue a lista de b(veja acima) para n e retorne o elemento sse x\\nfor uma lista de singleton ou f nnão.

nimi
fonte
Você pode se livrar da importação e salvar 3 bytes com f x|y@(_:z)<-x++[0]=(#)=<<(x\\)$[b|(a,b,c)<-zip3(0:y)y z,b<a||b<c].
Zgarb
@ Zgarb: \\ ainda precisa da importação. Btw, tailstambém pode ser substituído por ...|a:b:c:_<-scanr(:)[]$0:x++[0],....
nimi
Ohh certo, eu não percebi isso.
Zgarb 01/12/19
2

Mathematica, 107 108 bytes

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

Explicação

Primeiro, defina xe yigual à entrada List. O loop continua até Length@y==1. x~Split~Lessé a lista de listas de elementos consecutivos crescentes, Split[x,#>#2&]é a lista de listas de elementos consecutivos decrescentes. Tomar a lista Maxde todas as listas anteriores fornece a lista de crianças mais altas que a criança à direita (junto com a criança mais à direita). Tomar o primeiro argumento ( #&) de todas as listas deste último fornece a lista de filhos mais altos que o filho à sua esquerda (junto com o filho mais à esquerda). A interseção desses dois será a lista de crianças que levantaram a mão. Defina isso igual a y. x=DeleteCases[x,#|##&@@y]remove de xqualquer elemento correspondente a um elemento de y( #|##&é equivalente aAlternatives) Quando o loop terminar, retorne (+4 bytes).y. Se a saída deve ser um número inteiro (em vez de uma lista que contém um único número inteiro), retorne#&@@y

Agradeço a Martin Ender por salvar 2 bytes e me fazer cumprir as regras. Aberto a sugestões.

ngenisis
fonte
Eu não acho que !Lessfuncione como você espera, já que isso não é avaliado como uma função. Você provavelmente precisará usar Greater(ou #>#2&) lá. Você pode usar x~Split~Lesspara o primeiro Splite >para a Lengthcondição.
Martin Ender
11
Quanto a ter que avaliar Clear@yentre chamadas de função, receio que isso não seja válido . Você precisará redefini-lo, escopo melhor ou transformar isso em um programa completo com Inpute Print.
Martin Ender
1

Perl 6 , 111 bytes

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

Expandido:

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

}
Brad Gilbert b2gills
fonte
1

Python 2, 100 98 bytes

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]

Usa o retorno em curto-circuito como na resposta de Yodle (por Zachary T)

TFeld
fonte
Você pode desativar mais 3 bytes usando: using em +=b,vez de +=[b](credit to mathmandan), use t=[0]to use tto add to Ae, como agora começamos com 0 in t, a verificação t[-2]<1é mais curta que len(t)<2e, t[1]como resultado, nesse caso.
orion
A última linha se tornando return t[-2]and f(l)or t[1].
orion
0

Mathematica, 101 bytes

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

Função recursiva sem nome, obtendo uma lista de números como entrada e retornando uma lista com um único número (o vencedor) como saída.

O núcleo do algoritmo é Max/@Partition[#,3,1,{2,2},0] , que calcula a matriz de (o máximo de mim e meus vizinhos) s na lista de entrada. a=Position[...-#,0]subtrai a lista original e retorna onde estão os 0s; estes são os filhos que levantam as mãos.

If[Equal@@a, #[[Last@a]], #0@Fold[Drop@##&,#,Reverse@a]]&ramificações, dependendo se todos os elementos de asão iguais ou não (nesse caso, eles serão apenas se afor um singleton); se sim, então essa criança é a vencedora e nós produzimos o número dela; caso contrário, chamamos recursivamente essa função na lista com todos os elementos nas posições aremovidas.

Greg Martin
fonte
0

Python 2, 99 bytes

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)
Lulhum
fonte
0

PHP, 131 bytes

$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];

Obtém números dos argumentos da linha de comando. Falha se o nome do arquivo começar com um número positivo.

demolir

// 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];
Titus
fonte
0

k, 40 bytes

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

Explicação:
$ é um if-else.

A condição é se 1 é a soma de B, que é definida como o mínimo de duas listas geradas, verificando se x é maior que as posições anterior e posterior (o tubo é reverso).

Se isso for verdade, retornamos x onde B é verdadeiro.
Caso contrário, recorreremos sem as posições verdadeiras.

Paul Kerrigan
fonte
0

Scala 129 bytes

Golfe

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

Ao preencher a lista com os zeros à esquerda e à direita, é possível agrupar conjuntos de 3 e particionar a lista para aqueles em que a mão está para cima, os elementos esquerdo e direito se comparam a 0 no exterior, para obter o número correto (assumindo a altura de ninguém é negativo!)

sprague44
fonte
0

C ++ 14, 182 bytes

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

Aprendeu que o operador ternário pode ser usado com objetos C ++. Requer a entrada para ser um recipiente de acesso aleatório com push_back, como vector, dequeelist .

Cria dois contêineres te sdo mesmo tipo e anexa o local mais alto a te o restante a s. Se houver apenas 1 elemento em ttroca desse elemento , caso contrário, a chamada recursiva será chamada 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);
}
Karl Napf
fonte
0

R, 83 bytes

Duas versões diferentes:

Este pega um vetor N:

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

Este cria uma função F definida recursivamente:

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