Alpha-Numerical Bowtie

Output this exact text:

1                i
12              hi
123            ghi
1234          fghi
12345        efghi
123456      defghi
1234567    cdefghi
12345678  bcdefghi
123456789abcdefghi
12345678  bcdefghi
1234567    cdefghi
123456      defghi
12345        efghi
1234          fghi
123            ghi
12              hi
1                i


A single trailing newline is acceptable, but no other formatting changes are allowed.

Rules and I/O

• No input
• Output can be given by any convenient method.
• Either a full program or a function are acceptable. If a function, you can return the output rather than printing it.
• Standard loopholes are forbidden.
• This is so all usual golfing rules apply, and the shortest code (in bytes) wins.
• Can we use the uppercase alphabet instead? – Cows quack Jun 25 '18 at 15:47
• @Cowsquack That would be a rule change. It says Output this exact text. – Dennis Jun 25 '18 at 15:52
• @Cowsquack Nope - lowercase is required. – AdmBorkBork Jun 25 '18 at 15:57

C, 878581 80 bytes

j;main(i){for(;++i<19;)for(j=19;j--;)putchar(j?j<i^j<20-i?32:106-j-j/10*39:10);}


Try it online!

Explanation

j; // same as int j;
main(i){ // same as int main(int i){, where i = argc (1 with no arguments)
for(;++i<19;) // loop over rows, i = 2..18
for(j=19;j--;) // loop over chars, j = 19..0
putchar(j?j<i^j<20-i?32:106-j-j/10*39:10); // output characters:
//      j?                           :10 // on last char (j=0), output \n
//        j<i                            // check for top/left half
//            j<20-i                     // check for bottom/left half
//           ^                           // 1 if only one half matched
//                  ?32:                 // if so, output space
//                      106              // char code for j
//                         -j            // get desired letter
//                           -j/10*39    // subtract 39 for j>9 (numbers)
}

• I'm amazed ^ has lower precedence than <… what a pretty answer! – Lynn Jun 26 '18 at 13:12
• @Lynn The bitwise operators in C (and even Java/JS and such) all have a lower precedence than comparisons. This is both nice for code golf and a really nice source of errors (think if (x & 2 == 0), which always evaluates to 0) – PurkkaKoodari Jun 26 '18 at 21:57

Python 2, 73 bytes

i=9
exec"i-=1;a=abs(i);print'123456789'[:9-a]+'  '*a+'abcdefghi'[a:];"*17


Try it online!

R, 64 bytes

for(i in abs(8:-8))cat(intToUtf8(c(57-8:i,32*!!-i:i,97+i:8,13)))


Try it online!

• -3 bytes thanks to @Giuseppe
• -5 bytes thanks to @J.Doe
• 67 bytes with intToUtf8 – J.Doe Sep 7 '18 at 16:10
• cat for one byte? – JayCe Sep 7 '18 at 19:26
• 64 bytes building on your solution, using @Giuseppe's shortcut to rep plus the feature of intToUtf8 that a 0 turns into a "". – J.Doe Sep 7 '18 at 21:34
• @J.Doe great trick! – JayCe Sep 8 '18 at 0:22
• @J.Doe : Awesome, thanks ! – digEmAll Sep 8 '18 at 9:39

05AB1E (legacy), 16 bytes

9L©A9£S«®Âì×ζRû»


Try it online!

-1 thanks to Kevin Cruijssen.

• 16 bytes by changing žh¦A9£«S9L to 9L©A9£S«® (or 9LA9£S«9L or 9LDA9£S«s). – Kevin Cruijssen Aug 31 '18 at 9:05

Python 2, 80 bytes

j=i=1
exec"print'123456789'[:i]+'  '*(9-i)+'abcdefghi'[-i:];i+=j;j-=2*(i>8);"*17


Try it online!

• 77 bytes – ovs Jun 25 '18 at 15:27
• @ovs it would converge into Lynn's answer, so I'll leave this one as is – Rod Jun 25 '18 at 16:14

QBasic, 72 bytes

Based on Taylor Scott's submission.

FOR y=-8TO 8
z=ABS(y)
?"123456789abcdefghi";
LOCATE,10-z
?SPC(2*z)"
NEXT


Basic explanation

On each line, we print the full string 123456789abcdefghi. Then we go back and overwrite part of it with spaces.

