Породжуйте випадкову деградацію


30

Опис виклику

"Порушення" послідовності - перестановка, де жоден елемент не з'являється у вихідному положенні. Наприклад ECABD, це недоречність ABCDE, але CBEDAце не так:

ABCDE
 | |   <- B and D are in their orignal positions
CBEDA

Задавши послідовність, генеруйте її випадкову деструктурування.

Примітки

  • Ви можете взяти або рядок як вхід, або масив / список елементів (цілі числа, символи, об'єкти ...)

  • Замість того, щоб повертати новий об’єкт, ви можете змінити існуючий, замінивши його елементами

  • Кожна деградація повинна мати рівну ймовірність виникнення

  • Можна припустити, що в послідовності є більше одного елемента, і жоден не з’являється більше одного разу



3
@VoteToClose: ха-ха, повністю розбитий
shooqie

Я не знаю багато про все це, але чи пов’язано це якимось чином з теоремою про фіксовану точку ... згідно з якою речі завжди опиняться у власній позиції чи щось подібне ...? Я буду робити ставку Я помиляюся, але хтось, будь ласка, виправте мене :)
Farhan Anam

Чи є гарантія того, що елементи будуть унікальними, чи вони можуть містити дублікати?
Carcigenicate

1
@Carcigenicate: саме там, в описі; ви можете припустити, що немає дублікатів
shooqie

Відповіді:


12

CJam , 14 байт

q:X{mr_X.=:|}g

Спробуйте в Інтернеті!

Продовжує перетасовувати вхід, доки це не стане розладом.

Пояснення

q:X   e# Read input and store it in X.
{     e# While the condition at the end of the loop is truthy...
  mr  e#   Shuffle the string.
  _X  e#   Duplicate it and push the input.
  .=  e#   Element-wise equality check.
  :|  e#   Reduce OR over the list, gives something truthy if any character
      e#   remained in its original position.
}g

1
Я хотів би, щоб ОП вказала, що рішення повинні гарантувати, що вони завжди закінчуються.
Джон Дворак

4
@JanDvorak Що ж, ймовірність того, що це не закінчиться, дорівнює 0. Але ти маєш рацію, що вимагає детермінованого часу роботи зробило б виклик цікавішим.
Мартін Ендер

Чи справді ймовірність 0? Операція перетасування не буде ідеальною, як це насправді працює? Я думаю, що це, мабуть, є гарним наближенням того, про що вимагала ОП, але я сумніваюся, що ймовірність кожної дезагрегації однакова (ймовірно, це залежить від певного значення насіння PRNG, яке, ймовірно, використовується операцією перетасовки).
Ніхто

3
@Nobody Я сумніваюся, що ви можете отримати ідеально однакові результати від PRNG, використовуючи будь-який алгоритм. Однак, якщо припустити, що саме перетасування є рівномірним (що Java гарантує своєрідну гарантію із "Усі перестановки відбуваються приблизно з однаковою вірогідністю"), рішення, засноване на відхиленні, також дасть рівномірні дерангування, оскільки кожна дерантація - одна перестановка, і кожна перестановка має однакову ймовірність.
Мартін Ендер

1
@Nobody Math ботанік тут. Умова, що успішно або не вдається, називається статистичним випробуванням Бернуллі. Звідси випливає, що ймовірність необхідних k випробувань до першого успіху дорівнює (1 - p) ^ (k - 1) * p, де p - ймовірність успішного порушення. Неважко помітити, що по мірі збільшення k збільшується ймовірність необхідності випробувань k стає зникаючо малою. Тому ми кажемо, що алгоритм зупиняється з вірогідністю 1 («майже напевно»), але не виключено, що він ніколи не зупиняється.
десерт

9

Желе , 6 байт

Ẋ=³S$¿

Спробуйте в Інтернеті!

Пояснення

Ẋ    ¿    Shuffle the given list while this is nonzero for it:
    $       A two-step process:
 =³           Element-wise equality of it and L (the original list)...
   S          Sum the ones in this binary array.

Джонатан Аллан врятував байт.


5
Отже, ви отримали свою шапку Winter Bash достроково? :-)
Луїс Мендо

2
Час намалювати приємну нову картину, Ẋ=³S$¿економить байт.
Джонатан Аллан

2
Так, я ніколи про це не знав $. Спасибі!
Лінн

