Implémenter l'algorithme de tri Thanos

93

L'algorithme de tri va comme ceci:

Tant que la liste n'est pas triée, alignez la moitié des éléments (supprimez-les de la liste). Continuez jusqu'à ce que la liste soit triée ou qu'il ne reste qu'un élément (trié par défaut). Cet algorithme de tri peut donner des résultats différents en fonction de la mise en œuvre.

La procédure de suppression d’élément est laissée à l’implémentation, mais la liste doit être deux fois moins longue qu’avant la fin de la procédure de suppression d’élément. Votre algorithme peut décider de supprimer la première moitié ou la liste, la dernière moitié de la liste, tous les éléments impairs, tous les éléments pairs, un à la fois jusqu'à ce que la liste soit deux fois moins longue, ou tout élément non mentionné.

La liste d'entrées peut contenir un nombre d'éléments arbitraire (dans des limites raisonnables, disons jusqu'à 1000 éléments), pas seulement des listes parfaitement divisibles de 2 ^ n éléments. Vous devrez supprimer (n + 1) / 2 ou (n-1) / 2 éléments si la liste est impaire, codée en dur ou décidée de manière aléatoire au cours de l'exécution. Décidez vous-même: que ferait Thanos si l'univers contenait une quantité étrange de créatures vivantes?

La liste est triée si aucun élément n'est plus petit qu'un élément précédent. Des doublons peuvent apparaître dans l’entrée et dans la sortie.

Votre programme doit prendre un tableau d’entiers (via stdin ou en tant que paramètres, soit des éléments individuels, soit un paramètre de tableau), et renvoyer le tableau trié (ou l’imprimer sur stdout).

Exemples:

// 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] pourrait donner des résultats différents:

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

ou:

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

ou:

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

ou:

// 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]
vrwim
la source
Il serait très utile d'avoir un scénario de test nécessitant plusieurs captures pour plusieurs algorithmes de capture différents.
Unrelated String
22
N'avons-
4
Cas de test suggéré: [9, 1, 1, 1, 1]. Mon propre algorithme a échoué sur cette entrée
Conor O'Brien

Réponses:

19

R , 41 octets

x=scan();while(any(x-sort(x)))x=x[!0:1];x

Essayez-le en ligne!

Kirill L.
la source
3
is.unsortedplutôt que any(...)serait également 41 octets.
Giuseppe
Cette méthode de base est une fonction récursive de 44 octets. Elle peut être golfée: essayez-la en ligne!
CriminallyVulgar
18

Python 3 , 38 42 39 octets

q=lambda t:t>sorted(t)and q(t[::2])or t

Essayez-le en ligne!

-3 bytes grâce à @JoKing et @Quuxplusone

Sara J
la source
2
40 octets
Jo King
39 octets grâce à l' observation de TFeld selon laquelle toute permutation != sorted(t)doit être > sorted(t).
Quuxplusone
12

Brachylog (v2), 6 octets

≤₁|ḍt↰

Essayez-le en ligne!

Ceci est une soumission de fonction. Entrée de gauche, sortie de droite, comme d’habitude. (Le lien TIO utilise un argument de ligne de commande qui englobe automatiquement la fonction dans un programme complet afin que vous puissiez la voir en action.)

Explication

≤₁|ḍ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}

Tour bonus

≤₁|⊇ᵇlᵍḍhtṛ↰

Essayez-le en ligne!

Le claquement est censé être aléatoire, n'est-ce pas? Voici une version du programme qui choisit les éléments survivants au hasard (tout en veillant à ce que la moitié survive à chaque tour).

≤₁|⊇ᵇ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

Ce serait plutôt plus court si nous pouvions réorganiser les éléments, mais whyever serait un algorithme de tri voulez faire cela ?

ais523
la source
12
Un octet par pierre d'infini.
Djechlin
@djechlin l' octet de l'infini est la raison pour laquelle vous devez aller chercher la tête et surtout la mâchoire.
Le grand canard
10

Perl 6 , 30 octets

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

Essayez-le en ligne!

Fonction récursive qui supprime la seconde moitié de la liste jusqu'à ce que la liste soit triée.

Explication:

$!={                         }    # 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
Jo King
la source
8

Java 10, 106 à 97 octets

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 octets grâce à @ OlivierGrégoire .

Essayez-le en ligne.

Ne laissez que la première moitié de la liste à chaque itération et supprime n+12 éléments si la taille de la liste est impair.

Explication:

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
Kevin Cruijssen
la source
n->{for(;n.reduce((1<<31)+0d,(a,b)->a==.5|b<a?.5:b)==.5;n=n.skip(n.count()/2));return n;} est plus court en utilisant des flux, mais je n'ai pas été en mesure de comprendre comment éviter l' java.lang.IllegalStateException: stream has already been operated upon or closederreur après avoir renvoyé le flux
Incarnation de l'Ignorance
@EmbodimentofIgnorance Cela se produit car il reduces'agit d'une opération de terminal qui ferme le flux. Vous ne pourrez jamais appeler reducedeux fois sur le même flux. Vous pouvez cependant créer un nouveau flux.
Olivier Grégoire Le
1
97 octets
Olivier Grégoire Le
@ OlivierGrégoire Cet ordre a l'air si simple maintenant que je le vois. Parfois, il faut regarder sous un autre angle pour voir l'évidence évidente que d'autres manquent au départ, je suppose. :) Merci!
Kevin Cruijssen
1
Pas de souci, ce n'était pas évident: j'ai travaillé pour y arriver. J'ai testé au moins 10 versions avant de trouver celle-là;)
Olivier Grégoire
8

