Scrivi un programma di ordinamento che sembra errato ma in realtà è corretto [chiuso]


12

Scrivi un programma che ordina un vettore di numeri (o qualsiasi tipo di elemento) che sembra avere uno o più bug, ma in realtà è ok.

  • Il codice deve essere chiaro. Qualcuno che osserva il codice deve facilmente identificare che si tratta di un algoritmo di ordinamento e deve facilmente confondere un pezzo di codice corretto con un bug.
  • Il bug (apparente) può, per qualsiasi cosa, rendere il codice sintatticamente o semanticamente mal formato (ad esempio, rendere il programma non compilare / eseguire, mostrare UB quando eseguito), fare in modo che il programma produca risultati errati, non terminare o non deterministico.
  • Il codice deve effettivamente essere ben formato e il programma deve determinare in modo deterministico l'output corretto in un tempo finito.
  • L'input può essere hard coded nel programma o può essere letto (dall'utente, dal file ecc.).
  • L'input è considerato valido e il programma non è necessario per verificare la correttezza dell'input.
  • È accettato qualsiasi algoritmo di ordinamento. La struttura dei dati per contenere i numeri non è necessaria per essere un vettore reale. Il programma può essere progettato per ordinare un numero variabile di numeri o un numero fisso di numeri (ad es. Un programma per ordinare 3 numeri è ok ). L'ordinamento può essere stabile o no (nota: un programma progettato per eseguire un ordinamento stabile che presenta un bug apparente che rende instabile l'ordinamento, ma in realtà non è un bug: il programma esegue effettivamente un ordinamento stabile - è una risposta valida ).
  • puoi chiamare qualsiasi funzione (comprese le funzioni di ordinamento) tranne gli strumenti di terze parti (a meno che non siano ampiamente diffusi e utilizzati, ad esempio boosper C++, JQueryperché Javascript- sono accettabili)
  • specifica la lingua
  • commentare in codice la parte che sembra un bug.
  • spiegare che aspetto ha il bug nel fare qualcosa di sbagliato.
  • spiegare (in una scatola dello spoiler) perché in realtà non è un bug.

Questo è un concorso di popolarità. Vince la risposta con il maggior numero di voti.


Questa sfida è finita. Il vincitore è @Clueless /codegolf//a/30190/11400 con 8 voti. Grazie a tutti i partecipanti!

Se vuoi entrare dopo che il vincitore è stato assegnato, non esitare ad aggiungere una nuova risposta. Sei fuori gara, ma siamo tutti interessati a vedere risposte interessanti.


Posso usare valori booleani nilable anziché numeri?
Οuroso

sì, ha modificato anche la domanda: qualsiasi tipo di elementi
bolov

1
Sto votando per chiudere questa domanda come fuori tema perché le sfide subdole non sono più in argomento su questo sito. meta.codegolf.stackexchange.com/a/8326/20469
cat

Risposte:


11

C ++

Ispirato da Apple goto fail; bug .

#include <vector>
#include <map>
#include <iostream>

/**
 * Sorts a vector of doubles in reverse order using the bucket sort algorithm.
 */
std::vector<double> reverse_bucket_sort(const std::vector<double>& input) {
    // put each element into a bucket as many times as it appears
    std::map<double, int> bucket_counts;
    for (auto it : input)
        ++bucket_counts[it];

    std::vector<double> sorted_elements; // the return value

    // loop until we are done
    while (bucket_counts.size() > 0) {
        // find the largest element
        double maximum = std::numeric_limits<double>::lowest();
        for (auto it : bucket_counts) {
            if (it.first > maximum)
                maximum = it.first;
                maximum = it.first;
        }

        // add the largest element N times to our sorted vector
        for (int i = 0; i < bucket_counts[maximum]; ++i)
            sorted_elements.push_back(maximum);

        // and now erase the bucket
        bucket_counts.erase(maximum);
    }

    return sorted_elements;
}

int main(int argc, const char * argv[]) {
    std::vector<double> test_case = { 0, 1, 2.5, 10, 2.5, 2 };

    std::cout << "unsorted:";
    for (auto it : test_case) std::cout << " " << it;
    std::cout << std::endl;

    std::cout << "sorted:";
    for (auto it : reverse_bucket_sort(test_case)) std::cout << " " << it;
    std::cout << std::endl;

    return 0;
}

Circa a metà della pagina c'è un bug: abbiamo una riga duplicata dopo il nostro ifcontrollo! Aggiorneremo sempre il massimo con qualunque sia l'ultimo valore in bucket_count. Per fortuna siamo a posto. In C ++ std::mapè ordinato per chiavi. Quindi stiamo solo invertendo i secchi, che è quello che vogliamo.


Non hai usato goto, quindi non c'è nessun bug. (Riferendosi a tutte le persone che hanno affermato che il bug non si sarebbe mai verificato se Apple non avesse usato goto)
user253751

Congratulazioni, hai vinto questa sfida avendo il maggior numero di voti (8 voti dopo 7 giorni). Inoltre, mi piace molto la tua risposta perché hai usato un bug di vita reale.
Bolov,

8

python2.X

import random
L = [random.randrange(20) for x in range(20)]
print "Unsorted:", L