Full explanation

With code slightly ungolfed:

FOR y = -8 TO 8           ' Loop for 17 rows
z = ABS(y)               ' z runs from 8 to 0 and back to 8
? "123456789abcdefghi";  ' Print the full string and stay on the same line (important!)
LOCATE , 10-z            ' Go back to column 10-z on that line
? SPC(2*z); ""           ' Print 2*z spaces
' (SPC keeps the cursor on the same line unlesss you print
' something after it, so we'll use the empty string)
NEXT                      ' Go to the next y value

• That's a really clever use of the Locate command – Taylor Scott Jul 9 '18 at 18:42

T-SQL, 108 bytes

DECLARE @ INT=8a:
PRINT STUFF('123456789abcdefghi',10-abs(@),2*abs(@),SPACE(2*abs(@)))
SET @-=1IF @>-9GOTO a


Tried lots of other variations, including number tables, this was the shortest.

05AB1E, 20 bytes

9LJη.BA9£.sí.Bí)øJû»


Try it online!

Japt, 20 bytes

9Æ9Ç>YÃê1 Ë?S:°EsH
ê


Japt Interpreter

Output as an array of arrays of characters. The -R flag isn't necessary to work, it just makes the output look nicer.

Explanation:

9Æ9Ç                    create a 9x9 2D array
>YÃ                 fill bottom left triangle with "false", upper right with "true"
ê1               mirror horizontally
Ë?S           replaces "true" with a space
:°EsH      replaces "false" with the horizontal index + 1 converted to base 32
\n    Store the result in U (saves bytes by not closing braces)
ê   palindromize vertically


Stax, 18 bytes

â4+╤jo♂▐▀3bkWíæß╝╖


Run and debug it

Explanation:

9R$|[|<Va17T|]r|>\|pm Full program 9R$                   Produce "123456789"
|[|<               Left-aligned prefixes (["1        ", "12       ", ...])
Va17T          Produce "abcdefghi"
|]        Suffixes (["abcdefghi", "bcdefghi", ...])
r|>     Reverse and left-align (["        i", "       hi", ...])
\    Zip both arrays (["1                i", "12              hi", ...])
|p  Palindromize array
m Map over array, printing each with a newline


APL (Dyalog Unicode), 30 bytes

(⊢⍪1↓⊖)(↑,\1↓⎕d),⌽↑,\⌽819⌶9↑⎕a


Try it online!

↑ convert to a matrix (auto pads with spaces)

• ,\ the prefixes of

• 1↓ the first element dropped from

• ⎕d this string '0123456789'

• This gives the character matrix

1
12
123
1234
12345
123456
1234567
12345678
123456789


, concatenated with

• ⌽ the reversed

• ↑ matrixified

• ,\ prefixes of

• ⌽ the reversed

• 819⌶ and lowercased

• 9↑ first 9 elements of

• ⎕a this string 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

• This gives the character matrix

        i
hi
ghi
fghi
efghi
defghi
cdefghi
bcdefghi
abcdefghi


and on this result

1                i
12              hi
123            ghi
1234          fghi
12345        efghi
123456      defghi
1234567    cdefghi
12345678  bcdefghi
123456789abcdefghi


perform the following train (⊢⍪1↓⊖)

⊢ the right argument

⍪ concatenated vertically with

1↓ the first row dropped from (this avoids the repeating of the middle row)

⊖ the right argument reversed vertically

Other solutions

33 bytes

(⊢⍪1↓⊖)(↑,\⍕¨q),⌽↑,\⎕ucs 106-q←⍳9


Try it online!

33 bytes

(⊢⍪1↓⊖)(↑,\⍕¨q),⌽↑,\⌽⎕ucs 96+q←⍳9


Try it online!

Charcoal, 22 17 bytes

Ｇ↗↓←⁹β←Ｇ↖↓⁹⭆χι‖Ｏ↓


Try it online! Link is to verbose version of code. Explanation:

Ｇ↗↓←⁹β


Draw a lower right triangle and fill it using the lowercase alphabet. (The fill is based on tiling the plane with the alphabet and then copying the drawn area.)

←


Move left to draw the numeric triangle.

Ｇ↖↓⁹⭆χι


Draw a lower left triangle and fill it using the digits. (Since the triangle is drawn to the left of the origin, the digits are taken right-justified, so only the digits 1 to 9 get used.)

