Nombre d'Alk à chaîne droite * nes de longueur donnée

28

Un alk * ne à chaîne droite est défini comme une séquence d'atomes de carbone reliés par des liaisons simples (alcane), doubles (alcène) ou triples (alcyne) (des hydrogènes implicites sont utilisés.) Les atomes de carbone ne peuvent former que 4 liaisons, donc aucun atome de carbone ne peut être contraint d'avoir plus de quatre liaisons. Un alk * ne à chaîne droite peut être représenté comme une liste de ses liaisons carbone-carbone.

Voici quelques exemples d'alc * nes à chaîne droite valides:

[]       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
...

Bien que ce ne soit pas le cas, car au moins un atome de carbone aurait plus de 4 liaisons:

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

Votre tâche consiste à créer un programme / une fonction qui, étant donné un entier positif n, génère / renvoie le nombre d'alc * nes à chaîne droite valides d'une nlongueur exacte d' atomes de carbone. Il s'agit d' OEIS A077998 .

Spécifications / clarifications

  • Vous devez gérer 1correctement en revenant 1.
  • Alk * nes aiment [1,2]et [2,1]sont considérés comme distincts.
  • La sortie est la longueur d'une liste de tous les alc * nes possibles d'une longueur donnée.
  • Vous n'avez pas à gérer correctement 0.

Cas de test:

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

C'est le golf de code, donc le nombre d' octets le plus bas gagne!

Zacharý
la source
juste pour clarifier, une chaîne est valide si toutes les paires consécutives sont additionnées <=4, non?
Maltysen
Fixé. @Maltysen: oui.
Zacharý
4
Pourquoi y a-t-il une séquence OEIS pour tout? : P
HyperNeutrino
2
@ZacharyT, il y a précisément un hydrocarbure avec zéro atome de carbone, et c'est celui qui a aussi zéro atome d'hydrogène. C'est exactement le même argument que pour le triangle de Pascal ayant un 1 en haut plutôt qu'un 0, ou pour des centaines d'autres séquences combinatoires.
Peter Taylor
1
@Emigna, c'est parce que la mauvaise séquence a été liée. Je vais le corriger.
Peter Taylor

Réponses:

7

Oasis , 9 7 octets

xcd-+3V

Essayez-le en ligne!

Explication

Cela utilise la relation de récurrence dans 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)
Luis Mendo
la source
1
Belle utilisation des valeurs initiales! Vous gagnez cette fois;)
Emigna
Ouais, il n'y a probablement aucun moyen de battre ça.
Zacharý
4
@ZacharyT Seulement si quelqu'un peut trouver un moyen d'y intégrer le programme xkcd.
hBy2Py
4
@ hBy2Py Eh bien, ça xkcd-+311marche , parce que kc'est actuellement un no-op ...
Luis Mendo
10

MATL , 10 octets

7K5vBiY^1)

Essayez-le en ligne!

Explication

Cela utilise la caractérisation trouvée dans OEIS

a (n) est l'entrée supérieure gauche de la n-ième puissance de la matrice 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
Luis Mendo
la source
6

Oasis , 9 8 octets

Un octet enregistré grâce à Adnan

xc+d-63T

Essayez-le en ligne!

Explication

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)
Emigna
la source
1
Agréable! Aussi, xest l'abréviation de 2*:).
Adnan
1
Beat ya :-P (je n'avais pas vu qu'il y avait déjà une réponse OASIS)
Luis Mendo
@Adnan Existe-t-il un moyen de dire à Oasis que vous souhaitez décaler l'index de séquence de sortie de 1? Je veux dire, soustrayez 1 à l'argument d'entrée (au lieu d'utiliser une initiale 0ici)
Luis Mendo
1
@LuisMendo Ah, ce n'est pas encore implémenté. Mais c'est une bonne idée pour la prochaine version :).
Adnan
Pour référence future, ceci est maintenant implémenté
Luis Mendo
4

