Draw an ASCIIrisk

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. • I want to try this challenge... but it sounds kinda risky. Please excuse my terrible humor. Feb 3 '17 at 2:35 • Stack Overflow has a NoBadJokes policy so I'm going to have to ignore that comment. Sorry but it policy – user63571 Feb 3 '17 at 19:28 • Okay. Sorry for violating the policy. Thank you for ignoring my comment by replying to it. Feb 4 '17 at 0:39 • @HyperNeutrino Don't judge a challenge by its cover. Now you've missed a really good challenge just because of your prejudice. – user99151 Jan 28 '21 at 3:16 • @2x-1 I can't tell if you're being ironic. Jan 28 '21 at 6:28 22 Answers 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))  • It deserves a Eiffel Tower similarity award! Jan 22 '17 at 12:47 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.

• Nice job abusing the implicit ÿ :) Jan 22 '17 at 6:27

05AB1E, 40383736 35 bytes

žQ2ô376S3*£2ôvyN·ð×ýð«}rsJ2äsr)˜.c


Try it online!

Explanation

žQ                                   # push the printable ascii chars
2ô                                 # split into pairs
376S                             # split the number 376 into a list of digits
3*                           # multiply each by 3 to get [9,21,18]
£                          # divide the pairs of ascii chars into
# pieces of these sizes
# flatten list to stack
2ô                       # split the "legs" of the asterisk into pairs of pairs
v                      # loop over the pairs of pairs
yN·ð×ý                # join the pairs by index*2 spaces
ð«              # append a space
}             # end loop
rs           # move the middle section to top of stack
J2ä        # convert to a string split into 2 pieces
sr      # rearrange the stack in the correct order
)˜    # wrap in a flattened list
.c  # pad each element with spaces on either side

• žQ2ôÐ9£s30£R21£RøsrR18£R2ôvyN·ð×ý})˜.C», I got 39, but I think you can shave some off with ZIP. Jan 23 '17 at 17:28
• @carusocomputing: I don't think zip is very useful here since we want the characters to remain sequential. Splitting everything in pairs at the start was a good idea though. It feels wasteful using so many r and s but I don't see a way around it. Jan 23 '17 at 23:32
• 31 bytes: Ć added after žQ so the ð« can be removed; vy to ε; rs to Š; sr removed and À added after the ). Jan 27 '21 at 13:30

Python 3170165155 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!

JavaScript (ES6), 156 … 115 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

• I think you can do String.fromCharCode(...[...Array(n)].map(_=>k++)) to save 4 bytes. Jan 21 '17 at 23:41
• @ETHproductions I like the idea of calling String.fromCharCode() on an array, but I went for another approach. Thanks anyway! Jan 21 '17 at 23:50

Poetic, 899 bytes

ill be honest with you
i expect a big solitude
i guess i had a guilt
my own idea being:i was real alone,i was a lonely human
also,i am still
o,i guess i was expecting a shift
i figured,surely i know i am tired of silence
now i dreamed for a shift
a magical desire cant come
i am barely a man,so i guess i see why a woman i see ignores myself
i know i am awful
o,a night of passion and a moment of love
i am truly the foolish person,every time i am saying i may recapture a love
o,i think i can,i think i can
i really do know i am unfit
o,i notice a lot,i think i know i am unfit
o,a novel,or perhaps poetry in code,i do enjoy the writing
and i shudder and i wonder in a moment
i was a weirdo,i was a freak,or like,i am creepy
o,i think i was a misfit
i know i am,really
o,i ought not concern myself
and sure,i am still some joyless man
i focused and i tried
a lasting solace and joy is nearby for me


Try it online!

Poetic is an esolang I made in 2018 for a class project. It's basically brainfuck with word-lengths instead of symbols.

This poem is...depressing. 😟

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{
|}                ~


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!

