# Print an arch of ascending / descending numbers

I figured an "arch" was the best way to describe this pattern of numbers:

1234567887654321
1234567  7654321
123456    654321
12345      54321
1234        4321
123          321
12            21
1              1


Formally defined, each line consists of the numbers 1 through 9-n, (n-1)*2 spaces, and the numbers 9-n through 1 (where n is the current line).

Your task is to write, using the shortest code possible, a small script/program that prints the above pattern subject to the following restrictions:

1. You may not hardcode the entire pattern. You may only hardcode a single line of the pattern at most.
2. Your program must print a newline (any combination of \n or \r) at the end of each line.

• Additional little trick would be available with upper line 123456787654321 as it equals to 11111111^2 ;-) May 12, 2013 at 13:57
• @EgorSkriptunoff 11111111^2 == 123465787654321 != 1234567887654321 (notice the repeated 8)
– Bob
May 12, 2013 at 14:43
• This is sort-of the inverse of Print this diamond May 14, 2013 at 9:23
• It looks rather like a curtain. May 15, 2013 at 8:53

## Python 2, 655553 51

s=12345678
while s:r='%-8d'%s;print r+r[::-1];s/=10


Shortened using some of ugoren's ideas.

• Heh, I knew there was room for improvement :P May 12, 2013 at 7:51
• You can save a lot by s=s[1:] per loop and while s: May 12, 2013 at 8:39

8,{.~10,<1>\' '*.2$-1%n}/  ## APL (18) k,⌽k←↑↑∘(1↓⎕D)¨⌽⍳8  Explanation: • 1↓⎕D: the string of digits ("0123456789") minus its first element • ↑∘(1↓⎕D)¨⌽⍳8: select the first [8..1] characters ('12345678', '1234567'...) • ↑: format as matrix (filling the unused characters with blanks) • k,⌽k←: store in k, and display k followed by the vertical mirroring of k # Ruby: 61 50 characters s="87654321";s.chars{|c|puts s.reverse+s;s[c]=" "}  Sample run: bash-4.2$ ruby -e 's="87654321";s.chars{|c|puts s.reverse+s;s[c]=" "}'
1234567887654321
1234567  7654321
123456    654321
12345      54321
1234        4321
123          321
12            21
1              1


## Befunge - 3 x 18 = 54

I felt I had to do something with befunge, it's been too long since I last used it. This problem felt the most appropriate for the language.

It is horrendously slow due to the print loop that takes about 8 actions per character (counting styles differ).

80v >#v"12345678"<
>5 *^ >,#$:_$:1-:v
^2< 0p0+7\*48\_@#<


# JavaScript, 71

s='1234567887654321',i=10;while(--i)console.log(s=s.split(i).join(' '))

• s="1234567887654321";for(i=10;--i;)console.log(s=s.split(i).join(" ")) for 70 characters, @SteveWorley Oct 27, 2014 at 0:02

## C, 83 chars

main(a,b,n){
for(a=12345678,n=1e8,b=n-a-1;a;a/=10)
printf("%-8d%8d\n",a,b),
b%=n/=10;
}


# Python 2, 75 62

It won't beat Volatility's answer, but here's another approach using python's mutable strings (bytearray):

s=bytearray('1234567887654321')
for i in range(8):s[8-i:8+i]=i*'  ';print s


Edit

I found a shorter version, using str.replace:

s='1234567887654321'
for c in s[8:]:print s;s=s.replace(c,' ')


# Perl, 41

plus -E switch. Total characters on the command line: 50

requires at least perl5, version 10.

