以字典顺序排序生成一组前置-追加排列


14

长度的前置-追加序列定义为可以通过以下过程生成n的数字的排列1, 2, ..., n

  • 从数字开始1

  • 用于从每个数字2n,放置这个号码到该序列的开头或结尾(或前置追加它,顺序因此得名)。

例如,这是生成长度为4的前置-添加序列的有效方法:

1
21     [beginning]
213    [end]
2134   [end]

您的任务是构建一个程序或函数,该程序或函数将一个n从数字3到的数字30作为输入,并按n字典顺序打印或返回所有长度的前-后加序列(如果您输出的是字符串而不是列表,则表示大于9的数字以字母表示a-u,以保留字符串长度)。例如,这是以下命令n = 4

1234  [RRR]
2134  [LRR]
3124  [RLR]
3214  [LLR]
4123  [RRL]
4213  [LRL]
4312  [RLL]
4321  [LLL]

通常,长度为2 n-1个前置-追加排列n

您不得在代码中使用任何使用您语言的内置排序功能。以任何语言进行此操作的最短程序都会胜出。


我不喜欢输出格式要求,尤其是转换为letter a-u。我们可以只输出数字列表吗?
xnor

3
一段时间后,您可能想接受答案,因为有些人倾向于不回答问题(如果答案已接受)。
Optimizer

1
因此,您接受的答案有误..
优化器

2
FryAmTheEggman在您编辑答案前21分钟发布了答案。
Joe Z.

2
@Optimizer我不太认为这是最怪异的方法-FryAmTheEggman的答案是19字节长,比您早21分钟。这是最早发布的最短答案。
Joe Z.

Answers:


10

CJam,22 20 19 17个字节

]]l~{)f+_1fm>|}/p

代码扩展

]]                   "Put [[]] onto stack. What we will do with this array of array is";
                     "that in each iteration below, we will first append the next";
                     "number to all present arrays, then copy all the arrays and";
                     "move the last element to first in the copy";
  l~                 "Read input number. Lets call it N";
    {         }/     "Run this code block N times ranging from 0 to N - 1";
     )f+             "Since the number on stack starts from 0, add 1 to it and append";
                     "it to all arrays in the array of array beginning with [[]]";
        _1fm>        "Copy the array of array and move last element from all arrays";
                     "to their beginning";
             |       "Take set union of the two arrays, thus joining them and eliminating";
                     "duplicates. Since we started with and empty array and started adding";
                     "numbers from 1 instead of 2, [1] would have appeared twice if we had";
                     "simply done a concat";
                p    "Print the array of arrays";

运作方式

这是代码的调试版本:

]]l~ed{)edf+ed_ed1fm>ed|ed}/edp

让我们看看它如何用于输入3

[[[]] 3]                                 "]]l~"            "Empty array of array and input";
[[[]] 1]                                 "{)"              "First iteration, increment 0";
[[[1]]]                                  "{)f+"            "Append it to all sub arrays";
[[[1]] [[1]]]                            "{)f+_"           "Copy the final array of array";
[[[1]] [[1]]]                            "{)f+_1fm>"       "shift last element of each";
                                                           "sub array to the beginning";
[[[1]]]                                  "{)f+_1fm>|}"     "Take set based union";
[[[1]] 2]                                "{)"              "2nd iteration. Repeat";
[[[1 2]]]                                "{)f+"
[[[1 2]] [[1 2]]]                        "{)f+_";
[[[1 2]] [[2 1]]]                        "{)f+_1fm>";
[[[1 2] [2 1]]]                          "{)f+_1fm>|}";
[[[1 2] [2 1]] 3]                        "{)";
[[[1 2 3] [2 1 3]]]                      "{)f+"
[[[1 2 3] [2 1 3]] [[1 2 3] [2 1 3]]]    "{)f+_";
[[[1 2 3] [2 1 3]] [[3 1 2] [3 2 1]]]    "{)f+_1fm>";
[[[1 2 3] [2 1 3] [3 1 2] [3 2 1]]]      "{)f+_1fm>|}";
[[[1 2 3] [2 1 3] [3 1 2] [3 2 1]]]      "{)f+_1fm>|}/";

在这里在线尝试


6

Haskell,47个字节

f 1=[[1]]
f n=(\x->map(++[n])x++map(n:)x)$f$n-1

1
切换到列表理解将节省一些字节:(f n=[[n:x,x++[n]]|x<-f$n-1]>>=id使用code-golfers concat函数>>=id)。
nimi 2015年

1
@nimi,但顺序错误r
骄傲的haskeller 2015年

@proudhaskeller:亲爱的,没有足够仔细地阅读规范。我试图对其进行修复,并发现了四种略有不同的方式,它们的长度与@alephalpha的版本相同,因此我无法提供改进。f n=[x++[n]|x<-f$n-1]++[n:x|x<-f$n-1]f n=map(++[n])(f$n-1)++[n:x|x<-f$n-1]f n=map(++[n])(f$n-1)++map(n:)(f$n-1)f n=(++[n])#n++(n:)#n;p#i=map p$f$i-1
NIMI

5

蟒蛇2,68

f=lambda n:[[1]]*(n<2)or[x*b+[n]+x*-b for b in[1,-1]for x in f(n-1)]

输出数字列表。

递归解决方案。对于n==1,输出[[1]]。否则,将其添加n到所有(n-1)排列的开头或结尾。前置使排列在字典上晚于附加,因此排列保持排序。