Wolfram Language (Mathematica) , 30 octets

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

Essayez-le en ligne!

@Doorknob a enregistré 12 octets

J42161217
la source
1
Au lieu de prendre la première moitié, vous pouvez économiser des octets en prenant tous les autres éléments ( x[[;;;;2]]).
Poignée de porte
@Doorknob oui bien sûr ...
J42161217 Le
pensait qu'il pourrait y avoir des économies en utilisant OrderedQ, mais ne pourrait pas le faire fonctionner
Greg Martin
@ GregMartin j'ai utilisé OrderedQdans ma toute première approche (voir modifications)
J42161217
7

JavaScript (ES6),  49  48 octets

Sauvegardé 1 octet grâce à @tsh

Supprime chaque 2ème élément.

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

Essayez-le en ligne!

Arnauld
la source
p++&1->a^=1
tsh
6

05AB1E , 8 7 octets

[Ð{Q#ιн

-1 octet grâce à @Emigna .

n-12

Essayez-le en ligne ou vérifiez quelques autres cas de test (ou vérifiez-les étape par étape pour chaque itération ).

Alternative de 7 octets par @Grimy :

ΔÐ{Ê>äн

n2n-12

Essayez-le en ligne ou vérifiez quelques autres cas de test (ou vérifiez-les étape par étape pour chaque itération ).

Explication:

[        # 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)
Kevin Cruijssen
la source
3
Vous pouvez utiliser ιau lieu de si vous passez à une stratégie de garder tous les autres éléments .
Emigna
1
Alternative 7 en utilisant la stratégie "enlever la dernière moitié":ΔÐ{Ê>äн
Grimy
@ Grimy C'est une très belle approche aussi. Dois-je l'ajouter à mon message (en vous créditant bien sûr), ou voulez-vous le poster en tant que réponse séparée?
Kevin Cruijssen
N'hésitez pas à l'ajouter.
Grimy
6

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

-1 octet grâce à @SolomonUcko!

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

La liste des entrées est en Ans.
La sortie est Ansentrée et est imprimée implicitement.

Explication:

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

Remarque: TI-BASIC est un langage à jeton. Le nombre de caractères ne correspond pas au nombre d'octets.

Tau
la source
Je pense que vous pouvez remplacer not(min(L1=Anspar max(L1≠Anspour sauvegarder un octet.
Solomon Ucko
3

Haskell , 57 à 55 octets (uniquement grâce à ASCII)

f x|or$zipWith(>)x$tail x=f$take(div(length x)2)x|1>0=x

Essayez-le en ligne!


Code d'origine:

f x|or$zipWith(>)x(tail x)=f(take(div(length x)2)x)|1>0=x

Essayez-le en ligne!


Ungolfed:

f xs | sorted xs = f (halve xs)
     | otherwise = xs

sorted xs = or (zipWith (>) xs (tail xs))

halve xs = take (length xs `div` 2) xs
Sachera
la source
1
Bienvenue chez PPCG!
Rɪᴋᴇʀ
56
ASCII uniquement
57 :(
ASCII uniquement
55
ASCII uniquement
3

Octave , 49 octets

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

Essayez-le en ligne! Ce fut un voyage où plus ennuyeux, c'est mieux. Notez les deux entrées beaucoup plus intéressantes ci-dessous:

50 octets

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

Essayez-le en ligne! Au lieu de la solution impérative sans intérêt, nous pouvons faire une solution récursive, pour un seul octet supplémentaire.

53 octets

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

Essayez-le en ligne! Oui. Une fonction anonyme récursive, grâce à la réponse brillante de @ ceilingcat sur ma question de . Une fonction anonyme qui retourne une fonction anonyme récursive en se définissant dans sa liste d'arguments. J'aime les fonctions anonymes. Mmmmm.

Sanchises
la source
2

MATL , 11 octets

tv`1L)ttS-a

Essayez-le en ligne!

Cela fonctionne en supprimant chaque deuxième élément.

Explication

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
Luis Mendo
la source
2
Cassé pour la liste initialement triée: [1, 2, 3, 4, 5] devrait rester [1, 2, 3, 4, 5]
Falco
@ Falco Merci! Corrigé maintenant
Luis Mendo
2

Japt , 10 octets

eUñ)?U:ßUë

L'essayer

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
Hirsute
la source
2

Java (JDK) , 102 octets

n->{for(;n.stream().reduce((1<<31)+0d,(a,b)->a==.5|b<a?.5:b)==.5;n=n.subList(0,n.size()/2));return n;}

Il y a déjà une réponse C #, alors j'ai décidé de tenter ma chance avec une réponse Java.

Essayez-le en ligne!

Incarnation de l'ignorance
la source
Il est temps d'essayer F # :)
aloisdg
2

Crystal , 58 octets

Avec Array#sort( 58 octets ):

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

Essayez-le en ligne!

Sans Array#sort( 101 octets ):

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

Essayez-le en ligne!

Kinxer
la source
2

Husk , 6 à 5 octets

1 octet économisé grâce à Zgarb

ΩΛ<Ċ2

Essayez-le en ligne!

Explication

ΩΛ<Ċ2
Ω         Repeat until
 Λ<         all adjacent pairs are sorted (which means the list is sorted)
   Ċ2         drop every second element from the list
Leo
la source
C'est 11 octets, pas 6. ›echo -n" ΩΛ <(← ½ "| wc - octets 11
Mike Holler
@MikeHoller Comme beaucoup d'autres langues de golf, Husk utilise une page de code personnalisée, afin de pouvoir accéder à plusieurs personnages différents: github.com/barbuz/Husk/wiki/Codepage
Leo
Merci, j'ai appris quelque chose aujourd'hui :)
Mike Holler
1
Utilisez Ċ2au lieu de (←½pour sauvegarder un octet.
Zgarb le
2

Gaia , 9 à 8 octets

eo₌⟨2%⟩↻

Essayez-le en ligne!

Explication:

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

Julia 1.0 , 30 octets

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

Essayez-le en ligne!

Prend chaque deuxième élément du tableau s'il n'est pas trié.

niczky12
la source
utilisez un opérateur ASCII comme -pour 20 octets. aussi nous ne comptons presque toujours pas les caractères: | donc ce serait bien si cela était retiré de l'en-tête
ASCII uniquement
Changé cela. Merci pour 2 octets!
niczky12
2

C ++ (gcc) , 103 octets

Je ne peux pas commenter, mais j'ai amélioré la version de movatica en réduisant le nombre d'inclusions et en utilisant auto.

-2 octets: ceilingcat
-2 octets: uniquement en ASCII

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

Essayez-le en ligne!

Peterzuger
la source
1
une raison que vous ne pouvez pas simplement utiliser l.size()/2?
ASCII uniquement
Oui, ça ne marche pas comme ça :)
peterzuger
1
Que voulez-vous dire? renvoyer une liste de taille (n+1)/2ou (n-1)/2sont les deux valides. hmm ....
ASCII seulement
Ohh oups je ne voyais pas ça merci
peterzuger
1

VDM-SL , 99 octets

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

Jamais soumis dans vdm auparavant, donc pas sûr des règles spécifiques à la langue. Donc, j'ai soumis comme une définition de fonction qui prend un seq of intet retourne unseq of int

Un programme complet à exécuter pourrait ressembler à ceci:

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]) 
Données expirées
la source
1

Pyth, 10 octets

.W!SIHhc2Z

Essayez-le en ligne ici . Cela supprime la seconde moitié à chaque itération, en arrondissant au bas. Pour le changer, supprimer la première moitié, en arrondissant vers le haut, changer le hen 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
Sok
la source
Prendre tous les autres éléments de la liste est plus court. Remplacer hcpar %. Cela vous permet également de supprimer la variable lambda de fin Zet de laisser Pyth la remplir implicitement, pour un total de 2 octets enregistrés.
hakr14
1

C ++ (gcc) , 139 137 116 octets

-2 octets merci à ceilingcat, -21 octets merci à PeterZuger

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

Redimensionnez le vecteur à sa première moitié jusqu'à ce qu'il soit trié.

Essayez-le en ligne!

movatica
la source
1
Les importations doivent être incluses dans le nombre d'octets. Vous devez donc ajouter le signe includes
Incarnation de l'Ignorance
Merci, je vais les ajouter.
movatica
1

K (oK) , 22 à 20 octets

Solution:

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

Essayez-le en ligne!

Parcourez l'entrée jusqu'à ce qu'elle soit triée ... Si ce n'est pas le cas, prenez d'abord n ​​/ 2 éléments.

{(*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      

Modifications:

  • -2 octets grâce à ngn
streetster
la source
1
(.5*#x)#x->*2 0N#x
NDGN
J'ai envisagé de le faire 2 0Nmais j'ai supposé que ce serait plus long (sans test), merci!
streetster le
0

Retina , 38 octets

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

Essayez-le en ligne! Prend des nombres séparés par des virgules. Explication:

\d+
*

Convertir en unaire.

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

Répétez l'opération tant que la liste n'est pas triée ...

,_+(,?)
$1

... supprimer tous les éléments pairs.

_+
$.&

Convertir en décimal.

Neil
la source
0

C (gcc) , 66 octets

Détache la deuxième moitié de la liste à chaque itération ( n/2+1éléments si la longueur est impair).

Essayez-le en ligne!

Prend l'entrée comme un pointeur au début d'un tableau de intsuivi de sa longueur. Les sorties en retournant la nouvelle longueur du tableau (trie sur place).

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

Version non-golfée:

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
}
OOBalance
la source
Suggérez au ~i+nlieu dei<n-1
ceilingcat