잘못 보이는 정렬 프로그램을 작성하지만 실제로는 정확합니다.


12

하나 이상의 버그가있는 것처럼 보이는 숫자 벡터 (또는 모든 유형의 요소)를 정렬하는 프로그램을 작성하지만 실제로는 괜찮습니다.

  • 코드는 명확해야합니다. 코드를 살펴 보는 사람은 정렬 알고리즘임을 쉽게 식별하고 올바른 코드를 버그와 혼동해야합니다.
  • (명확한) 버그는 코드를 구문 적으로 또는 의미 론적으로 잘못 만드는 (예 : 프로그램 컴파일 / 실행, 실행시 UB 표시) 프로그램이 잘못된 결과를 생성하거나 종료하지 않거나 비 결정적이지 않게 만드는 모든 방법으로 발생할 수 있습니다.
  • 실제로 코드의 형식이 양호해야하며 프로그램은 유한 한 시간 내에 정확한 출력을 결정적으로 생성해야합니다.
  • 입력은 프로그램에서 하드 코딩되거나 사용자, 파일 등에서 읽을 수 있습니다.
  • 입력은 유효한 것으로 간주되며 입력 정확성을 확인하기 위해 프로그램이 필요하지 않습니다.
  • 모든 정렬 알고리즘이 허용됩니다. 숫자를 보유하는 데이터 구조는 실제 벡터 일 필요는 없습니다. 이 프로그램은 다양한 수의 숫자 또는 고정 된 수의 숫자를 정렬하도록 설계 될 수 있습니다 (예 : 3 개의 숫자를 정렬하는 프로그램은 괜찮습니다 ). 정렬은 안정적이거나 안정적이지 않을 수 있습니다 (참고 : 정렬을 불안정하게 만드는 명백한 버그가있는 안정적인 정렬을 수행하도록 설계된 프로그램이지만 실제로는 버그가 아닙니다. 프로그램은 실제로 안정적인 정렬을 수행함-유효한 답변 임) ).
  • (그들은 널리 확산과 사용 예를 들면 않는 한 당신은 타사 도구를 제외하고 (정렬 기능 포함) 함수를 호출 할 수 있습니다 boos위해 C++, JQuery위해 Javascript- 그 사용에 확인됩니다)
  • 언어를 지정하십시오
  • 코드에서 버그처럼 보이는 부분을 주석 처리하십시오.
  • 버그가 어떻게 보이는지 설명하십시오.
  • 실제로 버그가 아닌 이유를 스포일러 상자에 설명하십시오.

이것은 인기 콘테스트입니다. 가장 많은 표를 얻은 답이 이깁니다.


이 도전은 이제 끝났습니다. 우승자는 @Clueless /codegolf//a/30190/11400 으로 8 표를 받았습니다 . 모든 제출자에게 감사합니다!

우승자가 수여 된 후 들어 오려면 언제든지 새 답변을 추가하십시오. 귀하는 경쟁에서 벗어날 수 있지만 우리는 모두 흥미로운 답변을보고자합니다.


숫자 대신 부인 가능한 부울을 사용할 수 있습니까?
OUurous

예, 질문도 편집했습니다 : 모든 종류의 요소
bolov

1
나는이 문제를 주제로 다루지 않기로 결심했다. 왜냐하면이 사이트에서 미숙 한 도전은 더 이상 주제가 아니기 때문이다. meta.codegolf.stackexchange.com/a/8326/20469
cat

답변:


11

C ++

애플의goto fail 영감 ; 버그 .

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

페이지 중간 쯤에 버그가 있습니다. if확인 후 중복 된 줄이 있습니다! 우리는 항상의 마지막 값으로 최대 값을 업데이트하려고합니다 bucket_count. 고맙게도 우리는 괜찮습니다. C ++에서는 std::map키를 기준으로 정렬됩니다. 따라서 버킷을 뒤집는 것입니다. 이것이 바로 우리가 원하는 것입니다.


