Wie viele mischen

18

Ein Riffle-Shuffle ist eine Art von Shuffle, bei dem das Deck in zwei Partitionen aufgeteilt wird und die Partitionen dann wieder zusammengefügt werden, um ein neues gemischtes Deck zu erstellen.

Die Karten werden so zusammengefügt, dass die relative Reihenfolge der Karten in der Partition erhalten bleibt, in der sie Mitglied sind . Wenn die Karte zum Beispiel A vor Karte B im Deck und Karten A und B sind in der gleichen Partition, Karte A muss vor der Karte sein B im Endergebnis, auch wenn die Anzahl der Karten zwischen ihnen erhöht. Wenn sich A und B in unterschiedlichen Partitionen befinden, können sie im Endergebnis unabhängig von ihrer Startreihenfolge in beliebiger Reihenfolge sein.

Jedes Riffle-Shuffle kann dann als eine Permutation des ursprünglichen Kartenstapels angesehen werden. Zum Beispiel die Permutation

1,2,3 -> 1,3,2

ist ein Riffle Shuffle. Wenn Sie das Deck so teilen

1, 2 | 3

Wir sehen, dass jede Karte in 1,3,2der Partition dieselbe relative Reihenfolge zu jeder anderen Karte in der Partition hat. 2ist immer noch hinterher 1.

Andererseits ist die folgende Permutation kein Riffle-Shuffle.

1,2,3 -> 3,2,1

Wir können dies sehen, weil für alle zwei (nicht-trivialen) Partitionen

1, 2 | 3
1 | 2, 3 

Es gibt ein Paar Karten, deren relative Reihenfolge nicht eingehalten wird. In der ersten Partition 1und 2ändern Sie ihre Reihenfolge, während in der zweiten Partition 2und 3ändern Sie ihre Reihenfolge.

Wir sehen jedoch, dass 3, 2, 1dies durch das Zusammenstellen von zwei Riffle-Shuffles erreicht werden kann.

1, 3, 2 + 2, 3, 1 = 3, 2, 1

In der Tat ist eine ziemlich einfache Tatsache, die bewiesen werden kann, dass jede Permutation gemacht werden kann, indem eine Anzahl von Riffle-Shuffle-Permutationen kombiniert wird.

Aufgabe

Ihre Aufgabe ist es, ein Programm oder eine Funktion zu erstellen , die eine Permutation (der Größe N ) als Eingabe verwendet und die kleinste Anzahl von Riffle-Shuffle-Permutationen (der Größe N ) ausgibt, die kombiniert werden können, um die Eingabepermutation zu bilden. Sie müssen die Riffle-Shuffles nicht selbst ausgeben, wie viele es gibt.

Dies ist daher werden die Antworten in Bytes bewertet, wobei weniger Bytes besser sind.

Sie können entweder 1 oder 0 für eine Identitätspermutation ausgeben.

Testfälle

1,3,2 -> 1
3,2,1 -> 2
3,1,2,4 -> 1
2,3,4,1 -> 1
4,3,2,1 -> 2
Weizen-Assistent
quelle
3
Werden wir bald RiffleSort-Algorithmen sehen?
mbomb007
Sollte nicht 4,3,2,1sein 2? Zuerst teilen wir uns in der Mitte und gewinnen, 3,1,4,2dann teilen wir uns wieder in der Mitte und verwenden die gleiche Permutation
Halvard Hummel
@HalvardHummel Das stimmt. Ich muss das Problem mit meiner Referenzimplementierung finden.
Weizen-Assistent

Antworten:

2

Python 3 , 255 Bytes

Überprüft alle möglichen Riffles bis zur Länge der Liste (maximale Anzahl erforderlich), daher ist es für größere Eingaben sehr langsam. Könnte wohl auch ganz schön golfen sein.

lambda x:f(range(1,len(x)+1),x)
f=lambda x,y,i=0:x==y and i or i<len(x)and min(f(q,y,i+1)for a in range(1,len(x))for q in g(x[:a],x[a:]))or i
g=lambda x,y:(x or y)and[[v]+q for v in x[:1]for q in g(x[1:],y)]+[[v]+q for v in y[:1]for q in g(x,y[1:])]or[[]]

Probieren Sie es online!

Halvard Hummel
quelle
2

Sauber , 206 ... 185 Bytes

import StdEnv
f=flatten
$a b#[c:d]=b
|a>[]#[u:v]=a
=[a++b,b++a:f[[[u,c:e],[c,u:e]]\\e<- $v d]]=[b]
@l#i=length l
=hd[n\\n<-[0..],e<-iter n(f o map(uncurry$o splitAt(i/2)))[[1..i]]|l==e]

Probieren Sie es online!

Generiert alle möglichen Ergebnisse von Mischen- nZeiten und prüft, ob die Liste ein Mitglied ist.
Dies ist zwar eine schrecklich ineffiziente Methode zur Behebung des Problems, dieser Code ist jedoch besonders langsam da Listenverständnisse anstelle von Kompositionen verwendet werden, wodurch die Reduzierung elementarer Grafiken stark eingeschränkt führt zu einer spektakulären Präsentation von Clean's Garbage Collector.

Ungolfed:

import StdEnv
shuffle [] l
    = [l]
shuffle [a: b] [c: d]
    = [[a: b]++[c: d], [c: d]++[a: b]: flatten [
        [[a, c: e], [c, a: e]]
        \\ e <- shuffle b d
        ]]
numReq l
    = until cond ((+)1) 0
where
    cond n 
        = let
            mapper
                = map (uncurry shuffle o splitAt (length l/2))
            options
                = iter n (removeDup o flatten o mapper) [[1..length l]]
        in isMember l options

Probieren Sie es online!

Οurous
quelle