Gelée, 10 octets

745DBæ*µḢḢ

Essayez-le en ligne!

Utilise l'algorithme de Luis Mendo .

Explication

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

Gelée, 15 octets

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

Essayez-le en ligne!

Utilise la force brute.

Explication

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
PurkkaKoodari
la source
4

MATL , 14 octets

q3:Z^TTZ+!5<As

Essayez-le en ligne!

Explication

Cela génère la puissance cartésienne de [1 2 3]"augmenté" au nombre d'atomes moins 1, puis utilise la convolution pour vérifier qu'il n'y a pas deux nombres contigus dans chaque tuple cartésien totalisant plus de 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
Luis Mendo
la source
3

Mathematica, 48 octets

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

Comme l'a souligné Luis Mendo , il s'agit de l' A006356 dans l'OEIS. Voici mes tentatives originales:

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

Pour une entrée n, Tuples[{1,2,3},n-1]est la liste de tous les (n-1)-tuples d'éléments {1,2,3}représentant toutes les séquences possibles de liaisons simples, doubles ou triples pour nles atomes de carbone. +##<5&est une fonction pure qui retourne si la somme de ses arguments est inférieure à 5, Split[#,+##<5&]&divise donc une liste en sous-listes constituées d'éléments consécutifs dont les sommes par paire sont inférieures à 5. Décrire un alk * ne valide est équivalent à cette liste ayant une longueur 0(dans le cas où n=1) ou 1, donc je viens Countdu nombre de (n-1)-tuples où la longueur de cette liste correspond 0|1.

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

If[+##>4,4,#2]&renvoie 4si la somme de ses arguments est supérieure à 4et renvoie le deuxième argument dans le cas contraire. Fold[If[+##>4,4,#2]&]fait une gauche Foldde son entrée avec cette fonction. Voici donc Countle nombre de (n-1)-tuples auxquels l'application de cet opérateur ne donne pas 4. Le cas où n=1est couvert depuis Foldreste non évalué lorsque son deuxième argument est la liste vide {}.

ngenisis
la source
1
Est-ce que cela fonctionnerait? (Sorte de droite arrachée à OEIS avec ajustements) LinearRecurrence[{2,1,-1},{1,3,6},#][[#]]&?
Zacharý
Une des raisons pour lesquelles j'aime ce site est d'apprendre toutes les fonctionnalités que Mathematica a à offrir :)
ngenisis
Par this site, voulez-vous dire OEIS ou PPCG?
Zacharý
PPCG. J'ai ramassé beaucoup de Mathematica parmi les suggestions des gens.
ngenisis
3

Python, 51 octets

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

Il s'agit d'une implémentation simple de la relation de récurrence. Merci à Tim Pederick pour 3 octets. La sortie est un flottant en Python 3 et un entier en Python 2.

Essayez-le en ligne!

Mego
la source
(n*n+n)/2est plus court que [1,3,6][n-1]. Et si vous utilisez Python 3 et que vous n'aimez pas vous retrouver avec une sortie en virgule flottante, (n*n+n)//2c'est toujours plus court.
Tim Pederick
2

Pyth - 16 octets

Utilise la force brute.

lf.AgL4+VTtT^S3t

Suite de tests .

Maltysen
la source
1
Ce serait bien de fournir une description pour ceux d'entre nous qui ne "grok" pas Pyth.
Zacharý
2

Rubis, 62 octets

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

Approche horriblement inefficace de la force brute de la base 10. Pourrait être amélioré à la base 5 pour des octets supplémentaires.

Les nombres sont générés où chaque chiffre représente une liaison (n-1 chiffres.) 0Représente un ordre de liaison de 1, 2représente un ordre de liaison de 3. Les chiffres supérieurs à 2 ne sont pas valides.

Nous multiplions cela par 11 pour additionner la paire adjacente de chiffres. Encore une fois, les chiffres supérieurs à 3 ne sont pas valides.

Nous combinons les deux nombres dans une chaîne et effectuons une expression régulière pour rechercher des chiffres invalides. Si aucun n'est trouvé, nous incrémentons le compteur.

dans le programme de test

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

p f[gets.to_i]
Level River St
la source
2

Rubis, 51 octets

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

Basé sur la relation de récurrence selon OEIS A006356.

Commence par un tableau pour les éléments 0,1 et 2 de la séquence qui sont 1 (comme calculé par moi, pour le faire fonctionner), 1 et 3 respectivement.

Ajoute itérativement nplus d'éléments à la séquence, puis renvoie l'élément n. Il calcule toujours 2 éléments de plus que ce dont il a réellement besoin, mais c'est toujours du temps linéaire, ce qui est beaucoup plus efficace que ma réponse précédente.

dans le programme de test

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

p f[gets.to_i]
Level River St
la source
2

Mathematica, 42 40 octets

Le nombre d'octets suppose un codage à un octet compatible comme CP-1252 (la valeur par défaut sur les installations Windows).

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

Cela implémente simplement la récurrence donnée sur OEIS en tant qu'opérateur unaire.

Martin Ender
la source
2

CJam (19 octets)

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

Suite de tests en ligne . Il s'agit d'un bloc (fonction) anonyme qui prend un élément sur la pile et en laisse un sur la pile. Notez que la suite de tests comprend a(0) = 1.

La récurrence utilisée est basée sur l'observation de la séquence OEIS associée A006356 :

Égale la transformée INVERT de (1, 2, 1, 1, 1, ...) équivalente à 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). - Gary W. Adamson, 27 avril 2009

