# The Digit Triangles

## Challenge:

Input: A positive integer $$\n\$$

Output:

Create a list in the range $$\[1,n]\$$, and join it together to a string (i.e. $$\n=13\$$ would be the string 12345678910111213).

Now we output a triangle using the prefixes or suffixes of this string, in one of the following four orientations based on the input integer:

• If $$\n\equiv 0\pmod 4\$$, output it in the triangle shape ◣
• If $$\n\equiv 1\pmod 4\$$, output it in the triangle shape ◤
• If $$\n\equiv 2\pmod 4\$$, output it in the triangle shape ◥
• If $$\n\equiv 3\pmod 4\$$, output it in the triangle shape ◢

Example:

Input: $$\n=13\$$

Because $$\13\equiv 1\pmod 4\$$, the shape will be ◤. Here three possible valid outputs:

12345678910111213    11111111111111111    12345678910111213
1234567891011121     2222222222222222     2345678910111213
123456789101112      333333333333333      345678910111213
12345678910111       44444444444444       45678910111213
1234567891011        5555555555555        5678910111213
123456789101         666666666666         678910111213
12345678910          77777777777          78910111213
1234567891           8888888888           8910111213
123456789            999999999            910111213
12345678             11111111             10111213
1234567              0000000              0111213
123456               111111               111213
12345                11111                11213
1234                 1111                 1213
123                  222                  213
12                   11                   13
1                    3                    3


## Challenge rules:

• As you can see at the three valid outputs above, only the correct shape and using all the digits in the correct order is important. Apart from that you're free to use prefixes or suffixes; reverses/reflects; diagonal printing; etc. etc. Any of the six possible outputs for each shape is allowed (see the test case below to see all valid outputs based on the shape). This allows languages with rotation builtins to use it, but those without can also use an alternative approach of using the prefixes in the correct size from top-to-bottom, or using the prefixes for two of the shapes but suffixes for the other two shapes. Choosing the most appropriate output options for your language is part of the golfing process. :)
• Input is guaranteed to be a positive integer. For $$\n=1\$$ we simply output 1.
• Any amount of leading/trailing newlines/spaces are allowed, as long as it prints the correct triangle (without vertical nor horizontal delimiters!) somewhere on the screen.

## General rules:

• This is , so shortest answer in bytes wins.
Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
• Standard rules apply for your answer with default I/O rules, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters and return-type, full programs. Your call.
• Default Loopholes are forbidden.

## Test cases:

Input: $$\n=5\$$
All possible valid outputs:

12345    54321    12345    54321    11111    55555
1234     5432     2345     4321     2222     4444
123      543      345      321      333      333
12       54       45       21       44       22
1        5        5        1        5        1


Input: $$\n=6\$$
All possible outputs:

123456    654321    123456    654321    111111    666666
12345     65432     23456     54321     22222     55555
1234      6543      3456      4321      3333      4444
123       654       456       321       444       333
12        65        56        21        55        22
1         6         6         1         6         1


Input: $$\n=7\$$
All possible outputs:

      1          1          7          7          7          1
12         21         67         76         66         22
123        321        567        765        555        333
1234       4321       4567       7654       4444       4444
12345      54321      34567      76543      33333      55555
123456     654321     234567     765432     222222     666666
1234567    7654321    1234567    7654321    1111111    7777777


Input: $$\n=8\$$
All possible outputs:

1           1           8           8           8           1
12          21          78          87          77          22
123         321         678         876         666         333
1234        4321        5678        8765        5555        4444
12345       54321       45678       87654       44444       55555
123456      654321      345678      876543      333333      666666
1234567     7654321     2345678     8765432     2222222     7777777
12345678    87654321    12345678    87654321    11111111    88888888


Input: $$\n=1\$$
Only possible output:

1


Input: $$\n=2\$$
All possible outputs:

12    21    12    21    11    22
1     2     2     1     2     1

• Can we use other values for different triangles, like 1 for ◤, etc? Mar 20, 2019 at 16:44
• @EmbodimentofIgnorance Unfortunate example, since that's what the spec says. I think you wanted to ask if we can change the order of the four arrangements as long as we keep it consistent (I think that would be a no). Mar 20, 2019 at 17:04
• If n==13, can the topmost row be '33333333333333333' (or, equivalently, '31211101987654321')? Mar 20, 2019 at 19:42
• @EmbodimentofIgnorance Sorry, but I'd say no in this case. The shapes and their corresponding mod 4 are strict pairs for this challenge. So you may not switch the four shapes for the four mod 4 cases. But good question nonetheless. Mar 20, 2019 at 21:42
• @ChasBrown Yes, both of those are fine. I only gave three possible examples for the $n=13$, but all six options (like the $n=5$ test case) are valid outputs. Mar 20, 2019 at 21:44

