Паритет перестановки


14

Фон

Парність перестановки , як визначено вікіпедії , виглядає наступним чином :

Знак або підпис перестановки σ позначається sgn (σ) і визначається як +1, якщо σ парне і −1, якщо σ непарне.

Знак перестановки можна явно виразити як

sgn (σ) = (−1) ^ N (σ)

де N (σ) - кількість інверсій у σ.

Альтернативно, знак перестановки σ можна визначити з її розкладання на продукт транспозицій як

sgn (σ) = (−1) ^ m

де m - кількість транспозицій при розкладанні.

Для тих із вас, хто не любить грецький алфавітний суп у своїй математиці, я спробую трохи спростити визначення на прикладі (також вкрадене з wikipedia).

Приклад

Розглянемо вхідний масив {1, 2, 3, 4, 5}і перестановку його, скажімо, {3, 4, 5, 2, 1}. Для того щоб дістатись з початкового масиву до його перестановки, ви повинні поміняти індекси 0та 2, 1і 3, потім 2і 4. Хоча це не унікальне рішення, паритет чітко визначений, тому це працює у всіх випадках.

Оскільки для цього потрібні 3 підкачки, ми позначимо цю перестановку oddпарністю. Як ви могли очікувати, перестановка, яка вимагає рівного розміру свопів, має evenпаритет.

Виклик

Ваше завдання полягає в тому, щоб написати програму в якомога менше байтах, щоб визначити парність перестановки. Ваша програма чи функція повинні:

  • Прийняти як аргументи два вхідні масиви (або рядки), що представляють набір до перестановки та після неї.
  • Поверніть або роздрукуйте символ eдля парного або oнепарного, враховуючи перестановку.
  • Слід припустити, що всі індекси в масивах або рядках мають унікальні значення.

Випробування

Якщо припустити, що ви оголосили функцію з назвою f:

f([10], [10]) == "e"
f([10, 30, 20], [30, 20, 10]) == "e"
f([10, 30, 20, 40], [30, 20, 40, 10]) == "o"

Це , найкоротша програма в байтах виграє!


4
Людям не сподобається строгий формат виводу. Як щодо правди для парного і хибного для непарного? (або навпаки)
CalculatorFeline

Я справді сподівався зберегти вихідний формат, який я вказав, якщо хтось насправді не турбує це. Редагуйте, тримайтеся, я піду на компроміс.
Патрік Робертс

@CatsAreFluffy це краще?
Патрік Робертс

Ну, певно, ми побачимо!
CalculatorFeline

Надобраніч! Ось кілька пропозицій щодо повернення до цього (але, будь ласка, перевірте себе): [10], [10] -> e(нульові переміщення). [10 30 20], [30 20 10] -> e(два транспозиції). [10 30 20 40], [30 20 40 10] -> o(три транспозиції)
Луїс Мендо

Відповіді:


5

Желе, 13 12 байт

żṗ2</€⁺Sị“oe

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

Як це працює

żṗ2</€⁺Sị“oe  Main link. Arguments: A, B (lists)

ż             Zip A with B. Yields an array of pairs [x, σ(x)].
 ṗ2           Generate all pairs [[x, σ(x)], [y, σ(y)]].
   </€        Reduce each pair by </€.
              This maps [[x, σ(x)], [y, σ(y)]] to [x < y, σ(x) < σ(y)].
      ⁺       Repeat the previous link, i.e., execute </€ once more.
              This maps [x < y, σ(x) < σ(y)] to ((x < y) < (σ(x) < σ(y))), which is
              true if and only if x > y and σ(x) < σ(y).
       S      Sum. This counts the number of inversions.
        ị“oe  Retrieve the letter at the corresponding index.
              Indexing is 1-based and modular, so an odd sum retrieves the first
              letter, an even sum the second.

1
Це вражаюче мало. Кудо!
Патрік Робертс

6

MATL , 17 16 байт

1 байт вилучено завдяки пропозиції Денніса

2$St!<Rz2\'oe'w)

Це працює в поточній версії (15.0.0) мови.

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

Пояснення

При цьому використовується визначення паритету з точки зору інверсій. Інверсія - це пара елементів у другому масиві, які в «неправильному» порядку порівняно з першим масивом. Оскільки перший масив не потребує сортування, ми спочатку його сортуємо, та ж перестановка, необхідна для цього сортування, застосовується до другого масиву. Тоді інверсія відповідає парі елементів, яка не збільшується у другому масиві.

Зауважте також, що два вхідні масиви можуть бути замінені, а результат однаковий. Тому не важливо, який масив вважається "оригінальним", а який "перестановленим".

2$S     % implicitly take two row vectors. Sort second and apply the indices
        % of that sorting to the first
