Implementare l'algoritmo di ordinamento Thanos


93

L'algoritmo di ordinamento è il seguente:

Mentre l'elenco non è ordinato, scatta la metà di tutti gli elementi (rimuovili dall'elenco). Continua fino a quando l'elenco non viene ordinato o rimane solo un elemento (che viene ordinato per impostazione predefinita). Questo algoritmo di ordinamento può fornire risultati diversi in base all'implementazione.

La procedura di rimozione degli articoli dipende dall'implementazione per decidere, ma l'elenco dovrebbe essere lungo la metà rispetto a prima dopo un passaggio della procedura di rimozione degli articoli. L'algoritmo può decidere di rimuovere la prima metà o l'elenco, l'ultima metà dell'elenco, tutti gli elementi dispari, tutti gli elementi pari, uno alla volta fino a quando l'elenco è lungo la metà o qualsiasi altro non menzionato.

L'elenco di input può contenere una quantità arbitraria di elementi (entro limiti ragionevoli, diciamo fino a 1000 elementi), non solo elenchi perfettamente divisibili di 2 ^ n elementi. Dovrai rimuovere (n + 1) / 2 o (n-1) / 2 elementi se l'elenco è dispari, codificato o deciso casualmente durante il runtime. Decidi tu stesso: cosa farebbe Thanos se l'universo contenesse una strana quantità di esseri viventi?

L'elenco viene ordinato se nessun elemento è più piccolo di qualsiasi elemento precedente. I duplicati possono verificarsi nell'input e possono verificarsi nell'output.

Il programma dovrebbe includere un array di numeri interi (tramite stdin o come parametri, singoli elementi o un parametro array) e restituire l'array ordinato (o stamparlo su stdout).

Esempi:

// A sorted list remains sorted
[1, 2, 3, 4, 5] -> [1, 2, 3, 4, 5]

// A list with duplicates may keep duplicates in the result
[1, 2, 3, 4, 3] -> [1, 3, 3] // Removing every second item
[1, 2, 3, 4, 3] -> [3, 4, 3] -> [4, 3] -> [3] // Removing the first half
[1, 2, 3, 4, 3] -> [1, 2] // Removing the last half

[1, 2, 4, 3, 5] potrebbe dare risultati diversi:

// Removing every second item:
[1, 2, 4, 3, 5] -> [1, 4, 5]

o:

// Removing the first half of the list
[1, 2, 4, 3, 5] -> [3, 5] // With (n+1)/2 items removed
[1, 2, 4, 3, 5] -> [4, 3, 5] -> [3, 5] // With (n-1)/2 items removed

o:

// Removing the last half of the list
[1, 2, 4, 3, 5] -> [1, 2] // With (n+1)/2 items removed
[1, 2, 4, 3, 5] -> [1, 2, 4] // With (n-1)/2 items removed

o:

// Taking random items away until half (in this case (n-1)/2) of the items remain
[1, 2, 4, 3, 5] -> [1, 4, 3] -> [4, 3] -> [4]

Avere un caso di test che in realtà richiede più snap per più algoritmi di snap diversi sarebbe molto utile.
Stringa non correlata

22
Non abbiamo bisogno di ordinare ed eliminare la metà delle risposte ...
Sumner18

4
Banco di prova consigliato: [9, 1, 1, 1, 1]. Il mio algoritmo non è riuscito su questo input
Conor O'Brien il

Risposte:





12

Brachylog (v2), 6 byte

≤₁|ḍt↰

Provalo online!

Questa è una presentazione di funzione. Input da sinistra, output da destra, come al solito. (Il collegamento TIO utilizza un argomento della riga di comando che avvolge automaticamente la funzione in un programma completo, in modo da poterlo vedere in azione.)

Spiegazione

≤₁|ḍt↰
≤₁       Assert that {the input} is sorted {and output it}
  |      Handler for exceptions (e.g. assertion failures):
   ḍ     Split the list into two halves (as evenly as possible)
    t    Take the last (i.e. second) half
     ↰   Recurse {and output the result of the recursion}

Round bonus

≤₁|⊇ᵇlᵍḍhtṛ↰

Provalo online!

