Список * всех * кортежей!


35

Напишите программу с заданным значением n , которая сгенерирует все возможные n-кортежи, используя натуральные числа.

n=1
(1),(2),(3),(4),(5),(6)...

n=2
(1,1),(1,2),(2,1),(2,2),(1,3),(3,1),(2,3),(3,2),(3,3)...

n=6
(1,1,1,1,1,1) (1,1,1,1,2,1) (1,1,1,2,1,1)... 
  • Вывод может быть в любом порядке, который не нарушает никаких других правил.
  • Программа должна быть написана так, чтобы она работала вечно и теоретически перечисляла все соответствующие кортежи ровно один раз.
    • В действительности ваша программа достигнет предела целочисленного типа и вылетит. Это приемлемо, если программа будет работать бесконечно долго, если только ваш целочисленный тип будет неограниченным.
    • Каждый допустимый кортеж должен быть указан в течение конечного времени, если только программе разрешено запускаться так долго.
  • Вывод может, по вашему выбору, включать нули в дополнение к натуральным числам.
  • Вы можете выбрать формат вывода вашей программы для вашего удобства, если разделение между кортежами и числами внутри каждого кортежа является четким и последовательным. (Например, один кортеж на строку.)
  • Ввод (n) является целым числом от одного до шести. Требуемое поведение не определено для входов за пределами этого диапазона.
  • Применяются правила Code-golf, выигрывает самая короткая программа.

Спасибо "Artemis Fowl" за отзывы на этапе песочницы.


Я предполагаю, что это действительно, если при сбое программы она выдает какой-то посторонний вывод в дополнение к напечатанным на данный момент кортежам, верно?
— Луис Мендо

1
Должны ли мы выводить данные по ходу или будет достаточной функция, которая в конце времени выдаст бесконечный список?
— Джонатан Аллан

6
«Вы можете выбрать выходной формат вашей программы для вашего удобства, если разделение между кортежами и числами внутри каждого кортежа является четким и последовательным» - можем ли мы вывести различное (хотя и последовательно различающееся) разделение (например, вот так )?
— Джонатан Аллан

@JonathanAllan Я должен был бы включить вывод бесконечного содержимого этого объекта как часть программы.
— billpg

1
Связанный (целые числа вместо натуральных чисел)
— Esolanging Fruit

Ответы:


24

Шелуха , 2 байта

πN

Попробуйте онлайн!

объяснение

Nэто бесконечный список натуральных чисел [1,2,3,4,... πэто декартова сила. Результатом является бесконечный список списков. Каждый список желаемой длины встречается ровно один раз, потому что πэто круто. Ввод и вывод неявные.


1
Вау, и это тоже не подходит [1,1, n]. Есть ли шаблон порядка, который он выводит?
— billpg

1
@billpg Он рекурсивно строит кортежи: n- кортежи получают, беря декартово произведение исходного списка и списка n-1кортежей в порядке возрастания суммы индексов.
— Згарб

«В порядке возрастания суммы индексов» - Вы можете это уточнить? Мне трудно понять, почему, например, 2,2,2приходит после 4,1,2и 5,1,1.
— Иона

2
@Jonah Рекурсия работает так. Вы начинаете с 1-го кортежа N. Для 2-х кортежей берется декартово произведение с Nупорядоченным по сумме показателями. В обоих списках каждое число nимеет индекс, nпоэтому для длины 2 результат упорядочивается по сумме. Для получения 3-кортежей вы берете декартово произведение Nи список 2-кортежей, упорядоченный по сумме индексов элементов в этих списках. Он не смотрит на сумму кортежа, он смотрит на свою позицию в списке кортежей.
— Згарб

2
«Выясните различные измерения бесконечности в этой задаче и найдите шаблон, который сводит его к счетной бесконечности, а затем напишите программу, которая выполняет итерацию по этому шаблону». - "Эй, у меня есть встроенный для этого!"
— Фабиан Релинг

10

Haskell , 62 байта

([1..]>>=).(!)
0!s=[[]|s<1]
n!s=[a:p|a<-[1..s],p<-(n-1)!(s-a)]

Попробуйте онлайн!

n!sгенерирует все nкортежи, которые суммируются с s.

Тогда ответ ([1..]>>=).(!), то есть \n -> [t | s<-[1..], t<-n!s].

Это функция, отображающая целое число nв бесконечный ленивый список кортежей (списков целых чисел).


5

Haskell , 50 байтов

f n=[l|k<-[0..],l<-mapM([0..k]<$f)[0..n],sum l==k]

Попробуйте онлайн!

Списки- nкортежи отсортированы по сумме. mapMвыполняет тяжелую работу для генерации всех nнаборов чисел от 0 до k. <$fТрюк объясняется здесь .

Haskell , 51 байт

f 1=pure<$>[0..]
f n=[a-k:k:t|a:t<-f$n-1,k<-[0..a]]

Попробуйте онлайн!

Рекурсивно растягивает все n-1кортежи на все nкортежи, разбивая первое число aкаждого n-1кортежа на два числа, a-k,kкоторые суммируются с ним всеми возможными способами.


4

Pyth - 9 байт

Спасибо @FryAmTheEggman за гольф

Перебирает все x и принимает [1..x] ^ n. Это делает дубликаты, поэтому сохраняются только те, которые являются новыми для этого x, то есть содержат в них x. Форматирование немного странное, но его можно сделать стандартным с помощью еще одного байта,.V1j}#b^Sb

