There are an abundance of questions involving drawing shapes using asterisks - so I thought, with so many asterisks out there, we should draw one, using the ASCII table.

Challenge

Your task is to write a program or function which takes no input, and outputs this exact text:

          !
         "#
         $%
         &'
         ()
         *+
         ,-
         ./
         01
23456789:;<=>?@ABCDEF
GHIJKLMNOPQRSTUVWXYZ[
        \]^_
       `a  bc
      de    fg
     hi      jk
    lm        no
   pq          rs
  tu            vw
 xy              z{
|}                ~

For reference, this site lists the complete ASCII table.

Rules

  • The output should be the exact text, as shown above. Leading/trailing whitespace is allowed.
  • Standard golfing loopholes apply - no reading this ASCIIrisk from the internet, etc.
  • This is , so the shortest solution (in bytes) wins.
share|improve this question

13 Answers 13

Python 3, 110 bytes

s='%c';print(('\n'.join(['%10c%c']*9+[s*21]*2+[' '*(8-i)+s*2+'  '*i+s*2for i in range(9)]))%(*range(32,128),))

Generates the template

         xx
         xx
         xx
         xx
         xx
         xx
         xx
         xx
         xx
xxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxx
        xxxx
       xx  xx
      xx    xx
     xx      xx
    xx        xx
   xx          xx
  xx            xx
 xx              xx
xx                xx

with %c for x, then uses string interpolation on range(32,128) to insert the ASCII values into the pattern.

Try it online!

Python 2 is one byte longer, with longer tuple unpacking but shorter print.

s='%c';print('\n'.join(['%10c%c']*9+[s*21]*2+[' '*(8-i)+s*2+'  '*i+s*2for i in range(9)]))%tuple(range(32,128))
share|improve this answer
    
It deserves a Eiffel Tower similarity award! – sergiol 18 hours ago

V, 54, 50 bytes

¬ ~9ñ9É 11|á
ñ2ñ20lá
ñ$18é 9ñ^y|Ehé
Pf xxywk$hP>ñd

Try it online!

Unlike usual, this program does not contain any unprintable characters.

Explanation:

¬ ~                     " Insert the entire printable ASCII range
   9ñ           ñ       " 9 times:
     9É                 "   Insert 9 spaces at the beginning of this line
        11|             "   Move to the 11'th column on this line
           á<CR>        "   And append a newline after the 11'th column

Now the buffer looks like this:

          !
         "#
         $%
         &'
         ()
         *+
         ,-
         ./
         01
23456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

Now we build up the middle:

2ñ        ñ             " Two times:
  20l                   "   Move 20 characters to the right (because 'l' == 'right', duh)
     á<CR>              "   Append a newline

Here's where it gets a little weird.

$                       " Move to the end of this line 
 18é                    " Insert 18 spaces before the last character
     9ñ                 " Repeat the following 9 times:
       ^                "   Move to the first non-whitespace character
        y|              "   Yank all the whitespace before the current character. 
                        "   We'll call this the "Leading whitespace register"
          E             "   Move to the end of the current WORD (up to before a space)
           h            "   Move back one character
            é<CR>       "   And insert a newline before the current character
P                       "   Paste the leading whitespace for indentation
 f                      "   Move forward to a space
   xx                   "   Delete two characters
                        "   (Note how we are inbetween the two bottom branches right now)
     yw                 "   Yank everything upto the next branch (all spaces)
                        "   We'll paste this on the line up so that we can yank it again later
                        "   To keep track of how far apart the branches are
       k$               "   Move up a line and to the end of that line
         hP             "   Move back a character and paste the whitespace we yanked
           >            "   Indent this line by one space
            ñ           "   End the loop

Here's an important note. The > command is actually an operator, which means it doesn't do anything without an argument, the text to operate on. For example,

>_      "Indent the current line
>>      "Indent the current line
>j      "Indent the current and next line
>G      "Indent every line

But since this command is in a loop, we can save a character by not giving an operator. At the end of a loop, if any operator is pending it will fill in _ (the current line) as an argument implicitly.

Now I'll admit this loop is a little weird, and it can be hard to keep track of what all text should look like at any given moment. So you can use this simpler program to see what it will look like after N loops.

If you set it to 9, you can see that we have a little bit of extra text to get rid of. (Just the current line).

So we delete the current line with dd. But wait! You know how I said that operators have to take an argument which is sometime implicitly filled in? Arguments are also implicitly filled at the end of the program. So rather than dd or d_ (which are equivalent), we can simply to d and let V fill in the _ for us.

share|improve this answer
    
Nice job abusing the implicit ÿ :) – Kritixi Lithos yesterday
    
@DLosc Done! :) – DJMcMayhem 8 hours ago

Python 3 170 165 155 147 bytes

I've golfed this so much, I've forgotten how it works...

i=b=0
for x in range(32,127):a=x%2<1;c=x>90;d=x<50;print(end=[' '*9*d,['\n'+' '*(8-i),'  '*~-i][b]][c]*a+chr(x)+'\n'*(x==70or d*x%2));b^=a;i+=b*c*a

Try it online!

share|improve this answer

QBIC, 153 151 bytes

[32,49,2|?space$(9)+chr$(a)+chr$(a+1)][2|X=Y[a,a+20|X=X+chr$(c)]a=a+21?X][0,8|X=space$(8-d)[0,1|X=X+chr$(a+e)]X=X+space$(d*2)[2,3|X=X+chr$(a+f)]a=a+f?X

It's really just a series of FOR-loops and casting an int to a character (chr$()).

Sample output:

          !
         "#
         $%
         &'
         ()
         *+
         ,-
         ./
         01
23456789:;<=>?@ABCDEF
GHIJKLMNOPQRSTUVWXYZ[
        \]^_
       `a  bc
      de    fg
     hi      jk
    lm        no
   pq          rs
  tu            vw
 xy              z{
|}                ~
share|improve this answer

