Реализовать Богосорт


29

Является ли решение судоку слишком сложно? Даже версия грубой силы ? Вот упражнение по кодированию, которое немного проще. Я надеюсь. :-П

Напишите самую короткую функцию для реализации bogosort. В частности, ваша функция должна:

  • Возьмите массив (или эквивалент вашего языка) в качестве ввода
  • Проверьте, находятся ли его элементы в отсортированном порядке; если это так, вернуть массив
  • Если нет, перетасуйте элементы и начните снова

Самый короткий вход побеждает. В случае связи предпочтительнее использовать функцию, которая поддерживает пользовательский компаратор (и / или генератор псевдослучайных чисел). Любые оставшиеся связи решаются в пользу более раннего представления.


Пояснения: Вы можете использовать любой тип элемента, если хотите, если, конечно, есть какой-то способ их заказать. Кроме того, перетасовка должна быть равномерной; ничего из этого «я просто быстро сортирую и назову это перетасованным» бизнесом. :-)


Какие типы элементов? int или строки?
— Александру

@Alexandru: Либо в порядке. Твой выбор.
— Крис Джестер-Янг

Добавление пользовательского компаратора увеличит длину кода, поэтому в выигрышной записи не будет пользовательского компаратора. Я думаю, что разрывать галстук не имеет смысла.
— Александру

1
Возможно, что этот алгоритм может не работать при использовании генератора псевдослучайных данных. например, когда длина списка превышает, скажем, 2000, есть 2000! состояния для списка, которые могут превышать количество внутренних состояний prng.
— gnibbler

2
Да, соответствующая цитата из Википедии: «Однако, если вместо случайного источника используется генератор псевдослучайных чисел, он может никогда не завершиться, поскольку они демонстрируют длительное циклическое поведение».
— Гнибблер

Ответы:


8

APL (Дьялог), 20

{⍵≡⍵[⍋⍵]:⍵⋄∇⍵[?⍨⍴⍵]}

объяснение

⍵является (правым) аргументом
⍵≡⍵[⍋⍵]: Проверяет, ⍵равна ли сортируемая величина ⍵самому себе
:⍵: Если да, то возвращает ⍵
∇⍵[?⍨⍴⍵]: Иначе, генерирует массив от 1 до ⍴⍵(длина ⍵) в случайном порядке, переупорядочивает в ⍵соответствии с этим ( ⍵[...]) и применяет функцию к нему ( ∇)


Внезапно вернуться к этой проблеме и ...

APL (Дьялог), 19

{∧/2≤/⍵:⍵⋄∇⍵[?⍨⍴⍵]}

Просто мысль о сортировке массива в проверке делает его бессмысленным (не говоря о том, что Bogosort имеет смысл), более точная реализация будет ∧/2≤/⍵, и это приведет к снижению количества символов.


15

Perl 6: 23 символа

@s.=pick(*)until[<=] @s

1
Это функция в Perl? Это выглядит красиво :)
— Eelvex

1
Если вы не знаете, [<=]проверяет, отсортирован ли список:, [<=] (1, 2, 3,) == (1 <= 2 <= 3) == (1 <= 2) and (2 <= 3)и .pick(n)выбирает из списка n случайных элементов, и .pick(*)позволяет Perl выбирать все элементы. use.perl.org/~masak/journal/40459
— Минг-Тан

Это должно быть Perl 6. Я никогда не видел pickраньше, не говоря уже о [<=]. Где в документации те?
— Мистер Лама

@GigaWatt Это Perl 6 (не Perl 5). []это оператор сокращения, который переводит оператор в квадратные скобки. Например, [<=] 1, 2, 3есть 1 <= 2 <= 3(и да, вы делаете такие диапазоны в Perl 6). В этом случае он используется для определения порядка элементов. .pick(*)метод перемешивает список ( pick(N)выбирает Nэлементы из списка). .=вызывает метод и присваивает результат переменной. Что касается документации - на данный момент существует только спецификация Perl 6 - feather.perl6.nl/syn , но она существует.
— Конрад Боровски

7

APL (22)

{(⍳X←⍴⍵)≡⍋⍵:⍵⋄∇⍵[X?X]}

Использование:

    {(⍳X←⍴⍵)≡⍋⍵:⍵⋄∇⍵[X?X]} 3 2 1
1 2 3

Объяснение:

  • ⍋⍵: возвращает индексы элементов в отсортированном порядке, поэтому ⍋30 10 20дает2 1 3
  • (⍳X←⍴⍵)≡⍋⍵:⍵Сохраните длину входного списка в X. Если диапазон [1..X]равен порядку отсортированного индекса, список отсортирован, поэтому верните его.
  • ⋄∇⍵[X?X]: если это не так, рекурсивно использовать перемешанный массив.

