Кількість прямих ланцюгів * не вказаної довжини


28

Прямоланцюговий алк * ne визначається як послідовність атомів вуглецю, з'єднана одинарними (алканами), подвійними (алкеном) або потрійними зв’язками (алкіном) (використовуються неявні водневі речовини). Атоми вуглецю можуть утворювати лише 4 зв’язки, тому жоден атом вуглецю не може бути змушений мати більше чотирьох зв'язків. Прямоланцюговий алк * не може бути представлений у вигляді переліку його вуглець-вуглецевих зв'язків.

Ось декілька прикладів дійсних прямих ланцюгів alk * nes:

[]       CH4              Methane
[1]      CH3-CH3          Ethane
[2]      CH2=CH2          Ethene
[3]      CH≡CH            Ethyne
[1,1]    CH3-CH2-CH3      Propane
[1,2]    CH3-CH=CH2       Propene
[1,3]    CH3-C≡CH         Propyne
[2,1]    CH2=CH-CH3       Propene
[2,2]    CH2=C=CH2        Allene (Propadiene)
[3,1]    CH≡C-CH3         Propyne 
[1,1,1]  CH3-CH2-CH2-CH3  Butane
...

Хоча це не так, оскільки принаймні один атом вуглецю мав би більше 4 зв'язків:

[2,3]
[3,2]
[3,3]
...

Ваше завдання - створити програму / функцію, яка, даючи ціле натуральне число n, виводить / повертає кількість дійсних алкіл прямих ланцюгів nдовжиною рівно атомів вуглецю. Це OEIS A077998 .

Технічні умови / Пояснення

  • Ви повинні 1правильно поводитися , повертаючись 1.
  • Алк * не подобається [1,2]і [2,1]вважається виразним.
  • Вихід - це довжина списку всіх можливих алк * нев заданої довжини.
  • Вам не доведеться правильно обробляти 0.

Випробування:

1 => 1
2 => 3
3 => 6
4 => 14

Це кодовий гольф, тому виграє найменший байт !


просто для уточнення, ланцюжок є дійсним, якщо всі пари підряд підсумовуються <=4, правда?
Мальтісен

Виправлено. @Maltysen: так.
Zacharý

4
Чому для всього існує послідовність OEIS? : P
HyperNeutrino

2
@ZacharyT, є точно один вуглеводень з нульовими атомами вуглецю, і це той, який також має нульові атоми водню. Це абсолютно такий же аргумент, як для трикутника Паскаля, який має верх 1, а не 0, або буквально сотні інших комбінаторних послідовностей.
Пітер Тейлор

1
@Emigna, це тому, що була пов’язана неправильна послідовність. Я виправлю це.
Пітер Тейлор

Відповіді:


7

Оазис , 9 7 байт

xcd-+3V

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

Пояснення

Для цього використовується відношення рецидиву в OEIS :

a (n) = 2 * a (n-1) + a (n-2) - a (n-3)

x    Multiply a(n-1) by 2: gives 2*a(n-1)
c    Push a(n-2)
d    Push a(n-3)
-    Subtract: gives a(n-2) - a(n-3)
+    Add: gives 2*a(n-1) + a(n-2) - a(n-3)
3    Push 3: initial value for a(n-1)
V    Push 1, 1: initial values for a(n-2), a(n-3)

1
Приємне використання початкових значень! Ви виграєте цього разу;)
Емінья

Так, напевно, немає способу перемогти це.
Zacharý

4
@ZacharyT Тільки якщо хтось може придумати спосіб зробити програму xkcdв ній.
hBy2Py

4
@ hBy2Py Ну, xkcd-+311працює , бо kнаразі не працює ...
Луїс Мендо

10

MATL , 10 байт

7K5vBiY^1)

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

Пояснення

Для цього використовується характеристика, знайдена в OEIS

a (n) - верхній лівий запис n-ї потужності матриці 3 X 3 [1, 1, 1; 1, 0, 0; 1, 0, 1]

7    % Push 7
K    % Push 4
5    % Push 5
v    % Concatenate all numbers into a column vector: [7; 4; 5]
B    % Convert to binary: gives 3×3 matrix [1, 1, 1; 1, 0, 0; 1, 0, 1]
i    % Input n
Y^   % Matrix power
1)   % Take the first element of the resulting matrix, i.e. its upper-left corner.
     % Implicitly display

6

Оазис , 9 8 байт

Збережено байт завдяки Аднану

xc+d-63T

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

Пояснення

a(0) = 0
a(1) = 1
a(2) = 3
a(3) = 6

a(n) = xc+d-

