ABAA / ABBB: Створіть цей рекурсивний 2D шаблон


30

Я плутався з нескінченними резисторними мережами (довга історія), коли зіткнувся з такою цікавою рекурсивною схемою:

|-||
|---

Кожен екземпляр цього шаблону вдвічі ширший, ніж високий. Щоб перейти від одного рівня шаблону до іншого, ви розділите цей прямокутник на два підблоки (кожен з яких - квадрат NxN):

AB =
|-||
|---

so A = 
|-
|-

and B = 
||
--

Потім ці половинки дублюються та переставляються відповідно до наступної схеми:

ABAA
ABBB

giving

|-|||-|-
|---|-|-
|-||||||
|-------

Виклик

Напишіть програму / функцію, яка, задавши число N, виводить Nітерацію цієї рекурсивної конструкції. Це гольф.

Формат вводу / виводу є порівняно м'яким: ви можете повернути один рядок, список рядків, двовимірний масив символів тощо. Дозволено довільний пробіл пробілів. Ви також можете використовувати індексацію 0 або 1.

Приклади

Перші кілька ітерацій шаблону наступні:

N = 0
|-

N = 1
|-||
|---

N = 2
|-|||-|-
|---|-|-
|-||||||
|-------

N = 3
|-|||-|-|-|||-||
|---|-|-|---|---
|-|||||||-|||-||
|-------|---|---
|-|||-|-|-|-|-|-
|---|-|-|-|-|-|-
|-||||||||||||||
|---------------

N = 4
|-|||-|-|-|||-|||-|||-|-|-|||-|-
|---|-|-|---|---|---|-|-|---|-|-
|-|||||||-|||-|||-|||||||-||||||
|-------|---|---|-------|-------
|-|||-|-|-|-|-|-|-|||-|-|-|||-|-
|---|-|-|-|-|-|-|---|-|-|---|-|-
|-|||||||||||||||-|||||||-||||||
|---------------|-------|-------
|-|||-|-|-|||-|||-|||-|||-|||-||
|---|-|-|---|---|---|---|---|---
|-|||||||-|||-|||-|||-|||-|||-||
|-------|---|---|---|---|---|---
|-|||-|-|-|-|-|-|-|-|-|-|-|-|-|-
|---|-|-|-|-|-|-|-|-|-|-|-|-|-|-
|-||||||||||||||||||||||||||||||
|-------------------------------

Цікаво, чи існує якийсь короткий алгебраїчний спосіб обчислити цю структуру.


Що ви маєте на увазі під "алгебраїкою"?
користувач202729

4
@ user202729 Можливо, можливо, є якась "проста" математична формула, f(n,x,y)яка може безпосередньо обчислити, чи повинна містити дана координата -або |. Це може включати модульні операції або бітові операції. До цих пір усі методи, які я бачив, включають різання / з'єднання масивів, як показано у специфікації.
PhiNotPi

3
f(x,y)також працює, оскільки якщо x,yце дійсно, результат не залежить відn
amara

2
Чи може висновок бути 1-індексованим, тобто давати вхід 1 |-?
Згарб

2
Це втрата? 🤔
qwr

Відповіді:


13

APL (Dyalog Classic) , 29 25 байт

'|-'[{a,⊖⌽⍉~a←⍪⍨⍵}⍣⎕⍉⍪⍳2]

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

⍳2 - вектор 0 1

перетворює його в матрицю 2x1

транспортує його, тому він стає 1x2

оцінений вхід

{ }⍣⎕ застосувати функцію, яка багато разів

⍪⍨⍵ об'єднати аргумент поверх себе - матриця 2x2

a← запам'ятати як a

~ заперечувати

переносити

повернути горизонтально

назад вертикально

a,з’єднатися з aліворуч

'|-'[ ]використовувати матрицю як індекси в рядку '|-', тобто перетворити 0 в |і 1 в-


10

JavaScript (Node.js) , 130 ... 106 94 92 байт

Гольф від мого альтернативного методу та виправлення символів, -14 байт Спасибі @Shaggy

f=n=>n?f(n-1).replace(/.+/g,x=>(g=i=>x.replace(/./g,p=>p<i?s[i]+s[i]:s))`0`+`
`+g`1`):s="|-"

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