‖Ｏ↓


Reflect to complete the bottom half.

V, 25, 21 bytes

¬19¬ai8ñHÄ/á
r ge.YGp


Try it online!

2-4 bytes saved thanks to nmjcman101!

Hexdump:

00000000: ac31 39ac 6169 38f1 48c4 2fe1 0a72 2067  .19.ai8.H./..r g
00000010: 652e 5947 70                             e.YGp

• I know all I'm doing is stalking your answers today but I think this works for 23: Try it online! – nmjcman101 Jun 25 '18 at 21:38
• @nmjcman101 For whatever reason, I can't comprehend how that version works. But I figured out an even shorter one, so thanks! – DJMcMayhem Jun 25 '18 at 21:52
• It went to the end of a /\d* search – nmjcman101 Jun 25 '18 at 22:43

J, 44 bytes

(m]\u:49+i.9),.(m=.,}.@|.)]\&.(|."1)u:97+i.9


Try it online!

I tried to generate numerically a mask of 1 and zero to use for indexing, but the cost of getting rid of the extra row was high and I gave up:

   (9-.~i.18){0<:-/~(,|.)i.9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1
1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1
1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1
1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1
1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1
1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1
1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1
1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1
1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1
1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1
1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1


Perl 5 + -M5.010, 49 bytes

say 1..9-abs,"  "x abs,(a..i)[-9+abs..-1]for-8..8


Try it online!

Japt, 24 bytes

Returns an array of lines

9Æ´AçXÄ
c¡A°îYd#a
Vù y ê


Test it

Explanation

9Æ            :Map each X in the range [0,9)
´A          :  Prefix decrement A (initially 10)
ç         :  Repeat
XÄ       :  X+1
\n            :Assign to variable U
¡            :Map each element at index Y in U
A°          :  Postfix increment A
î         :  Repeat
d       :  The character at codepoint
Y #a     :  Y+97
c             :Concatenate with U
\n            :Assign to variable V
Vù            :Left pad each element in V to the length of the longest element
y          :Transpose
ê        :Palindromise


Alternatives

9õÈîZqÃú Ë+EòdEn#i)¬ù9Ãê


Test it

9ÇòdZn#i)cZòÄ)¬Ãú ®éJ´Ãê


Test it

• I'm wondering now if building this horizontally might not have led to a shorter solution! :\ – Shaggy Jun 25 '18 at 16:56

QBasic, 87 bytes

An anonymous function that takes no input and outputs to the console.

For y=-8To 8:z=Abs(y):a$="123456789abcdefghi":?Mid$(a$,1,9-z)Spc(2*z)Mid$(a$,10+z):Next  This answer is technically a polyglot, and will function in VBA Canvas, 13 bytes ９Ｒ［］ｚ９ｍ±［］±＋─  Try it here! Befunge-93, 314 308 bytes <p0+3*67p0+4*77p0+3*77p0-7*88p0-6*88"#v#v>" "i "11g1-21p56+1g1+56+1p28*1g1+28*1p ^ >25* " 1"92g1+82p56+2g1-56+2p28*2g1-28*2p91g00g#v_^ > "ihgfedcba "93p26*3g1-26*3p">^"88*7-0p88*7-4pv >25* "987654321 "14p26*4g1+26*4p26*4g12g#v_ ^ >:#,_@#:<  Try it online! Golfed 6 bytes by placing a > with the p instruction Matlab, 122 bytes function[r]=f,s=[49:57,'a':'i'];r=[];for i=1:9,r=[r;s(1:i),repmat(' ',[1,18-2*i]),s(19-i:18)];end,r=[r;flip(r(1:8,:))];end  Try it Online! PowerShell 5.1, 706964 57 Bytes Thanks Mazzy for -7 bytes 1..9+8..1|%{-join(1..$_+'  '*(9-$_)+' ihgfedcba'[$_..1])}


Turns out gluing it together manually saves a byte. Making it all one mega-join also saves 5 more. Also works by turning a range of ints into a char[] to get the a-i. Using a range over the actual letters is 5 bytes better.

• try this: 1..9+8..1|%{-join(1..$_+' '*(9-$_)+' ihgfedcba'[$_..1])}. Note ' '*(9-$_) contains 2 space symbols – mazzy Sep 5 '18 at 14:05
• @mazzy ooof, missing that double space trick. I was thinking of a variety of math statements but the obvious solution never occurred to me. – Veskah Sep 5 '18 at 20:51

C (gcc), 143142127+10=137 136+10=146 (compiler flags) bytes

-1 byte by replacing logical OR with bitwise operator.

-5 bytes thanks to Logern.

+9 bytes to fix the median line, that was output twice.

char*s="123456789abcdefghi";G{for(;j<18;++j)putchar(i>j|j>17-i?s[j]:32);puts("");}f(){int i=0,j=0;for(;i++<8;)G;g(i+1,j);for(;i-->1;)G;}


Compiler flag:

-DG=g(i,j)


This macro factorizes the occurences of g(i,j): function declaration and calls.

Try it online!

Different approach than Pietu1998's great answer, more straightforward (and readable), but higher score.

Entry point is function f(); function g() handles the printing of each consecutive line.

Could be made a full program by renaming f to main, but it would yet increase the score.

Pretty version, macro G expanded:

char *s = "123456789abcdefghi";
int g(int i, int j) {
for(; j < 18; ++j)
putchar((i > j | j > 17 - i) ? s[j] : 32);
puts(""); // Break the line -- shorter than putchar(10) or printf("\n")
}
int f() {
int i = 0, j = 0; // j is constant, declared here to not have to declare and init it inside g()
for(; i++ < 8;) // Upper half of the tie
g(i, j);
g(i + 1, j); // Median line
for(; i-- > 1;) // Lower half; --i > 0 would also work for the condition
g(i, j);
}

• 137 bytes - Try it online! – Logern Sep 24 '18 at 23:28
• 137 but +10 for the compiler flags though – joH1 Sep 25 '18 at 15:38
• 137 is the total, 127 bytes of code and 10 bytes of compiler flags. – Logern Sep 25 '18 at 16:50
• Oops sorry, my bad. Updating now! – joH1 Sep 25 '18 at 19:34
• @Logern I took the liberty to rename the macro to G, to match the function name. – joH1 Sep 25 '18 at 19:51

JavaScript (ES6), 76 bytes

f=(x=y=0)=>y<17?(x>y^x++<17-y?x.toString(36)+[
[x%=18]]:' ')+f(x||!++y):''


Try it online!

Wolfram Language (Mathematica), 81 79 bytes

a=Table[" ",17,18];Do[a[[i;;-i,i]]=a[[1-i;;i-1,i]]=i~IntegerString~35,{i,18}];a


Try it online!

Throws a lot of ignorable errors.

VBA, 75 bytes

An anonymous VBE immediate window function that takes no input and outputs to the console.

For y=-8To 8:z=Abs(y):a="123456789abcdefghi":Mid(a,10-z)=Space(2*z):?a:Next


9R€z⁶Zµạ106Ọ$Ṡ¡€Uṭ)ŒḄ  Try it online! Relies on the (likely) unintended behavior that when Ṡ (sign) acts on a character it yields Python's None. Because of this, Ṡ is a one byte check for whether it's argument is a nonzero integer since None is falsey in Python. If this behavior is changed then OƑ works as well for one more byte. Function that returns a list of lines. Java 8, 107 bytes v->{for(int i=1,j;++i<19;)for(j=19;j-->0;)System.out.printf("%c",j>0?(j<i)!=(j<20-i)?32:106-j-j/10*39:10);}  Port of @Pietu1998's C answer, so make sure to upvote him! Try it online. Python 2, 97 94 bytes i=o="123456789abcdefghi";c=8 while c:i=i[:c]+' '*(9-c)*2+i[-c:];o=i+'\n'+o+'\n'+i;c-=1 print o  Try it online! Only posted as an alternative to using eval() and because I finally got it under 100. Basically starts with the middle row then works both up and down at the same time. Yabasic, 103 bytes a$="123456789abcdefghi"
For y=-8To 8
z=Abs(y)
?Mid$(a$,1,9-z);
For i=1To z?"  ";Next
?Mid$(a$,10+z)Next


Try it online!

Pascal (FPC), 110 105 bytes

var i:int32;begin for i:=-8to 8do writeln('123456789'[1..9-abs(i)],'abcdefghi'[abs(i)+1..9]:abs(i)+9)end.


Try it online!