Perl, 113 bytes

112 bytes of code + -l flag.

sub g{chr$c+++32}print$"x9,&g,&g for 0..8;print map&g,0..20for 0,1;print$"x-$_,&g,&g,$"x(16+2*$_),&g,&g for-8..0

Try it online!

share|improve this answer

JavaScript (ES6), 156115 114 bytes

Sadly, the infamous String.fromCharCode() costs 19 bytes.

f=(x=y=k=1)=>k<96?String.fromCharCode(x-22?y/2^5&&(y>9?x-y+1>>1&&22-y-x>>1:x/2^5)?32:31+k++:(x=!++y,10))+f(x+1):''

console.log(f())

Formatted and commented

f = (                         // given:
  x =                         //   - x = current column
  y =                         //   - y = current row
  k = 1                       //   - k = current ASCII character code, minus 31
) =>                          //
  k < 96 ?                    // if we havent't reached character #127 (96 + 31):
    String.fromCharCode(      //   let's compute the next character
      x - 22 ?                //   if x is not equal to 22 (end of line):
        y / 2 ^ 5 && (        //     if y doesn't equal 10 or 11 (horizontal bar):
          y > 9 ?             //       and either y is greater than 9:
            x - y + 1 >> 1 && //         and we are not located on one of the
            22 - y - x >> 1   //         bottom diagonals
          :                   //       or y is less or equal to 9:
            x / 2 ^ 5         //         and x doesn't equal 10 or 11 (vertical bar)
        ) ?                   //     then:
          32                  //       append a space
        :                     //     else:
          31 + k++            //       append the next ASCII character
      :                       //   else:
        (x = !++y, 10)        //     increment y, reset x and append a LineFeed
    ) + f(x + 1)              //   do a recursive call with x + 1
  :                           // else:
    ''                        //   stop recursion
share|improve this answer
    
I think you can do String.fromCharCode(...[...Array(n)].map(_=>k++)) to save 4 bytes. – ETHproductions yesterday
    
@ETHproductions I like the idea of calling String.fromCharCode() on an array, but I went for another approach. Thanks anyway! – Arnauld yesterday

Pyth, 53 bytes

js.e@[+L*9;cb2c2b.e+*-8Ydj*yYdZcL2cb4)kcsrdC127,18 60

A program that prints the result.

Try it online!

How it works

srdC127 creates a list of the printable ASCII characters and concatenates this to a string.

c....,18 60 splits this string at indices 18 and 60, giving a list of three strings corresponding to the different parts of the output: the top, the middle and the bottom.

.e begins an enumerated map over the strings with the strings as b and their indices as k.

[...) creates a list containing the desired action for each part of the diagram. The correct action is chosen by indexing into the list with the current index, using @...k.

  • Top

    cb2 splits the string into pairs of characters, and +L*9; prepends 9 spaces to each pair.

  • Middle

    c2b splits the string into two equal-length strings.

  • Bottom

    cL2cb4 splits the string into groups of four characters, and each group into pairs.

    .e begins an enumerated map, with the string pairs as Z and their indices as Y.

    j*yYdZ joins the pairs on 2*Y spaces, and +*-8Yd prepends 8-Y spaces.

js merges all the results and joins the resulting list on newlines. This is then implicitly printed.

share|improve this answer

05AB1E, 40 38 37 bytes

