排列步骤


10

编写一个函数,该函数采用一组整数并打印该组的每个排列,并在每个步骤之间执行交换

输入值

一组整数,例如(0,1,2)

输出量

格式(set)(交换)(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)无效)

这是代码高尔夫球,所以最短的代码胜出!


我们可以使用随机性吗?
Zgarb

您的意思是只是进行大量随机交换,直到碰巧实现所有排列?是的,但是您必须确保已打印所有排列
Billyoyo,2016年

3
欢迎来到PPCG!不错的第一个挑战。我建议编辑该示例,以使元素不要与索引混淆,例如use set (3, 1, 4)左右-第一次读它时我很困惑,因为第一次交换0,1交换了元素0,1但也交换了索引0,1,但是接下来交换了交换没有遵循这种模式。我还将指向您指向“ 沙箱”,您可以在其中发布挑战并获得反馈,然后再将其发布到主站点。
AdmBorkBork

2
@TimmyD感谢您的建议,我更改了示例。发布此消息后,我立即看到了沙箱的链接,从现在开始,我将首先在其中发布!
Billyoyo

1
所述豪斯-约翰逊-Trotter的算法产生最小必要序列。
尼尔

Answers:


3

Mathematica,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,449426字节

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+")");}}

蛮力法。它会一直进行随机交换,直到发生所有可能的排列。它使用数组的字符串表示形式的Set来检查已生成了多少个不同的状态。对于n个不同的整数,有n个!= 1 * 2 * 3 * .. * n个不同的排列。

更新资料

  • 跟随凯文·克鲁伊森(Kevin Cruijssen)的建议,再打一点高尔夫球。

取消高尔夫:

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

@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个字节
凯文·克鲁伊森

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}

通过对随机排列的索引数组执行Steinhaus–Johnson–Trotter算法并转换回输入数组来工作。取消高尔夫:

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

Ruby,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函数,该函数不基于交换,因此我要对置换进行排列并找到恰好是交换链的一个。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.