Це 6 символів, але більше 6 байт. Довжина байтів ¿= ³S $ ¿становить: 312112. Всього 10 байт.
mxfh

6

Пітон, 85 байт

Модифікує переданий до нього список (дозволено мета та у питанні).

from random import*
def D(l):
 o=l[:]
 while any(x==y for x,y in zip(o,l)):shuffle(l)

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


1
Якщо ви вкажете Python 2, я думаю , ви могли б замінити def D(l):з , l=input()а потім зберегти відступи прогалин в наступних рядках (так у вас є програма замість функції). Хоча не спростував!
математиканда

@mathmandan хороша ідея, але тоді мені потрібно буде знову роздрукувати його, якщо це повноцінна програма, яка коштує більше байтів.
FlipTack

1
Добре, якщо ти так кажеш. Напевно, мені здавалося, що специфікація говорить про те, що вам не доведеться роздруковувати або повертати результат - цього достатньо для того, щоб взяти список [із введення користувача] та перетасувати його. Але розумно читати "існуючий" як "існуючий до запуску будь-якого вашого коду", і в цьому випадку я згоден з вами. (Можливо, щодо цього є налагоджений консенсус.) :)
mathmandan

5

ES6 (Javascript), 71, 69 байт

Введення та вихід - це масиви, які повинні працювати з будь-якими типами елементів (рядками, числами тощо), якщо їх можна порівняти з "==".

Гольф

F=s=>(r=[...s]).sort(_=>Math.random()-.5).some((e,i)=>s[i]==e)?F(s):r

Тест

F=s=>(r=[...s]).sort(_=>Math.random()-.5).some((e,i)=>s[i]==e)?F(s):r

F(['A','B','C','D'])
Array [ "D", "C", "A", "B" ]

F(['A','B','C','D'])
Array [ "D", "A", "B", "C" ]

F(['A','B','C','D'])
Array [ "C", "D", "B", "A" ]

F(['A','B','C','D'])
Array [ "D", "C", "B", "A" ]

F(['A','B','C','D'])
Array [ "C", "D", "B", "A" ]

Інтерактивний знімок

F=s=>(r=[...s]).sort(_=>Math.random()-.5).some((e,i)=>s[i]==e)?F(s):r

function G() {
    console.log(F(T.value.split``).join``); 
}
<input id=T value="ABCDEF"><button id=G onclick="G()">GENERATE</button>


5

Perl 6 , 33 байти

{first (*Zne$_).all,.pick(*)xx *}

Лямбда, яка приймає список цілих чисел або символів як вхідний і повертає новий список.

Якщо він повинен підтримувати списки довільних значень, neйого доведеться замінити на !eqv(+2 байти).

( Спробуйте в Інтернеті. )

Пояснення:

  • { }: Визначає лямбда.
  • .pick(*): Створює випадкове переміщення списку входів.
  • .pick(*) xx *: Створюється лінива нескінченна послідовність таких перетасовок.
  • (* Zne $_).all: Лямбда, яка збирає два списки (її аргумент *та аргумент зовнішньої лямбда $_) з neоператором (негативна рівність рядків), отримуючи список булевих, а потім створює allперехід для згортання їх до єдиного булевого стану.
  • first PREDICATE, SEQUENCE: Бере перший елемент з нашої нескінченної послідовності перестановок, що відповідає тесту на "зрив".


3

Perl 6 , 45 байт

{(@^a,{[.pick(*)]}...{none @a Zeqv@$_})[*-1]}
{(@^a,{[.pick(*)]}...{!sum @a Zeqv@$_})[*-1]}

Спробуй це

Введення - це масив чого-небудь.

Розширено:

{
  (

    @^a,          # declare parameter, and seed sequence generator

    {             # lambda with implicit parameter 「$_」
      [           # store into an array
        .pick(*)  # shuffle 「$_」
      ]
    }

    ...           # keep generating the sequence until

    {
      none        # none
      @a          # of the outer blocks input
      Z[eqv]      # is zip equivalent
      @$_         # with the current value being tested
    }

  )[ * - 1 ]      # return the last value
}

3

MATL, 7 байт

Це переклад моєї публікації Octave (і подібний до деяких інших публікацій тут). Я вчора опублікував свій перший MATL-пост (тріщина CNR), тому я думаю, що це не оптимально, але це найкраще, що я отримав до цих пір.