PHP, 11010510393 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 or test it online.

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)  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. 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 ' '. • Super late to the party here, but that " "!(2*n) can be "(TWO SPACES)"!n. – Lynn Apr 23 '18 at 16:43 Charcoal, 39 bytes (noncompeting) ＧＨ↑χ→⁴↓χ→¹¹↓⁴←χ↘χ←⁴↖⁹←²↙⁹←⁴↗χ←⁹↑⁴→⁹ ↓¤γ  Try it online! AST provided for explanation, χ being the preinitialized variable for 10. J, 63 (not competing) a.{~32>.31+20 21$(* +/\),(9 21&$@{.,1:,1:,}.)(+.1&|."1)|.=|i:10  the expression evaluates right to left thus: • i: 10 counts from -10 to +10 • | take abs to get +10 to 0 back to +10 • = self classify to get V shape of 1's in a block of 0's • |. reverse row order to get /\ shape • ( +. 1&|."1 ) hook expression shifts each row right by one and OR's with original • ( 9 21&$@{. , 1: , 1: , }. ) nested forks to put in horizontals and stretch top
• , to raze the block into a linear sequence for cumulation
• ( * +/\ ) cumulate and multiply with self
• 20 21 $ revert shape to a block 20 rows of 21 elements • 31 + add 31 because first 1 should be a space char code 32 • 32 >. floor at 32 • a. {~ pick chars from ascii built-in • Welcome to PPCG! How come you marked this as not competing? Apr 23 '18 at 12:51 • I just thought I'd add my effort even though it's a long time [15mths] after the competition was launched .. are you saying each puzzle stays open? .. also for J expression to print outside the REPL, i.e when executed in a script I'd need to prefix smoutput command or equivalent Apr 23 '18 at 14:53 • Challenges generally stay open indefinitely (even if an answer has already been accepted). There are some special types of challenges that sometimes get closed to new entries (answer-chaining, cops-and-robbers, king-of-the-hill come to mind), but those will usually say so in the challenge description. As for whether this is a valid answer format, you'd have to ask someone with more J experience, but REPL answers are generally fine as long as they're marked as such. Apr 23 '18 at 16:08 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.
}


I missed an answer in C# so...

C# (.NET Core), 175 174 bytes

_=>{var r="";for(int i=0,j,d=32,s=1;i<54;i++)for(j=0;j++<"*#4#4#4#4#4#4#4#4#+K)%1###/#%#-#'#+#)#)#+#'#-#%#/###1#"[i]-33;)r+=(char)(i%2<1?32:d++)+(s++%21<1?"\n":"");return r;}


Try it online!

• 1 byte saved thanks to Kevin Cruijssen!
• You can save a byte by putting the ints inside the for-loop: for(int i=0,j,d=32,s=1;i<54;i++)for(j=0 Oct 4 '17 at 7:01
• 172 bytes Sep 1 '20 at 16:55

Tcl, 209 bytes

proc I {} {incr ::i}
proc A {} {time {append a [$::F %c [I]]} 21;puts$a}
set i 31
time {puts [[set F format] %10c%c [I] [I]]} 9
A
A
time {puts [$F %[expr 32-[I]/4]c%c$i [I]][$F %[expr$i/2-45]c%c [I] [I]]} 9


Try it online!

Tcl, 212 bytes

proc I {} {incr ::i}
proc A {} {time {append a [$::F %c [I]]} 21;puts$a}
set i 31
time {puts [[set F format] %10c%c [I] [I]]} 9
A
A
time {puts [$F %[expr (129-[I])/4]c%c$i [I]][$F %[expr$i/2-45]c%c [I] [I]]} 9


Try it online!

tcl, 213

proc I {} {incr ::i}
set F format
proc A {} {time {append a [$::F %c [I]]} 21;puts$a}
set i 31
A
A
time {I;puts [$F %[expr (129-$i)/4]c%c $i [I]][$F %[expr $i/2-45]c%c [I] [I]]} 9  demo tcl, 227 proc I {} {incr ::i} set F format proc A {} {time {append ::a [$::F %c [I]]} 21}
set i 31
time {puts [$F %10c%c [I] [I]]} 9 A set a$a\n
A
puts $a time {I;puts [$F %[expr (129-$i)/4]c%c$i [I]][$F %[expr$i/2-45]c%c [I] [I]]} 9


tcl, 236

proc I {} {incr ::i}
set F format
proc A {} {time {append ::a [$::F %c [I]]} 21} set i 31 time {puts [$F %10c%c [I] [I]]} 9
set a ""
A
set a $a\n A puts$a
time {I;puts [$F %[expr (129-$i)/4]c%c $i [I]][$F %[expr $i/2-45]c%c [I] [I]]} 9  demo tcl, 237 proc I {} {incr ::i} set F format proc A {} {time {set ::a$::a[$::F %c [I]]} 21} set i 31 time {puts [$F %10c%c [I] [I]]} 9
set a ""
A
set a $a\n A puts$a
time {I;puts [$F %[expr (129-$i)/4]c%c $i [I]][$F %[expr $i/2-45]c%c [I] [I]]} 9  demo Alternative approach with same size: proc I {} {incr ::i} set F format proc A b {time {upvar$b c;set c $c[$::F %c [I]]} 21}
set i 31
time {puts [$F %10c%c [I] [I]]} 9 set a "" A a set a$a\n
A a
puts $a time {I;puts [$F %[expr (129-$i)/4]c%c$i [I]][$F %[expr$i/2-45]c%c [I] [I]]} 9


Tcl, 288

lassign {set while puts format incr expr} S W P F I E
$S i 31$W $i<48 {P [F %10c%c [I i] [I i]]} S a "" W {[I i]<71} {S a a[F %c i]} S a a\n W$i<92 {$S a$a[$F %c$i];$I i}$P $a$W $i<128 {P [F %[E (129-i)/4]c%c i [I i]][F %[E i/2-45]c%c [I i] [I i]]; I i}  demo tcl, 297 bytes (naïve attempt) set i 31 while$i<48 {puts [format %10c%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 [format %[expr (129-$i)/4]c%c $i [incr i]][format %[expr$i/2-45]c%c [incr i] [incr i]]; incr i}


demo

• What do you mean by "naïve attempt"? Shouldn't you put the length in the title instead?
– user63571
Jan 21 '17 at 23:28
• I mean there is space for golfing it more, because there is still much repetition. And I will golf it more. Jan 21 '17 at 23:50
• Raw approach has 254 byte extent. Oct 3 '17 at 23:20
• 209 Apr 25 '18 at 7:34
• @ASCII-only: Thanks. Mine is not exactly equal to your suggestion! ;) Apr 25 '18 at 10:46

Stax, 33 bytes

¬♣╘╣Ye╗}Ω╩Ñ╬↓ï|§≈b↕£♠╨z▐₧3→ÿ≡Δ:╔♫


