p
ist eine (typklassenpolymorphe) Funktion, die eine Permutation als Liste von Int
s und eine verschachtelte Liste als mehrdimensionales Array von Int
s verwendet.
Rufen Sie als auf p [2,1] [[10,20,30],[40,50,60]]
. Wenn jedoch die Standardeinstellung des Typs nicht erfolgreich ist, müssen Sie möglicherweise eine Typanmerkung wie :: [[Int]]
(entsprechend verschachtelt) hinzufügen , die den Typ des Ergebnisses angibt.
import Data.List
class P a where p::[Int]->[a]->[a]
instance P Int where p _=id
instance P a=>P[a]where p(x:r)m|n<-p r<$>m,y:z<-sort r=last$n:[p(x:z)<$>transpose n|x>y]
Probieren Sie es online!
Golf-Herausforderungen mit verschachtelten Arrays beliebiger Tiefe sind in Haskell etwas umständlich, da die statische Typisierung eher stört. Während Haskell-Listen (mit genau der gleichen Syntax wie in der Challenge-Beschreibung) problemlos verschachtelt werden können, sind Listen mit unterschiedlicher Verschachtelungstiefe nicht kompatibel. Für Standard-Parsingfunktionen von Haskell ist es außerdem erforderlich, den Typ des zu analysierenden Werts zu kennen.
Infolgedessen scheint es unvermeidlich, dass das Programm typbezogene Erklärungen enthalten muss, die relativ ausführlich sind. Für den Golf-Teil habe ich mich darauf festgelegt, eine Typklasse zu definieren P
, p
die über den Typ des Arrays polymorph sein kann.
In der Zwischenzeit zeigt das Test-Gurtzeug des TIO einen Weg, um das Parsing-Problem zu umgehen.
Wie es funktioniert
Um das Wesentliche dieses Algorithmus zusammenzufassen: Er führt eine Blasensortierung für die Permutationsliste durch und transponiert benachbarte Dimensionen, wenn die entsprechenden Permutationsindizes vertauscht werden.
Wie in der class P a
Deklaration angegeben, werden in jedem Fall p
zwei Argumente verwendet, eine Permutation (immer vom Typ [Int]
) und ein Array.
- Die Permutation kann in der Form in der Herausforderungsbeschreibung angegeben werden, obwohl die Art und Weise, wie der Algorithmus arbeitet, die Auswahl der Indizes bis auf ihre relative Reihenfolge willkürlich ist. (Also sowohl 0- als auch 1-basierte Arbeit.)
- Die Basis
instance P Int
behandelt Arrays der Dimension 1, die p
einfach unverändert zurückgegeben werden, da die eine Dimension nur auf sich selbst abgebildet werden kann.
- Die andere
instance P a => P [a]
ist rekursiv definiert und ruft p
mit Dimension n Subarrays auf, um sie für Dimension n + 1 Arrays zu definieren .
p(x:r)m
first ruft p r
rekursiv jedes Element von auf m
und gibt ein Ergebnisfeld an, n
in dem alle Dimensionen mit Ausnahme der ersten relativ zueinander korrekt permutiert wurden.
- Die verbleibende Permutation, die durchgeführt werden muss,
n
ist gegeben durch x:y:z = x:sort r
.
- Wenn dies
x<y
der Fall n
ist, n
ist die erste Dimension von bereits korrekt platziert und wird einfach zurückgegeben.
- Wenn ja
x>y
, dann müssen die erste und zweite Dimension n
getauscht werden, was mit der transpose
Funktion erledigt wird . Schließlich p(x:z)
wird rekursiv auf jedes Element des Ergebnisses angewendet, um sicherzustellen, dass die ursprüngliche erste Dimension an die richtige Position verschoben wird.
exec
(zwei Bytes sparen) , da es sich um eine Anweisung in Python 2 handelt.