“布尔” b编码是放在[n]开头还是结尾。实际上,我们x在表达式中移动列表的其余部分x*b+[n]+x*-b。把b作为-11通过否定允许采用翻转,因为乘以一个列表-1是空列表。


4

珀斯,19岁

usCm,+dH+HdGr2hQ]]1

在这里在线尝试

这是一个完整的程序,需要从stdin输入。

这与xnor解决方案的工作方式相似,但是生成的值有些混乱,因此必须重新排序。在每个级别上发生的事情是,每个先前的值列表都将新值添加到末尾和开头,并且每个值都包裹在一个2元组中,并打包在一个列表中。例如,第一步是这样做的:

[[1]]
[([1,2], [2,1])]

然后,将此元组列表压缩(然后求和以删除最外面的列表)。在第一种情况下,这只是从上方给出未包装的值,因为列表中只有一个值。

显示2-> 3的步骤:

([1,2], [2,1])
[([1,2,3],[3,1,2]),([2,1,3],[3,2,1])]
([1,2,3],[2,1,3],[3,1,2],[3,2,1])

2

Mathematica,57 54 49字节

f@1={{1}};f@n_:=#@n/@f[n-1]&/@Append~Join~Prepend

例:

f[4]

{{1、2、3、4},{2、1、3、4},{3、1、2、4},{3、2、1、4},{4、1、2、3} ,{4,2,1,3},{4,3,1,2},{4,3,2,1}}


2

J,26个字节

   0|:<:((,,.,~)1+#)@[&0,.@1:

   (0|:<:((,,.,~)1+#)@[&0,.@1:) 3
1 2 3
2 1 3
3 1 2
3 2 1

得益于FUZxxl改进了1字节。


替换,.,"1一个字符。
FUZxxl 2015年

1

Pyth, 34 33 31 29

基本上是xnorPython答案的翻译。我对Pyth仍然不太满意,因此欢迎提出改进建议。

定义一个函数y以返回整数列表的列表。

L?]]1<b2smm++*kdb*k_dy-b1,1_1

更新:由于FryAmTheEggman而节省了2个字节。

说明:

L                                  define a function y with argument b that returns
 ?*]]1<b2                          [[1]] if b < 2 else
         s                         sum(
          m                        map(lambda d:
           m                       map(lambda k:
            ++*kdb*k_d             k*d + [b] + k*-d
                      y-b1         , y(b - 1))
                          ,1_1)    , (1, -1))

一些pyth的东西:-b1可以是tb[1_1)可以是,1_1(但是,您可以放下右括号,因为您只需要计算创建函数所需的字节数,即使您不关闭它也无法调用它),并且您不需要包装b列表,因为将列表添加到int时pyth会自动转换为列表。
FryAmTheEggman 2015年

我想出了一种方法,可以通过手动执行第二个映射来节省几个字节[1,-1]。我可以保存字节来对较短的内容进行硬编码,特别是在简化逻辑时。我知道了L?]]1<b2sCm,+db+bdytb
FryAmTheEggman 2015年

@FryAmTheEggman您可能实际上想将其添加为自己的答案。太棒了
PurkkaKoodari'3

好的,我想在发布之前尝试击败CJam,但我想邮编的技巧很有趣,值得推荐。佩思(Pyth)祝你好运;)
FryAmTheEggman 2015年

1

纯净重击,103

比我期望的更长:

a=1..1
for i in {2..9} {a..u};{
((++c<$1))||break
a={${a// /,}}
a=`eval echo $a$i $i$a`
}
echo ${a%%.*}

1

JavaScript(ES6)73 80

@Optimizer的漂亮解决方案的JavaScript实现。

递归(73):

R=(n,i=1,r=[[1]])=>++i>n?r:r.map(e=>r.push([i,...e])+e.push(i))&&R(n,i,r)

迭代(74):

F=n=>(i=>{for(r=[[1]];++i<=n;)r.map(e=>r.push([i,...e])+e.push(i))})(1)||r

测试在Firefox / FireBug控制台中

R(4)

[[1、2、3、4],[2、1、3、4],[3、1、2、4],[3、2、1、4],[4、1、2、3] ,[4、2、1、3],[4、3、1、2],[4、3、2、1]]


0

我的Java解决方案:

public static void main(String[] args) {
    listPrependAppend(4);
}

private static void listPrependAppend(int n) {
    int total = (int) Math.pow(2, n - 1);
    int ps;
    boolean append;
    String sequence;
    String pattern;

    for (int num = 0; num < total; num++) {
        sequence = "";
        pattern = "";
        append = false;
        ps = num;
        for (int pos = 1; pos < n + 1; pos++) {
            sequence = append ? (pos + sequence) : (sequence + pos);
            append = (ps & 0x01) == 0x01;
            ps = ps >> 1;
            if (pos < n) {
                pattern += append ? "L" : "R";
            }
        }
        System.out.format("%s\t[%s]%n", sequence, pattern);
    }
}

噢,天哪,现在看到其他答案之后,我明白了您对最短答案的意思。
布雷特·瑞安

2
尽管您的解决方案本身是受人尊敬的,简洁的且易于使用的,但您是正确的,它并不是解决当前问题的候选者。
Joe Z.

1
@BrettRyan您可以通过删除不必要的空格并使用一字符变量名称来使代码更短。您也可以替代false由类似5<4
ProgramFOX

1
谢谢你们。这是我第一次参加代码挑战。我只是在寻找一些编程挑战,却没有意识到目标是获得最短的解决方案。:)感谢您让我参加。
Brett Ryan
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.