perl -E'say@!=1..8-$_,$"x(2*$_),reverse@!for-0..7'  • I would say this is 42, due to the fact that the standard look on -E is a one-byte addition to the program. Oct 26, 2014 at 21:25 # Mathematica 92 85 67 54 51 Method #1: (54 chars) Makes array using row#, col#, and distance from left-right edge. Grid@Array[If[#2<9,#2,17-#2]/.x_/;x+#>9:>" "&,{8,16}]  Method #2: (67 chars) Pad ever-shortening ranges. Print@@@Table[Join[k = PadRight[Range@i, 8, " "], Reverse@k], {i, 8, 1, -1}];  Method #3: (85 chars) Selectively fill each row of an array. Start with list of 8 space characters. Replace positions 1 and 16 with "1"; replace "2" at positions 2 and 15, etc. p = 0; q = 16; Print @@@Reverse@Rest@NestList[ReplacePart[#, {++p -> p, q-- -> p}]&,Array[" "&,q], 8];  Method #4: (86 chars) Selectively empty each row of an array. p=8;q=9; Print@@@NestList[ReplacePart[#,{p---> " ",q++-> " "}]&,Join[k=Range@8,Reverse@k],7];  Method #5: Using strings (92 chars) p=8;s="12345678"; Print[#,StringReverse@#]&/@NestList[StringReplace[#,ToString@p-- -> " "]&,s,7];  • That new one is slick! I'd +1 again if I could. :-) btw, you can drop the (), and replace #1 with #: Grid@Array[If[#2<9,#2,17-#2]/.x_/;x+#>9:>" "&,{8,16}] May 13, 2013 at 23:38 • Thanks for the tips. Yes, Array can sometimes make nice tables without one's having to add iterators. May 14, 2013 at 2:17 ## PHP, 68 (Inspired by HamZa's answer) for($n=8;$n;$r[]=$n--)echo str_replace($r," ","1234567887654321\n");

Plays on the fact that PHP's str_replace can accept an array for search and a string for replace, it'll replace every item in the array with the given string. After each iteration, the current number is added to the search array, removing it from the next loop.

Example of the code in action: http://ideone.com/9wVr0X

• hehe nice +1 Jun 3, 2013 at 13:58
• doesn't appear to put the right number of spaces in the middle though Jun 4, 2013 at 22:14
• @nathanhayfield: How so? First line has 0 spaces, second has 2, then 4, 6, 8, etc. Jun 5, 2013 at 16:27
• not when i ran it on writecodeonline.com/php Jun 5, 2013 at 16:54
• That's because the output wasn't wrapped in <pre> tags. When interpreted as html text, the spaces are collapsed and the newlines are ignored, but if you check the source you'll see otherwise. Jun 5, 2013 at 17:30

# Marbelous 165

@0
08
>0
LN
--
@0
:LN
}0}0}0}0
..SAPSSD0A
{0
:PS
}0
~~09
..//
<<@0
\\>0
&0//
--@1
@020
&0/\&0
@1
:SA
@0
}0
>0!!
--00@1
@0++//
+O/\@1
+O
:SD
}0@0
\\>0\/
--/\+O
@0..+O


Pseudocode:

MB():
for x in 8..1:
LN(x)
LN(x):
SA(x)
PS(x)
SD(x)
print "\n"
PS(x):
print " "*(8-x)*2
SA(x):
for n in 1..x:
print n
SD(x):
for n in x..1:
print n


## Python 2.x - 736563 61 chars

c=1;s='87654321'
while c<9:print s[::-1]+s;s=' '*c+s[c:];c+=1


## PHP, 76

