สร้างการสุ่มเรียงความแบบสุ่ม


30

คำอธิบายการท้าทาย

"derangement" ของลำดับคือการเรียงสับเปลี่ยนโดยไม่มีองค์ประกอบใดปรากฏในตำแหน่งดั้งเดิม ตัวอย่างเช่น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
ฉันหวังว่า OP ได้ระบุไว้ว่าการแก้ปัญหาจะต้องรับประกันว่ามันจะเสร็จสิ้นเสมอ
John Dvorak

4
@JanDvorak ทีนี้ความน่าจะเป็นที่นี่ยังไม่เสร็จคือ 0 แต่คุณพูดถูกที่ต้องใช้เวลาที่กำหนดขึ้นมาจะทำให้ความท้าทายน่าสนใจยิ่งขึ้น
Martin Ender

ความน่าจะเป็นเป็นจริงใช่ไหม การดำเนินการสลับแบบไม่สมบูรณ์แบบมันใช้งานได้จริงอย่างไร ฉันคิดว่านี่น่าจะเป็นการประมาณที่ดีสำหรับสิ่งที่ OP ร้องขอ แต่ฉันสงสัยว่าความน่าจะเป็นของแต่ละค่าความเหมือนกัน (อาจขึ้นอยู่กับมูลค่าเมล็ดของ PRNG ซึ่งน่าจะใช้ในการสับเปลี่ยน)
ไม่มีใคร

3
@ ไม่มีใครฉันสงสัยว่าคุณจะได้ผลลัพธ์ที่เหมือนกันอย่างสมบูรณ์จาก PRNG โดยใช้อัลกอริทึมใด ๆ อย่างไรก็ตามสมมติว่าการสับเปลี่ยนเป็นแบบเดียวกัน (ซึ่งเอกสาร Java เรียงลำดับของการรับประกันด้วย "การเรียงสับเปลี่ยนทั้งหมดเกิดขึ้นโดยมีความเป็นไปได้ประมาณเท่ากัน") โซลูชันที่ใช้การปฏิเสธก็จะให้ผลการทดสอบที่เหมือนกัน การเรียงสับเปลี่ยนมีความน่าจะเป็นเหมือนกัน
Martin Ender

1
@Nobody Math คนโง่ที่นี่ เงื่อนไขที่ประสบความสำเร็จหรือล้มเหลวเรียกว่าการทดลองใช้ Bernoulli ในสถิติ นี่ก็หมายความว่าความน่าจะเป็นที่จะต้องมีการทดลอง k เพื่อความสำเร็จครั้งแรกคือ (1 - p) ^ (k - 1) * p โดยที่ p คือความน่าจะเป็นที่จะประสบความสำเร็จ มันง่ายที่จะเห็นว่าเมื่อ k โตขึ้นความน่าจะเป็นที่ต้องการการทดลอง k จะน้อยลง ดังนั้นเราจึงพูดว่าอัลกอริทึมหยุดด้วยความน่าจะเป็น 1 ("เกือบจะแน่นอน") แต่ก็เป็นไปไม่ได้ที่มันจะไม่หยุด
maservant

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.

Jonathan Allan บันทึกหนึ่งไบต์


5
คุณได้หมวก Winter Bash มาก่อนหรือเปล่า? :-)
Luis Mendo

2
ได้เวลาวาดรูปใหม่แล้วẊ=³S$¿บันทึกไบต์
Jonathan Allan

2
ฉันไม่เคยรู้เรื่อง$นี้เลย ขอบคุณ!
ลินน์

มันคือ 6 ตัวอักษร แต่มากกว่า 6 ไบต์ Ẋ = ³S $ ¿ไบต์มีความยาว: 312112 ดังนั้นทั้งหมด 10 ไบต์
mxfh

6

Python ขนาด 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

@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: ใช้องค์ประกอบแรกจากลำดับการเรียงสับเปลี่ยนที่ไม่มีที่สิ้นสุดของการทดสอบ "derangement"


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 bytes

This is a translation of my Octave post (and similar to some of the other submissions here). I posted my first MATL post yesterday (CNR crack), so I guess this is not optimal, but it's the best I've got so far.

To be honest, I'm not entirely sure t is needed in there, but it's the only way I can get this to work. It's used so that I can compare the user input (retrieved with G), with the random permutation. I would think I could compare the two without it, but...?

Anyway, here goes:

