# Self-referential triangle sequence

Output the flattened version of the sequence A297359, which starts like the following:

1, 1, 1, 1, 2, 1, 1, 3, 3, 1, 2, 4, 6, 4, 2, 1, 6, 10, 10, 6, 1,
1, 7, 16, 20, 16, 7, 1, 3, 8, 23, 36, 36, 23, 8, 3, 3, 11, 31, 59,
72, 59, 31, 11, 3, 1, 14, 42, 90, 131, 131, 90, 42, 14, 1,...
----------------
1,
1,   1,
1,  2,   1,
1,  3,   3,  1,
2,  4,  6,   4,  2,
1,  6,  10, 10,  6,  1,
1, 7,  16,  20,  16,  7, 1,
3, 8,  23,  36, 36,  23,  8, 3,
3, 11, 31, 59,  72,  59, 31, 11, 3,
1, 14, 42, 90, 131, 131, 90, 42, 14, 1,
...


The defining property of the sequence is that

• the entire triangle is generated like the Pascal's triangle (i.e. each entry inside the triangle is the sum of the two numbers above it), and
• the left and right boundaries are identical to the entire triangle read by rows.

Standard rules and I/O methods apply. See https://codegolf.stackexchange.com/tags/sequence/info and https://codegolf.stackexchange.com/tags/code-golf/info.

The shortest code in bytes wins.

• There are so many questions about the Pascal's triangle. Should we add a new tag for that? Commented Oct 22, 2021 at 2:00
• @alephalpha Chat feedback was negative. Commented Oct 22, 2021 at 6:10
• Strictly speaking don't you also need to define the first two values as being 1? (After that subsequent values depend on the first two.)
– Neil
Commented Oct 22, 2021 at 8:33
• The tag info doesn't include the possibility of outputting the sequence indefinitely, as in "the program prints sequence terms forever (or until stopped)". This is usually accepted. Is it accapted in this challenge? Maybe we should update the tag? Item 3 in the tag says a "lazy list", which I think is a different thing Commented Oct 22, 2021 at 9:25
• @LuisMendo Yes, "outputting terms indefinitely" is OK. Commented Oct 22, 2021 at 10:52

1:t
r!b=b:zipWith(+)r(tail r)++[b]
t=1:tail(scanl(!)[]t>>=id)


Try it online!

Feels a bit clunky, and frankly I'm not entirely sure I understand what I've done with both of those explicit leading ones.

# 05AB1E, 14 13 bytes

λε=Dˆ}ü+¯Nè.ø


Infinitely outputs each integer on a separated line.

-1 byte thanks to @ovs.

Try it online.

Explanation:

λ          # Create a recursive environment,
# starting with a(0)=1 by default
# And we calculate every following a(n) as follows:
ε         #  Map over the integers in the current list (or the digit(s) of the 1):
=        #   Print the current integer with trailing newline (without popping)
Dˆ      #   Add a copy of the integer to the global array
}ü        #  After the map: map over the overlapping pairs:
+       #   And sum them together
¯Nè    #  Index n of the recursive environment into the global array
.ø  #  And surround the list with this integer as leading/trailing item

• 13 bytes, relying even more on the --no-lazy flag.
– ovs
Commented Oct 22, 2021 at 8:53

# Python 3, 94,93(@xnor),88(use infinite generator),83(smarter buffering),79(obvious saving),67 bytes(@dingledooper)

*P,z=p=1,1
for x in P:print(z);z,*q=p;p=x,*map(sum,zip(p,q)),x;P+=p


Try it online!

I doubt this is competitive, but there is only one way to find out...Beginning to get the hang of it.

The code works row-by-row (the computation, output is element by element) and is pretty straight-forward, the only mildly tricky thing being that the for loop actually sees the intermittent updates of the P list (This relies on += actually being equivalent to .extend which also allows us to be a bit cavalier with list vs tuple). And perhaps the backwards-in-time order of assignments towards the yieldprint statement whose effect is a two-cycle-buffering (z is the x from two iterations ago).

Old version

Old version

Old version

Old version

• It looks like you have an extra trailing newline that's eating up a character.
– xnor
Commented Oct 22, 2021 at 10:53
• Thanks, @xnor. Didn't know whether leaving it out was allowed or not. Commented Oct 22, 2021 at 21:27
• Outputting the sequence indefinitely is a valid format, so you can get yours down to 67 bytes Commented Oct 22, 2021 at 23:08
• Thanks @dingledooper! So, if there is no argument you needn't wrap things in a function? Commented Oct 22, 2021 at 23:58

# JavaScript (Node.js), 72 bytes

f=(n,l=0,a=[],x)=>a[n]||(n<2?1:f(n-l,a.push(x),a.map(m=>x+(x=m)||f(l))))


Try it online!