for($i=9;$i>1;){$r[]=$i--;echo str_replace($r,' ','1234567887654321')."\r";}  # K, 28 -1_a,'|:'a:8$'{-1_x}\,/$1+!8  . k)-1_a,'|:'a:8$'{-1_x}\,/$1+!8 "1234567887654321" "1234567 7654321" "123456 654321" "12345 54321" "1234 4321" "123 321" "12 21" "1 1"  You could generalise it for 36: {-1_a,'|:'a:(#*m)$'m:{-1_x}\,/$1+!x} k){-1_a,'|:'a:(#*m)$'m:{-1_x}\,/$1+!x} 5 "1234554321" "1234 4321" "123 321" "12 21" "1 1" q)k){-1_a,'|:'a:(#*m)$'m:{-1_x}\,/$1+!x} 15 "123456789101112131415514131211101987654321" "12345678910111213141 14131211101987654321" "1234567891011121314 4131211101987654321" "123456789101112131 131211101987654321" "12345678910111213 31211101987654321" "1234567891011121 1211101987654321" "123456789101112 211101987654321" "12345678910111 11101987654321" "1234567891011 1101987654321" "123456789101 101987654321" "12345678910 01987654321" "1234567891 1987654321" "123456789 987654321" "12345678 87654321" "1234567 7654321" "123456 654321" "12345 54321" "1234 4321" "123 321" "12 21" "1 1"  # GoRuby 2.1 ### 36 chars 8.w(1){|x|a=[*1..x].j.lj 8;s a+a.rv}  ### Ungolfed 8.downto(1) do |x| a = [*1..x].join.ljust(8) puts a + a.reverse end  K 20 {x,'|:'x:|x$,$1+!x} q)k){x,'|:'x:|x,$1+!x}8
"1234567887654321"
"1234567  7654321"
"123456    654321"
"12345      54321"
"1234        4321"
"123          321"
"12            21"
"1              1"

• Can trim a byte by using {x,|x}' instead of x,'|:'x:. Jan 2, 2021 at 15:54

# Javascript, 67 chars

Insipired by steveworley's answer (I would comment if I could):

### Code snippet

a='1234567887654321\n',b='',c=10;while(--c)b+=a=a.split(c).join(' ')
<a href="#" onclick="javascript:document.getElementById('output').innerHTML = b;">Display</a>
<pre id="output">...</pre>

The presence of the last newline does follow the rules.

update: cut 2 chars by removing parentheses (operator precedence) and 1 by removing an unneeded space

It seemed like it's trolling me, because no matter how many different ways I tried to shorten or simplify by un-hardcoding a segment of code, the length stayed the same until I let the "I think this counts" rule written below apply.

(If printing counts as what comes back when this is executed in the chrome console)

• It doesn't look like the other answer, the numbers are not aligned on the right column.
– A.L
Oct 26, 2014 at 1:51
• @A.L. The alert isn't necessary if you read what output comes out of the consonle btw. Oct 26, 2014 at 12:35
• To align right column, there should be 1 space instead of 2 in join's string argument. With 2 spaces it is correct aligned in chrome-based browser alert. Oct 26, 2014 at 13:00
• I updated your post (the edit should be accepted) to display the result in a snippet without a JS alert, only one space is needed in this case.
– A.L
Oct 27, 2014 at 16:58

# Brainfuck: 542 Bytes

-[----->+<]>--.+.+.+.+.+.+.+..-.-.-.-.-.-.-.>++++++++++.[->+++++
<]>-.+.+.+.+.+.+.+[-->+<]>++++..----[->++<]>-.-.-.-.-.-.-.>++++++++++.[->+++++
<]>-.+.+.+.+.+.[-->+<]>+++++....-----[->++<]>.-.-.-.-.-.>++++++++++.[->+++++
<]>-.+.+.+.+.--[--->++<]>--......-----[->++<]>-.-.-.-.-.>++++++++++.[->+++++
<]>-.+.+.+.-[--->++<]>--........++[-->+++<]>+.-.-.-.>++++++++++.[->+++++
<]>-.+.+.[--->++<]>--..........++[-->+++<]>.-.-.>++++++++++.[->+++++
<]>-.+.--[--->++<]>............[-->+++<]>++.-.>++++++++++.[->+++++
<]>-.-[--->++<]>..............[-->+++<]>+.


## Mathematica, 59

61 using my own ideas:

