⊥1↓⍧|/⌽(+/g[⍸⌽+/⊤⎕]),↑,\⌽g←(2+/,)⍣38⍨⍳2
Спробуйте в Інтернеті!
Змінився на повну програму, взявши один аргумент довжиною 2, а також змінив генератор Фібоначчі. Дякуємо @ngn за безліч ідей.
Використовує ⎕IO←0
так, що ⍳2
оцінює до 0 1
.
Генератор Фібоначчі (новий)
Зауважте, що останні два числа є неточними, але це не змінює вихід програми.
(2+/,)⍣38⍨⍳2
→ 0 1 ((2+/,)⍣38) 0 1
Step 1
0 1 (2+/,) 0 1
→ 2+/ 0 1 0 1
→ (0+1) (1+0) (0+1) ⍝ 2+/ evaluates sums for moving window of length 2
→ 1 1 1
Step 2
0 1 (2+/,) 1 1 1
→ 2+/ 0 1 1 1 1
→ 1 2 2 2
Step 3
0 1 (2+/,) 1 2 2 2
→ 2+/ 0 1 1 2 2 2
→ 1 2 3 4 4
Зекендорф до рівнини (частково)
⍸⌽+/⊤⎕
⎕ ⍝ Take input from stdin, must be an array of 2 numbers
⊤ ⍝ Convert each number to base 2; each number is mapped to a column
+/ ⍝ Sum in row direction; add up the counts at each digit position
⌽ ⍝ Reverse
⍸ ⍝ Convert each number n at index i to n copies of i
g←1↓(1,+\⍤,)⍣20⍨1
{⊥1↓⍧|/⌽⍵,↑,\⌽g}+⍥{+/g[⍸⌽⊤⍵]}
Спробуйте в Інтернеті!
Змінено частину 1 попередньої відповіді для повторного використання чисел Фібоначчі. Крім того, киньте дублікат 1, щоб зберегти деякі байти в інших місцях.
Частина 1 (нова)
{+/g[⍸⌽⊤⍵]}
⊤⍵ ⍝ Argument to binary digits
⍸⌽ ⍝ Reverse and convert to indices of ones
g[ ] ⍝ Index into the Fibonacci array of 1,2,3,5,...
+/ ⍝ Sum
{⊥1↓¯1↓⍧|/⌽⍵,↑,\⌽(1,+\⍤,)⍣20⍨1}+⍥({+∘÷⍣(⌽⍳≢⊤⍵)⍨1}⊥⊤)
Спробуйте в Інтернеті!
Як це працює
Немає фантазійного алгоритму для додавання в Zeckendorf, оскільки APL не відомий для роботи з окремими елементами в масиві. Натомість я пішов перетворити два входи із Зекендорфа в прості цілі числа, додати їх та перетворити їх назад.
Частина 1: Зекендорф до простого числа
{+∘÷⍣(⌽⍳≢⊤⍵)⍨1}⊥⊤ ⍝ Zeckendorf to plain integer
⊤ ⍝ Convert the input to array of binary digits (X)
{ ( ≢⊤⍵) } ⍝ Take the length L of the binary digits and
⌽⍳ ⍝ generate 1,2..L backwards, so L..2,1
{+∘÷⍣( )⍨1} ⍝ Apply "Inverse and add 1" L..2,1 times to 1
⍝ The result looks like ..8÷5 5÷3 3÷2 2 (Y)
⊥ ⍝ Mixed base conversion of X into base Y
Base | Digit value
-------------------------------
13÷8 | (8÷5)×(5÷3)×(3÷2)×2 = 8
8÷5 | (5÷3)×(3÷2)×2 = 5
5÷3 | (3÷2)×2 = 3
3÷2 | 2 = 2
2÷1 | 1 = 1
Частина 2: Додайте два прості цілі числа
+⍥z2i ⍝ Given left and right arguments,
⍝ apply z2i to each of them and add the two
Частина 3: Перерахуйте суму назад в Зекендорф
"Ви можете припустити, що представлення Zeckendorf і вхідного, і вихідного вкладається в 31 біт" було досить зручно.
{⊥1↓¯1↓⍧|/⌽⍵,↑,\⌽(1,+\⍤,)⍣20⍨1} ⍝ Convert plain integer N to Zeckendorf
(1,+\⍤,)⍣20⍨1 ⍝ First 41 Fibonacci numbers starting with two 1's
⌽ ⍝ Reverse
↑,\ ⍝ Matrix of prefixes, filling empty spaces with 0's
⌽⍵, ⍝ Prepend N to each row and reverse horizontally
|/ ⍝ Reduce by | (residue) on each row (see below)
⍧ ⍝ Nub sieve; 1 at first appearance of each number, 0 otherwise
1↓¯1↓ ⍝ Remove first and last item
⊥ ⍝ Convert from binary digits to integer
Генератор Фібоначчі
(1,+\⍤,)⍣20⍨1
→ 1 ((1,+\⍤,)⍣20) 1 ⍝ Expand ⍨
→ Apply 1 (1,+\⍤,) x 20 times to 1
First iteration
1(1,+\⍤,)1
→ 1,+\1,1 ⍝ Expand the train
→ 1,1 2 ⍝ +\ is cumulative sum
→ 1 1 2 ⍝ First three Fibonacci numbers
Second iteration
1(1,+\⍤,)1 1 2
→ 1,+\1,1 1 2 ⍝ Expand the train
→ 1 1 2 3 5 ⍝ First five Fibonacci numbers
⍣20 ⍝ ... Repeat 20 times
Це випливає із властивості чисел Фібоначчі: якщо Фібоначчі визначено як
Ж0=Ж1= 1 ; ∀ n ≥ 0 ,Жn + 2=Жn + 1+Жн
тоді
∀ n ≥ 0 ,∑i = 0нЖi=Жn + 2- 1
Таким чином, сукупна сума (масив Фібоначчі, передбачуваний 1) стає . Потім я знову додаю 1, щоб отримати звичайний масив Фібоначчи, починаючи з індексу 0.1 ,Ж0, ⋯ ,ЖнF1,⋯,Fn+2
Цифри Фібоначчі до Зекендорфа
Input: 7, Fibonacci: 1 1 2 3 5 8 13
Matrix
0 0 0 0 0 0 13 7
0 0 0 0 0 8 13 7
0 0 0 0 5 8 13 7
0 0 0 3 5 8 13 7
0 0 2 3 5 8 13 7
0 1 2 3 5 8 13 7
1 1 2 3 5 8 13 7
Reduction by residue (|/)
- Right side always binds first.
- x|y is equivalent to y%x in other languages.
- 0|y is defined as y, so leading zeros are ignored.
- So we're effectively doing cumulative scan from the right.
0 0 0 0 0 0 13 7 → 13|7 = 7
0 0 0 0 0 8 13 7 → 8|7 = 7
0 0 0 0 5 8 13 7 → 5|7 = 2
0 0 0 3 5 8 13 7 → 3|2 = 2
0 0 2 3 5 8 13 7 → 2|2 = 0
0 1 2 3 5 8 13 7 → 1|0 = 0
1 1 2 3 5 8 13 7 → 1|0 = 0
Result: 7 7 2 2 0 0 0
Nub sieve (⍧): 1 0 1 0 1 0 0
1's in the middle are produced when divisor ≤ dividend
(so it contributes to a Zeckendorf digit).
But the first 1 and last 0 are meaningless.
Drop first and last (1↓¯1↓): 0 1 0 1 0
Finally, we apply base 2 to integer (⊥) to match the output format.