30
\$\begingroup\$

Goal

You have to print the ASCII printable characters' code page (0x20-0x7E). The output should look like this:

 !"#$%&'()*+,-./
0123456789:;<=>?
@ABCDEFGHIJKLMNO
PQRSTUVWXYZ[\]^_
`abcdefghijklmno
pqrstuvwxyz{|}~

Rules

  • The output should be exactly like shown above, but trailing whitespace is OK.
  • No builtins that trivialize the question (e.g. the ones that print the ASCII table) ! They can be posted for documentation purposes, but will not be in the leaderboards.
  • Standard rules for I/O and loopholes apply.
  • Lowest bytecount wins.

Good Luck!

P.S. This challenge is well-known, but a straight "print every single printable ASCII character" has somehow never been done here.

\$\endgroup\$
17
  • 7
    \$\begingroup\$ Could you clarify exactly what you mean by "No builtins"? No builtins if they return exactly that output? No builtins that return any kind of ASCII table? No builtins at all (which would make this impossible in most languages)? \$\endgroup\$
    – pxeger
    Jun 29, 2022 at 7:23
  • 5
    \$\begingroup\$ Many built-ins for the ascii table seem to include characters like the line break and tab so I think they wouldn't work anyways. \$\endgroup\$
    – mousetail
    Jun 29, 2022 at 7:27
  • 5
    \$\begingroup\$ trivialize the question is not objectively defined. If a builtin outputs the string of ASCII codes (not formatted as a table), does that trivialize the question? If it outputs an ASCII table with a different format? \$\endgroup\$
    – Luis Mendo
    Jun 29, 2022 at 12:24
  • 6
    \$\begingroup\$ Is a trailing space accepted, to make the last line the same length as the others? \$\endgroup\$
    – Luis Mendo
    Jun 29, 2022 at 12:28
  • 2
    \$\begingroup\$ @LuisMendo Yes, it trivializes the question. A trailing space is OK but not necessary. \$\endgroup\$
    – loggeek
    Jun 29, 2022 at 14:24

79 Answers 79

1 2
3
1
\$\begingroup\$

POSIX Shell Command Language + Utilities + V10 UNIX seq, 54 bytes

printf %b `seq -f'obase=8;"\";%g' 32 126|bc`|fold -w16

Self-explanatory: seq generates lines in the obase=8;"\";100 format, bc turns them into lines in the \144 format, printf expands them and pastes them together, fold wraps the output at 16 columns

There is, of course, trouble with seq. The minimal seq required here is Version 10 AT&T UNIX (and, hence, Plan 9), V8-V9 won't work since they take a -ppicture argument. Realistically this is not a problem since all modern systems include a V10-compatible seq, but.

Transcript of test cases:

$ cat b.sh; echo; wc -c b.sh
printf %b `seq -f'obase=8;"\";%g' 32 126|bc`|fold -w16
54 b.sh
$ ./b.sh; echo
 !"#$%&'()*+,-./
0123456789:;<=>?
@ABCDEFGHIJKLMNO
PQRSTUVWXYZ[\]^_
`abcdefghijklmno
pqrstuvwxyz{|}~
$ ./b.sh | hd
00000000  20 21 22 23 24 25 26 27  28 29 2a 2b 2c 2d 2e 2f  | !"#$%&'()*+,-./|
00000010  0a 30 31 32 33 34 35 36  37 38 39 3a 3b 3c 3d 3e  |.0123456789:;<=>|
00000020  3f 0a 40 41 42 43 44 45  46 47 48 49 4a 4b 4c 4d  |?.@ABCDEFGHIJKLM|
00000030  4e 4f 0a 50 51 52 53 54  55 56 57 58 59 5a 5b 5c  |NO.PQRSTUVWXYZ[\|
00000040  5d 5e 5f 0a 60 61 62 63  64 65 66 67 68 69 6a 6b  |]^_.`abcdefghijk|
00000050  6c 6d 6e 6f 0a 70 71 72  73 74 75 76 77 78 79 7a  |lmno.pqrstuvwxyz|
00000060  7b 7c 7d 7e                                       |{|}~|
00000064

Here's a 100-byte fully-standards-conformant version, same output:

i=32
printf %b $(while [ $i -le 126 ]
do
printf %s\\n 'obase=8;"\";'$i
i=$((i+1))
done|bc)|fold -w16
\$\endgroup\$
1
\$\begingroup\$

Thunno N, \$5\log_{256}(96)\approx\$ 4.12 bytes

zC6AP

Attempt This Online!

Explanation

zC6AP   # Full program. No inputs.
zC      # Push the ASCII codepage as a string
  6AP   # Split into 6 chunks
        # The N flag automatically joins by newlines
        # And then it is output implicitly
\$\endgroup\$
1
\$\begingroup\$

J, 19 bytes

echo _16]\u:32+i.95

Full program with trailing whitespace.

Attempt This Online!

echo _16]\u:32+i.95
               i.95  NB. range 0..94
            32+      NB. offset, 32..126
          u:         NB. convert codes to chars
     _16 \           NB. for every non-overlapping length 16 slice
        ]            NB. simply return that slice
echo                 NB. return the resulting table
\$\endgroup\$
0
\$\begingroup\$

vim, 77 bytes

qqA<C-V><C-A><C-V><ESC><ESC>v0da0x0<ESC>@"0xII<C-V><C-V><ESC>A<C-V><ESC><ESC>v0d@"qxV!seq 32 126
:%norm @q
VgggJ0qq16li
<ESC>q4@q

<C-V> is 0x16. <C-A> is 0x01. <ESC> is 0x1b.

Annotated

qq                                   # define macro q that changes e.g. "48" to "0" as follows:
    A<C-V><C-A><C-V><ESC><ESC>          # Change e.g. "48" to "48<INC>"
    v0d                                 # Place the above command in register "
    a0x0<ESC>@"                         # Write 0x0, then use above command to increment. Thus, "48" becomes "0x30"
    0xII<C-V><C-V><ESC>A<C-V><ESC><ESC> # Convert "0x30" to "I<C-V>x30<ESC>" (command that appends character 0x30, i.e. "0")
    v0d@"                               # Pull command into register and execute
q
xV!seq 32 126         # Populate file with numbers 32-126, one per line.
:%norm @q             # Execute macro q over each line
VgggJ                 # Join lines
0qq16li<NL><ESC>q     # Insert a newline 16 characters from the start, and record as a macro while we're at it
4@q                   # Execute that macro 4 more times

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Java (JDK), 63 bytes

v->{for(char c=31;++c<127;)System.out.print(c%16>14?c+"\n":c);}

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Stax, 10 bytes

Ç·qª>%bΓ½⌠

Run and debug it

Approach

  • [0..126]
  • Keep only 95 last elements.
  • Split into chunks of 16
  • Print each
\$\endgroup\$
0
\$\begingroup\$

Ly, 25 bytes

88+sp' '~R' r[l[fo,]p9`o]