Якщо чесно, я не зовсім впевнений, що tтам потрібно, але це єдиний спосіб, коли я можу це зробити для роботи. Він використовується, щоб я міг порівнювати дані користувача (отримані з G) із випадковою перестановкою. Я б подумав, що я міг би порівняти двох без цього, але ...?

У будь-якому випадку:

`Z@tG=a

`          % Loop
 Z@        % Random permutation of input
   t       % Duplicating the stack
    G      % Paste from clipboard G (user input)
     =     % Comparing the random permutation with the input (retrieved from clipboard)
      a    % any(input == random permutation)
           % Implicit end and display

Спробуйте в Інтернеті!


Будь-які поліпшення? Мені tтам дійсно потрібно чи я можу його позбутися? Було весело намагатися грати в гольф у MATL ... :)
Гріффін

:-) Я не бачу, як позбутися цього t(або іншого іншого G). Вам потрібно залишити щось на стеці для наступної ітерації або як остаточний результат
Луїс Мендо

3

Власне , 13 байт

;;WX╚│♀=ΣWX)X

Спробуйте в Інтернеті!

Пояснення:

;;WX╚│♀=ΣWX)X
;;             make two copies of input
  WX╚│♀=ΣW     while top of stack is truthy:
   X             discard top of stack
    ╚            shuffle array
     │           duplicate entire stack
      ♀=         compare corresponding elements in shuffled and original for equality
        Σ        sum (truthy if any elements are in the same position, else falsey)
          X)X  discard everything but the derangement

2

Октава, 56 55 байт

x=input('');while any(x==(y=x(randperm(nnz(x)))));end,y

Ми повинні використовувати, input('')оскільки це не функція. Крім того, оскільки я можу вибрати вхід як рядок, ми можемо використовувати трюк, який nnz(x)==numel(x).

Пояснення:

x=input('')            % Self-explanatory
while any(x==y)        % Loop until x==y has only 0s (i.e. no elements are equal)
y=x(randperm(nnz(x)))  % Continue to shuffle the indices and assign x(indices) to y
end                    % End loop
y                      % Display y

Завдяки Луїсу за те, що помітив, що вхід може бути рядок, тому я міг би використовувати, nnzа не numelзберігати два байти.


Примітка до себе: Прочитайте все питання наступного разу :) Дякую!
Стюі Гріффін

1
Це трапляється зі мною весь час :-)
Луїс Мендо

2

MATL, 13 байт

Це спільні зусилля @LuisMendo і я. На відміну від багатьох інших відповідей тут, це детерміновано в тому сенсі, що він не вибирає випадкові перестановки, поки не отримає дерангування, але генерує всі дерангування і вибирає їх випадковим чином.

Y@tG-!Af1ZrY)

Спробуйте в Інтернеті!

Пояснення

Y@tG-!Af1ZrY)
Y@             generate all permutatoins
  t            create a duplicate
   G-!A        find the (logical) indices of all valid derangements (where no character of the string is in the same position as the original string)
       f       convert logical to linear indices
        1Zr    choose one of those indices randomly
           Y)  get the derangement (from the ones we generated earlier) at this index

2

Pyth - 10 9 байт

Це продовжує переміщувати введення, коли будь-який із символів дорівнює символам за їх індексом на вході.

.WsqVHQ.S

Спробуйте його онлайн тут .

.W           Iterate while
 s           Sum, this is works as any() on a boolean list
  qV         Vectorized equality
   H         The lambda variable for the check step
   Q         The input
 .S          Shuffle
  (Z)        Lambda variable, implicit
 (Q)         Start .W with input, implicit

Чи можете ви додайте пояснення. Я хотів написати відповідь піта. Я мало що про це знаю.
Гурупад Мамадапур

@GurupadMamadapur впевнений, також був би радий.
Мальтісен

1
@GurupadMamadapur додано. У нас є підручник . Це досить застаріло, але навчить вас азам. Якщо вам потрібна допомога з чим-небудь, пов’язаним з pyth, не соромтесь надіслати мене в чаті.
Мальтісен

2

Математика, 57 байт

#/.x_:>RandomChoice@Select[Permutations@x,FreeQ[#-x,0]&]&

Безіменна функція, що приймає список whatevers як вхідний та вихідний список. Після генерування всіх перестановок #вхідних даних xми зберігаємо лише ті, для яких набір #-xвідмінностей від елементів не містить а 0; то робимо (рівномірно) випадковий вибір із цього набору.


