Танець багатьох вимірів


19

Виклик

З огляду на n-вимірний масив цілих чисел та перестановку перших nнатуральних чисел, перестановіть розміри масиву відповідно.

Деталі

Цей виклик надихає MATLAB permute. демонстрація Перестановка задається у вигляді списку цілих чисел, наприклад, [1,3,2]засіб 1 відображається на 1, 2 відображається на 3 і 3 відображається на 2 (тут цей iзапис вказується на значення 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 потрібно знати тип значення, яке ви намагаєтеся розібрати.

Як результат, видається неминучим необхідність програми включати декларації, що стосуються типу, які є відносно багатослівними. Щодо гольф-частини, я зупинився на визначенні класу типу 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 байти завдяки @Jonathan Frech.


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

Тут також є зайвий простір z(p) for.
Джонатан Фрех

1
Використовується map(z,l), s%jі printдля 301 байт - Спробуйте його в Інтернеті!
Містер Xcoder

3

Python 2 , 41 25 байт

import numpy
numpy.einsum

Спробуйте в Інтернеті!

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

Завдяки @EriktheOutgolfer збережено 16 байт!


Чи підтримує це більше 26 вимірів?
Ерік Аутгольфер

Насправді не більше 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.