# JavaScript (ES6),  93  89 bytes

Returns a matrix of characters.

n=>[...(g=n=>n?g(n-1)+n:'')(n)].map((d,y,a)=>a.map(_=>y-(n&2)*y--<0?' ':d)).sort(_=>-n%2)


Try it online!

Alternate pattern (same size):

n=>[...(g=n=>n?g(n-1)+n:'')(n)].map((_,y,a)=>a.map(d=>y-(n&2)*y--<0?' ':d)).sort(_=>-n%2)


Try it online!

### Commented

n =>                 // n = input
[...               // split the result of ...
( g = n =>       //   ... a call to the recursive function g, taking n
n ?            //     if n is not equal to 0:
g(n - 1)     //       append the result of a recursive call with n - 1
+ n          //       append n
:              //     else:
''           //       stop recursion and return an empty string
)(n)             //   initial call to g
].map((d, y, a) => // for each digit d at position y in this array a[]:
a.map(_ =>       //   for each character in a[]:
y -            //     we test either y < 0 if (n AND 2) is not set
(n & 2)        //     or -y < 0 (i.e. y > 0) if (n AND 2) is set
* y-- < 0      //     and we decrement y afterwards
?              //     if the above condition is met:
' '          //       append a space
:              //     else:
d            //       append d
)                //   end of inner map()
)                  // end of outer map()
.sort(_ => -n % 2) // reverse the rows if n is odd


### Shape summary

Below is a summary of the base shape (generated by the nested map loops) and the final shape (after the sort) for each $$\n\bmod 4\$$:

 n mod 4  | 0     | 1     | 2     | 3
----------+-------+-------+-------+-------
n & 2    | 0     | 0     | 2     | 2
----------+-------+-------+-------+-------
test     | y < 0 | y < 0 | y > 0 | y > 0
----------+-------+-------+-------+-------
base     | #.... | #.... | ##### | #####
shape    | ##... | ##... | .#### | .####
| ###.. | ###.. | ..### | ..###
| ####. | ####. | ...## | ...##
| ##### | ##### | ....# | ....#
----------+-------+-------+-------+-------
n % 2    | 0     | 1     | 0     | 1
----------+-------+-------+-------+-------
reverse? | no    | yes   | no    | yes
----------+-------+-------+-------+-------
final    | #.... | ##### | ##### | ....#
shape    | ##... | ####. | .#### | ...##
| ###.. | ###.. | ..### | ..###
| ####. | ##... | ...## | .####
| ##### | #.... | ....# | #####

• thank you for your detail explaining. Mar 22, 2019 at 10:43

# Python 2, 94 bytes

n=0;s=''
exec"n+=1;s+=n;"*input()
K=k=len(s)
while k:k-=1;print s[k^n/-2%-2:].rjust(n%4/2*K)


Try it online!

# Japt, 8 bytes

Returns an array of lines.

õ ¬å+ zU


Try it

Saved 2 bytes thanks to Kevin.

õ ¬å+ zU     :Implicit input of integer U
õ            :Range [1,U]
¬          :Join to a string
å+        :Cumulatively reduce by concatenation
zU     :Rotate clockwise by 90 degrees U times

• Is the ú necessary? It seems the rotate does this implicitly? Mar 20, 2019 at 14:12
• @KevinCruijssen, hmm ... so it does. I always forget that; rarely get to use z. Mar 20, 2019 at 14:24
• Well, I don't know Japt at all. Was just curious what the output looked like without the padding for fun, and saw it worked exactly the same.. ;) Mar 20, 2019 at 14:30

# Canvas, 8 bytes

ŗ］∑［］⁸［↷


Try it here!