t!      % duplicate. Transpose into column vector
<       % true for elements of the column vector that exceed those of the 
        % row vector. Gives a 2D array with all pairs of comparisons
R       % keep only upper triangular part of that array
z       % number of nonzero elements. This is the number of inversions
2\      % parity of that number: gives 0 or 1
'oe'w   % push string 'eo' below the top of the stack
)       % apply index to produce 'e' or 'o'. An index 1 refers to the first
        % element, whereas 0 refers to the last. Implicitly display 

1
Це дійсно розумне рішення!
Алекс А.

@AlexA. Спасибі! Я відредагував відповідь, щоб уточнити, що робить частина попереднього замовлення: ми сортуємо один масив, а потім та сама перестановка, необхідна для цього сортування, застосовується до іншого масиву.
Луїс Мендо

1
Ви повинні додати модульну індексацію до MATL. Це врятувало б 3 байти.
Денніс

@Dennis Так, я часто думав про це ... але в даний час він використовує формат, де негативні значення мають інше значення. Я вибрав це для того, щоб мати індекси форми x(1:end-2)тощо, не чітко вказуючи розмір x. Не впевнений, чи це був вдалий вибір, але, мабуть, зараз уже пізно змінити :-) Можливо, я знайду сумісний спосіб додати модульну індексацію
Луїс Мендо

... та індекси, що перевищують поточну довжину, використовуються для призначення нових значень. Але індекс 0має значення "останній запис", тому я можу зберегти байт (видалити приріст). Дякую за ідею!
Луїс Мендо

5

Октава, 56 52 байти

Здається, поки що ніхто не використовує цей підхід: в основному я просто використовую детермінанти відповідних матриць перестановки. Вираз det(eye(nnz(a))(a,:))повертає визначник матриці перестановки, визначений вектором a. Тоді лише питання вилучення потрібного символу з рядка, залежно від результату.

p=@(v)eye(nnz(v))(v,:);@(a,b)'ole'(det(p(a)*p(b))+2)

2
Гарна ідея використовувати детермінанти. Оле!
Луїс Мендо

5

Хаскелл, 58 байт

k%l|m<-zip k l=cycle"eo"!!sum[1|(a,b)<-m,(c,d)<-m,a<c,b>d]

Використання:

*Main> [8,3,5]%[5,3,8]
'o'

Той самий метод, що і моя відповідь Python . гордий haskeller врятував байт с cycle.


1
Ви можете писати cycle"eo"!!...Замість "eo"!!mod(...)2, зберігаючи один байт.
гордий haskeller

4

Python 2, 68 байт

lambda*M:"eo"[sum(a<b<M>A>B for a,A in zip(*M)for b,B in zip(*M))%2]

Використання:

>>> f=lambda*M:"eo"[sum(a<b<M>A>B for a,A in zip(*M)for b,B in zip(*M))%2]
>>> f([8,3,5],[5,3,8])
'o'

Підраховує кількість пар інверсії двох списків-блискавок, i, e. значення (a,A)та (b,B)з кожного списку в одному індексі з a<bі A>B. Ці порівняння поєднуються як a<b<M>A>B, використовуючи властивість, що список Mє більшим за будь-яке число. Потім сума береться за модулем 2 і перетворюється на eабо o.


3

JavaScript (ES6), 73 байти

(a,b)=>"eo"[r=0,g=a=>a.map((e,i)=>a.slice(i).map(d=>r^=d<e)),g(a),g(b),r]

Оскільки нас цікавить лише паритет, будь-які повторювані перенесення просто скасовуються. Зручно, що підписи масиву JavaScript не є багатовимірними.


1
Цікаве місце для коми ... не знав, що ти можеш це зробити. Не забувайте про закваску на 1 байт
Патрік Робертс

2

Математика, 77 байт

If[Mod[Plus@@Length/@(Join[{0},#]&)/@PermutationCycles[#][[1]],2]==0,"e","o"]&

Я згоден!


Зручна функція, на жаль, довга назва!
Патрік Робертс

Дратівливо, правда? Я ненавиджу Cycles. Він стикається PermutationCyclesз назвою імені і навіть PermutationCyclesдурний, повертаючи Cyclesоб'єкт! `
CalculatorFeline

2

Математика, 31 байт

If[Tr[Signature/@{##}]==0,o,e]&

Підпис [список] дає підпис перестановки, необхідної для розміщення елементів списку в канонічному порядку

Ми можемо переупорядкувати один список до іншого, попередньо відпорядкувавши один список у будь-якому порядку (у цьому випадку канонічний порядок) та перепорядкувавши цей список до остаточного. Ознака загальної перестановки є рівною, якщо ознаки двох субперестановок рівні.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.