Lo snap è pensato per essere casuale, vero? Ecco una versione del programma che sceglie gli elementi sopravvissuti in modo casuale (garantendo al contempo che la metà sopravviva ad ogni round).

≤₁|⊇ᵇlᵍḍhtṛ↰
≤₁            Assert that {the input} is sorted {and output it}
  |           Handler for exceptions (e.g. assertion failures):
   ⊇ᵇ         Find all subsets of the input (preserving order)
     lᵍ       Group them by length
       ḍht    Find the group with median length:
         t      last element of
        h       first
       ḍ        half (split so that the first half is larger)
          ṛ   Pick a random subset from that group
           ↰  Recurse

Questo sarebbe piuttosto breve se potessimo riordinare gli elementi, ma whyever sarebbe un algoritmo di ordinamento vuole fare che ?


12
Un byte per pietra infinita.
Djechlin,

@djechlin il byte infinito è il motivo per cui devi cercare la testa e soprattutto la mascella.
The Great Duck

10

Perl 6 , 30 byte

$!={[<=]($_)??$_!!.[^*/2].&$!}

Provalo online!

Funzione ricorsiva che rimuove la seconda metà dell'elenco fino a quando l'elenco non viene ordinato.

Spiegazione:

$!={                         }    # Assign the function to $!
    [<=]($_)??                    # If the input is sorted
              $_                  # Return the input
                !!                # Else
                  .[^*/2]         # Take the first half of the list (rounding up)
                         .&$!     # And apply the function again


8

Java 10, 106 97 byte

L->{for(;;L=L.subList(0,L.size()/2)){int p=1<<31,f=1;for(int i:L)f=p>(p=i)?0:f;if(f>0)return L;}}

-9 byte grazie a @ OlivierGrégoire .

Provalo online.

Lascia solo la prima metà dell'elenco ogni iterazione e rimuove n+12 elementi se la dimensione dell'elenco è dispari.

Spiegazione:

L->{               // Method with Integer-list as both parameter and return-type
  for(;;           //  Loop indefinitely:
      L=L.subList(0,L.size()/2)){
                   //    After every iteration: only leave halve the numbers in the list
    int p=1<<31,   //   Previous integer, starting at -2147483648
        f=1;       //   Flag-integer, starting at 1
    for(int i:L)   //   Inner loop over the integer in the list:
      f=p>(p=i)?   //    If `a>b` in a pair of integers `a,b`:
         0         //     Set the flag to 0
        :          //    Else (`a<=b`):
         f;        //     Leave the flag the same
    if(f>0)        //   If the flag is still 1 after the loop:
      return L;}}  //    Return the list as result

n->{for(;n.reduce((1<<31)+0d,(a,b)->a==.5|b<a?.5:b)==.5;n=n.skip(n.count()/2));return n;} è più breve usando gli stream, ma non sono stato in grado di capire come evitare l' java.lang.IllegalStateException: stream has already been operated upon or closederrore dopo aver restituito lo stream
Embodiment of Ignorance

@EmbodimentofIgnorance questo accade perché reduceè un'operazione terminale che chiude il flusso. Non sarai mai in grado di chiamare reducedue volte sullo stesso stream. Tuttavia, puoi creare un nuovo stream.
Olivier Grégoire,


@ OlivierGrégoire Quell'ordine sembra così semplice ora che lo vedo .. A volte ci vuole uno sguardo da un'altra angolazione per vedere gli altri ovvi inizialmente perdere immagino. :) Grazie!
Kevin Cruijssen il

1
Nessun problema, non era ovvio: ho lavorato per arrivarci. Ho provato almeno 10 versioni prima di trovarne una;)
Olivier Grégoire il

8

Wolfram Language (Mathematica) , 30 byte

#//.x_/;Sort@x!=x:>x[[;;;;2]]&

Provalo online!

@Doorknob ha salvato 12 byte


1
Invece di prendere la prima metà, è possibile salvare alcuni byte prendendo ogni altro elemento ( x[[;;;;2]]).
Maniglia della porta

@Doorknob sì, certo ...
J42161217

pensavo che ci fossero dei risparmi usando OrderedQ, ma non riuscivo a farlo funzionare
Greg Martin il

@GregMartin Ho usato OrderedQnel mio primo approccio (vedi modifiche)
J42161217