Run and debug it

Uses a similar idea to the 05AB1E 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

• You can drop 2 bytes by changing map(chr to map(c as c has already been defined as chr
– user63571
Jan 22 '17 at 23:25

Jq 1.5, 180 bytes

foreach((range(9)|[9,2]),(range(2)|[0,21]),(range(9)|[8-.,2,.+.,2]))as$r({s:[range(32;127)]|implode};.r=$r|.p=""|until(.r==[];.p+=" "*.r[0]+.s[:.r[1]]|.s =.s[.r[1]:]|.r=.r[2:]);.p)


Expanded

foreach (                              # instruction sequence: [indent, count]
(range(9)|[9,2]),                  # 9 rows of 2 characters indented 9 spaces
(range(2)|[0,21]),                 # 2 rows of 21 characters
(range(9)|[8-.,2,.+.,2])           # 9 rows of 4 characters with varying indent
) as $r ( {s:[range(32;127)]|implode} # state = ascii string ; .r =$r                            # current instruction
| .p = ""                            # print string for this row
| until(.r==[];                      # until current instruction is exhausted
.p += " "*.r[0] + .s[:.r[1]]   # add to print string
| .s = .s[.r[1]:]                # remove from state
| .r = .r[2:]                    # remove from instruction
)
; .p                                 # emit print string
)


Try it online!

Slashes (///), 324 bytes

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


The first (default) action in Slashes is 'print', so the string is printed. The / and \ must be escaped by proceeding \s.

• You should add the byte count and preferably a link to an interpreter. It looks rather ungolfed though (not sure if it's better to do better in ///). Apr 25 '18 at 12:06
• It's somewhat of a joke to show the beauties of ///, and I will add those! Apr 25 '18 at 12:08

Java 8, 176173 172 bytes

v->{for(char i=54,j,d=32,s=1;i-->0;)for(j=0;j++<"#1###/#%#-#'#+#)#)#+#'#-#%#/###1%)K+#4#4#4#4#4#4#4#4#*".charAt(i)-33;)System.out.print((i%2<1?d++:32)+(s++%21<1?"\n":""));}


Port of @Charlie's C# .NET answer, so make sure to upvote him.
-4 bytes thanks to @ceilingcat.

Try it online.

C (gcc), 119 117 bytes

-2 bytes thanks to ceilingcat

f(c){for(c=0;c<95;c++)printf("%*c%s",c&1?:c<18?10:c<60?:c&2?c/2-30:24-c/4,c+32,c&c<18|c==38|c>58&!(c-63&3)?"\n":"");}


Try it online!