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


10

Напишіть функцію, яка приймає набір цілих чисел і друкує кожну перестановку набору, а своп виконується між кожним кроком

Вхідні дані

набір цілих чисел, наприклад (0, 1, 2)

Вихідні дані

список перестановок і свопів у форматі (set) (swap) (set) ...

Тестовий випадок

Input: 
(3, 1, 5)

Output:
(3, 1, 5)
(3, 1)
(1, 3, 5)
(3, 5)
(1, 5, 3)
(1, 3)
(3, 5, 1)
(3, 5)
(5, 3, 1)
(3, 1)
(5, 1, 3)

Правила

  • Ви можете відформатувати набір чисел, скільки завгодно.
  • Ви можете робити свопи в будь-якому порядку
  • Ви можете повторити перестановки та заміни, щоб отримати нову
  • Ваш код не повинен насправді виконувати свопи, на виході потрібно просто показати, який своп був зроблений між вашим останнім виходом і поточним
  • Ваш код повинен функціонувати лише для наборів з 2 або більше елементами
  • Набір, який вам надано, не матиме повторюваних елементів (наприклад, (0, 1, 1, 2) недійсний)

Це код-гольф, тому найкоротший код виграє!


Чи можемо ми використовувати випадковість?
Згарб

Ви маєте на увазі просто робити навантаження випадковими свопами, поки вам не вдасться досягти всіх перестановок? Так, але ви повинні бути впевнені, що всі перестановки були надруковані
Billyoyo

3
Ласкаво просимо до PPCG! Гарний перший виклик. Я б запропонував редагувати приклад, щоб елементи не плуталися з індексами, як-от використання set (3, 1, 4)або так - читаючи його в перший раз, я дуже заплутався, тому що перший swap 0,1поміняв елементи, 0,1але й індекси 0,1, але потім наступний своп не пішов за цією схемою. Я також вкажу вам на пісочницю, де ви можете розмістити виклики та отримати зворотній зв'язок, перш ніж розміщувати їх на головному сайті.
AdmBorkBork

2
@TimmyD дякую за пропозицію, я змінив приклад. Я побачив посилання на пісочницю одразу після того, як я опублікував це, я опублікую там спочатку відтепер!
Біллійо

1
Алгоритм Steinhaus – Johnson – Trotter генерує мінімально необхідну послідовність.
Ніл

Відповіді:


3

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

