Б у я л і д е с т


30

Завдання проста: написати програму або функцію, яка, коли їй задано кінцеве невід'ємне ціле число, видає вкладений масив.

Правила

  • Ваш код повинен створювати унікальний дійсний вкладений масив для кожного цілого числа 0 ‌≤ n ‌ <2 31 .
  • Кожен можливий вкладений масив з до 16 відкритими дужками повинен виводитися в межах цього діапазону. (Це не означає, що ваш код ніколи не може вивести вкладений масив з більш ніж 16 відкритими дужками.)
  • Ваш код може виводити рядкове представлення вкладеного масиву замість фактичного масиву (із комами чи без).

Одне можливе відображення:

0 -> []
1 -> [[]]
2 -> [[[]]]
3 -> [[], []]
4 -> [[[[]]]]
5 -> [[[], []]]
6 -> [[[]], []]
7 -> [[], [[]]]
8 -> [[], [], []]
9 -> [[[[[]]]]]
etc.

Оцінка балів

Це , тому виграє найкоротший код у байтах.


Чи є обмеження в часі / пам’яті?
Денніс

@Dennis Чи 1 година здається розумною для обмеження часу? У мене немає поняття, що розумно для пам'яті.
ETHproductions

Пам’ять не є великою справою, якщо є обмеження в часі. Одна година здається дуже щедрою. Я не хотів би чекати повну годину, щоб перевірити, чи досить мій код.
Денніс

4
Я вважаю за краще обмеження часу. Це дає більше можливостей для оригінальності
Тон Євангелія,

2
@TonHospel Ви можете виводити без коми. Я думаю, що обмеження в часі не буде добре, доки ви зможете довести, що ваш запис дійсний.
ETHproductions

Відповіді:


12

Python 2.7, 172 149 124 118 байт

x=input();y="";z=0
for b in bin(x)[2+(x<1):]:y+="[]"[b<"1"];z+=b>"0"or-1;z+=99*(z<0)
print"["+(y,"[]"*(x+16))[z>0]+"]"

Пояснення:

Визначте біекцію за допомогою [1і ]0. Будь-яке розташування дужок може бути записане як двійкове число і навпаки, наприклад [][]1010(10) і [[][]]110100(52). Усі дійсні розташування до 15 відкритих дужок (всього 30 дужок) охоплені числами до 30 біт (ігноруючи провідні нулі), які є саме числами менше 2 31 .

Перший цикл for-циклу дає зворотну частину цього біекція, перетворюючи число в розташування дужок, перевіряючи, чи розташування дійсне.