7TDžx)3b+žQs£`2ô2ôvyN·ð×ýð«}r2ôR)˜R.c

Try it online!

share|improve this answer

Haskell, 144 bytes

b!n=[1..n]>>b
('*':r)#(a:s)=a:r#s
(a:r)#s=a:r#s
r#s=r
p="**"
f=unlines([" "!9++p]!9++["*"!21]!2++[" "!(8-n)++p++" "!(2*n)++p|n<-[0..8]])#[' '..]

Try it online!

Explanation:

b!n=[1..n]>>b defines a function ! which repeats a list or string b n-times.

unlines([" "!9++p]!9++["*"!21]!2++[" "!(8-n)++p++" "!(2*n)++p|n<-[0..8]]) uses this function to draw an asterisk of asterisks (Oh, the irony!):

         **
         **
         **
         **
         **
         **
         **
         **
         **
*********************
*********************
        ****
       **  **
      **    **
     **      **
    **        **
   **          **
  **            **
 **              **
**                **

# is defined as a function which consecutively replaces * in a string with chars from a given list. It's called with the above asterisk of asterisks and [' '..] which is an infinite list of all characters starting with the space ' '.

share|improve this answer

Python 2.7, 194 188 bytes

k,l,c,s,r=8,0,chr,' ',range;o=''.join(map(chr,r(32,127)))
for i in r(0,18,2):print s*9+o[i:i+2]
print o[18:39]+'\n'+o[39:60]
for i in r(60,95,4):print s*k+o[i:i+2]+s*l+o[i+2:i+4];k-=1;l+=2
share|improve this answer
    
You can drop 2 bytes by changing map(chr to map(c as c has already been defined as chr – Jack Bates 7 hours ago

tcl, 339 bytes (naïve attempt)

proc S x {string repeat \  $x}
set i 31
while \$i<48 {puts [S 9][format %c%c [incr i] [incr i]]}
set a ""
while {[incr i]<71} {set a $a[format %c $i]}
set a $a\n
while \$i<92 {set a $a[format %c $i];incr i}
puts $a
while \$i<128 {puts [S [expr (125-$i)/4]][format %c%c $i [incr i]][S [expr $i/2-46]][format %c%c [incr i] [incr i]]; incr i}

demo

share|improve this answer
1  
What do you mean by "naïve attempt"? Shouldn't you put the length in the title instead? – Jack Bates yesterday
1  
I mean there is space for golfing it more, because there is still much repetition. And I will golf it more. – sergiol yesterday

PHP, 110 105 103 93 91 bytes

for(;$c<95;$y+=!$x%=21)echo"
"[$x],chr(31+($y%11<9&(max($y,10)-abs(9.5-$x++))%11<9?:++$c));

prints a leading newline. Run with -nr.

The basic principle is adopted from Arnauld, but this iterates.
And it takes good advantage from PHP´s implicit typecasts:
NULL to int for string index, float to int for %, boolean to int for & and for +=.

explanation with pseudo code

If $x is 0, print a newline. ("\n"[$x] is newline for $x=0; empty for every larger $x)
if $y is neither 9 nor 10 (not middle part: $y<9|$y>10 <=> $y%11<9)
AND distance to center == abs(9.5-$x) (in [0.5,1.5,..,10.5]) ->
    lower part:     abs($y-10-distance)>1                   => ($y-distance)%11<9
                (this works because $y is always <20)
    upper part: $x<9|$x>10 <=> distance>1 <=> 10-distance<9 => (10-distance)%11<9
                (this works because % has negative results for negative first operands)
    both parts: $y>9?$y:10 <=> max($y,10)
// $a?:$b evaluates to $a if $a is truthy, to $b else
// and the ternary condition evaluates to 1 if the coords are not in the shape
then print chr(31+1) = space
else print chr(31+incremented $c)
share|improve this answer

Ruby, 91 bytes

->{(-11..8).map{|i|["%s"*21,"%#{9-i}s%s%#{i*2+1}s%s","%10s%s"][i/2<=>-1]}*$/%[*' '..?~,$/]}

Ungolfed

->{(-11..8).map{|i|            #For each line
  ["%s"*21,                    #If i/2==-1 make a format string of 21 %s
   "%#{9-i}s%s%#{i*2+1}s%s",   #If i/2>-1 make a format string %{9-i}s%s%{i*2+1}s%s
   "%10s%s"][i/2<=>-1]         #If i/2<-1 make a format string %10s%s
  }*$/%                        #Join the format strings with newlines $/ then use sprintf operator %
  [*' '..?~,$/]                #to replace the %s with *' '..'~' and a newline for last corner.
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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