7

JavaScript (ES6),  49  48 byte

Salvato 1 byte grazie a @tsh

Rimuove ogni secondo elemento.

f=a=>a.some(p=c=>p>(p=c))?f(a.filter(_=>a^=1)):a

Provalo online!


p++&1->a^=1
martedì


6

05AB1E , 8 7 byte

[Ð{Q#ιн

-1 byte grazie a @Emigna .

n-12

Provalo online o verifica alcuni altri casi di test (o verifica quei casi di test passo-passo per ogni iterazione ).

7 byte alternativi di @Grimy :

ΔÐ{Ê>äн

n2n-12

Provalo online o verifica alcuni altri casi di test (o verifica quei casi di test passo-passo per ogni iterazione ).

Spiegazione:

[        # Start an infinite loop:
 Ð       #  Triplicate the list (which is the implicit input-list in the first iteration)
  {Q     #  Sort a copy, and check if they are equal
    #    #   If it is: Stop the infinite loop (and output the result implicitly)
  ι      #  Uninterweave: halve the list into two parts; first containing all even-indexed
         #  items, second containing all odd-indexed items (0-indexed)
         #   i.e. [4,5,2,8,1] → [[4,2,1],[5,8]]
   н     #  And only leave the first part

Δ        # Loop until the result no longer changes:
 Ð       #  Triplicate the list (which is the implicit input-list in the first iteration)
       #  Sort a copy, and check if they are NOT equal (1 if truthy; 0 if falsey)
    >    #  Increase this by 1 (so 1 if the list is sorted; 2 if it isn't sorted)
     ä   #  Split the list in that many parts
      н  #  And only leave the first part
         # (and output the result implicitly after it no longer changes)

3
È possibile utilizzare ιinvece se si passa a mantenere ogni altra strategia di elemento .
Emigna,

1
Alternativa 7 usando la strategia "rimuovi l'ultimo tempo":ΔÐ{Ê>äн
Grimy

@Grimy Anche questo è un approccio molto carino. Devo aggiungerlo al mio post (accreditandoti ovviamente) o vuoi pubblicarlo come risposta separata?
Kevin Cruijssen,

Sentiti libero di aggiungerlo.
Grimy

6

TI-BASIC (TI-84), 47 42 45 44 byte

-1 byte grazie a @SolomonUcko!

Ans→L1:Ans→L2:SortA(L1:While max(L1≠Ans:iPart(.5dim(Ans→dim(L2:L2→L1:SortA(L1:End:Ans

Elenco di input in Ans.
L'output è in Ansed è implicitamente stampato.

Spiegazione:

Ans→L1                  ;store the input into two lists
Ans→L2
SortA(L1                ;sort the first list
                        ; two lists are needed because "SortA(" edits the list it sorts
While max(L1≠Ans        ;loop until both lists are strictly equal
iPart(.5dim(Ans→dim(L2  ;remove the latter half of the second list
                        ; removes (n+1)/2 elements if list has an odd length
L2→L1                   ;store the new list into the first list (updates "Ans")
SortA(L1                ;sort the first list
End
Ans                     ;implicitly output the list when the loop ends

Nota: TI-BASIC è un linguaggio tokenizzato. Il conteggio dei caratteri non equivale al conteggio dei byte.


Penso che puoi sostituire not(min(L1=Anscon max(L1≠Ansper salvare un byte.
Solomon Ucko



3

Ottava , 49 byte

l=input('');while(~issorted(l))l=l(1:2:end);end;l

Provalo online! Questo è stato un viaggio in cui è più noioso. Nota le due voci molto più interessanti di seguito:

50 byte

function l=q(l)if(~issorted(l))l=q(l(1:2:end));end

Provalo online! Invece della soluzione imperativa poco interessante, possiamo fare una soluzione ricorsiva, per un solo byte aggiuntivo.

53 byte

f(f=@(g)@(l){l,@()g(g)(l(1:2:end))}{2-issorted(l)}())

Provalo online! Sì. Una funzione anonima ricorsiva, grazie alla brillante risposta di @ ceilingcat sulla mia domanda di . Una funzione anonima che restituisce una funzione anonima ricorsiva definendosi nel suo elenco di argomenti. Mi piacciono le funzioni anonime. Mmmmm.


2

MATL , 11 byte

tv`1L)ttS-a

Provalo online!

Funziona rimuovendo ogni secondo elemento.

Spiegazione

t      % Take a row vector as input (implicit). Duplicate
v      % Vertically concatenate the two copies of the row vector. When read with
       % linear indexing (down, then across), this effectively repeats each entry
`      % Do...while
  1L)  %   Keep only odd-indexed entries (1-based, linear indexing)
  t    %   Duplicate. This will leave a copy for the next iteration
  tS   %   Duplicate, sort
  -a   %   True if the two arrays differ in any entry
       % End (implicit). A new iteration starts if the top of the stack is true
       % Display (implicit). Prints the array that is left on the stack

2
Rotto per l'elenco inizialmente ordinato: [1, 2, 3, 4, 5] dovrebbe rimanere [1, 2, 3, 4, 5]
Falco

@Falco Grazie! Ora corretto
Luis Mendo il

2

Japt , 10 byte

eUñ)?U:ßUë

Provalo

eUñ)?U:ßUë     :Implicit input of array U
e              :Compare equality with
 Uñ            :  U sorted
   )           :End compare
    ?U:        :If true then return U else
       ß       :Run the programme again with input
        Uë     :  Every second element of U


2

Cristallo , 58 byte

Con Array#sort( 58 byte ):

->(a : Array(Int32)){while a!=a.sort;a.pop a.size/2;end;a}

Provalo online!

Senza Array#sort( 101 byte ):

->(a : Array(Int32)){while a.map_with_index{|e,i|e>a.fetch i+1,Int32::MAX}.any?;a.pop a.size/2;end;a}

Provalo online!


2

Buccia , 6 5 byte

1 byte salvato grazie a Zgarb

ΩΛ<Ċ2

Provalo online!

Spiegazione

ΩΛ<Ċ2
Ω         Repeat until
 Λ<         all adjacent pairs are sorted (which means the list is sorted)
   Ċ2         drop every second element from the list

Sono 11 byte, non 6. ›echo -n" ΩΛ <(← ½ "| wc --bytes 11
Mike Holler


@MikeHoller Come molte altre lingue del golf, Husk utilizza una code page personalizzata, per avere accesso a personaggi più diversi: github.com/barbuz/Husk/wiki/Codepage
Leo

Grazie, ho imparato qualcosa oggi :)
Mike Holler il

1
Utilizzare Ċ2invece di (←½per salvare un byte.
Zgarb,

2

Gaia , 9 8 byte

eo₌⟨2%⟩↻

Provalo online!

Spiegazione:

e		| eval input as a list
       ↻	| until
 o		| the list is sorted
  ₌		| push additional copy
   ⟨2%⟩  	| and take every 2nd element

2

Julia 1.0 , 30 byte

-x=x>sort(x) ? -x[1:2:end] : x

Provalo online!

Accetta ogni secondo elemento dell'array se non ordinato.


usa un operatore ASCII come -per 20 byte. inoltre non contiamo quasi sempre i caratteri: | quindi sarebbe bello se fosse stato rimosso dall'intestazione
ASCII-solo

Modificato quello. Grazie per 2 byte!
niczky12,

2

C ++ (gcc) , 103 byte

Non posso commentare, ma ho migliorato la versione da movatica riducendo le inclusioni e usando auto.

-2 byte: ceilingcat
-2 byte: solo ASCII

#include<regex>
auto f(auto l){while(!std::is_sorted(l.begin(),l.end()))l.resize(l.size()/2);return l;}

Provalo online!


1
qualsiasi motivo non puoi semplicemente usare l.size()/2?
ASCII

Sì, non funziona così :)
peterzuger

1
cosa intendi? restituendo un elenco di dimensioni (n+1)/2o (n-1)/2sono entrambi validi. hmm ....
ASCII

Ohh oops non l'
ho

1

VDM-SL , 99 byte

f(i)==if forall x in set inds i&x=1or i(x-1)<=i(x) then i else f([i(y)|y in set inds i&y mod 2=0]) 

Mai inviato in vdm prima, quindi non sono sicuro delle regole specifiche della lingua. Quindi ho presentato come una definizione di funzione che accetta a seq of inte restituisce aseq of int

Un programma completo da eseguire potrebbe apparire così:

functions
f:seq of int +>seq of int
f(i)==if forall x in set inds i&x=1or i(x-1)<=i(x) then i else f([i(y)|y in set inds i&y mod 2=0]) 

1

Pyth, 10 byte

.W!SIHhc2Z

Provalo online qui . Ciò rimuove la seconda metà di ogni iterazione, arrotondando per difetto. Per cambiarlo per rimuovere la prima metà, arrotondando per eccesso, cambia hin e.

.W!SIHhc2ZQ   Q=eval(input())
              Trailing Q inferred
  !SIH        Condition function - input variable is H
   SIH          Is H invariant under sorting?
  !             Logical not
      hc2Z    Iteration function - input variable is Z
       c2Z      Split Z into 2 halves, breaking ties to the left
      h         Take the first half
.W        Q   With initial value Q, execute iteration function while condition function is true

Prendere ogni altro elemento della lista è più breve. Sostituisci hccon %. Ciò consente anche di eliminare la variabile lambda finale Ze di riempirla implicitamente di Pyth, per un totale di 2 byte salvati.
hakr14

1

C ++ (gcc) , 139 137 116 byte

-2 byte grazie a ceilingcat, -21 byte grazie a PeterZuger

#include<regex>
auto f(std::vector<int>l){while(!std::is_sorted(l.begin(),l.end()))l.resize(-~l.size()/2);return l;}

Ridimensiona il vettore nella sua prima metà fino a quando non viene ordinato.

Provalo online!


1
Le importazioni devono essere incluse nel conteggio dei byte, quindi è necessario aggiungere la includes
Incarnazione dell'ignoranza il

Grazie, li aggiungerò.
movatica,

1

K (oK) , 22 20 byte

Soluzione:

{(*2 0N#x;x)x~x@<x}/

Provalo online!

Scorri sull'input fino a quando non viene ordinato ... se non viene ordinato prendi i primi n / 2 elementi.

{(*2 0N#x;x)x~x@<x}/ / the solution
{                 }/ / lambda that iterates
                <x   / indices that sort x ascending (<)
              x@     / apply (@) these indices back to x
            x~       / matches (~) x? returns 0 or 1
 (       ; )         / 2-item list which we index into
          x          / original input (ie if list was sorted)
       #x            / reshape (#) x
   2 0N              / as 2 rows
  *                  / take the first one      

modifiche:

  • -2 byte grazie a ngn

1
(.5*#x)#x->*2 0N#x
ngn

Ho pensato di farlo, 2 0Nma ho pensato che sarebbe stato più lungo (senza test), grazie!
streetster


0

Retina , 38 byte

\d+
*
/(_+),(?!\1)/+`,_+(,?)
$1
_+
$.&

Provalo online! Accetta numeri separati da virgola. Spiegazione:

\d+
*

Converti in unario.

/(_+),(?!\1)/+`

Ripeti mentre l'elenco non è ordinato ...

,_+(,?)
$1

... cancella ogni elemento pari.

_+
$.&

Converti in decimale.


0

C (gcc) , 66 byte

Esegue lo snap della seconda metà dell'elenco ogni iterazione ( n/2+1elementi se la lunghezza è dispari).

Provalo online!

Accetta l'input come puntatore all'inizio di un array di intseguito dalla sua lunghezza. Emette restituendo la nuova lunghezza dell'array (ordina sul posto).

t(a,n,i)int*a;{l:for(i=0;i<n-1;)if(a[i]>a[++i]){n/=2;goto l;}a=n;}

Versione non golfata:

t(a, n, i) int *a; { // take input as a pointer to an array of int, followed by its length; declare a loop variable i
  l: // jump label, will be goto'ed after each snap
  for(i = 0; i < n - 1; ) { // go through the whole array …
    if(a[i] > a[++i]) { // … if two elements are in the wrong order …
      n /= 2; // … snap off the second half …
      goto l; // … and start over
    }
  }
  a = n; // implicitly return the new length
}

Suggerisci ~i+ninvece dii<n-1
ceilingcat il
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.