Try it online!

This one is pretty straightforward. It uses a range command to generate the codepoints, the two loops to print them with a \n every 16 characters.

88+sp                     - stash the number 16
     ' '~R                - push codepoints from " " to "~" to the stack
          ' r             - push a blank (for DEL) and reverse stack
             [          ] - loop until the stack it empty
              l           - push 16 (from back up cell)
               [  ,]p     - loop 16 times...
                fo        - pull codepoint forward and print as char
                     9`o  - print a LF
\$\endgroup\$
0
\$\begingroup\$

The Waterfall Model (with output extension), 166 bytes

[[30000,7,7,7,7,7,7,7],[3,2,2,0,0,0,7,0],[2,2,2,0,0,0,3,0],[1,0,2,300,0,0,0,0],[66,2,0,0,302,0,9,0],[4822,2,0,0,300,5100,9,0],[9,0,0,0,0,0,1,0],[29998,0,0,0,0,0,0,0]]

Try it online!

$$ \begin{array}{c|c|ccccccc} &start&A&B&α&β&γ&out&halt\\\hline A&3&2&2&&&&7&\\ B&2&2&2&&&&3&\\ α&1&&2&300&&&&\\ β&66&2&&&302&&9&\\ γ&4822&&&&300&5100&9&\\ out&9&&&&&&1&\\ halt&29998&&&&&&& \end{array} $$

  • A and B each (upon zeroing) add 2 to both of them, and stay 1 apart. This means one of them will be zeroing every 2 steps, and externally adding 2 to that one will switch it to the other one.
  • α and β cause switches to A and to B, respectively. β has a period 2 longer than α, so the time between α and β increases by 2 each cycle, and thus the number of times A zeroes increases by 1 each cycle.
  • A increments the output counter and β causes it to be output as a character and reset to 0, thus outputting an increasing sequence of characters. B increases the output waterclock by a non-output-affecting value of 3 to keep it away from zero.
  • γ first zeroes after the 17th zeroing of α and 10 following zeroings of A. It causes output as a character, for a line feed (ASCII 10), and increases β by 302 – equal to α's period rather than 2 greater – so that the difference between α and β does not change for this cycle.
    γ has a period 17 times that of α, to add a line feed after every 16 other characters.
  • The halt waterclock is never incremented, and simply counts down and ends the program after 100 characters (95 printable characters and 5 line feeds).
\$\endgroup\$
0
\$\begingroup\$

GolfScript, 21 bytes

96,{[32+]}[/]''*16/n*

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ -1 byte without trailing unprintable: 95,{[32+]''+}/]16/n* \$\endgroup\$
    – emirps
    Feb 1 at 15:43
0
\$\begingroup\$

Dyalog APL, 16 bytes

⎕UCS 6 16⍴31+⍳95
\$\endgroup\$
0
\$\begingroup\$

Befunge-93, 36 bytes

" ">:,1+:"~"1+\`v
   ^            _@

Try it online!

I don't know if i can optimize this code even further than i did.

An explanation

This code is comprised of 5 main parts:

  • " ": Push 0x20 onto the stack.
  • :,: Output the current character.
  • -1: Increment the current character.
  • :"~"1+`: Compare the current character with 0x7e.
  • _@: If current character is greater than 0x7e, end the program; else loop back to the start with ^.