x         # calculate 2*a(n-1)
 c        # calculate a(n-2)
  +       # add: 2*a(n-1) + a(n-2)
   d      # calculate a(n-3)
    -     # subtract: 2*a(n-1) + a(n-2) - a(n-3)

1
Приємно! Також xкороткий для 2*:).
Аднан

1
Удар: - П (я там уже не бачив відповіді на OASIS)
Луїс Мендо

@Adnan Чи є спосіб сказати Oasis, що ви хочете змістити індекс послідовності вихідних даних на 1? Я маю на увазі, відніміть 1 до вхідного аргументу (замість використання 0тут початкового )
Луїс Мендо

1
@LuisMendo Ах, це ще не реалізовано. Але це гарна ідея для наступного випуску :).
Аднан

Для подальшого ознайомлення це зараз реалізовано
Луїс Мендо

4

Желе, 10 байт

745DBæ*µḢḢ

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

Використовує алгоритм Луїса Мендо .

Пояснення

745DBæ*µḢḢ    Main link. Argument: n
745D          Get the digits of 745
    B         Convert each to binary
     æ*       Matrix power
        ḢḢ    First element of first row

Желе, 15 байт

3Rṗ’µ+2\<5PµÐfL

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

Використовує грубу силу.

Пояснення

3Rṗ’µ+2\<5PµÐfL    Main link. Argument: n
3R                 Start with [1, 2, 3]
   ’               Take the (n-1)'th
  ṗ                Cartesian power
            Ðf     Filter on:
     +2\             Sums of overlapping pairs
        <5           1 for sums < 5, 0 otherwise
          P          Product: 1 if all pairs < 5
              L    Length

4

MATL , 14 байт

q3:Z^TTZ+!5<As

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

Пояснення

Це генерує декартову силу [1 2 3]"піднятої" до числа атомів мінус 1, а потім використовує згортку, щоб перевірити, чи немає двох суміжних чисел у кожному декартовому наборі більше 4.

q    % Take number of atoms n implicitly
3:   % Push [1 2 3]
Z^   % Cartesian power. Gives a matrix with each (n-1)-tuple on a row
TT   % Push [1 1]
Z+   % 2D convolution. For each tuple this gives the sum of contiguous numbers
5<   % For each entry, gives true if less than 5
!    % Transpose
A    % True if all elements of each column are true. Gives a row vector
s    % Sum of true results. Implicitly display

3

Математика, 48 байт