def sort(L):
    # terminal case first. Otherwise sort each half recursively and combine
    return L.sort() if L > 1 else sort(L[:len(L)//2]) + sort(L[len(L)//2:])

sort(L)
print "Sorted:", L

Prova

list.sortritorna None, quindi la parte dopo la elseè None + None. Fortunatamente questo non causa problemi perché il confronto tra un elenco e un int (L > 1)è sempre True. La funzione restituisce sempre, Nonequindi ignoriamo il valore restituito e Just print, Lche è stato ordinato sul posto L'unione delle metà ordinate per catenazione non avrebbe funzionato neanche se l'esecuzione fosse arrivata lì.


Congratulazioni, sei arrivato secondo con 6 voti dopo 7 giorni. Grazie per la vostra presentazione.
Bolov,

5

C

L'uso dell'ordinamento in modo errato - su un sistema a 64 bit intè di 4 byte e di char *8 byte, quindi non dovrebbe funzionare.

Codice:

#include <stdlib.h>
#include <stdio.h>

/* Compare integers to sort in reverse order */
int compare(const void *p, const void *q)
{
    const int *a = p;
    const int *b = q;

    return *b - *a;
}

int main()
{
    char *strings[] = {"B", "Que", "Ro", "Sum", "T"};
    int i;

    /* Let's use the integer compare to sort strings */
    qsort(&strings, sizeof(strings) / sizeof(char *), sizeof(char *), compare);

    /* Output the sorted results */
    for (i = 0; i < sizeof(strings) / sizeof(char *); i++)
        printf("%s\n", strings[i]);

    return 0;
}

Costruire:

$ gcc -o sort-no-sort sort-no-sort.c 

Correre:

$ ./sort-no-sort 
T
Sum
Ro
Que
B

Sì, va bene!

Cinque cose in corso: 1) qsortpassa i puntatori agli interi, che hanno le stesse dimensioni dei puntatori ai caratteri. 2) Le stringhe non hanno più di quattro byte di lunghezza (tre + un terminatore) = la dimensione di un numero intero, che la routine di ordinamento considera felicemente come un numero intero. 3) La maggior parte dei compilatori forza l'allineamento delle strutture di dati, quindi stringhe più brevi occupano lo stesso spazio. Più grande però ed essere preparati per i fallimenti. 4) Endian-ness. 5) Zero inizializzazione di byte interni.


Grazie per la vostra presentazione. Sei arrivato terzo. Complimenti!
Bolov,

2

Cobra

class Program
    var _target as List<of bool?> = [true, true, false, true, true, nil, nil, false, true, nil, true]
    def main
        .sort(_target)
        print _target
    def sort(target as List<of bool?>)
        for i in target.count, for n, in target.count -1, if target[n] <> target[n + 1] and (target[n] or target[n + 1] == nil), target[n], target[n + 1] = target[n + 1], target[n]
            #should return sorted as [nil][false][true]

Oh caro, mi sembra che non sia stato assegnato correttamente n... e come sono arrivate tutte quelle virgole !?

Quando nviene assegnato, il compilatore presuppone che venga fornita la prima metà di una coppia chiave-valore (a causa della virgola), ma non esiste una coppia chiave-valore, quindi il compilatore non si lamenta quando non può assegnare la seconda metà di esso in una variabile inesistente. Ciò comporta nsemplicemente il valore chiave .. che in questo caso è un numero indice. Tutte le altre virgole fuori posto nella riga finale fanno effettivamente parte della sintassi Cobra standard.


Grazie per la vostra presentazione. Sei arrivato terzo. Complimenti!
Bolov,

2

Giava

public final class WeirdSort {
    public static void main(final String[] args) {

        //Random
        final Random random = new Random(441287210);

        //Some numbers:
        final List<Integer> list = new ArrayList<Integer>();
        list.add(9);
        list.add(11);
        list.add(3);
        list.add(5);
        list.add(7);

        //Sort randomly:
        Collections.sort(list, new Comparator<Integer>() {
            @Override
            public int compare(final Integer o1, final Integer o2) {
                return (o1 - o2) + random.nextInt(10);
            }
        });

        //Print
        for(final Integer i:list) {
            System.out.print(i + " ");
        }
    }
}

Prints: 3 5 7 9 11 

Funziona perché questo specifico valore casuale restituisce '1' per i primi 10 risultati


1
Che lingua usi?
Knerd,

Java, mi spiace aver dimenticato di menzionarlo (modificato).
Roy van Rijn,

2

Perl

Appaltatori in questi giorni! Non sanno che l' <=>operatore (noto anche come "astronave") viene utilizzato solo per l'ordinamento numerico?

E perché stanno confrontando gli operatori?

In che modo questo codice ha superato i nostri severi test ?? !! Utilizza persino stricte warnings!

use strict;
use warnings;

sub asciibetically { 0-($a lt $b) || 0+($a gt $b) || <=><=><=> }
                                                   #  ^  ^  ^
                                                   # What?? How did Perl even compile??!!

my @sorted = sort asciibetically qw( bravo charlie alpha );

print "@sorted";   # "alpha bravo charlie"
                   # And how come it works??!!

Perché viene compilato Perl

L'unico vero <=>operatore è quello nel mezzo. Gli altri due sono solo un altro modo di scrivere glob("="). Ciò significa che <=><=><=>(soprannominato "flotta spaziale") valuta 0.


Perché funziona

La asciibeticallysubroutine è un'implementazione della stringa-confrontando cmpoperator: Binario " cmp" ritorna -1, 0o 1seconda che l'argomento a sinistra è stringwise minore, uguale o maggiore rispetto all'argomento a destra.


3
Beh, Perl mi sembra comunque un insetto ...
chill0r
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.