.V1}#b^Sb

Попробуйте онлайн .


1
f}bT-> }#bКроме того, ваш счетчик байтов сейчас кажется неверным?
— FryAmTheEggman

@FryAmTheEggman подожди, почему это неправильно? Если вы говорите о ссылке TIO, это включает форматирование с помощью j(b). Также спасибо за гольф.
— Maltysen

Ах, вот что меня смутило, извините!
— FryAmTheEggman

3

Brachylog (v2), 9 байт

~l.ℕᵐ+≜∧≜

Попробуйте онлайн!

Это бесконечный генератор, который генерирует все возможные кортежи. Ссылка TIO имеет заголовок, который использует генератор, чтобы сгенерировать 1000 элементов и распечатать их (но генератор мог бы работать бесконечно, если бы я попросил об этом; целые числа Брахилога не ограничены).

Такое ощущение, что должен быть более краткий путь, но есть много ограничений, и это самое короткое, что я могу вписать их в одну программу.

объяснение

~l.ℕᵐ+≜∧≜
  .        Generate
        ≜  all explicit
~l         lists whose length is {the input}
    ᵐ      for which every element
   ℕ       is non-negative
     +     and whose sum
      ≜    is used to order the lists (closest to zero first)
       ∧   [remove unwanted implicit constraint]

Между прочим, меня удивляет, насколько разные мои объяснения двух ≜, несмотря на то, что они делают одно и то же с точки зрения Брахилога. Первый≜ - это первый недетерминированный предикат в программе, поэтому он устанавливает порядок результатов; в этом случае он вычисляет все возможные явные значения для суммы списка в порядке 0, 1, 2, 3… и используется для обеспечения вывода списков в порядке их суммы (это гарантирует, что каждое возможное список появляется после конечного количества вывода). Второй ≜используется для вычисления всех явных возможностей для списка (вместо вывода формулы, определяющей, как элементы списка связаны друг с другом).


↰₁ẉ⊥также хороший заголовок, для печати бесконечно.
— Несвязанная строка

Хотя я чувствую, что на самом деле это может быть не полный ответ, так как любой отдельный независимый вызов этого предиката будет просто генерировать нули , а часть «сгенерировать все» выполняется заголовком ᶠили ⊥в заголовке.
— Несвязанная строка

