Chi è il più alto?


32

N bambini, senza due che condividono la loro esatta dimensione, sono allineati in un certo ordine. Ognuno può solo confrontare le altezze con i propri vicini immediati. Quando l'insegnante grida "alzi la mano se sei il più alto", lo fanno se sono più alti di entrambi i loro vicini, e lo fanno contemporaneamente. Se solo uno alza la mano, vince. Se più di uno alza le mani, vengono tutti eliminati dalla fila (preservando l'ordine del resto dei bambini) e ripetono il processo.

Scrivi un programma, che prende una serie di interi distinti (puoi presumere che siano strettamente positivi) e genera il vincitore di questo gioco. Questo è code-golf, quindi vince il codice più corto.

Esempi (con fasi intermedie mostrate):

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


Leader attuali:

  1. Jelly: 17 bytes [di Dennis ♦]
  2. MATL: 20 byte [di Luis Mendo]
  3. APL: 28 byte [voidhawk]
  4. k: 40 byte [di Paul Kerrigan]

C'è anche una battaglia di Pythons in corso. Sto ancora aspettando altre lingue da golf.

Al momento ho accettato la risposta di Dennis ♦ - se ci sono nuovi vincitori, aggiornerò la selezione.


2
sembra più "chi potrebbe essere il più alto o no?" - effettivamente trovare "chi è il più alto" che avrebbe dovuto eliminare quelli che tengono le mani verso il basso
Alnitak

4
Ho disegnato una somiglianza con i giochi per bambini, in cui una persona urla una frase distintiva da cui prende il nome il gioco. Stranamente, il più alto ha meno probabilità di vincere (con un margine enorme). Asintoticamente, da N! permutazioni, solo in 2 ^ (N-1) casi vince.
Orione,

Risposte:


4

Gelatina , 17 byte

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

L'input è una stringa di numeri interi separati da virgola.

Provalo online!

I crediti vanno a @Xanderhall, @Sherlock e @ErikGolfer per aver posto le basi.

Come funziona

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 byte

Grazie a @ edc65 per -4 byte

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

Comprende un array di numeri interi e genera un array contenente solo il vincitore.

Snippet di prova

Ecco alcuni altri tentativi, utilizzando .filtere comprensioni array:

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

O un doppio for-loop, orribilmente lungo:

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

Spiegazione

Il modo in cui funziona è piuttosto semplice: crea un array di quelli che sono relativamente più alti ( r) e un array di quelli che non lo sono ( q), quindi ritorna rse ha solo un oggetto; in caso contrario, viene eseguito automaticamente qe restituisce il risultato.


Dov'è lo snippet di merenda?
Kritixi Lithos,

@KritixiLithos Aggiunto :-)
ETHproductions

"[1,2,5,8,9,12,3,4,10] Output: 5" Penso che questo dovrebbe produrre 8, non 5. Prima vengono eliminati 12 e 10, quindi 9 e 4, quindi 8 vittorie .
Orione,

1
@orion Mio male, lo snippet non stava convertendo i suoi argomenti in numeri prima di inviarli nella funzione. Questo è stato risolto.
ETHproductions

Puoi salvare 4 byte sul tuo esempio di filtro cambiando qe r. Si evita l' &&respressione del filtro e risulta essere anche un byte più breve.
Neil,

8

MATL , 20 byte

`tTYadZSd0<~&)nq}x2M

L'input è un vettore di colonna, che utilizza ;come separatore.

Provalo online! Oppure verifica tutti i casi di test .

Spiegazione

Questa è un'implementazione diretta della procedura descritta nella sfida. Un ciclo do... whilecontinua a rimuovere gli elementi finché non ne è stato rimosso solo uno; e quello è l'output.

Gli elementi da rimuovere vengono rilevati prendendo le differenze, signum, quindi di nuovo le differenze. Quelli che danno un valore negativo sono quelli da rimuovere.

`        % 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 byte

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)

Grazie @ZacharyT, @orion e @mathmandan per aver salvato 5 45 un sacco di byte!


2

Haskell, 85 byte

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

Esempio di utilizzo: f [9,3,8,7,4,12,5]-> 4.

Come funziona:

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

Una variante, anche 85 byte:

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

Associa l'elenco di b(vedi sopra) ae restituisce l'elemento sse x\\nè un elenco singleton e in f naltro modo.


È possibile eliminare l'importazione e salvare 3 byte con f x|y@(_:z)<-x++[0]=(#)=<<(x\\)$[b|(a,b,c)<-zip3(0:y)y z,b<a||b<c].
Zgarb,

@Zgarb: ha \\ ancora bisogno dell'importazione. A proposito, tailspuò anche essere sostituito da ...|a:b:c:_<-scanr(:)[]$0:x++[0],....
nimi

