Генерация набора перестановок и добавлений в лексикографически отсортированном порядке


14

Определите последовательность длины prepend-append,n которая будет перестановкой чисел, 1, 2, ..., nкоторые могут быть сгенерированы следующей процедурой:

  • Начните с номера 1.

  • Для каждого числа от 2до nпоместите этот номер в начало или конец последовательности (либо добавьте, либо добавьте его, отсюда и название последовательности).

Например, это допустимый способ генерации последовательности prepend-append длиной 4:

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

Ваша задача состоит в том, чтобы создать программу или функцию, которая будет принимать число nот как 3до 30входного, и печатать или возвращать все последовательности prepend-append длины 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.

Вы не можете использовать любые встроенные функции сортировки на вашем языке в вашем коде. Самая короткая программа для этого на любом языке выигрывает.


Я не фанат требования формата вывода, в частности, преобразования в буквы a-u. Можем ли мы просто вывести списки чисел?
xnor

3
Возможно, вы захотите принять ответ через некоторое время, поскольку некоторые люди, как правило, не отвечают на вопрос, если он имеет принятый ответ.
Оптимизатор

1
Таким образом, вы неправильно приняли ответ ..
Оптимизатор

2
FryAmTheEggman опубликовал свой ответ за 21 минуту до того, как вы отредактировали свой.
Джо З.

2
@ Оптимизатор Я не совсем думаю, что это самый странный путь - ответ FryAmTheEggman был длиной 19 байт за 21 минуту до того, как ваш. Это делает его самым коротким ответом.
Джо З.

Ответы:


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(с помощью функции concat code-golfers >>=id).
Nimi

1
@nimi, но в неправильном порядке
гордый haskeller

@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
Ними

5

Python 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как -1или 1позволяет использовать переворот путем отрицания, поскольку умноженный на список -1является пустым списком.


4

Пиф, 19

usCm,+dH+HdGr2hQ]]1

Попробуйте онлайн здесь

Это полная программа, которая принимает входные данные от стандартного ввода.

Это работает аналогично решению 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

1-байтовое улучшение благодаря FUZxxl .


Замена ,.для ,"1одного персонажа.
FUZxxl

1

Pyth, 34 33 31 29

В основном перевод ответа xnor на Python . Я все еще не очень хорошо разбираюсь в Pyth, поэтому предложения по улучшению приветствуются.

Определяет функцию yдля возврата списка списков целых чисел.

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

Обновление: сохранено 2 байта благодаря FryAmTheEggman .

Объяснение:

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переносить список, так как pyth автоматически конвертируется в список при добавлении списка в int.
FryAmTheEggman

Я придумал способ сохранить несколько байтов, вручную выполнив вторую карту [1,-1]. Я могу сохранить байты в жестком коде чего-то такого короткого, особенно когда вы упрощаете логику. Я получаюL?]]1<b2sCm,+db+bdytb
FryAmTheEggman

@FryAmTheEggman Возможно, вы захотите добавить это в качестве своего собственного ответа. Это просто потрясающе.
PurkkaKoodari

Хорошо, я хотел попробовать побить CJam перед публикацией, но я думаю, что трюк с zip достаточно интересен, чтобы его опубликовать. Удачи с Пифом;)
FryAmTheEggman


1

JavaScript (ES6) 73 80

Реализация JavaScript в прекрасном решении @ Optimizer.

Рекурсивный (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
Хотя ваше решение является респектабельным, лаконичным и хорошо изложенным само по себе, вы правы в том, что оно не совсем подходит для рассматриваемой проблемы.
Джо З.

1
@BrettRyan Вы можете сделать свой код намного короче, удалив ненужные пробелы и используя имена переменных, состоящие из одного символа. Вы также можете заменить falseчто-то вроде 5<4.
ProgramFOX

1
Спасибо ребята. Это была моя первая попытка участия в проблемах кода. Я просто искал некоторые проблемы с программированием и не понимал, что целью было найти самое короткое решение. :) Спасибо, что позволили мне принять участие.
Бретт Райан
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.