{[o](|(&reverse xx$_/2+.5),|(*>>.flip xx$_/2+1))([\~](my@a=[~](1..$_).comb)>>.fmt("%{+@a}s"))}  Try it online! Anonymous code block that takes a number and returns a list of lines. # Charcoal, 17 bytes Ｎθ≔⭆θ⊕ιηＧLＬηη⟲⊗θ‖  Try it online! Link is to verbose version of code. Explanation: Ｎθ  Input n. ≔⭆θ⊕ιη  Create a string by concatenating the numbers 1 to n. ＧLＬηη  Fill a triangle of that length with the string. ⟲⊗θ  Rotate the triangle anticlockwise by n*90 degrees. ‖  Reflect everything, thus ending up with a triangle that is rotated clockwise by n*90 degrees. # C# (Visual C# Interactive Compiler), 128 bytes n=>{var s="";int i=0,j,p;for(;i<n;s+=++i);for(p=j=s.Length;;)Write("{0,"+(n%4>1?p:0)+"}\n",new string(s[--j],-~n%4>1?j+1:p-j));}  Try it online! • Suggest n%4/2*p instead of n%4>1?p:0 Nov 27, 2020 at 1:57 # Ruby, 9582 79 bytes ->n{r=(0...z=/$/=~s=[*1..n]*'').map{|i|" "*n[1]*i+s[0,z-i]};-n&2>0?r:r.reverse}


Try it online!

3 bytes saved by G B.

# R, 152139137 134 bytes

function(n,N=nchar(s<-Reduce(paste0,1:n,'')),A=!n%%4%%3)for(i in 1:N)cat(rep('',(M=c(N-i+1,i))[1+!A]*(n%%4>1)),substr(s,1,M[1+A]),'
')


Unrolled code :

function(n){
s = Reduce(paste0,1:n,'')      # concat the digits from 1 to n into a string s

N = nchar(s)                   # store the length of s

A = !n%%4%%3                   # A = TRUE if n MOD 4 == 1 or 2

for(i in 1:N){                 # for 1 to N (length of s)

M = c(N-i+1,i)               # store N-i+1 and i into a vector

nSpaces = M[1+!A]*(n%%4>1)   # if n MOD 4 == 1 or 2 then nSpaces = i else nSpaces = N-i+1,
# but if n MOD 4 == 0 or 1, then force nSpaces = 0

nDigits = M[1+A]             # if n MOD 4 == 1 or 2 then nDigits = N-i+1 else nDigits = i

prfx = rep('',)              # create a character vector repeating '' nSpaces times

sufx = substr(s,1,M[1+A])    # substring s by taking the first nDigits characters

cat(pr,su,'\n')              # print prfx and sufx using space as separator for the values
# contatenation (cat function default) and append a newline
}


Try it online!

• ...it hasn't been my day for golfing, clearly. Mar 22, 2019 at 21:51
• @Giuseppe: ahah been there...and then you usually outgolfed me :P Mar 23, 2019 at 11:55

# APL+WIN, 45 bytes

Prompts for integer

m←⊃(⍳⍴s)↑¨⊂s←(⍕⍳n←⎕)~' '⋄⍎(' ⊖⍉⌽'[1+4|n]),'m'


Try it online! Courtesy of Dyalog Classic

param($n)0..($y=($x=-join(1..$n)).length-1)|%{' '*(0,0,$_,($z=$y-$_))[$n%4]+-join$x[0..($_,$z,$z,$_)[$n%4]]}  Try it online! A bit rough around the edges but works. Joins the digits 1 to n into a string then iterates from 0 to the length of that string-1. Each time, it uses list indexing to swap to the correct spacing method and number range used to slice our new string. # Jelly, 12 bytes D€Ẏ;\z⁶U$⁸¡Y


Try it online!

# 05AB1E (legacy), 1412 10 bytes

Using the legacy verion as the rewrite is extremely slow on this for some reason.

Saved 2 bytes thanks to Kevin Cruijssen

LSηsFRζ}J»


Try it online!

Explanation

L           # push range [1 ... input]
S          # split to list of individual digits
η         # calculate prefixes
sF  }    # input times do:
R      # reverse list
ζ     # and transpose it
J   # join to list of strings
»  # and join on newlines

• You can save 2 bytes changing LJη€S to LSη, since S implicitly flattens. Mar 20, 2019 at 14:22
• @KevinCruijssen: Oh yeah, thanks! I'd forgotten about that. I tried €S which didn't work out very well ;) Mar 20, 2019 at 14:24

# Stax, 10 bytes

Ç√çZ╟84Γó║


Run and debug it

# PowerShell, 105101 95 bytes