mais avec le décalage approprié, ce qui élimine le besoin de la finale + 1comme maintenant couvert par a(0).

Dissection

{         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
}
Peter Taylor
la source
2

Brain-Flak, 56 octets

Utilise l'algorithme détaillé dans le premier commentaire sur la page OEIS.

Essayez-le en ligne!

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

Explication

La séquence peut être définie comme telle:

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

Le programme démarre à 1et applique à plusieurs reprises cette récurrence pour calculeru(k)

Code annoté (annotation réelle à venir)

# 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).

Visualisation des piles

Dans une itération de la boucle principale, c'est ce qui se passe (notez que les zéros peuvent être présents ou non mais cela n'a pas d'importance dans les deux cas):

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
     ^

L'état des piles est maintenant le même que celui au début de la boucle , sauf que la pile courante a maintenant les valeurs suivantes pour u, vet wsur elle.

0 '
la source
2

Perl 6, 48

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

À l'origine

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

mais j'ai oublié que j'avais besoin de la sub fsolution itérative.

bb94
la source
2

Dyalog APL, 30 octets

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

Utilise la force brute. Explication (ma meilleure tentative, au moins):

⍵<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.
Zacharý
la source
1

Dyalog APL, 29 octets

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

Fonctionne en utilisant la définition récursive de la séquence entière OEIS A006356.

Zacharý
la source
1

Python avec Numpy, 62 octets

J'ai dû l'essayer, mais il semble que Python pur et la récursivité soient plus courts que numpy et le calcul explicite basé sur une matrice sur la page OEIS.

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

R, 61 58 55 51 50 octets

Prend l'entrée de stdin, utilise l'exponentiation matricielle pour déterminer le résultat exact.

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

Si vous préférez une solution récursive, voici une implémentation simple de la relation de récurrence répertoriée dans OEIS, pour 55 octets .

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

Excel, 123 octets

Implémente la formule d'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

Comme toujours, entrez la A1formule dans toute autre cellule.

Corrigez les anciennes identités Trig pour voir si cela pourrait être utile. Maintenant, ma tête me fait mal.

Wernisch
la source
0

Lithp , 79 octets

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

Implémente une séquence entière récursive répertoriée dans OEIS.

Implémentation et suite de tests lisibles.

% 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))))
)
Andrakis
la source