를 사용하지 않았 goto으므로 버그가 없습니다. (애플이 사용하지 않으면 버그가 발생하지 않았다고 말한 모든 사람들에게 언급 goto)
user253751

축하합니다. 가장 많은 표를 얻음으로써 (7 일 후 8 표)이 도전에서 승리했습니다. 또한 실제 버그를 사용했기 때문에 대답이 정말 마음에 듭니다.
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

시운전

list.sort를 반환 None하므로 이후의 부분은 else입니다 None + None. 운좋게도 이것은리스트와 int의 비교 (L > 1)가 항상 이므로 문제를 일으키지 않습니다 True. 이 함수는 항상 반환 None값을 무시하고 그 L자리에 정렬 된 Just print 를 무시합니다. 정렬에 의해 정렬 된 반쪽을 범주화로 병합해도 실행이 이루어지지 않았더라도 작동하지 않았습니다.


축하합니다. 7 일 후 6 표로 2 위를 차지했습니다. 당신의 의견에 대해 감사합니다.
bolov

5

정렬을 잘못 사용하면 64 비트 시스템 int에서 4 바이트이고 char *8 바이트이므로 작동하지 않아야합니다.

암호:

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

짓다:

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

운영:

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

그래, 괜찮아!

다섯 가지 일이 계속됩니다 : 1) qsort문자에 대한 포인터와 동일한 크기의 정수에 대한 포인터를 전달합니다. 2) 문자열의 길이는 4 바이트 (3 + 1 종결 자) = 정수의 크기를 넘지 않으며 정렬 루틴은 행복하게 정수로 취급합니다. 3) 대부분의 컴파일러는 데이터 구조를 강제로 정렬하므로 더 짧은 문자열은 동일한 공간을 차지합니다. 더 크고 실패에 대비하십시오. 4) 엔디안. 5) 내부 바이트 초기화 없음.


당신의 의견에 대해 감사합니다. 3 위를 차지했습니다. 축하합니다!
bolov

2

코브라

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]

오, 친애하는, 나는 잘못 할당 된 것 같습니다 n... 그리고 모든 쉼표는 어떻게 거기에 도착 했습니까!?

n컴파일러가 할당 되면 키-값 쌍의 첫 번째 절반 (쉼표로 인해)을 제공한다고 가정하지만 키-값 쌍이 없으므로 컴파일러는 후반을 할당 할 수 없을 때 불평하지 않습니다. 존재하지 않는 변수에. 이는 n단순히 키 값을 부여합니다.이 경우 인덱스 번호입니다. 마지막 줄의 다른 모든 겉보기 쉼표는 실제로 표준 코브라 구문의 일부입니다.


당신의 의견에 대해 감사합니다. 3 위를 차지했습니다. 축하합니다!
bolov

2

자바

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 

이 특정 임의의 값은 처음 10 개의 결과에 대해 '1'을 반환하기 때문에 작동합니다.


1
어떤 언어를 사용합니까?
Knerd

자바, 그것을 언급하는 것을 잊어 버렸습니다 (편집).
Roy van Rijn

2

요즘 계약자! 그들은 <=>(일명 "우주선") 연산자가 숫자 정렬에만 사용 된다는 것을 모르 십니까?

그리고 왜 연산자를 비교합니까?

이 코드는 어떻게 엄격한 테스트를 통과 했습니까? 심지어 사용 strict하고 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??!!

펄이 컴파일하는 이유

실제 <=>연산자는 중간에있는 유일한 연산자입니다. 다른 두 사람은 또 다른 글쓰기 방법입니다 glob("="). 이것은 <=><=><=>(별칭 "공간 함대")가로 평가됨을 의미 0합니다.


작동하는 이유

asciibetically루틴은 문자열 비교의 구현 cmp연산자 이진 " cmp"반환 -1, 0또는 1여부에 따라 왼쪽 인수 stringwise 이하, 또는 오른쪽 인자보다 동일,보다 길다.


3
글쎄 펄은 어쨌든 버그처럼 보인다 ...
chill0r
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.