1
@UnrelatedString Ваш код, тем не менее, не использует предикат в качестве генератора. У нас есть явные правила, разрешающие вывод списка с использованием генератора . То, что вы делаете в своей ссылке TIO, - это вызов предиката в цикле для получения 1000 различных генераторов, а затем получение первого вывода от каждого из них; это действительно неестественная операция для генераторов, и она не позволит вам увидеть другие элементы, которые они могут генерировать.
— ais523

Ах, так что я только что неверно истолковал семантику того, что такое предикат брахилога - все это время - моя идея «генератора» застряла на Python. Теперь, когда это прямо у меня в голове, я думаю, я пойду побриться на три байта от некоторых моих старых ответов.
— Несвязанная строка

2

Perl 6 , 37 байт

{$++.polymod(1+$++ xx $_-1).say xx *}

Попробуйте онлайн!

По сути, выполняется polymodс таким количеством записей, сколько необходимо, где модуль всегда больше, чем вход, т. Е. 0.polymod (1,1,1), 1.polymod (2,2,2) и т. Д. Таким образом, цифра всегда находится в пределах диапазон. Perl6 не позволит мне по модулю бесконечности ...


5
Это не перечисляет каждый кортеж ровно один раз (например, (0, 1, 0, 0)не указан).
— BB94


2

C # (интерактивный компилятор Visual C #) , 148 байт

n=>{var a=new int[n];int j=0;void g(int k){if(k<n)for(int i=0;i++<j;g(k+1))a[k]=i;else if(a.Sum()==j)WriteLine(string.Join(' ',a));}for(;;j++)g(0);}

Попробуйте онлайн!

-3 байта благодаря @ASCIIOnly!

// n: size of tuples to generate
n=>{
  // a: current tuple workspace
  var a=new int[n];
  // j: target sum value
  int j=0;
  // recursive function that works on slot k
  void g(int k){

    // tuple is not fully generated,
    if(k<n)

      // try all values from (0,j]
      for(int i=0;i++<j;
        // recursive call - generates all
        // values from (0,j] in the next slot
        g(k+1)
      )
        // update the kth slot
        a[k]=i;

    // tuple is fully generated, however
    // we should only display if the sum
    // is equal to the target sum. tuples
    // are generated many times, this
    // let's us enforce that they are only
    // displayed once.
    else if(a.Sum()==j)
      WriteLine(string.Join(' ',a));
  }
  // increment the high value forever
  // while continually starting the
  // recursive function at slot 0
  for(;;j++)
    g(0);
}

как ты вообще это сделал
— Stackstuck

прямой перенос этого на .NET Core, вероятно, все равно сэкономит мне много байтов.
— Stackstuck

Самый большой трюк здесь - рекурсия. Большинство техник, которые я видел, чтобы генерировать «перестановки», используют его. Я планирую добавить объяснение.
— Дана

Writeс eg '<literal tab>'или |имеет одинаковую длину и занимает намного меньше строк: P
— только ASCII


1

Желе , 10 (9?) Байтов

9 если мы можем вывести с использованием непоследовательного разделения (о котором я спрашивал) - удаление €.

‘ɼṗ³ċƇ®Ṅ€ß

Попробуйте онлайн!

Как?

‘ɼṗ³ċƇ®Ṅ€ß - Main Link: some argument, x (initially equal to n, but unused)
 ɼ         - recall v from the register (initially 0), then set register to, and yield, f(v)
‘          -   f = increment
           - (i.e. v=v+1)
   ³       - program's third command line argument (1st program argument) = n
  ṗ        - (implicit range of [1..v]) Cartesian power (n)
           - (i.e. all tuples of length n with items in [1..v])
     Ƈ     - filter keep those for which:
    ċ      -   count
      ®    -   recall from register
           - (i.e. keep only those containing v)
       Ṅ€  - print €ach
         ß - call this Link with the same arity
           - (i.e. call Main(theFilteredList), again the argument is not actually used)

1
Основываясь на « пока разделение между кортежами и числами внутри каждого кортежа является четким и непротиворечивым. (Например, один кортеж на строку.) » Я предположил, что это не разрешено и €требуется, но давайте подождем, что OP должен сказать.
— Кевин Круйссен