<<Combinatorica`
Riffle[#,BlockMap[Pick[#[[1]],#!=0&/@({1,-1}.#)]&,#,2,1]]&@*MinimumChangePermutations

Приклади

// Стовпець для більш чіткого результату

%[{1,3,5}]//Column
(*
{1,3,5}
{1,3}
{3,1,5}
{3,5}
{5,1,3}
{5,1}
{1,5,3}
{1,3}
{3,5,1}
{3,5}
{5,3,1}
*)

3

Java, 449 426 байт

import java.util.*;interface P{static Set s=new HashSet();static void main(String[]a){o(Arrays.toString(a));while(s.size()<n(a.length)){p(a);o(Arrays.toString(a));}}static<T>void o(T z){System.out.println(z);s.add(z);}static int n(int x){return x==1?1:x*n(x-1);}static void p(String[]a){Random r=new Random();int l=a.length,j=r.nextInt(l),i=r.nextInt(l);String t=a[j];a[j]=a[i];a[i]=t;System.out.println("("+a[j]+","+t+")");}}

Підхід грубої сили. Він продовжує робити випадкові заміни, поки не відбудуться всі можливі перестановки. Він використовує Набір рядкового представлення масиву, щоб перевірити, скільки різних станів було сформовано. Для n різних цілих чисел існує n! = 1 * 2 * 3 * .. * n різних перестановок.

Оновлення

  • Дотримуючись пропозицій Кевіна Круїссена, щоб трохи більше пограти в гольф.

Безголівки:

import java.util.*;

interface P {

    static Set<String> s = new HashSet<>();

    static void main(String[] a) {
        // prints the original input
        o(Arrays.toString(a));
        while (s.size() < n(a.length)) {
            p(a);
            // prints the array after the swap
            o(Arrays.toString(a));
        }
    }

    static void o(String z) {
        System.out.println(z);
        // adds the string representation of the array to the HashSet
        s.add(z);
    }

    // method that calculates n!
    static int n(int x) {
        if (x == 1) {
            return 1;
        }
        return x * n(x - 1);
    }

    // makes a random swap and prints what the swap is
    static void p(String[] a) {
        Random r = new Random();
        int l = a.length, j = r.nextInt(l), i = r.nextInt(l);
        String t = a[j];
        a[j] = a[i];
        a[i] = t;
        System.out.println("(" + a[j] + "," + t + ")");
    }
}

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

$ javac P.java
$ java P 1 2 3
[1, 2, 3]
(2,1)
[2, 1, 3]
(1,1)
[2, 1, 3]
(2,2)
[2, 1, 3]
(3,1)
[2, 3, 1]
(3,1)
[2, 1, 3]
(1,2)
[1, 2, 3]
(1,1)
[1, 2, 3]
(3,2)
[1, 3, 2]
(2,3)
[1, 2, 3]
(3,1)
[3, 2, 1]
(3,1)
[1, 2, 3]
(3,3)
[1, 2, 3]
(1,2)
[2, 1, 3]
(1,3)
[2, 3, 1]
(1,2)
[1, 3, 2]
(3,1)
[3, 1, 2]

Як бачите, є набагато більше свопів, ніж необхідний мінімум. Але, здається, працює :-D

Як бонус, він також працює з рядками, тобто

$ java P 'one' 'two'
[one, two]
(two,one)
[two, one]

чи є у вас версія для гольфу без гольфу, щоб ми подивилися на ваш метод, використовуючи?
Біллійо

@Billyoyo: Додано код без гольфу. Нічого фантазії там немає :-)
Master_ex

Ви можете трохи пограти в гольф. Немає необхідності виправити попередження, так що ви можете видалили Set декларації: Set s=new HashSet();. Ваш код в методі nможе бути один повернення: static int n(int x){return x==1?1:x*n(x-1);}. І ви можете замінити String zв методі oз родовим замість: static<T>void o(T z){System.out.println(z);s.add(z);}. Усього в поєднанні це призведе до 426 байт .
Kevin Cruijssen

1

JavaScript (ES6), 186 байт

f=
a=>{console.log(a);d=a.slice().fill(-1);s=[...d.keys()];for(i=l=a.length;i;)s[k=(j=s.indexOf(--i))+d[i]]<i?(console.log(a[s[j]=s[k]],a[s[k]=i]),console.log(s.map(n=>a[n])),i=l):d[i]*=-1}
;
<input id=i><input type=button value=Go! onclick=f(i.value.split`,`)>

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

a=>{console.log(a);d=a.slice().fill(-1);s=[...d.keys()];for(i=l=a.length;i;)s[k=(j=s.indexOf(--i))+d[i]]<i?console.log(a[s[j]=s[k]],a[s[k]=i],s.map(n=>a[n],i=l)):d[i]*=-1}

Працює, виконуючи алгоритм Штейнгауза-Джонсона – Троттера на масиві індексів переміщення та перекладі назад на вхідний масив. Безголівки:

function steps(array) {
    console.log(array); // initial row
    var d = a.slice().fill(-1); // direction values
    var s = [...a.keys()]; // initial (identity) shuffle
    var l = a.length;
    for (var i = l; i; ) { // start by trying to move the last element
        var j = s.indexOf(--i);
        var k = j + d[i]; // proposed exchange
        if (s[k] < i) { // only exchange with lower index (within bounds)
            console.log(a[s[k]],a[i]); // show values being exchanged
            s[j] = s[k];
            s[k] = i; // do the exchange on the shuffle
            console.log(s.map(n=>a[n])); // show the shuffled array
            i = l; // start from the last element again
        } else {
            d[i] *= -1; // next time, try moving it the other way
        } // --i above causes previous element to be tried
    } // until no movable elements can be found
}

1

Рубін, 86 байт

puts (2..(a=gets.scan(/\d+/).uniq).size).map{|i|a.permutation(i).map{|e|?(+e*", "+?)}}

1

Haskell - 135 байт

p=permutations;f=filter
q(a:b:xs)=(\x->f(uncurry(/=)).zip x)a b:q(b:xs);q _=[]
l=head.f(all((==2).length).q).p.p
f=zip.l<*>map head.q.l

вихід:

> f [3,1,5]
[([3,1,5],(3,1)),([1,3,5],(3,5)),([1,5,3],(1,5)),([5,1,3],(1,3)),([5,3,1],(5,3))]

Я використовую стандартну permutationsфункцію, яка не заснована на свопах, тому я беру перестановки перестановок і знаходжу ту, що трапляється як ланцюжок свопів.

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