`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

Try it online!


Any improvements? Do I really need t there or can I get rid of it? It was fun trying to golf in MATL... :)
Stewie Griffin

:-) I don't see how to get rid of that t (or equivalently another G) You need to leave something on the stack for the next iteration or as final result
Luis Mendo

3

Actually, 13 bytes

;;WX╚│♀=ΣWX)X

Try it online!

Explanation:

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

Octave, 56 55 bytes

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

We have to use input('') since this is not a function. Also, since I can choose to have the input as a string we can use the trick that nnz(x)==numel(x).

Explanation:

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

Thanks to Luis for noticing that the input can be a string, thus I could use nnz instead of numel saving two bytes.


Note to self: Read the entire question next time :) Thanks!
Stewie Griffin

1
That happens to me all the time :-)
Luis Mendo

2

MATL, 13 bytes

This is a joint effort of @LuisMendo and me. In contrast to many other answers here this one is deterministic in the sense that it does not sample random permutations until it gets a derangement, but it generates all derangements and chooses one randomly.

Y@tG-!Af1ZrY)

Try It Online!

Explanation

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 bytes

This keeps on shuffling the input while any of the characters equal the characters at their index in the input.

.WsqVHQ.S

Try it online here.

.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

Can you please add an explanation. I wanted to write a pyth answer. I don't know much about it.
Gurupad Mamadapur

@GurupadMamadapur sure, would be happy too.
Maltysen

1
@GurupadMamadapur added. We have a tutorial. Its pretty out of date, but will teach you the basics. If you need any help with anything related to pyth, feel free to ping me in chat.
Maltysen

2

Mathematica, 57 bytes

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

Unnamed function taking a list of whatevers as input and outputting a list. After generating all permutations # of the input x, we keep only the ones for which the set #-x of element-wise differences doesn't contain a 0; then we make a (uniformly) random choice from that set.


1
nice! Slightly longer #/.x_:>NestWhile[RandomSample[#,Length@#]&,#,Not@FreeQ[#-x,0]&]& obviously quicker in practice for long strings
martin

Wait, you're telling me there is no built-in for derangements in Mathematica? :o
shooqie

I was half expecting a built-in myself :)
Greg Martin

0

PHP, 85 bytes

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

Copies the string argument to two arrays, shuffles one of them until the difference between them (also comparing indexes of the elements) equals the other one. Run with -r.


0

R, 59 bytes

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

Reads a list of elements to STDIN, takes the length of the list and starts sampling ranges from 1 to the length, until it finds one that shares no places with the ordered list. Then prints that list.


0

Wonder, 32 bytes

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

Usage:

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

Explanation

More readable:

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

Recursive function f. Does an element-wise comparison between f's input list and and a shuffled version of the input list. If the comparison yields any equal values, then f is called on the shuffled list. Otherwise, we simply return the shuffled list.



0

Octave, 54 53 bytes

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

Generate all permutations of a and select randomly a row that doesn't have a common element with a .

note: It is accidentally the same as @flawr MATL answer!


0

Clojure, 94 90 79 bytes

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

-4 bytes by changing the conditional inside the reduction to an and, and inlining done?.

-11 bytes by converting the reduction to some.

WOOT! Beat PHP.

Brute-force method. Shuffles the list while it's invalid. This finishes stupid fast considering it's a brute force method that does nothing to prevent duplicate tries. It found 1000 dearangments of a 1000 element long list in less than a second.

Ungolfed:

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

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

Note that a string cannot be shuffled, must be passed through seq or vec.

Originally I tried #(first(remove(fn[s]((set(map = % s))true))(iterate shuffle %))) but recur approach is indeed shorter than iterate.

The magic is that (set(map = % s)) returns either a set of false, set of true or set of true and false. This can be used as a function, if it contains true then the answer is true, otherwise falsy nil. = is happy to take two input arguments, no need to wrap it with something.

((set [false]) true)
nil

Maybe there is even shorter way to check if any of the values is true?


0

APL, 11 bytes.

With the string in the right argument:

⍵[⍋(⍴⍵)?⍴⍵]

Explanation

ρ⍵ gets the length (or shape) of the right argument.

? returns a random array of (⍴⍵) of these numbers.

returns the order of them in order to ensure no duplicates.

⍵[..] represents the random assortment of the string using this index.


Welcome to PPCG! We require all entries to be valid functions or full programs, so your answer needs to take input through a function argument or input method.
ETHproductions

I think it should fit the requirements now. It takes in the right argument, or .
Jacob Utley
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.