Grid[Clip[#~Join~Reverse@#&@Range@8,{1,9-#},{," "}]&~Array~8]


Or 59, borrowing from David's answer:

Grid@Array[Join[k=PadRight[Range[9-#],8," "],Reverse@k]&,8]

• I just saved 4 chars by using Grid, inspired by your entry. May 13, 2013 at 23:26

## R: 52

for(i in 8:1)cat(1:i,rep(" ",16-2*i),i:1,"\n",sep="")


A starting point for someone to improve:

mapM_ putStrLn[let l=take(8-i)"12345678"++replicate i ' 'in l++reverse l|i<-[0..7]]


Most likely part would be to make the l++reverse l point free, letting us get rid of the let-statement, but I'll I could find was ap, which requires imports.

## Tcl: 91 characters

set i 10
set n 1234567887654321
while {[incr i -1]} {puts [set n [string map "$i { }"$n]]}


# PostScript: 105 characters

String handling is not easy in PS but can make for relatively simple code:

0 1 7{(1234567887654321)dup
8 3 index sub(              )0 6 -1 roll 2 mul getinterval putinterval =}for


A slightly longer version at 120 chars but can generate different number arches by replacing the 8 at the start of the second line with any number in the range 1 to 9:

/D{dup}def/R{repeat}def/P{=print}def
8 D -1 1{1 1 index{D P 1 add}R pop 2 copy sub{(  )P}R D{D P 1 sub}R pop()=}for pop

• Its nice to see that I'm not the only one who loves PostScript out there. Jul 12, 2013 at 12:59

## TSQL, 148

Edit: down to 148 with manatwork's suggestion and tweak to ORDER BY.

WITH t AS(
SELECT 1n, CAST(1 AS VARCHAR(MAX)) o
UNION ALL
SELECT n+1,o+CHAR(n+49)
FROM t
WHERE n<8
)
SELECT o  + SPACE(16-2*n) + REVERSE(o)
FROM t
ORDER BY 1 DESC


Golfed:

WITH t AS(SELECT 1n,CAST(1AS VARCHAR(MAX))o UNION ALL SELECT 1+n,o+CHAR(n+49)FROM t WHERE n<8)SELECT o+SPACE(16-2*n)+REVERSE(o)FROM t ORDER BY 1DESC


Output:

1234567887654321
1234567  7654321
123456    654321
12345      54321
1234        4321
123          321
12            21
1              1

• Nice one. But could you please post it also in the format in which you counted 153 characters? Anyway, you can spare 2 characters by using numeric 1 instead of string '1' where you immediately cast it into varchar. This gives me 149 characters: with t as(select 1n,cast(1as varchar(max))o union all select n+1,o+char(n+49)from t where n<8)select o+space(16-2*n)+reverse(o)from t order by o desc. Jun 7, 2013 at 9:15
• @manatwork: I couldn't reproduce the 153 number, because I kept getting lower. Applied your suggestion, though. Thanks! Jun 10, 2013 at 23:01

r n x|x>n=' '|True=x
t="87654321"
main=mapM(putStrLn.(map("12345678"++t)).r)t


This works by replacing characters > n with ' ', where characters n are sourced from "87654321" (which happens to be the tail of the string to perform substitution on).

# k, 33 chars

{|:{x,'|:'x}a$,/'$:{1+'!x}'1+!a:x}9


# PHP: 61 chars (or 60 chars if you replace the \n by a real ASCII newline)

(Inspired by GigaWatt's and HamZa's answer)

for($n=9;$n;$r[$n--]=" ")echo strtr("1234567887654321\n",$r);  http://ideone.com/FV1NXu # PowerShell: 38 Golfed code 8..1|%{-join(1..$_+"  "*(8-$_)+$_..1)}


Walkthrough

8..1|%{...} pipe integers from 8 to 1 into a ForEach-Object loop.
-join(...) joins output of the nested code into a single string with no delimiters.
1..$_ outputs integers ascending from 1 to the current integer in the loop. +" "*(8-$_) adds a double-space, multiplied by the difference between 8 and the current integer, to the output.
+$_..1 adds integers, descending from the current integer to 1, to the output. ## Javascript with lambdas, 147 (s="12345678")[r="replace"](/./g,i=>s[r](RegExp(".{"+(i-1)+"}$"),Array(i*2-1).join(" ")))[r](/\d{1,8} */g,m=>m+(Array(m%10+1).join(m%10+1)-m)+"\n")


Can be checked in Firefox.