# Shrinking Triangles

Write an infinite list of triangle codes, defined as code where the i-th line has i bytes for all lines, such that the i-th code generates (i-1)th code and has 1 more line than the (i-1)th code.

The score is the number of lines in the initial code. Lowest score wins.

For example, if

.
..
...
....


is outputted by

.
..
...
....
print


which is outputted by

.
..
...
....
print
print.


and so on, then the score is 4.

Sandbox

• @hyper-neutrino Same language. Not quine. – l4m2 Apr 17 at 8:09
• Oh I see. How can I write an "infinite list of triangle codes" then? Do I need to design a mechanism for generating infinitely large triangles? – pxeger Apr 17 at 8:10
• Should I read the question as this? Write a program $P$ in language $L_1$, take input $n$ $(n > k \ge 0)$, output $P(n)$. The output $P(n)$ contains $n$ lines. The $i$th (1-indexed) line of $P(n)$ contains $i$ characters. When execute $P(n)$ as a program in language $L_2$, it outputs $P(n-1)$. Your score is $k$ while the lower the better. – tsh Apr 17 at 15:06
• If this is not code-golf, you should remove the code-golf tag and add correct tag for winning criterion. – tsh Apr 17 at 15:07
• I suppose the smallest output just needs to be a valid triangle, but not valid code anymore. Is that correct? – Arnauld Apr 17 at 15:31

# JavaScript (ES6), Score  10  9

Below is an example starting point with 15 lines. Bigger triangles are obtained by padding the end with 0's while preserving the final ).

0
f=
_=>
0
${f= +f}. /*###*/ replace( /..\n.+$/
,')'||00
00000000000
000000000000
0000000000000
00000000000000
0000000000000)


which is eventually reduced to:

0
f=
_=>
0
${f= +f}. /*###*/ replace( /..\n.+)  Try it online! # R, 278 lines The output of this 279-byte program: '->w;s=substring;+=paste0;x=nchar(w);y=s(w,1,138);z=sQuote(s(w,1,x-1))+y;for(i in 2:nchar(z)-2)cat("#"+s(z,1,i),sep=intToUtf8(10));cat(z).'->w;s=substring;+=paste0;x=nchar(w);y=s(w,1,138);z=sQuote(s(w,1,x-1))+y;for(i in 2:nchar(z)-2)cat("#"+s(z,1,i),sep=intToUtf8(10));cat(z)  Try it online! Each successive program is created by adding an additional character character (any character) at position 139 of the final line of the 'base' program. Ungolfed program generator: w='->w;s=substring;+=paste0;x=nchar(w);y=s(w,1,138);z=sQuote(s(w,1,x-1))+y;for(i in 2:nchar(z)-2)cat("#"+s(z,1,i),sep=intToUtf8(10));cat(z).' # define string w as the golfed working program code, # appended with extra characters to generate # successively longer versions; +=paste0 # redefine + to concatenate strings; x=nchar(w) # Now, get x = the number of characters of w y=substring(w,1,138) # define y as the working program code without any extra characters z=sQuote(substring(w,1,x-1))+y # define z as the previous full working program: that is, # the definition of w minus 1 character, plus the program code. for(i in 2:nchar(z)-2){ # Loop up to the length of z minus 1 cat("#"+s(z,1,i),sep="\n") # printing its prefixes after a "#" } # (so these are all comments in the outputted program), cat(z) # finally output the previous program code.  # Zsh, score 5 The pattern repeats like this: # h\ ea\ d -\ n-1 \$0 ###
#######
########
#########
##########
###########
############
#############


Try it online!

With this as the ultimate program:

#
h\
ea\
d -\
n-1 \
$0 ###  • #: comments, ignored • h\ea\d -\n-1 \$0: the backslashes and line breaks are eaten up to produce head -n-1 $0 • head: print the first $$\ n \$$ lines • $0: of the current program
• -n-1: with $$\ n = -1 \$$, which is treated as "all but the last"
• Runned your code score should be 5? – l4m2 Apr 17 at 20:23
• Oh, the score should be the length of the output of the final program, not the final program itself, ok – pxeger Apr 18 at 5:53

