Многогранный танец


19

Вызов

При наличии n-мерного массива целых чисел и перестановки первых nнатуральных чисел, переставьте размеры массива соответственно.

Детали

Эта задача вдохновлена ​​MATLABs permute. Демонстрация Перестановка задается в виде списка целых чисел, например, [1,3,2]средство 1 отображается на 1, 2 отображается на 3, а 3 отображается на 2 (здесь ith-я запись - это значение, на которое iотображается). Но вы можете использовать другие удобные форматы, например, как циклы или как функции. Если это более удобно, вы также можете использовать индексирование на основе 0.

Можно считать, что массив представляет собой полный «прямоугольный» m1 x m2 x ... x mnмассив (т.е. вы можете предположить, что он не рваный / неровный ).

Можно предположить, что nон не слишком велик, поскольку многие языки имеют ограничение на количество измерений во вложенном массиве.

Если ваш язык не поддерживает многомерные массивы, вы также можете взять строку, которая представляет массив в качестве входных данных.

Примеры

  • Любой nодномерный массив с перестановкой тождеств [1,2,3,...,n]будет неизменен.
  • Массив [[10,20,30],[40,50,60]]с перестановкой [2,1]сопоставляется с [[10,40],[20,50],[30,60]].
  • Массив [[[1,2],[3,4]],[[5,6],[7,8]]]с перестановкой [2,3,1]сопоставляется с [[[1,3],[5,7]],[[2,4],[6,8]]].

Ответы:


13

9

Haskell , 168 байт

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), применяется рекурсивно к каждому элементу результата, гарантируя, что исходное первое измерение перемещается в правильную позицию.

3

Python 2 , 312 байт

Это использует 0-индексацию для перестановки

from numpy import*
from itertools import*
z=range
def f(i,r):
	l=array(i).shape;R={b:a for a,b in enumerate(r)};r=len(r);m=eval('['*r+'0'+q('for k in z(l[R[%s]])]',r-1,-1,-1))
	for d in product(*[z(p) for p in l]):exec'm'+q('[d[R[%s]]]',r)+'=i'+q('[d[%s]]',r)
	return m
q=lambda s,*j:''.join(s%(j)for j in z(*j))

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

-2 байта благодаря @ Джонатану Фреху.


Вам не нужны круглые скобки для вызова exec (сохраняя два байта) , так как это утверждение в Python 2.
Джонатан Фрех

Там также есть лишнее пространство в z(p) for.
Джонатан Фрех

1
Используется map(z,l), s%jи printдля 301 байт - Попробуйте его в Интернете!
Мистер Кскодер

3

Python 2 , 41 25 байт

import numpy
numpy.einsum

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

Вектор перестановки pзадается в виде строки букв. Так [2,3,1]можно дать как 'bca'.

Благодаря @EriktheOutgolfer сэкономлено 16 байт!


Поддерживает ли это более 26 измерений?
Эрик Outgolfer

На самом деле не более 52 размеров: прописные + строчные.
rahnema1

2

JavaScript (ES6), 136 132 байта

(a,p,v=[],r=[],g=(a,[d,...p],_,h=(r,[i,...v])=>1/v[0]?h(r[i]=r[i]||[],v):r[i]=a)=>1/d?a.map((e,i)=>g(e,p,v[d]=i)):h(r,v))=>g(a,p)&&r

0 индексированные. Объяснение: gрекурсивно перебирает массив, aсоздавая массив vиндексов, переупорядоченных с использованием перестановки p. Как только pон исчерпан, hон рекурсивно вставляет элемент в массив результатов rс использованием переставленных индексов.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.