MatrixPower[{{1,1,1},{1,0,0},{1,0,1}},#][[1,1]]&

Як зазначив Луїс Мендо , це A006356 в OEIS. Ось мої оригінальні спроби:

Count[Length@Split[#,+##<5&]&/@Tuples[{1,2,3},#-1],0|1]&

Для введення n, Tuples[{1,2,3},n-1]список всіх (n-1)-кортежей елементів в {1,2,3}які представляють усі можливі послідовності одно-, дво-, або потрійних зв'язків для nатомів вуглецю. +##<5&це чиста функція, яка повертає, чи менша сума її аргументів 5, тому Split[#,+##<5&]&розбиває список на підсписи, що складаються з послідовних елементів, парні суми яких менші 5. Опис дійсного alk * ne еквівалентно цьому списку, що має довжину 0(у випадку, коли n=1) або 1, тому я просто Countкількість- (n-1)пар, де довжина цього списку відповідає 0|1.

Count[Fold[If[+##>4,4,#2]&]/@Tuples[{1,2,3},#-1],Except@4]&

If[+##>4,4,#2]&повертається, 4якщо сума його аргументів більша за 4та повертає другий аргумент інакше. Fold[If[+##>4,4,#2]&]робить ліворуч Foldвід його введення за допомогою цієї функції. Отже, ось я Countкількість (n-1)-парів, до яких застосовує цей оператор, не дає 4. Випадок, коли n=1це стосується, Foldзалишається неоціненим, коли його другим аргументом є порожній список {}.


1
Це би спрацювало? (Вигляд відірваного прямо від OEIS з коригуваннями) LinearRecurrence[{2,1,-1},{1,3,6},#][[#]]&?
Zacharý

Частина того, чому я люблю цей сайт, - це вивчення всіх можливостей, які може запропонувати Mathematica :)
ngenisis

До this site, ви маєте в виду OEIS або PPCG?
Zacharý

PPCG. Я зібрав багато математики з пропозицій людей.
ngenisis

3

Пітон, 51 байт

f=lambda n:n<4and(n*n+n)/2or 2*f(n-1)+f(n-2)-f(n-3)

Це прямо реалізація відношення рецидивів. Завдяки Тіму Педеріку за 3 байти. Вихід - поплавок у Python 3 та ціле число в Python 2.

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


(n*n+n)/2коротше, ніж [1,3,6][n-1]. А якщо ви використовуєте Python 3 і вам не подобається закінчувати висновок з плаваючою комою, (n*n+n)//2все одно коротше.
Тім Педерік


2

Рубін, 62 байти

->n{c=0
(10**n/10).times{|i|"#{i}#{i*11}"=~/[3-9]/||c+=1}
c}

Жахливо неефективний підхід на базі 10 грубої сили. Може бути покращено до бази 5 для додаткових байтів.

Числа генеруються там, де кожна цифра являє собою зв’язок (n-1 цифр.) 0Являє собою порядок зв'язку 1, 2являє собою порядок зв’язку 3. Цифри понад 2 недійсні.

Помножимо це на 11, щоб підсумовувати сусідню пару цифр. Знову цифри понад 3 недійсні.

Ми поєднуємо два числа в рядку і виконуємо регулярний вираз для пошуку недійсних цифр. Якщо жодної не знайдено, ми збільшуємо лічильник.

в тестовій програмі

f=->n{c=0
(10**n/10).times{|i|"#{i}#{i*11}"=~/[3-9]/||c+=1}
c}

p f[gets.to_i]

2

Рубі, 51 байт

->n{a=[1,1,3]
n.times{a<<2*a[-1]+a[-2]-a[-3]}
a[n]}

На основі співвідношення рецидивів для OEIS A006356.

Починається з масиву для елементів 0,1 і 2 послідовності, які дорівнюють 1 (як я порахував, щоб він працював), 1 і 3 відповідно.

Ітеративно додає nбільше елементів до послідовності, потім повертає елемент n. Він завжди обчислює на 2 елементи більше, ніж потрібно насправді, але це все ще лінійний час, що набагато ефективніше моєї попередньої відповіді.

в тестовій програмі

f=->n{a=[1,1,3]
n.times{a<<2*a[-1]+a[-2]-a[-3]}
a[n]}

p f[gets.to_i]

2

Математика, 42 40 байт

Кількість байтів передбачає сумісне однобайтове кодування, як CP-1252 (за замовчуванням в установках Windows).

±0=±1=1;±2=3;±n_:=±(n-1)2+±(n-2)-±(n-3);

Це просто реалізує повторення, задані на OEIS як одинарний оператор.


2

CJam (19 байт)

{2,{__-2=+1b+}@*W=}

Інтернет-тестовий набір . Це анонімний блок (функція), який бере один елемент на стек і залишає один на стеці. Зверніть увагу, що тестовий набір включає a(0) = 1.

Використовуваний рецидив заснований на спостереженні для відповідної послідовності OEIS A006356 :

Дорівнює перетворення INVERT (1, 2, 1, 1, 1, ...), еквівалентного a (n) = a (n-1) + 2 * a (n-2) + a (n-3) + a (n-4) + ... + 1. a (6) = 70 = (31 + 2 * 14 + 6 + 3 + 1 + 1). - Гері В. Адамсон, 27 квітня 2009 року

але з відповідним зміщенням, що знімає потребу у фіналі, + 1як зараз охоплено a(0).

Розсічення

{         e# Define a block
  2,      e#   Take starting sequence [0 1] (beginning at index -1 for golfiness)
  {       e#   Loop...
    _     e#     Copy sequence so far
    _-2=+ e#     Append an extra copy of a(n-2)
    1b    e#     Sum
    +     e#     Append
  }@*     e#   ...n times
  W=      e#   Take the final value from the sequence
}

2

Мозок-Флак, 56 байт

Використовується алгоритм, детально описаний у першому коментарі на сторінці OEIS.

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

({}[()]<(((())))>){({}[()]<{({}<>({}))<>}<>>)}{}({}<>{})

Пояснення

Послідовність може бути визначена як така:

For u(k), v(k), and w(k) such that
u(1) = v(1) = w(1) = 1
u(k+1) = u(k) + v(k) + w(k)
v(k+1) = u(k) + v(k)
w(k+1) = u(k)
u(k) is the number of straight-chain alk*nes with length k

Програма починається з 1та повторно застосовує цю повторюваність для обчисленняu(k)

Код з анотацією (фактична анотація в майбутньому)

# Setup: decrement the input by one and push three 1's to the stack under it
({}[()]<(((())))>)

# Calculation:
{                          }           # While the input is not zero (main loop)
 ({}[()]                  )            # Pop the counter decrement it by one and push it
        <                >             # Before the counter gets pushed back to the stack...
         {            }                # Loop while the top of the stack is not zero (subloop)
          (        )                   # Push...
           {}                          # The top of the stack (popped)...
             <>                        # to the other stack...
               ({})                    # plus the top of the other stack (peeked)
                    <>                 # Switch back to the first stack.
                       <>              # Switch to the other stack
                            {}         # Pop the input (now zero)
                              (      ) # Push...
                               {}      # The top of the stack (u(k))...
                                 <>    # to the other stack...
                                   {}  # plus the top of the other stack (zero).

Візуалізація стеків

В одній ітерації основного циклу відбувається те, що відбувається (зауважте, що нулі можуть бути, а можуть і не бути, але це не має значення в будь-якому випадку):

Start of main loop iteration/subloop first iteration:
A    B

u
v
w
0    0
^

After first subloop iteration:
A    B

v
w    u
0    0
^

After second subloop iteration:
A    B

    u+v
w    u
0    0
^

After third subloop iteration (top of stack is zero so subloop terminates):

A    B

   u+v+w
    u+v
     u
0    0
^

End of main loop iteration:
A    B

   u+v+w
    u+v
     u
0    0
     ^

Стан стеків тепер так само , як це було на початку циклу , за винятком , що поточний стек тепер має наступні значення u, vі wна ньому.


2

Перл 6, 48

{my @a=1,0,0;@a=reverse [\+] @a for 1..$_;@a[0]}

Спочатку

sub f {$_>2??2*f($_-1)+f($_-2)-f($_-3)!!(1,1,3)[$_]}

але я забув, що мені потрібно, sub fщоб ітераційне рішення виграло.


2

Діалог APL, 30 байт

{⍵<3:⍵⌷1 3⋄+/∧/¨4≥2+/¨,⍳1↓⍵/3}

Використовує грубу силу. Пояснення (як мінімум, моя краща спроба):

⍵<3:⍵⌷1 3 - if ⍵ (function arg) is 1 (case 1) or 2 (case 2), return 1 (case 1) or 3 (case 2)
⋄ - separate statements
⍵/3 - otherwise, 3 repeated ⍵ times
1↓ - without the first element
⍳ - the matrix of possible indices of a matrix of that size
,  - ravel, return a list of all the elements of the matrix
2+/¨ - sum of each contiguous pair on each element
4≥ - tests whether each element is less than or equal to 4
∧/¨ - all elements are true, applied to each item.
+/ - Sum.

1

Діалог APL, 29 байт

{⍵<4:⍵⌷1 3 6⋄+/2 1 ¯1×∇¨⍵-⍳3}

Працює з використанням рекурсивного визначення цілої послідовності OEIS A006356.


1

Пітон з Numpy, 62 байти

Мені довелося спробувати, але здається, чистий Python і рекурсія коротша, ніж numpy, і явний розрахунок на основі матриці на сторінці OEIS.

from numpy import*
lambda n:(mat('1 1 1;1 0 0;1 0 1')**n)[0,0]

1

R, 61 58 55 51 50 байт

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

el(expm::`%^%`(matrix(!-3:5%in%2^(0:2),3),scan()))

Якщо ви віддаєте перевагу рекурсивному рішенню, ось пряма реалізація відношення рецидивів, перерахованого в OEIS, на 55 байт .

f=function(n)`if`(n<4,(n*n+n)/2,2*f(n-1)+f(n-2)-f(n-3))

1

Excel, 123 байти

Реалізує формулу від OEIS:

=4*(SIN(4*PI()/7)^2*(1+2*COS(2*PI()/7))^A1+SIN(8*PI()/7)^2*(1+2*COS(4*PI()/7))^A1+SIN(2*PI()/7)^2*(1+2*COS(8*PI()/7))^A1)/7

Як завжди, введіть A1формулу в будь-якій іншій комірці.

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


0

Літп , 79 байт

#N:(((if(< N 4)((/(+ N(* N N))2))((-(+(* 2(f(- N 1)))(f(- N 2)))(f(- N 3)))))))

Реалізує рекурсивну цілочисленну послідовність, перелічену в OEIS.

Зрозуміла програма для впровадження та тестування.

% alkaline.lithp
% run with: ./run.js alkaline.lithp
(
    (def f #N : ((
        (if (< N 4) (
            (/ (+ N (* N N)) 2)
        ) (else (
            (- (+ (* 2 (f (- N 1))) (f (- N 2))) (f (- N 3)))
        )))
    )))

    % Test cases 1 to 4
    (import lists)
    (each (seq 1 4) #I :: ((print (f I))))
)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.