Мій оригінальний підхід ( 106 102 байт)

f=n=>n?[0,1].map(j=>f(n-1).split`
`.map(x=>x+x.substr((i=x.length/2)*j,i).repeat(2)).join`
`).join`
`:"|-"

-4 байти Спасибі @Shaggy

f=n=>n?[0,1].map(j=>f(n-1).split`
`.map(x=>x+(y=x.substr((i=x.length/2)*j,i))+y).join`
`).join`
`:"|-"

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

Пояснення та незахищеність:

function f(n) {                     // Main Function
 if (n != 0) {                      //  If n != 0: (i.e. not the base case)
  return [0, 1].map(                //   Separate the pattern into 2 parts
  function(j) {                     //   For each part:
   return f(n - 1).split("\n")      //    Split the next depth into lines
    .map(function(x) {              //    For each line in the result:
    return x                        //     The common part: "AB"
     + x.substr(
      (i = x.length / 2) * j        //     Take A if j == 0, B if j == 1
      , i                           //     Take half the original length
     ).repeat(2);                   //     Double this part
   }).join("\n");                   //    Join all lines together
  }).join("\n");                    //   Join the two parts together
 }
 else return "|-";                  //  If not (base case): return "|-";
}

Мій оригінальний альтернативний метод, якщо "|"->"2", "-"->"1"це дозволено, 105 104 байт:

f=n=>n?f(n-1).replace(/[12]+/g,x=>(g=(y,i)=>y.replace(/1|2/g,p=>[,i?11:22,21][p]))(x,0)+`
`+g(x,1)):"21"

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

Щойно з'ясував якийсь алгебраїчний метод вирішення цієї проблеми.

x=>y=>"|-||--"[(f=(x,y,t=0,m=2**30,i=!(y&m)*2+!(x&m)<<1)=>m?f(x^m,y^m,([18,0,90][t]&3<<i)>>i,m>>1):t)(x>>1,y)*2+x%2]

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

(нарешті, функція, довжина якої порівнянна з моєю оригінальною відповіддю)

f(n, x, y)обчислює тип блоку в (x, y) блоці при nітерації наступної підстановки:

0 => 0 1      1 => 0 0      2 => 1 1
     0 2           0 0           2 2

звідки 0 = "|-", 1 = "||", 2 = "--", починаючи з f(0, 0, 0) = 0.

Потім g(x)(y)обчислює символ у (x, y) вихідного малюнка.


102 байти для першого рішення.
Кудлатий

88 байт за секунду.
Кудлатий

1
Отримайте ваше друге рішення, працюючи з правильними символами на 95 байт
Shaggy



9

Стакс , 24 17 15 байт