-4 bytes thanks Arnauld for the trick with Sort.

param($n)($x=1..$n-join'')|% t*y|%{($s+="$_")}|sort -d:($n%4-in1,2)|% *ft($x.Length*($n%4-ge2))


Try it online!

Less golfed:

param($n)$x=1..$n-join''$x|% toCharArray |% {
($s+="$_")
} | sort -Descending:($n%4-in1,2) |% PadLeft ($x.Length*($n%4-ge2))  # R, 175172 154 bytes function(n)write(c(" ",0:9)[1+(x=utf8ToInt(Reduce(paste0,1:n,""))-47)*!upper.tri(diag(y<-sum(x|1)))["if"(n%%4>1,1:y,y:1),"if"(!n%%4%%3,y:1,1:y)]],1,y,,"")  Try it online! A horrible in-line mess! -3 bytes by changing the rotation condition -17 bytes thanks to digEmAll's suggestion, and another byte after golfing that further • I like this upper.triangle approach and can be shortened to 155 bytes... maybe even more, I'm sure I'm missing something obvious... Mar 23, 2019 at 13:35 • @digEmAll ah, much improved, but still long :-( Mar 24, 2019 at 0:46 # Wolfram Language (Mathematica), 137 bytes (t=Table[Table[" ",If[(m=#~Mod~4)>1,Tr[1^s]-k,0]]<>ToString/@s[[;;k]],{k,Length[s=Join@@IntegerDigits/@Range@#]}];If[0<m<3,Reverse@t,t])&  Try it online! # Python 2, 116 bytes n=input() s=''.join(map(str,range(1,n+1)));L=len(s) p=-~n/2%2;i=~-L*p+1 exec'print s[:i].rjust(n/2%2*L);i+=1-2*p;'*L  Try it online! # Red, 155 bytes func[n][b: copy""repeat i n[append b i]repeat i l: length? b[t:[l - i + 1]set[k m]pick[i t[l t][l i]]n % 4 + 1 print pad/left copy/part b do do m do do k]]  Try it online! # perl 5, 117 bytes $p=$_++&2?'/ ':'$/';$s='(.*\d.\n)';$r=$_--&2?$s.'\K$':"^(?=$s)";$_=(join"",1..$_).$/;1while s,$r,'$1=~s/\d'."$p/r",ee


TIO

# PHP, 116111 109 bytes

for($m=$l=strlen($s=join(range(1,$n=$argn)));$l--;)printf('%'.($n&2?$m:-$l).'.'.($n-1&2?$m-$l:$l+1)."s ",$s);


Try it online!

Run with php -nF input from STDIN.

\$ echo 6|php -nF t.php

123456
12345
1234
123
12
1


# Java (JDK), 247209188186160 148 bytes

i->{String s="";int l=0,w;for(;l<i;s+=++l);for(w=s.length(),l=0;l<w;)System.out.printf("%"+(1>i%4/2?1:w)+"s\n",s.substring(0,1>~-i%4/2?w-l++:++l));}


Try it online!

-38 bytes thanks to @KevinCruijssen
-21 bytes by letting printf handle the padding.
-2 bytes by doing substring before replace, allowing us to increment l in one location rather than two.
-26 bytes - with printf doing the padding, the string full of spaces was no longer necessary, and the digit strings could be generated in a shorter way apparently.
-12 bytes by not messing about with single digits instead of printing substrings of the perfectly servicable digit string we already have.

# Ungolfed

input->{
// Lambda expression with target type of IntConsumer
String allDigits = "";
int lineLength, line = 0;

// Collect a list of all digits in order.
for (;line < input; allDigits += ++line) {}

// Save the max length of a line, and create a string of that many spaces.
for (lineLength=allDigits.length(), line=0; line < lineLength;) {
System.out.printf(   "%" // construct a format string to handle the padding
+ (   1 > input%4/2

• Nice answer. There are a bunch of things to golf more, though: The spaces after the for( can be removed. new String(new char[w=s.length()]).replace('\0',' ') can be " ".repeat(w=s.length()) using Java 11+. You can remove the parenthesis around the ternary-checks. 1>(i-1)%4/2 can be 1>~-i%4/2. w-1-l++ can be w+~l++. And you don't have to count the trailing semicolon in the byte-count. Which all combined becomes 209 bytes. Mar 24, 2019 at 16:56