32
\$\begingroup\$

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.

Ready... set.... go!

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

43 Answers 43

22
\$\begingroup\$

Python 2, 65 55 53 51

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

Shortened using some of ugoren's ideas.

\$\endgroup\$
2
  • \$\begingroup\$ Heh, I knew there was room for improvement :P \$\endgroup\$ Commented May 12, 2013 at 7:51
  • 2
    \$\begingroup\$ You can save a lot by s=s[1:] per loop and while s: \$\endgroup\$
    – ugoren
    Commented May 12, 2013 at 8:39
10
\$\begingroup\$

GolfScript (25 chars)

8,{.~10,<1>\' '*.2$-1%n}/
\$\endgroup\$
9
\$\begingroup\$

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
\$\endgroup\$
5
\$\begingroup\$

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
\$\endgroup\$
4
\$\begingroup\$

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\_@#<
\$\endgroup\$
4
\$\begingroup\$

JavaScript, 71

s='1234567887654321',i=10;while(--i)console.log(s=s.split(i).join(' '))
\$\endgroup\$
1
  • \$\begingroup\$ s="1234567887654321";for(i=10;--i;)console.log(s=s.split(i).join(" ")) for 70 characters, @SteveWorley \$\endgroup\$ Commented Oct 27, 2014 at 0:02
3
\$\begingroup\$

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;
}
\$\endgroup\$
3
\$\begingroup\$

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,' ')
\$\endgroup\$
3
\$\begingroup\$

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'
\$\endgroup\$
2
  • \$\begingroup\$ I would say this is 42, due to the fact that the standard look on -E is a one-byte addition to the program. \$\endgroup\$
    – Timtech
    Commented Oct 26, 2014 at 21:25
  • \$\begingroup\$ " "x$_ is shorter than $"x(2*$_) for the void space in the middle. \$\endgroup\$
    – Xcali
    Commented Apr 29 at 21:47
3
\$\begingroup\$

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];
\$\endgroup\$
2
  • \$\begingroup\$ 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}] \$\endgroup\$
    – Mr.Wizard
    Commented May 13, 2013 at 23:38
  • \$\begingroup\$ Thanks for the tips. Yes, Array can sometimes make nice tables without one's having to add iterators. \$\endgroup\$
    – DavidC
    Commented May 14, 2013 at 2:17
3
\$\begingroup\$

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

\$\endgroup\$
5
  • \$\begingroup\$ hehe nice +1 \$\endgroup\$
    – HamZa
    Commented Jun 3, 2013 at 13:58
  • \$\begingroup\$ doesn't appear to put the right number of spaces in the middle though \$\endgroup\$ Commented Jun 4, 2013 at 22:14
  • \$\begingroup\$ @nathanhayfield: How so? First line has 0 spaces, second has 2, then 4, 6, 8, etc. \$\endgroup\$
    – Mr. Llama
    Commented Jun 5, 2013 at 16:27
  • \$\begingroup\$ not when i ran it on writecodeonline.com/php \$\endgroup\$ Commented Jun 5, 2013 at 16:54
  • \$\begingroup\$ 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. \$\endgroup\$
    – Mr. Llama
    Commented Jun 5, 2013 at 17:30
3
\$\begingroup\$

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
\$\endgroup\$
2
\$\begingroup\$

Python 2.x - 73 65 63 61 chars

c=1;s='87654321'
while c<9:print s[::-1]+s;s=' '*c+s[c:];c+=1
\$\endgroup\$
2
\$\begingroup\$

PHP, 76

for($i=9;$i>1;){$r[]=$i--;echo str_replace($r,' ','1234567887654321')."\r";}
\$\endgroup\$
2
\$\begingroup\$

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"
\$\endgroup\$
2
\$\begingroup\$

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
\$\endgroup\$
2
\$\begingroup\$

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"    
\$\endgroup\$
1
  • \$\begingroup\$ Can trim a byte by using {x,|x}' instead of x,'|:'x:. \$\endgroup\$
    – coltim
    Commented Jan 2, 2021 at 15:54
2
\$\begingroup\$

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)

\$\endgroup\$
4
  • \$\begingroup\$ It doesn't look like the other answer, the numbers are not aligned on the right column. \$\endgroup\$
    – A.L
    Commented Oct 26, 2014 at 1:51
  • \$\begingroup\$ @A.L. The alert isn't necessary if you read what output comes out of the consonle btw. \$\endgroup\$ Commented Oct 26, 2014 at 12:35
  • \$\begingroup\$ 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. \$\endgroup\$
    – Qwertiy
    Commented Oct 26, 2014 at 13:00
  • \$\begingroup\$ 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. \$\endgroup\$
    – A.L
    Commented Oct 27, 2014 at 16:58
2
\$\begingroup\$

Brainfuck: 542 Bytes

-[----->+<]>--.+.+.+.+.+.+.+..-.-.-.-.-.-.-.>++++++++++.[->+++++
<]>-.+.+.+.+.+.+.+[-->+<]>++++..----[->++<]>-.-.-.-.-.-.-.>++++++++++.[->+++++
<]>-.+.+.+.+.+.[-->+<]>+++++....-----[->++<]>.-.-.-.-.-.>++++++++++.[->+++++
<]>-.+.+.+.+.--[--->++<]>--......-----[->++<]>-.-.-.-.-.>++++++++++.[->+++++
<]>-.+.+.+.-[--->++<]>--........++[-->+++<]>+.-.-.-.>++++++++++.[->+++++
<]>-.+.+.[--->++<]>--..........++[-->+++<]>.-.-.>++++++++++.[->+++++
<]>-.+.--[--->++<]>............[-->+++<]>++.-.>++++++++++.[->+++++
<]>-.-[--->++<]>..............[-->+++<]>+.
\$\endgroup\$
1
\$\begingroup\$

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]
\$\endgroup\$
1
  • \$\begingroup\$ I just saved 4 chars by using Grid, inspired by your entry. \$\endgroup\$
    – DavidC
    Commented May 13, 2013 at 23:26
1
\$\begingroup\$

R: 52

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

Haskell, 84

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.

\$\endgroup\$
1
\$\begingroup\$

Tcl: 91 characters

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

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
\$\endgroup\$
1
  • \$\begingroup\$ Its nice to see that I'm not the only one who loves PostScript out there. \$\endgroup\$ Commented Jul 12, 2013 at 12:59
1
\$\begingroup\$

TSQL, 148

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

Readable:

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
\$\endgroup\$
2
  • 1
    \$\begingroup\$ 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. \$\endgroup\$
    – manatwork
    Commented Jun 7, 2013 at 9:15
  • \$\begingroup\$ @manatwork: I couldn't reproduce the 153 number, because I kept getting lower. Applied your suggestion, though. Thanks! \$\endgroup\$ Commented Jun 10, 2013 at 23:01
1
\$\begingroup\$

Haskell, 79

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

\$\endgroup\$
1
\$\begingroup\$

k, 33 chars

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

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

\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.