# JavaScript (Node.js), 74 bytes

f=(n,q=(n*8+1)**.5,r=q-1>>1)=>n>1?(n*8+9)**.5%1&&q%1?f(n+~r)+f(n-r):f(r):1


Try it online!

I have no idea whether following 70 byte version works or not. If you can prove its correctness or find out failed testcases, please leave a comment here:

f=(n,q=(n*8+1)**.5,r=--q>>1)=>n>1?q%2<2-2/r&&q%2?f(n+~r)+f(n-r):f(r):1


Try it online!

# Appleseed, 127 bytes

(def T(q(((R(q(1)))(S(concat(q(1 1 1))(drop 4(T)))))(concat R(T(cons(head S)(insert-end(head S)(zip-with add(tail R)R)))(tail S


Defines a function T that takes no arguments and returns the sequence as an infinite list. Try it online!

### Ungolfed + explanation

(def TriSeq
(lambda
((Row (q (1)))
(Seq (concat (q (1 1 1)) (drop 4 (TriSeq)))))
(concat Row
(TriSeq
(tail Seq)))))


TriSeq builds the sequence one triangle row at a time. It takes two optional arguments: Row, the current row, and Seq, the sequence up to this point. The first row is the default value for Row, (q (1)), a list containing a single 1. After that, the interior portion of the next row is calculated from Row by (zip-with add (tail Row) Row). The exterior numbers come from the next element in the sequence, (head Seq). Seq is initialized by its default value, (concat (q (1 1 1)) (drop 4 (TriSeq))). Conceptually, this is:

(1 1 1 1 2 1 1 3 3 ...)   ; (TriSeq) (a recursive call with lazy evaluation)
(2 1 1 3 3 ...)           ; (drop 4 (TriSeq))
(1 1 1 2 1 1 3 3 ...)     ; (concat (q (1 1 1)) (drop 4 (TriSeq)))


We don't need the first 1 in the sequence because it's supplied by the default value for Row. We have to do the drop/concat routine because the first few values of the sequence are self-referential, and Appleseed will get into an infinite recursion trying to calculate them unless we specify them explicitly.

# Ruby, 85.. 72 bytes

*l=1
1.step{|i|p *l[-i,i]
l+=[m=l[i]||1,*(-i..-2).map{|j|l[j,2].sum},m]}


Try it online!

• Thanks to @Dingus for the 5 Bytes saved!

Full program, outputs the sequence indefinitely vertically.

*l=1       # we start with [1]
1.step{|i| # iterate i starting from 1(i is the boundary position == triangle line length)
p *l[-i,i] # puts last i elements
l+=[...]   # append new triangle line :
[m=l[i]||1   #[ m=boundary || 1 because initially not available
*            #, splat inner elements :
(-i..-2).map{  #* range of last i pos.
|j|l[j,2].sum} #* take 2 and sum
m            # right bound]
} repeat indefinitely

• 72 bytes as a full program. Commented Oct 23, 2021 at 2:49
• @Dingus you are 1.step ahead! Commented Oct 23, 2021 at 7:50

# Charcoal, 47 bytes

ＮθＦ³⊞υ¹≔…υ²ηＷ‹Ｌυθ«⊞η⁻§υＬη§υ⊖ＬηＵＭη⁺κ§η⊖λ≔⁺υηυ»Ｉυ


Try it online! Link is to verbose version of code. Outputs the first n terms. Explanation:

Ｎθ


Input n.

Ｆ³⊞υ¹


Start the flattened list with the first three terms.

≔…υ²η


This corresponds to having already generated the second row.

Ｗ‹Ｌυθ«


Repeat until sufficient terms have been collected.

⊞η⁻§υＬη§υ⊖Ｌη


Push the difference between the next two terms to the row. (Normally Pascal's Triangle just needs 0 pushed here, but this makes the row ends follow the sequence itself.)

ＵＭη⁺κ§η⊖λ


Generate the next row of the triangle.

≔⁺υηυ


Accumulate it to the flattened list.

»Ｉυ


Output the first n terms.

# Raku, 60 bytes

my@a=flat(1,<1 1>,{@a[++$+1],|(.[1..*]Z+@$_),@a[++$+1]}...*)  Try it online! This is a lazy, self-referential, infinite list, stored in the variable @a. The expression inside the flat is a sequence of rows, where .[1..*] Z+ @$_ generates the inside sums (by addition-zipping the row with itself without its first element), and the endpoints are taken from the flattened outer array @a. The two lone $s are anonymous state variables that start off undefined/zero, so the first time the generator block is entered for the third row, the endpoints @a[++$+1] are @a[2], when the fourth row is generated the endpoints are @a[3], etc.

# R, 89 85 bytes

-4 bytes thanks to @Giuseppe

function(n){s=r=!!1:2