pявляется (полиморфной) функцией типа, принимающей перестановку в качестве списка Ints, и вложенный список, представляющий многомерный массив Ints.
Вызовите как p [2,1] [[10,20,30],[40,50,60]], однако, если заданный по умолчанию тип не удался, вам, возможно, придется добавить аннотацию типа вроде :: [[Int]](вложенную соответствующим образом), дающую тип результата.
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]
Попробуйте онлайн!
Задачи игры в гольф с вложенными массивами произвольной глубины немного неудобны в Haskell, потому что статическая типизация имеет тенденцию мешать. Хотя списки на Haskell (с точно таким же синтаксисом, что и в описании задачи) могут быть вложены просто отлично, списки с различной глубиной вложенности относятся к несовместимым типам. Кроме того, стандартные функции синтаксического анализа Haskell требуют знания типа значения, которое вы пытаетесь проанализировать.
В результате кажется неизбежным, что программа должна включать в себя объявления, относящиеся к типу, которые являются относительно многословными. Для части игры в гольф я остановился на определении типа P, такого, который pможет быть полиморфным по типу массива.
Между тем, тестовое устройство TIO показывает способ обойти проблему разбора.
Как это устроено
Подводя итог сути этого алгоритма: он выполняет пузырьковую сортировку в списке перестановок, транспонируя соседние измерения, когда соответствующие индексы перестановки меняются местами.
Как указано в class P aобъявлении, в любом случае pпринимает два аргумента: перестановку (всегда типа [Int]) и массив.
- Перестановка может быть дана в форме в описании вызова, хотя способ работы алгоритма, выбор индексов является произвольным, за исключением их относительного порядка. (Так что и 0- и 1-основанная работа.)
- База
instance P Intобрабатывает массивы измерения 1, которые pпросто возвращаются без изменений, поскольку одно измерение может быть отображено только на себя.
- Другой
instance P a => P [a]определяется рекурсивно, вызывая pс подмассивами измерения n , чтобы определить его для массивов измерений n + 1 .
p(x:r)mпервый вызов p rрекурсивно для каждого элемента m, давая массив результатов, nв котором все измерения, кроме первого, были правильно переставлены относительно друг друга.
- Оставшаяся перестановка, которая должна быть выполнена,
nопределяется как x:y:z = x:sort r.
- Если
x<yтогда первое измерение nуже правильно размещено и nпросто возвращается.
- Если
x>y, то первое и второе измерение nнужно поменять местами, что и делается с помощью transposeфункции. Наконец p(x:z), применяется рекурсивно к каждому элементу результата, гарантируя, что исходное первое измерение перемещается в правильную позицию.
exec(сохраняя два байта) , так как это утверждение в Python 2.