Ohh giusto, non me ne sono reso conto.
Zgarb,

2

Mathematica, 107 108 byte

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

Spiegazione

Innanzitutto, impostare xe yuguale all'input List. Il ciclo continua fino al Length@y==1. x~Split~Lessè l'elenco di elenchi di elementi consecutivi in ​​aumento, Split[x,#>#2&]è l'elenco di elenchi di elementi consecutivi in ​​diminuzione. Prendendo la Maxlista di tutte le liste nella prima si ottiene la lista dei bambini più alti del bambino alla loro destra (insieme al bambino più a destra). Prendendo il primo argomento ( #&) di tutte le liste in quest'ultima si ottiene la lista dei bambini più alti del bambino alla loro sinistra (insieme al figlio più a sinistra). L'intersezione di questi due sarà l'elenco dei bambini che hanno alzato la mano. Impostare questo uguale a y. x=DeleteCases[x,#|##&@@y]rimuove da xtutti gli elementi corrispondenti a un elemento di y( #|##&è equivalente aAlternatives). Una volta terminato il loop, ritorna y. Se l'output deve essere un numero intero (anziché un elenco contenente un singolo numero intero), restituisce #&@@y(+4 byte).

Grazie a Martin Ender per aver salvato 2 byte e avermi fatto rispettare le regole. Aperto a suggerimenti.


Non penso che !Lessfunzioni come previsto, dal momento che in realtà non si valuta una funzione. Probabilmente dovrai usare Greater(o #>#2&) lì. È possibile utilizzare x~Split~Lessper il primo Splitperò e >per la Lengthcondizione.
Martin Ender,

1
Per quanto riguarda la valutazione Clear@ytra chiamate di funzione, temo che non sia valido . Dovrai ripristinarlo da solo, cercarlo meglio o trasformarlo in un programma completo con Inpute Print.
Martin Ender,

1

Perl 6 , 111 byte

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

Allargato:

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

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]

Utilizza il ritorno di corto circuito come nella risposta di Yodle (di Zachary T)


Puoi togliere altri 3 byte: usando +=b,invece di +=[b](credito a Mathmandan), usando t=[0]per usare tper aggiungere a A, e poi, dato che ora iniziamo con 0 in t, il controllo t[-2]<1è più breve di len(t)<2, e usa t[1]come risultato in quel caso.
Orione,

L'ultima linea sta diventando return t[-2]and f(l)or t[1].
Orione,

0

Mathematica, 101 byte

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

Funzione ricorsiva senza nome che prende un elenco di numeri come input e restituisce un elenco con un singolo numero (il vincitore) come output.

Il nucleo dell'algoritmo è Max/@Partition[#,3,1,{2,2},0], che calcola l'array di (i-max-of-me-and-my-neighbors) dall'elenco di input. a=Position[...-#,0]quindi sottrae l'elenco originale e ritorna dove sono gli 0; questi sono i bambini che sollevano la mano.

If[Equal@@a, #[[Last@a]], #0@Fold[Drop@##&,#,Reverse@a]]&rami a seconda che tutti gli elementi di asiano uguali o meno (in questo caso, saranno solo se aè un singleton); in tal caso, allora questa bambina è la vincitrice e abbiamo pubblicato il suo numero; in caso contrario, chiamiamo ricorsivamente questa funzione nell'elenco con tutti gli elementi nelle posizioni arimosse.


0

Python 2, 99 byte

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 byte

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

Prende numeri dagli argomenti della riga di comando. Non riesce se il nome file inizia con un numero positivo.

abbattersi

// 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 byte

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

Spiegazione:
$ è un if-else.

La condizione è se 1 è la somma di B, che è definita come il minimo di due elenchi generati verificando se x è maggiore delle posizioni precedenti e post (Pipe è inversa).

Se questo è vero, restituiamo x dove B è vero.
Altrimenti ricorremo senza le vere posizioni.


0

Scala 129 byte

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

Riempiendo la lista a sinistra e a destra con 0, puoi quindi raggruppare in gruppi di 3 e partizionare l'elenco per quelli in cui la mano è alzata, la maggior parte degli elementi a sinistra e a destra si confronta con 0 all'esterno in modo da ottenere il numero corretto (assumendo l'altezza di Nobodys è negativo!)


0

C ++ 14, 182 byte

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

Ho imparato che l'operatore ternario può essere usato con oggetti C ++. Richiede l'ingresso da un contenitore ad accesso casuale con push_back, come vector, dequee list.

Crea due contenitori te sdello stesso tipo e aggiunge il locale più alto a te il resto a s. Se c'è solo 1 elemento in tcambio di quello, altrimenti si chiama ricorsivo 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 byte

Due diverse versioni:

Questo prende un vettore N:

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

Questo crea una funzione F definita in modo ricorsivo:

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.