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


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) - ціле число від одного до шести. Необхідна поведінка не визначена для входів за межами цього діапазону.
  • Діють правила кодового гольфу, найкоротші виграші програми.

Дякуємо "Артеміді Фолд" за відгуки під час фази пісочниці.


Я припускаю, що це дійсно, якщо при збої програми вона створює додаткові вихідні дані на додаток до друкованих кортежів, правда?
Луїс Мендо

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

Хаскелл , 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 за гольф

Прокручує всі х, і бере [1..x] ^ n. Це робить дублікати, тому зберігає лише ті, що є новими для цього x, він також містить x у них. Форматування трохи дивне, але його можна зробити стандартним ще одним байтом,.V1j}#b^Sb

.V1}#b^Sb

Спробуйте в Інтернеті .


1
f}bT-> }#bТакож здається, що кількість байтів наразі неправильна?
FryAmTheEggman

@FryAmTheEggman зачекайте, чому це неправильно? Якщо ви говорите про посилання TIO, що включає форматування за допомогою j(b). Також спасибі за гольф.
Малтісен

Ах, ось що мене бентежило, вибачте!
FryAmTheEggman

3

Брахілог (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.полімод (1,1,1), 1.полімод (2,2,2) і т.д. Таким чином, цифра завжди знаходиться в межах асортимент. Perl6 не дозволить мені безмежність модуля ...


5
Це не перераховує кожен кортеж точно один раз (наприклад, (0, 1, 0, 0)не вказаний).
bb94


2

C # (Visual C # Interactive Compiler) , 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, ймовірно, все-таки збереже мені багато байтів.
Стек

Найбільший трюк тут - рекурсія. Більшість методів, які я бачив для створення "перестановок", використовують його. Планую додати пояснення.
дата

Writeнаприклад, '<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
Виходячи з "до тих пір, поки розділення між кортежами та цифрами всередині кожного кортежа є чітким та послідовним. (Наприклад, один кортеж на рядок.) " Я припускав, що це не дозволено і потрібно, але давайте почекати, що має зробити ОП сказати.
Кевін Круїссен

1

05AB1E , 15 11 байт

[¼¾LIãvy¾å—

-4 байти, створивши порт відповіді @Maltysen 's Pyth .

Спробуйте в Інтернеті.

Пояснення:

[             # 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

Пітон 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 байт thx до 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
ArBo

Схоже, i+pце просто підрахунок 1, 2, 3 ... закрученим способом, і так може бути просто одна змінна.
xnor

@xnor: D'oh! Отоплений в концепції, не міг побачити ліс для дерев.
Час Браун

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

... о дорогий, я не впевнений, що цей код працює більше.
Стек

аааа, і це не так.
Стек

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.