Недійсні розташування замінюються в операторі друку довгими послідовностями дужок, щоб уникнути зіткнень. Наприклад 11(3) ↔ [[недійсний, тому ми об'єднуємо 3 + 16 дужок. Це гарантує, що всі домовленості є унікальними.

Отримане розташування розміщується всередині пари дужок для створення вкладеного масиву, так що 1010(10) стає [[][]]і 110100(52) стає [[[][]]]. Додаткова відкрита дужка означає, що ми тепер покрили всі масиви 16 відкритими дужками.


Наступна програма може бути використана для визначення числа для даного масиву з до 16 дужками.

s=raw_input();o="";
for c in s[1:-1]:
 if c=="[":o+="1"
 if c=="]":o+="0"
print int(o,2)


Це просто геній. Молодці. (І формат без комами дозволений.)
ETHproductions

12

Python, 153 128 байт

s=l=0;r="";n=input()
for d in bin(n)[2:]*(n>0):c=d<"1";l=[l,s>1][c];r+="]"*c+(1-l*c)*"[";s+=1-c-l*c
print"["+r+"["*l+"]"*(s+l+1)

Ми відображаємо число n до вкладеного списку, дивлячись на його двійкові цифри зліва направо. Цей алгоритм працює для будь-якого числа, а не лише під 2 32 .

  1. Якщо поточна двійкова цифра дорівнює 1, виведіть [.
  2. В іншому випадку, якщо послідовність дужок, яку ми вивели до цього часу, буде врівноважена однією дужкою, що закривається, вивести ][.
  3. В іншому випадку, якщо це останній 0 у двійковому номері, виведіть ][.
  4. В іншому випадку виведіть ].

Нарешті, ми закриваємо будь-які відкриті дужки.


5

Ложка , 63 байти (501 біт)

000001001001001011001101001010011011111001010001000000101010
101101100110100101101001000101100010001000000100011000010000
000000000000001110111110010000001110110110010100100100100100
000110011010001000000110110000010000001010110011011011011001
000000011010010010010001000000111011011011101001001001000110
110110010100100101011001000100000011010001000000111011011001
010010010010010001101101101001000110110010110001101101101101
100100010001010010001010011011001000000011001101001001010010
000001100101001000111

Це наступна програма для мозкових переходів, перетворена на ложку:

-[+[+<]>>+]<+++.[->+>+<<]>>++>>,[>-[<->-----]+<+++[-<+<<.>>>>-<]>[-<<-[->+<]<<<[-]>>>>[-<+<<<+>>>>]<<.>>+<[>-]>[-<+<<.>>>>]<<>>]<,]<<<<[>.>.<<[-]]>>>+[-<.>]+

Читає ціле число у двійковій формі на stdin та виводить вкладений список на stdin. Потрібно вводити 0 як порожній рядок (без цифр), і потрібен перекладач мозкових записів з 8-бітовими комірками. Той самий алгоритм, що і моя відповідь Python.

Читаема версія:

-[+[+<]>>+]<+++.           push open bracket and print it
[->+>+<<]                  dup
>>++                       increment to close bracket

>>,[                       read input loop
    >-[<->-----]+<+++          subtract 48 and set up if/else
    [-                         if c == 1
        <+                         increment s
        <<.>>>                     output open bracket
    >-<]>[-<                   else
        <-[->+<]                   decrement and move s
        <<<[-]                     zero l
        >>>>[-<+<<<+>>>>]          l = s and restore s
        <<.>                       output close bracket
        >+<[>-]>[-                 if s == 0
            <+                         undo s decrement
            <<.                        output open bracket
        >>>>]<<
    >>]<
,]

<<<<[                      if l
    >.>.                   output pair
<<[-]]
>>>+[-<.>]                 output close bracket s+1 times

3
Нещодавно ми обговорювали цю дискусію з іншою відповіддю, і, здається, немає фактичного інтрепретератора, який би міг обробити 63-байтовий файл. Реалізація посилання використовувала байти 0x30 та 0x31, тому для цього відповіді знадобиться файл 501 байт .
Денніс


5

Perl, 80 79 байт

Знову використовується алгоритм orlp , але цього разу я вперше перевірив, чи працює він ...

Включає +1 для -p

Дайте вхідний номер на STDIN

nest.pl <<< 8

nest.pl:

#!/usr/bin/perl -p
($_=sprintf"%b",$_).=2x(s^.^$&or++$n-pos&&/.0/g?++$n%1:$`&&21^eg-$n);y;102;();

Рішення Лінуса становить 64 байти в perl:

#!/usr/bin/perl -p
$_=sprintf"%b",/.+/g;$_=10x($&&&$&+16)if!/^(1(?1)*0)+$/;y;10;()

Рішення Денніса становить 59 байт в perl (все повільніше для великої кількості):

#!/usr/bin/perl -p
1while$_-=(sprintf"%b",$n++)=~/^(1(?1)*0)+$/;$_=$&;y;10;()

Я відчуваю, що ви повинні оцінити це як 65 байт (чи не насправді це 64)?
Лінус

1
@Linus У той час як ваші правила ухилення є геніальними і заслуговують на всі оновлення, я вважаю це чимось обманом. Для зарахування балів -pзараховується 1 додатковий байт
Тон Євангелія,

5

Python 3, 120 114 байт

def f(n,k=0):
 while~n:
  k+=1
  try:r=eval(bin(k).translate({48:'],',49:'['})[3:-1])+[];n-=1
  except:0
 print(r)

Перевірте це на Ideone .

Як це працює

Визначена функція f приймає вхід n та ініціалізує k до 0 . Ми будемо тримати збільшення k до тих пір, поки n + 1 значення k не приведуть до дійсного результату. Кожного разу, коли ми знаходимо таке значення k , n зменшується, коли воно досягає -1 , ~nвиходить 0 , і друкується список r, що відповідає останньому значенню k .

Часткове відображення від додатних цілих чисел до вкладених списків (тобто k ↦ r ) повинно бути бієктивним, але інших обмежень немає. Той, що використовується у цій відповіді, діє наступним чином.

  1. Перетворіть k у двійкове подання рядка, починаючи з 0b .

    Наприклад, 44 ↦ "0b101100" .

  2. Замініть всі 0 's (кодова точка 48 ) у поданні рядка рядком "]," та всі 1 ' (кодова точка 49 ) на [ .

    Наприклад, "0b101100" ↦ "], b [], [[],]," .

  3. Видаліть перші три символи (вони відповідають "0b" ) та контурний знак (сподіваємось, кома).

    Наприклад, "], b [], [[],]," ↦ "[], [[],]" .

  4. Спробуйте оцінити створений код. Якщо це призведе до помилки, k не відображається в жодному списку.

    Наприклад, "[], [[],]" ↦ ([], [[]]) .

  5. Об'єднайте результат (якщо такий є) з порожнім списком. Якщо це призведе до помилки, k не відображається в жодному списку.

    Наприклад, помилки ([], [[]]) + [], оскільки + не можуть об'єднати списки та кортежі.


4

Haskell, 71 байт

p 1=["[]"]
p n=['[':h++t|k<-[1..n-1],h<-p k,_:t<-p$n-k]
((p=<<[1..])!!)

Основна функція в останньому рядку індексує список усіх вкладених масивів, відсортованих за розмірами (кількість відкритих дужок). Отже, усі масиви розміром не більше 16 перераховані першими.

Давайте спочатку розглянемо код, який є приємнішим і коротшим, але вимикач Хаскелла відмовляється приймати.

p 1=[[]]
p n=[h:t|k<-[1..n-1],h<-p k,t<-p$n-k]
((p=<<[1..])!!)

Функція pна вході nдає список усіх вкладених масивів розміру n(відкриті дужки). Це робиться рекурсивно. Кожен такий масив складається з певного розміру головки h(перший член) і розміру kхвоста t(інші члени) розміру n-k, обидва розміри не нульові. Або це порожній масив за розміром n==1.

Потім вираз p=<<[1..]сплющується p(1), p(2), ...в єдиний нескінченний список всіх масивів, відсортованих за розміром

[ [], [[]], [[],[]], [[[]]], [[],[],[]], [[],[[]]], [[[]],[]], [[[],[]]], ...

і основні функції вказує на нього.

... Або так, якби Хаскелл не скуголив про "побудову [ing] нескінченного типу: t ~ [t]". Haskell не може представляти нескінченний список, елементи якого є довільно вкладеними масивами. Усі його елементи повинні мати один і той же тип, але тип t не може бути таким самим, як список t. Насправді, самій функції pне може бути призначений послідовний тип без залежного введення, чого не вистачає Haskell.

Отже, замість цього ми працюємо над рядками дужок, імітуючи роботу проти мінусів, діючи на символи [та ]символи. Це займає додаткові 9 байт. Небезпека гольфу на безпечній мові.


3

Haskell, 87 82 байти

0#0=[""]
n#m=['[':x|n>0,x<-(n-1)#m]++[']':x|n<m,x<-n#(m-1)]
(([0..]>>= \y->y#y)!!)

Виводить елементи масиву. Приклад використання: (([0..]>>= \y->y#y)!!) 3-> "[][]".

Функція #будує всі вкладені масиви як рядки для nвідкритих і mзакритих дужок, відстежуючи, скільки з них залишилося. Завжди починається з n == m. Основна функція викликає y # yкожного y <- [0,1,...]і вибирає елемент у індексі, заданому входом.


2

MATL , 31 байт

O`@BEqXJYs0&)0>w~hA+tG>~]x92J-c

Спробуйте в Інтернеті! Або перевірте перші кілька тестових випадків (займає кілька секунд).

Вироблене відображення:

0 -> []
1 -> [[]]
2 -> [[][]]
3 -> [[[]]]
4 -> [[][][]]
5 -> [[][[]]]
6 -> [[[]][]]
7 -> [[[][]]]
...

Пояснення

Код продовжує тестувати збільшення двійкових чисел, цифру 0замінюють на -1; тобто використовуючи 1і -1як цифри. Цифра 1буде представляти '['і -1представлятиме ']'.

Програма рахується, поки не буде отримано n +1 дійсних чисел. Число дійсне, якщо дотримуються наступні дві умови:

  1. Сума цифр дорівнює нулю (тобто є рівна кількість 1і -1)
  2. Сукупна сума цифр завжди позитивна (тобто накопичена кількість 1цифр завжди перевищує кількість -1), за винятком кінця (де умова 1 дорівнює нулю).

Після отримання n +1 дійсних чисел останнє транслітерується шляхом зміни 1в [і -1в ], а потім відображається.

Код:

O          % Push 0: initial count of valid numbers
`          % Do...while
  @        %   Push iteretation index k, starting at 1
  B        %   Convert to binary. For example, k=6 gives [1 1 0 0]
  Eq       %   Multiply by 2, subtract 1: transforms [1 1 0 0] into [1 1 -1 -1]
  XJ       %   Copy that to clipboard J, without popping it
  Ys       %   Cumulative sum: gives [1 2 1 0]
  0&)      %   Split array into its final element and the rest. Gives 0, [1 2 1]
  0>       %   Yields 1 for positive entries (condition 2). So in this case it
           %   gives [1 1 1]
  w        %   Swap: moves second-top element in the stack (0 in this case) to top
  ~        %   Negate: yields 1 if input is 0 (condition 1). Gives 1 in this case
  h        %   Concatenate horizontally. Gives [1 1 1 1]
  A        %   All: gives 1 if all elements are 1. Gives 1 in this case, meaning
           %   that this k is valid
  +        %   Add the result (0 or 1) to the count of valid numbers
  t        %   Duplicate
  G        %   Push input n
  >~       %   Loop condition: false (exit loop) if count exceeds input n
]          % End loop. At this point the result is in clipboard J, in 1/-1 format
x          % Delete count
92         % Push 92. Will be used to convert 1, -1 to '[', ']' (ASCII 91, 93)
J          % Push result in 1/-1 format
-          % Subtract: converts 1 to 91, -1 to 93
c          % Convert to char. Implicitly display
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.