7

Рубин - 33 персонажа

g=->l{l.shuffle!!=l.sort ?redo:l}

На 1 символ меньше:g=proc{|l|0until l.sort==l.shuffle!}
— AShelly

@ AShelly, ваша версия не работает. Моя версия (на 5 символов меньше) f=->l{l.sort!=l.shuffle!?redo:l}(Ruby 1.9)
— Hauleth

Может кто-нибудь, пожалуйста, объясните мне, почему redoработает, procно не в классическом методе с def...end? Я думал, что redoработает только с петлями?
— Патрик Осцити

1
Хорошо, неважно, я нашел что-то в книге «Язык программирования Ruby»: « redo[…] передает управление обратно в начало процесса или лямбды». Это просто так.
— Патрик Осцити

6

Математика , 40 37

NestWhile[RandomSample,#,Sort@#!=#&]&

С пробелами:

NestWhile[RandomSample, #, Sort@# != # &] &

Если вы игнорируете ошибки, вы можете сохранить три байта с помощью:#//.l_/;Sort@l!=l:>RandomSample@l&
— Martin Ender

13 байт в Mthmca.
— Майкл Стерн

5

J - 34 27

f=:({~?~@#)^:(1-(-:/:~))^:_

например:

f 5 4 1 3 2
1 2 3 4 5

f 'hello'
ehllo

Часть {~? ~ @ # Тасует ввод:

({~ ?~@#) 1 9 8 4
4 8 9 1
({~ ?~@#) 'abcd'
bdca

3

Python 61

Сортировка на месте.

import random
def f(l):
 while l!=sorted(l):random.shuffle(l)

Ваша функция не возвращает массив в случае успеха.
— Hallvabo

Сортировка на месте. Переданный массив модифицируется.
— Александру

Вопрос действительно говорит о том, что функция должна возвращать массив - даже если технически нет необходимости получать результат.
— Джонатан М Дэвис

1
from random import*может сохранить символ
— Угорен

1
Это может не всегда работать: (из документации модуля Python для случайных чисел): «Обратите внимание, что даже для довольно небольшого len (x) общее число перестановок x больше, чем период большинства генераторов случайных чисел; это означает, что большинство перестановок длинная последовательность никогда не может быть сгенерирована ".
— Мэтт

3

Python 94

from itertools import*
def f(a):return [x for x in permutations(a) if x==tuple(sorted(a))][0]

Другие ответы Python используют random.shuffle (). Документация случайного модуля Python гласит:

Обратите внимание, что даже для довольно небольших len (x) общее число перестановок x больше, чем период большинства генераторов случайных чисел; это подразумевает, что большинство перестановок длинной последовательности никогда не может быть сгенерировано.


Сделайте лямбду вместо этого; Я думаю, что это будет короче. Также обратите внимание, что вы можете сделать return[x...в отличие от return [x.... То же самое с permutations(a) if- это может быть permutations(a)if.
— 0WJYxW9FMN

lambda a: [x for x in __import__("itertools").permutations(a) if x==tuple(sorted(a))][0]составляет 88 байтов
— известно1622

3

К, 31 25

{while[~x~x@<x;x:x@(-#x)?#x];x}

{x@(-#x)?#x}/[{~x~x@<x};]

,

k){x@(-#x)?#x}/[{~x~x@<x};] 3 9 5 6 7 9 1
`s#1 3 5 6 7 9 9

,

k){x@(-#x)?#x}/[{~x~x@<x};] "ascsasd"
`s#"aacdsss"

2

Python (69 символов)

from random import*
def f(a):
 while a>sorted(a):shuffle(a)
 return a

Сортирует целые числа в порядке возрастания чисел. Обратите внимание, что рекурсивные решения, такие как

from random import*;f=lambda a:a>sorted(a)and(shuffle(a)or f(a))or a

потерпит неудачу из-за переполнения стека даже для небольших входных данных (скажем, N> 5), потому что Python не выполняет оптимизацию хвостового вызова.


2

D без пользовательского компаратора: 59 символов

R f(R)(R r){while(!isSorted(r))r.randomShuffle();return r;}

Более разборчиво:

R f(R)(R r)
{
    while(!r.isSorted)
        r.randomShuffle();

    return r;
}

D с пользовательским компаратором: 69 символов

R f(alias p,R)(R r){while(!isSorted!p(r))r.randomShuffle();return r;}

Более разборчиво:

R f(alias p, R)(R r)
{
    while(!isSorted!p(r))
        r.randomShuffle();

    return r;
}

2

Скала 73:

def s(l:Seq[Int]):Seq[Int]=if(l==l.sorted)l else s(util.Random.shuffle l)

В Scala мы можем проверить, выполнял ли компилятор оптимизацию хвостового вызова:

@annotation.tailrec
def s(l:Seq[Int]):Seq[Int]=if(l==l.sorted)l else s(util.Random shuffle l)

и да, это так. Однако для краткого списка из 100 значений:

val rList = (1 to 100).map(x=>r.nextInt (500))
s(rList) 

Потребовалось почти 4 месяца, чтобы завершить. ;)


2

C # (184 символа)

T[]S<T>(T[]i)where T:IComparable<T>{T l=default(T);while(!i.All(e=>{var r=e.CompareTo(l)>=0;l=e;return r;})){i=i.OrderBy(a=>Guid.NewGuid()).ToArray();l=default(T);}return i.ToArray();}

Это не очень приятно делать в C #. Вы должны поддерживать дженерики для поддержки как значений, так и ссылочных типов. Нет функции перемешивания массива или функции, чтобы проверить, отсортировано ли что-либо.

У кого-нибудь есть советы, как сделать это лучше?

Редактировать версию, которая только сортирует int (134 символа):

int[]S(int[]i){var l=0;while(!i.All(e=>{var r=e>=l;l=e;return r;})){i=i.OrderBy(a=>Guid.NewGuid()).ToArray();l=0;}return i.ToArray();}

2

GNU / BASH 65

b(){ IFS=$'\n';echo "$*"|sort -C&&echo "$*"||b $(shuf -e "$@");}

Хм, можно ли получить специальное исключение для возврата правила массива, поскольку функции bash могут буквально возвращать только неподписанный байт?
— Кодзиро

2

C ++ 11, 150 символов

#include<deque>
#include<algorithm>
void B(std::deque &A){while(!std::is_sorted(A.begin(),A.end())std::random_shuffle(myvector.begin(),myvector.end());}

Просто .. сделано для удовольствия.


1
std :: random_shuffle не является равномерным. В пояснениях говорится: «Кроме того, перемешивание должно быть равномерным»
— STDQ

Хорошо ... я не знал, что это не было равномерным.

Он основан на rand (), который не является единообразным - см. Open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3924.pdf . Кажется, не многие другие следят за мной, так что я думаю, это не имеет большого значения.
— STDQ

Так что, если я использую полностью случайный тип, например srand (time (0)), то будет ли это учитываться?

Проблема в том, что rand не гарантирует хорошего качества случайных чисел, не говоря уже об однородности, некоторые выдают неслучайные биты младших разрядов. Я думаю, это не имеет значения и не должно иметь значения в конце концов. Я получил только 8 байтов, используя унифицированный распределитель с std :: shuffle и так далее, достаточно хорошо для меня.
— STDQ

2

Питон - 61 символ

рекурсивный

from random import*;f=lambda l:l==sorted(l)or shuffle(l)>f(l)

Ваша функция возвращает True или False, а не массив.
— Hallvabo

2
Также обратите внимание, что рекурсивные решения обречены на провал даже при небольших затратах.
— Hallvabo

1
@hallvabo: На самом деле я хочу написать хвостовое рекурсивное решение в Scheme, которое, конечно, не истощит ваш стек.
— Крис Джестер-Янг

@hallvabo, Александру уже сделал очевидное решение Python, поэтому я просто собирался сделать что-то другое здесь. Конечно, рекурсивное решение просто для развлечения, а не для серьезного соперника
— gnibbler

from random import*может быть короче.
— 0WJYxW9FMN

2

PowerShell , 85 82 56 55 52 байта

-26 байт благодаря предложениям mazzy
-1 байт благодаря AdmBorkBork
-3 байт благодаря mazzy

for($l=$args;"$l"-ne($l|sort)){$l=$l|sort{random}}$l

Попробуйте онлайн!

PowerShell имеет сравнительно дешевое сравнение массивов, приводя их к строкам и сравнивая их.


2
Переместите свою paramинициализацию в свою forинициализацию, чтобы сохранить байт -for($l=$args;
— AdmBorkBork

1
хороший. -neприводит правый оператор к скалярному типу левого оператора. Итак, вы можете сохранить несколько байтов: попробуйте онлайн!
— Маззи

1

Javascript 291 символов

мин

function f(e){var t=[].concat(e).sort();t.e=function(e){var n=true;t.forEach(function(t,r){if(t!=e[r])n=false});return n};while(!t.e(e.sort(function(){return Math.floor(Math.random()*2)?1:-1}))){console.log(e)}return e}

ун-мин

function f(a) {
var b = [].concat(a).sort();
b.e = function (z) {
    var l = true;
    b.forEach(function (v, i) {
        if (v != z[i]) l = false;
    });
    return l
};
while (!b.e(a.sort(function () {
    return Math.floor(Math.random() * 2) ? 1 : -1;
}))) {
    console.log(a);
}
return a;
}

У меня такое чувство, что я говорил это раньше, но вы можете удалить все vars. Просто сделайте их неявными глобальными переменными, просто код будет максимально коротким.
— gcampbell

1

Matlab, 59 байт

Относительно прямой подход:

x=input('');while~issorted(x);x=x(randperm(numel(x)));end;x

1

J, 22 байта

$:@({~?~@#)`]@.(-:/:~)

Это рекурсивная, молчаливая монада, использующая повестку дня. Вот как это работает:

Позвольте yбыть нашим списком. Во-первых, глагол справа от повестки дня -:/:~. Этот глагол любезно предоставлен Лики Нун . Он соответствует ( -:) независимо от того, отсортирован ли ввод ( /:~) с использованием монадического хука. ( (f g) y = y f (g y)) Это возвращает один или ноль соответственно. Левая часть повестки дня представляет собой герунду из двух глаголов: справа - глагол тождества ], а слева - место, где происходит рекурсия. По вопросам повестки дня выбирает либо личность глагола в позиции , 1если список будет отсортирован, и больше глагола в положении , 0если список не отсортирован.

$:@({~?~@#)звонки $:(самый длинный глагол, в котором он содержится) поверх результата {~?~@#on y. Это перемешивает список, так как ?~@#принимает перестановки длины y, будучи случайным образом отсортированными индексами y. {~в монадическом хуке возвращает список y, индексами которого являются правильные аргументы. Этот перетасованный список затем вызывается снова с повесткой дня и повторяется, пока он не будет отсортирован.


1

C ++ 14, 158 байт

#include <algorithm>
#include <random>
[](int*a,int s){std::random_device r;for(std::knuth_b g(r());!std::is_sorted(a,a+s);std::shuffle(a,a+s,g));return a;};

1

Желе , 6 байтов, языковые проблемы

ẊŒ¿’$¿

Попробуйте онлайн!

объяснение

ẊŒ¿’$¿
     ¿  While
 Œ¿’$     the input is not in its earliest possible permutation (i.e. sorted)
Ẋ       shuffle it

Œ¿присваивает номер каждой перестановке списка; 1 отсортировано, 2 имеет два последних замененных элемента и т. Д., Вплоть до факториала длины списка (который является списком в обратном порядке). Таким образом, для отсортированного списка это значение равно 1, и мы можем уменьшить его, используя ’для создания «не отсортированного» теста, который можно использовать в качестве логического значения в условии цикла while. Это $вызывает условие для анализа в группе.


1

C ++, 166 байт

Мех.

#import<algorithm>
#import<random>
#define r b.begin(),b.end()
template<class v>
v f(v b){auto a=std::mt19937();while(!std::is_sorted(r))std::shuffle(r,a);return b;}

Это должно работать на всех контейнерах STL, которые имеют begin()и end().

Ungolfed:

#include <algorithm>
#include <random>
template <class v>
v f(v b) {
    auto a = std::mt19937();
    while (!std::is_sorted(b.begin(),b.end()))
        std::shuffle(b.begin(),b.end(),a);

    return b;
}


1

Брахилог , 5 байт

∈&ṣ≤₁

Попробуйте онлайн!

Когда я впервые увидел ответ Brachylog от ais523 (в отличие от его ответа Jelly, потому что, если я не ошибаюсь, user62131 также был им), я подумал: а что, если вместо рекурсии будет использоваться возврат назад? Итак, сначала я попробовал ṣ≤₁. Оказывается, поскольку случайный выбор чего-либо не приводит к множественным выводам, а только к тому, что один вывод недетерминированно, к предикату ṣшаффла нельзя вернуться, поэтому запуск, который просто не удастся, если вам не повезет правильно перетасовать его с первой попытки. После этого я попробовал pṣ≤₁, что сработало большую часть времени, но, поскольку конечный длинный список содержит конечное число перестановок, иногда он по-прежнему терпел неудачу. После того как я отказался от цели сокращения длины, я наконец-то придумал:

         The input
∈        is an element of
         an unused implicit variable,
 &       and the input
  ṣ      shuffled randomly
   ≤₁    which is increasing
         is the output.

(Демонстрация случайности)

Хотя на самом деле это может быть немного короче, если мы возьмем некоторые свободы с I / O ...

Брахилог , 4 байта

⊆ṣ≤₁

Попробуйте онлайн!

Чтобы выходные данные были полезными, входные данные не должны содержать дублирующихся элементов, поскольку в дополнение к сортировке входных данных этот предикат bogosort добавляет случайное количество дублирующих элементов и нули. (Гипотетически, это может добавить что угодно, но это как бы не так.) Обычно я бы не стал упоминать что-то настолько далекое от правильного функционирования, но я чувствую, что это в духе задачи.

⊆        An ordered superset of the input
 ṣ       shuffled randomly
  ≤₁     which is increasing
         is the output.

1

Perl 6 , 28 байт

{({.pick(*)}...~.sort).tail}

Попробуйте онлайн!

Блок анонимного кода, который перемешивает список до его сортировки. Обратите внимание, что он сортирует список хотя бы один раз, что разрешено. И нет, его {.pick(*)}нельзя заменить*.pick(*)


1

Pyth , 11 байт

Wn=Q.SQSQ;Q

Довольно доволен этим, наверное, можно еще немного поиграть в гольф

объяснение


Wn=Q.SQSQ;Q
W    While
  =Q.SQ    Variable Q (input variable) shuffled 
 n  Does not equal
       SQ    Variable Q sorted
             ;  Do nothing (loop ends)
              Q    And output variable Q

Попробуйте онлайн!


Вы можете сократить =Q.SQдо =.SQ-1 байт (работает и с другими операторами, например =QhQ-> =hQ)
— ar4093

1

Japt , 11 9 байт

_eZñ}a@öx

Попытайся

_eZñ}a@öx     :Implicit input of array U
_             :Function taking an array as argument via parameter Z
 e            :  Test Z for equality with
  Zñ          :  Z sorted
    }         :End function
     a        :Repeat and return the first result that returns true
      @       :Run this function each time and pass the result to the first function
       öx     :  Random permutation of U

1

Brachylog (v2), 5 байт

≤₁|ṣ↰

Попробуйте онлайн!

Функция представления. (Ссылка TIO использует аргумент командной строки, который автоматически превращает функцию в полную программу.)

объяснение

≤₁|ṣ↰
≤₁      Assert that {the input} is (nonstrictly) sorted in ascending order
  |     Output it
  |     Exception handler: if an assertion fails:
   ṣ      Randomly shuffle {the input}
    ↰     and run this function recursively on it, {outputting its output}

Prolog (язык, на котором компилируется Brachylog) является хвостово-рекурсивным, поэтому эта функция в конечном итоге компилируется в узкий цикл.


0

C (203 символа, без входного цикла: только функция)

#include <stdio.h>
#define P (int*a,int n){
#define F for(i=0;i<n;i++){
int i,j,v;s P F if(a[i]>a[i+1])return 0;}return 1;}void h P F v=a[i];a[i]=a[j=rand()%n];a[j]=v;}}void b P while(!s(a,n-1))h(a,n);}

Это то же самое, что и ниже, где мы также читаем массив из stdin и записываем отсортированный массив. Так как Q попросил функцию, а не целую программу ...

С (296 символов)

#include <stdio.h>
#define P (int*a,int n){
#define F for(i=0;i<n;i++){
int i,j,n,v,x[999];s P F if(a[i]>a[i+1])return 0;}return 1;}void h P F j=rand()%n;v=a[i];a[i]=a[j];a[j]=v;}}void b P while(!s(a,n-1))h(a,n);}main(){while(scanf("%d",&v)==1)x[n++]=v;if(!s(x,n))b(x,n);F printf("%d\n",x[i]);}}

Компиляция может дать предупреждение (неявные объявления). Ограничение размера массива Hardencoded 999 элементов. Хрупкое.

если нет необходимости предварительно проверять, отсортирован ли массив, это можно сделать в 284.

С (251 символ, было 284)

#include <stdio.h>
#define F for(i=0;i<n;i++){
int i,j,n,v,a[999];s(int n){F if(a[i]>a[i+1])return 0;}return 1;}void h(){F v=a[i];a[i]=a[j=rand()%n];a[j]=v;}}void b(){while(!s(n-1))h();}main(){while(scanf("%d",&a[n++])>0);b();F printf("%d\n",a[i]);}}

(используя глобальные переменные вместо аргументов функций).

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.