1
приємно! Трохи довше, #/.x_:>NestWhile[RandomSample[#,Length@#]&,#,Not@FreeQ[#-x,0]&]&очевидно, швидше на практиці для довгих струн
мартін

Зачекайте, ви кажете мені, що в Mathematica немає вбудованого для дегранувань? : o
shooqie

Я наполовину очікував на себе вбудований :)
Грег Мартін

0

PHP, 85 байт

for($a=$b=str_split($argv[1]);array_diff_assoc($a,$b)!=$a;)shuffle($b);echo join($b);

Копіює аргумент рядка у два масиви, переміщує один з них, поки різниця між ними (також порівнюючи індекси елементів) не дорівнює іншому. Бігайте з -r.


0

R, 59 байт

z=x=1:length(y<-scan(,""));while(any(x==z))z=sample(x);y[z]

Читає список елементів до STDIN, приймає довжину списку і починає вибірки від 1 до довжини, поки не знайде той, який не розділяє місця з упорядкованим списком. Потім друкує цей список.


0

Диво , 32 байти

f\@[/>#I zip#=[#0a\shuf#0]?f a?a

Використання:

f\@[/>#I zip#=[#0a\shuf#0]?f a?a];f[1 2 3 4 5]

Пояснення

Більше читати:

f\@[
  some #I zip #= [#0; a\ shuf #0]
    ? f a
    ? a
]

Рекурсивна функція f. Чи порівнює елементне порівняння між fсписком вводу 's та перетасованою версією списку введення. Якщо порівняння дає будь-які рівні значення, то fвикликається у перетасованому списку. В іншому випадку ми просто повертаємо перетасований список.



0

Октава, 54 53 байти

@(a)((p=perms(a))(L=!any(p==a,2),:))(randi(sum(L)),:)

Створіть усі перестановки aта виберіть випадковим чином рядок, що не має спільного елемента a.

Примітка: Це випадково те саме, що і відповідь @flawr MATL!


0

Clojure, 94 90 79 байт

#(let[s(shuffle %)](if(not(some(fn[[x y]](= x y))(map vector % s)))s(recur %)))

-4 байти шляхом зміни умовного скорочення на скорочення на andі вставки done?.

-11 байт шляхом перетворення скорочення в some.

WOOT! Збийте PHP.

Метод грубої сили. Переміщує список, поки він недійсний. Це закінчує нерозумно швидко, враховуючи, що це метод грубої сили, який не робить нічого для запобігання повторних спроб. Він знайшов 1000 деагрегацій списку з 1000 елементами менше ніж за секунду.

Безголовки:

(defn dearang [ls]
  (let [s (shuffle ls)
        bad? (some (fn [[x y]] (= x y))
                (map vector ls s))]
    (if (not bad?) s (recur ls))))

0

Clojure, 56 байт

#(let[s(shuffle %)](if((set(map = % s))true)(recur %)s))

Зауважте, що рядок не можна перетасувати, її потрібно пропустити через seqабо vec.

Спочатку я намагався, #(first(remove(fn[s]((set(map = % s))true))(iterate shuffle %)))але recurпідхід дійсно коротший, ніж iterate.

Магія полягає в тому, що (set(map = % s))повертає або набір хибного, набір істинного, або набір істинного і хибного. Це може використовуватися як функція, якщо вона містить, trueто відповідь є true, інакше хибною nil. =із задоволенням приймає два вхідні аргументи, не потрібно обробляти це чимось.

((set [false]) true)
nil

Можливо, є ще коротший спосіб перевірити, чи якесь із значень відповідає дійсності?


0

APL, 11 байт.

З рядком у правильному аргументі:

⍵[⍋(⍴⍵)?⍴⍵]

Пояснення

ρ⍵ отримує довжину (або форму) правильного аргументу.

?повертає випадковий масив (⍴⍵)цих чисел.

повертає їх порядок, щоб забезпечити відсутність дублікатів.

⍵[..] являє собою випадковий асортимент рядка з використанням цього індексу.


Ласкаво просимо до PPCG! Ми вимагаємо, щоб усі записи були дійсними функціями або повноцінними програмами, тому для вашої відповіді потрібно взяти введення через аргумент функції або метод введення.
ETHproductions

Я думаю, це має відповідати вимогам зараз. Він бере правильний аргумент, або .
Яків Утлі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.