╛ä├¼àz[{╧↑;ε╖>╠

Запустіть і налагоджуйте його

Ось представлення тієї ж програми ascii.

'|'-{b\2*aa+c\}N\m

Основна ідея - почати з сітки 0 покоління, а потім повторити блок, який розширює сітку.

'|'-                    Push "|" and "-"
     {         }N       Get input and repeat block that many times.
      b                 Copy two top stack values
       \2*              Zip two parts, and double the height
          aa            Roll the top of the stack down to 3rd position.
            +           Concatenate two grids vertically
             c\         Copy result and zip horizontally
                  \     Zip the two parts horizontally
                   m    Output each row

8

Полотно , 17 16 байт

|∙-╶[∔αω+:∔;:+}+

Спробуйте тут!

Пояснення, що показує стек для введення 1:

|∙-               push "|" and "-" - the initial halves  "|", "-"
   ╶[         }   repeat input times                     
     ∔              add the two parts vertically         "|¶-"
      αω            get the original arguments to that   "|¶-", "|", "-"
        +           and add those horizontally           "|¶-", "|-"
         :∔         and add to itself vertically         "|¶-", "|-¶|-"
           ;        get the vertically added parts       "|-¶|-", "|¶-"
            :+      and add to itself horizontally       "|-¶|-", "||¶--"
               +  finally, add the halves together       "|-||¶|---"

Оновлено до 16 байт шляхом виправлення помилки, коли значення, встановлені для α/ ωдля роботи, не були скопійовані належним чином (Canvas повинен бути повністю незмінним, але, на жаль, цього не було).




4

Лушпиння , 17 байт

!¡§z+DȯṁmDTm½;"|-

1-індексований. Спробуйте в Інтернеті!

Пояснення

!¡§z+DȯṁmDTm½;"|-  Implicit input: a number n.
              "|-  The string "|-".
             ;     Wrap in a list: ["|-"]
 ¡                 Iterate this function on it:
                    Argument is a list of lines, e.g. L = ["|-||","|---"]
           m½       Break each line into two: [["|-","||"],["|-","--"]]
          T         Transpose: [["|-","|-"],["||","--"]]
      ȯṁ            Map and concatenate:
        mD           Map self-concatenation.
                    Result: ["|-|-","|-|-","||||","----"]
   z+               Zip using concatenation
  §  D              with L concatenated to itself: ["|-|||-|-","|---|-|-","|-||||||","|-------"]
                   Result is the infinite list [["|-"],["|-||","|---"],["|-|||-|-","|---|-|-","|-||||||","|-------"],...
!                  Take n'th element, implicitly display separated by newlines.

3

Желе , 21 19 байт

;"/;`,Ẏ;`€$
⁾|-Ç¡ZY

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


Пояснення:

Спочатку значення є ⁾|-, тобто ["|","-"].

Останнє посилання ( Ç), наведене [A, B], повернеться

   AB     AA
[  AB  ,  BB  ]

. ¡Неодноразово застосувати остання ланка (вхід) число раз, і ZYформатує його.

Пояснення останнього посилання:

-----------------
;"/;`,Ẏ;`€$  Monadic link. Value = [A, B]
;"/          Accumulate vectorized concatenate. Calculates (A ;" B).
             Represented as a matrix, it's |AB| (concatenated horizontally)
   ;`        Concatenate with self.      |AB|
                                Value =  |AB|  (concatenate vertically)
     ,    $  Pair with ...
      Ẏ        Tighten.  |A|    (concatenate vertically)
                 Value = |B|
       ;`€     Concatenate each with self.    |AA|
                                      Value = |BB|  (duplicate horizontally)


2

Haskell , 86 байт

(%)=zipWith(++)
f 0=["|-"]
f n|(a,b)<-unzip$splitAt(2^(n-1))<$>f(n-1)=a%b%a%a++a%b%b%b

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

Досить просто. Вихід - це список рядків. Ми беремо попередню версію і розділяємо кожен рядок навпіл, потім збираємо їх у два нові списки, використовуючи unzip. Тоді це просто питання поєднання масивів разом правильним шляхом



1

Вугілля деревне , 47 46 байт

M²↖|-¶¶FENX²ι«F²C±ι⁰C⁰ιC⊗ι±ιC׳ι±ι≦⊗ιM±ι±ιT⊗ιι

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Пояснення:

M²↖|-¶¶

Щоб отримати послідовне положення курсору для наступного циклу, я повинен надрукувати крок 0 у позиції (-2, -2) і залишити курсор у (-2, 0). (Це може бути пов’язано з помилкою у вугіллі.)

FENX²ι«

Петля над першими Nпотужностями 2.

F²C±ι⁰C⁰ιC⊗ι±ιC׳ι±ι

Зробіть копії попереднього виводу з різними зміщеннями, що призведе до полотна, яке містить бажаний наступний крок у прямокутнику всередині нього.

≦⊗ιM±ι±ιT⊗ιι

Перейдіть до положення прямокутника та обріжте полотно.

Альтернативне рішення, також 46 байт:

M²→|-FENX²ι«F432C×Iκι׳ιF245C×Iκι⊗ι≦⊗ιJ⊗ιιT⊗ιι

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Пояснення:

M²→|-

Цей крок 0 повинен бути надрукований у положенні (2, 0), але принаймні положення курсору не має значення.

FENX²ι«

Петля над першими Nпотужностями 2.

F432C×Iκι׳ιF245C×Iκι⊗ι

Зробіть копії попереднього виводу з різними зміщеннями, що призведе до полотна, яке містить бажаний наступний крок у прямокутнику всередині нього.

≦⊗ιJ⊗ιιT⊗ιι

Перейдіть до положення прямокутника та обріжте полотно.




Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.