# Haskell (GHC 8.4.1, -cpp), score 28

This is the initial triangle (the first line is actually a space).


q\
=p\
rint
p=pu\
tStr;\
f(x:y)\
|length\
y>25=p"\
f ">>q('.\
'<$y);f s=\ p$show s++"\
]\n";l=putSt\
rLn;main=   do
l. concat<>map\
M_((>>p",\\\10"\
).p.show)$init[ \ " \nq\\\n=p\\\n",\ "rint\np=pu\\\nt",\ "Str;\\\nf(x:y)\\",\ "\n|length\\\n y>2",\ "5=p\"\\\nf \">>q('",\ ".\\\n'<$y);f s=\\\n",\
"q$show s++\"\\\n]\\n",\ "\";l=putSt\\\nrLn;mai",\ "n= do\nl. concat<>ma",\ "p\\\nM_((>>p\",\\\\\\10",\ "\"\\\n).p.show)$init[ \\",\


To obtain the the 29-lines triangle we add the following line.

".........................."]


From the 30th line onwards, the pattern becomes regular.


q\
=p\
rint
p=pu\
tStr;\
f(x:y)\
|length\
y>25=p"\
f ">>q('.\
'<$y);f s=\ p$show s++"\
]\n";l=putSt\
rLn;main=   do
l. concat<>map\
M_((>>p",\\\10"\
).p.show)$init[ \ " \nq\\\n=p\\\n",\ "rint\np=pu\\\nt",\ "Str;\\\nf(x:y)\\",\ "\n|length\\\n y>2",\ "5=p\"\\\nf \">>q('",\ ".\\\n'<$y);f s=\\\n",\
"q$show s++\"\\\n]\\n",\ "\";l=putSt\\\nrLn;mai",\ "n= do\nl. concat<>ma",\ "p\\\nM_((>>p\",\\\\\\10",\ "\"\\\n).p.show)$init[ \\",\
".........................."]
f ".........................."
f "..........................."
f "............................"


Try it online!

You can find a program to generate arbitrarily large triangles here.

## How?

We use the -cpp flag to allow line breaking in the source code by means of \. GHC 8.4.1 is necessary since it is the first version to export the (<>) Semigroup operator in Prelude. My answer uses a variation of this clever technique typically employed in quines. Here is the de-triangularized code.

q=print
p=putStr
f(x:y)|length y>25=p"f ">>q('.'<$y) f s=p$show s++"]\n"
l=putStrLn
main=do
l.concat<>mapM_((>>p",\\\10").p.show)$init[ " \nq\\\n=p\\\n", "rint\np=pu\\\nt", "Str;\\\nf(x:y)\\", "\n|length\\\n y>2", "5=p\"\\\nf \">>q('", ".\\\n'<$y);f s=\\\n",
"q$show s++\"\\\n]\\n", "\";l=putSt\\\nrLn;mai", "n= do\nl. concat<>ma", "p\\\nM_((>>p\",\\\\\\10", "\"\\\n).p.show)$init[ \\",
".........................."]
f ".........................."
f "..........................."
f "............................"
f "............................."


The part before f ".........................." defines a function f and then prints itself (minus the last line ".........................."]). The behaviour of f depends on the length of its argument: if the length is 26 then it prints ".........................."], otherwise if prints f "....[...].....", where the number of dots is one less then the length of its argument. In both cases, f is basically printing the line just before its invocation.

By the way, making sure that the strings of the list had the correct length was a total nightmare. You think adding some random spaces to the code above would be enough? No no no! I spent way too much time trying all the possible combinations of putStr and putStrLn, moving things around to change the number of \ in the code. The winning move was finally replacing a \n with \10`, and after that everything was magically aligned.

• Can you make a link where we can try-out the program? I tried pasting it into TIO but it gave me an error... – Dominic van Essen Apr 18 at 0:16
• @DominicvanEssen Yes, sorry, I forgot. Edited. – Delfad0r Apr 18 at 0:27