\$\endgroup\$
0
\$\begingroup\$

Kotlin, 89 73 bytes

print((' '..'~').chunked(16).map{it.joinToString("")}.joinToString("\n"))

Kotlin Playground

Edits

  • -16, inlined conversion to Char
\$\endgroup\$
0
\$\begingroup\$

Knight, 31 bytes

;=a 32W>127aO+AaI%=a+1a 16"\"""

Try it online!

Unminified:

; = a 32
: WHILE (> 127 a)
    : OUTPUT (+ (ASCII a) (IF (% (= a (+ 1 a)) 16) "\" ""))
\$\endgroup\$
0
\$\begingroup\$

Japt -R, 9 bytes

#_odH ¬òG

Test it

\$\endgroup\$
0
\$\begingroup\$

Python 3, 92 bytes

print('\n'.join([''.join([chr(32+j+16*i)for j in range(16)])for i in range(6)]).rstrip(''))

Note that the blank looking character inside rstrip is DEL.

Try it online!

Explanation:

                [''.join([chr(32+j+16*i)for j in range(16)])for i in range(6)] # generate rows of string
      '\n'.join(                                                              ) # join with new lines
                                                                               .rstrip('') # strip the DEL out
print(                                                                                    
 ) # then print
\$\endgroup\$
0
\$\begingroup\$

Pascal, 104 B

This source code complies with the ISO standard 7185 “Standard Pascal” (level 0).

program p(output);var c:char;begin for c:=' 'to'~'do if ord(c)mod 16=15 then writeLn(c)else write(c)end.

The output lacks of trailing newline.

Extended Pascal, 94 B

In “Standard Pascal” (ISO standard 7185) width specifiers in have to be positive. That means the n in write(123:n) has to be ≥ 1. “Extended Pascal”, as laid out in ISO standard 10206, permits a zero-write-width format specifier. We can utilize this and “conditionally” print chr(10) – the newline character as used in Unixoid environments (Linux, FreeBSD, …).

program p(output);var c:char;begin for c:=' 'to'~'do write(c,chr(10):ord(ord(c)mod 16=15))end.

In Pascal, the newline character is the only character that may not appear in a string literal. Thus chr(10) cannot be shortened any further.

\$\endgroup\$
0
\$\begingroup\$

ARM Thumb-2 machine code (Linux), 30 bytes

20 24 06 a1 01 22 01 34 25 07 08 bf 02 22 04 27
01 20 00 df 0c 70 7f 2c f3 d1 00 de 20 0a

Put this in a read-write-execute section at a 4 byte aligned address.

Assembler source:

    .syntax unified
    .arch armv7-a
    // Store in a read-write-execute section so I don't need to address
    // a different section or use the stack for my buffer
    .section ".wtext", "awx", %progbits
    .thumb
    .globl _start
    .thumb_func
    // Aligned address is necessary for the buffer
    .p2align 2, 0
_start:
    // First char
    movs    r4, #' '
.Lloop:
    // syscall setup for write(1, .Lbuf, 1)
    movs    r0, #1
    adr     r1, .Lbuf
    movs    r2, #1
    movs    r7, #4
    // Increment r4
    adds    r4, #1
    // And test r4 & 0xF to see if the NEXT char is a multiple
    // of 16. I do this with my favorite narrow instruction, LSLS,
    // where I shift out all the other bits into a dummy register and set
    // the flags.
    lsls    r5, r4, #32 - 4
    // If so, set the length to 2 to print the newline
    // if ((r4 & 0xF) == 0) length = 2;
    it      eq
    moveq   r2, #2
    // Syscall
    svc     #0
    // Store new byte into the buffer. This is why a writable .text
    // is needed.
    strb    r4, [r1]
    // Check if we are at the end (DEL), if not, loop again
    cmp     r4, #0x7f
    bne     .Lloop
.Lexit:
    // Exit with a SIGILL crash because I don't care :)
    udf     #0
    .p2align 2, 0
    // mutable buffer
.Lbuf:
    // Current char
    .byte ' '
    // Additional newline
    .byte '\n'

enter image description here

\$\endgroup\$
0
\$\begingroup\$

Arturo, 42 bytes

loop split.every:16` `..`~`=>[print join&]

Try it

                   ` `..`~`                 ; a block of characters from space to tilde
     split.every:16                         ; split a block into groups of sixteen
loop                       =>[           ]  ; loop over every element in a block
                                        &   ; current element being looped over
                                    join    ; join block of chars to a string
                              print         ; print with newline
\$\endgroup\$
0
\$\begingroup\$

Wolfram Language (Mathematica), 56 bytes

Print/@BlockMap[FromCharacterCode,32~Range~126,UpTo@16];

Unfortunately it doesn't work on TryItOnline due to an outdated interpreter that can't handle the UpTo abstraction in the BlockMap function call. I can offer this screenshot of my local machine: Screenshot "proof"

In case that ever gets fixed (or someone knows how to work around it), here is a TIO link anyway: Try it online!

If you are not in a notebook environment the ; at the end can be removed to save one byte.

\$\endgroup\$
1 2
3

Your Answer

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

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