1

05AB1E , 15 11 байт

[¼¾LIãvy¾å—

-4 байт путем создания порта @Maltysen Pyth ответа «s .

Попробуйте онлайн.

Объяснение:

[             # Start an infinite loop:
 ¼            #  Increase the counter_variable by 1 (0 by default)
  ¾L          #  Create a list in the range [1, counter_variable]
    Iã        #  Take the cartesian power of this list with the input
      v       #  Loop over each list `y` in this list of lists:
       y¾å    #   If list `y` contains the counter_variable:
          —   #    Print list `y` with trailing newline

2
Когда программа доберется до [1,2,1]? Помните, это должно быть в течение конечного времени.
— billpg

@billpg Должно быть исправлено сейчас.
— Кевин Круйссен


1

Python 2 , 126 112 106 101 100 83 байта

n=input()
i=1
while 1:
 b=map(len,bin(i)[3:].split('0'));i+=1
 if len(b)==n:print b

Попробуйте онлайн!

5 байтов спасибо mypetlion ; 1 байт от орлиного глаза АрБо ; 17 байт из xnor !

Построить заказанные перегородки m в nбункеры, m = 0,1,2,3,...выбрав для двоичных чисел с n-1 0s и m 1s.


if i==p:i=0;p*=2может стать i%=p;p<<=i<1экономить 5 байт.
— Mypetlion

Я почти уверен, что место после print bне нужно: D
— АрБо

Похоже, что i+pпросто подсчитывает 1, 2, 3 ... в запутанном виде и может быть просто одной переменной.
— xnor

@xnor: Д'Ох! Я был настолько погружен в концепцию, что не мог видеть лес за деревьями.
— Час Браун

1

C # (.NET Core) , 608 570 567 байт

using C=System.Console;using L=System.Collections.Generic.List<int[]>;class A{static void Main(){L x=new L(),y=new L(),z=new L();int i=int.Parse(C.ReadLine()),j=0,k,l,m;x.Add(new int[i]);while(i>0){j++;for(m=0;m++<i;){foreach(var a in y)x.Add(a);y=new L();foreach(var a in x){for(k=0;k<i;){int[] t=new int[i];System.Array.Copy(a,t,i);t[k++]=j;var b=true;z.AddRange(x);z.AddRange(y);foreach(var c in z){for(l=0;l<i;l++)if(c[l]!=t[l])break;if(l==i)b=false;}if(b)y.Add(t);}}}}for(k=0;k<x.Count;k++){C.Write("[ ");for(l=0;l<i;l++)C.Write(x[k][l]+" ");C.WriteLine("]");}}}

Попробуйте онлайн!

Боже мой, что я сделал (так много петель, это то, что я сделал)

Это должно работать, хотя!

Если вы переместите цикл печати на одну скобку назад, он будет показывать вам список в том виде, в котором он был создан, каждый раз, когда он повторяется. (Я рекомендую добавить новую строку или что-то, чтобы отличить каждый цикл, если вы делаете.)

Честно много я потратил времени на борьбу с языком ... никаких красивых печатных массивов, различного поведения == ...

Надеюсь, эту версию легче читать.

using C=System.Console;
using L=System.Collections.Generic.List<int[]>;
class A{
    static void Main(){
        L x=new L(),y=new L(),z=new L();
        int i=int.Parse(C.ReadLine()),j=0,k,l,m;
        x.Add(new int[i]);
        while(i>0){
            j++;
            for(m=0;m++<i;){
                foreach(var a in y) x.Add(a);
                y=new L();
                foreach(var a in x){
                    for(k=0;k<i;){
                        int[] t=new int[i];
                        System.Array.Copy(a,t,i);
                        t[k++]=j;
                        var b=true;
                        z.AddRange(x);
                        z.AddRange(y);
                        foreach(var c in z){
                            for(l=0;l<i;l++) if(c[l]!=t[l])break;
                            if(l==i)b=false;
                        }
                        if(b)y.Add(t);
                    }
                }
            }
        }
        for(k=0;k<x.Count;k++){
            C.Write("[ ");
            for(l=0;l<i;l++)C.Write(x[k][l]+" ");
            C.WriteLine("]");
        }
    }
}

Я только что понял, что могу вставить цикл печати в оператор if, чтобы он печатался по ходу дела. лицевой импульс один момент.
— Stackstuck

подождите, нет, не могу этого сделать
— Stackstuck

... о боже, я не уверен, что этот код работает больше.
— Stackstuck

ааааа и нет
— Stackstuck

1
Удачи в этом :) Я начал кодировать решение в C # и понял, что это немного сложнее, чем я надеялся. Почему бы не использовать интерпретатор Visual C # Interactive? Это сэкономит кучу, просто не добавляя определение класса. В любом случае +1 от меня :)
— Дана

1

Perl 6 , 50 байт

{grep $_,{S/.//.split(0)>>.chars}($++.base(2))xx*}

Попробуйте онлайн!

Блок анонимного кода, который возвращает ленивый бесконечный список. Это использует ту же стратегию, что и ответ Чаза Брауна .

Объяснение:

{grep $_,{S/.//.split(0)>>.chars}($++.base(2))xx*}
{                                                } # Anonymous code block
                                              xx*  # Repeat indefinitely
                                 ($++        )     # From the current index
                                     .base(2)      # Get the binary form
         {S/.//                 }   # Remove the first digit
               .split(0)            # And split by zeroes
                        >>.chars    # And get the length of each section
 grep   ,   # From this infinite list, filter:
      $_      # The groups with length the same as the input

0

VDM-SL , 51 байт

g(i)==if i=0then{}else{[x]^y|x:nat,y in set g(i-1)}

Понимание рекурсивных множеств с конкатенацией последовательностей.

Не на TIO, вы можете запустить в программе (если вы включите ограничения для типа nat или он не завершится):

functions 
g:nat->set of ?
g(i)==if i=0then{}else{[x]^y|x:nat,y in set g(i-1)}

Включает необязательные 0 в ответ, иначе это будет 52 байта привязки на nat1



0

perl -M5.010 122 байта

$n=shift;
$s.="for\$x$_(1..\$m){"for 1..$n;
$t.="\$x$_ "for 1..$n;
$u.='}'x$n;
eval"{\$m++;$s\$_=qq' $t';/ \$m /&&say$u;redo}"

Добавлено несколько новых строк для удобства чтения (не учитывается при подсчете байтов)


0

Python 2 , 120 байт

from random import*
m=n=input()
a=()
while 1:
 m+=len(a)==m**n;t=[randint(1,m)for _ in[1]*n]
 if(t in a)<1:a+=t,;print t

Попробуйте онлайн!

Чуть дольше, чем большинство других ответов, но мне понравилась идея, стоящая за этим.



0

JavaScript (V8) , 98 байт

n=>{for(a=[],b=[j=1];;b.push(++j))(g=k=>k<n?b.map(i=>(a[k]=i)|g(k+1)):a.includes(j)&&print(a))(0)}

Попробуйте онлайн!

Ура! Наконец получил его под 100 :) В основном это порт моего ответа C # .

// n: length of tuples to generate
n=>{
  // a: workspace for current tuple
  // b: range of numbers that grows
  //     - iteration 1: [1]
  //     - iteration 2: [1,2]
  //     - iteration 3: [1,2,3]
  // j: largest number in b
  for(a=[],b=[j=1];;b.push(++j))
    // g: recursive function to build tuples
    // k: index of slot for current recursive call
    (g=k=>
       // current slot less than the tuple size? 
       k<n?
         // tuple generation not complete
         // try all values in current slot and
         // recurse to the next slot
         b.map(i=>(a[k]=i)|g(k+1)):
         // tuple generation complete
         // print tuple if it contains the
         // current high value
         a.includes(j)&&print(a)
    // start recursive function at slot 0
    )(0)
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.