28
\$\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
  • 6
    \$\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 at 7:23
  • 4
    \$\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 at 7:27
  • 4
    \$\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 at 12:24
  • 5
    \$\begingroup\$ Is a trailing space accepted, to make the last line the same length as the others? \$\endgroup\$
    – Luis Mendo
    Jun 29 at 12:28
  • 2
    \$\begingroup\$ @LuisMendo Yes, it trivializes the question. A trailing space is OK but not necessary. \$\endgroup\$
    – loggeek
    Jun 29 at 14:24

75 Answers 75

16
\$\begingroup\$

Python 3, 42 bytes

print(('%c'*16+'\n')*6%(*range(32,127),9))

Try it online!

Includes a trailing tab on the last line and a trailing newline.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ print have another extra \n. So it actually ends with \r\n\n on Linux or \r\r\n\r\n on Windows. If multiple line breaks are allowed at the ending, you may simply output triple line breaks at the end. \$\endgroup\$
    – tsh
    Jun 29 at 13:41
  • 2
    \$\begingroup\$ Nice! %c is a proper game changer here. \$\endgroup\$
    – loopy walt
    Jun 29 at 13:42
  • 1
    \$\begingroup\$ \n alongside \r\n definitely looks cheaty to me. But if I were OP which I am not I'd argue a space should be perfectly fine. If the gap weren't at the end but at the beginning or in the middle of a row one clearly would want a placeholder there. Why should the end be different? \$\endgroup\$
    – loopy walt
    Jun 29 at 13:47
  • 1
    \$\begingroup\$ @loopywalt it's okay. \$\endgroup\$
    – loggeek
    Jun 29 at 14:25
  • 2
    \$\begingroup\$ Pretty sneaky putting a tab at the end instead of a space to save one character. \$\endgroup\$ Jun 30 at 3:13
15
\$\begingroup\$

Python 3, 52 bytes

for i in range(95):print(chr(i+32),end='\n'[~i%16:])

Try it online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Very clever use of slicing to vary the end-of-line character. I'd give this an upvote except somebody else has a shorter Python solution. \$\endgroup\$ Jun 30 at 3:19
  • 6
    \$\begingroup\$ @MarkRansom you can upvote any answers you find clever or interesting! \$\endgroup\$
    – qwr
    Jun 30 at 17:15
12
\$\begingroup\$

Prelude, 50 42 bytes

88+
6(1-) v^^(  1-++!)^6-!)
1- v+(1-) v(1-

Try it online!

Explanation

88+
6(1-)
1- v+

Push \$16\$ to Voice 1 and \$95\$ to Voice 3.


       v^^
      (1-)

For each value from \$95\$ down to \$1\$, push that value and two copies of \$16\$ to Voice 2. When the loop ends, the stack in Voice 2 is [..., 0, 0, 0, 95, 16, 16, 94, 16, 16, ..., 1, 16, 16].


         (  1-++!     )

For each triplet of values in Voice 2, sum them and subtract \$1\$, then print the result as an ASCII character...


                 )
          v(1-

in groups of 16...


                  ^6-!

with a newline appended to each group.

Printing fails on the (non-existent) 96th character because the triplet of values summed is [0, 0, 0], with the result that the code attempts to convert \$-1\$ to ASCII and thus exits with an out-of-range error.


Fugue

Fugascii

Fugue is a musical encoding for Prelude. Fugascii*, a short trio for woodwinds, was generated from the Prelude code above using a script that I wrote for this purpose. Read all about it in this answer.

* The title is a pun on a previous Fugue composition of mine, Fugacity.

\$\endgroup\$
4
  • 2
    \$\begingroup\$ Now I want to hear the music! \$\endgroup\$
    – emanresu A
    Jul 1 at 7:34
  • 5
    \$\begingroup\$ @emanresuA I transcribed it here: t.pxeger.com/files/Fugascii.mscz. You can listen to it on YouTube (or see it on Musescore.com). It doesn't sound very good. \$\endgroup\$
    – pxeger
    Jul 1 at 7:59
  • 1
    \$\begingroup\$ @pxeger That's cool! I think the clarinet part needs to be transposed down a tone to sound as intended (it's not much improvement though). I wrote it at transposed rather than concert pitch, which admittedly would be more obvious if I'd put in key signatures. \$\endgroup\$
    – Dingus
    Jul 1 at 8:19
  • \$\begingroup\$ Now I want to see a whole challenge around the idea of "best sounding solution", though popularity-contest seems to be out of fashion nowadays. \$\endgroup\$
    – ojdo
    Jul 1 at 10:07
10
\$\begingroup\$

Zsh, 26 bytes

printf %s {\ ..~}|fold -16

Attempt This Online!

\$\endgroup\$
1
  • \$\begingroup\$ I was curious if this worked in bash as well: it doesn't. Bash supports range-expansions like {A..z} which include some non-alphanumeric characters in the expansion, but not a range starting or ending with a space or punctuation. \$\endgroup\$ Jul 1 at 2:01
6
\$\begingroup\$

R, 35 bytes

write(intToUtf8(32:126,T),1,16,,"")

Try it online!

\$\endgroup\$
6
\$\begingroup\$

Rust, 58 bytes

||for i in' '..''{print!("{:
<1$}",i,i as usize%16/15+1)}

Attempt This Online!

Explanation

  • The answer is a closure expression implementing the Fn() trait.

  • print! can pad outputs to a given length: print!("{:x<5}", 'a')axxxx

  • The length can come from an argument: print!("{:x<1$}", 'a', 5)axxxx

  • The padding char can be a raw newline in place of the x in this example.

  • In my program, the length is either 1 (just the char) or 2 (char + newline).

\$\endgroup\$
3
  • \$\begingroup\$ If you remove fn main(){ this would be shorter than mine \$\endgroup\$
    – mousetail
    Jun 30 at 12:25
  • \$\begingroup\$ It would end up being a "snippet" I think. I can't dig up the relevant Meta link right now but we tend to expect answers to be either full programs or function definitions / lambda expressions (so puts("Hello world!"); is not a valid C answer, but f(){puts("Hello world!");} is). \$\endgroup\$
    – Lynn
    Jun 30 at 13:18
  • \$\begingroup\$ oh, this is sort of relevant codegolf.meta.stackexchange.com/questions/2419/… \$\endgroup\$
    – Lynn
    Jun 30 at 13:18
6
\$\begingroup\$

MS-DOS (.COM format), 33 30 26 bytes

  • -3 thanks to Deadcode
  • -4 by using INT 29H to output

Iterates through 20H and 7EH, printing each character and a line break between the 16th character of each line.

0000 B0 20 CD 29 40 3C 7F 74 10 A8 0F 75 F5 50 B0 0A
0010 CD 29 B0 0D CD 29 58 EB E9 C3

Assembly version (TASM):

IDEAL
P8086

MODEL   TINY
CODESEG
ORG 100H

MAIN:   
    MOV  AL,20H ; Start at ' '
PRINT:
    INT  29H    ; Print character
    INC  AX     ; Increment character
    CMP  AL,7FH ; Done?
    JZ   DONE   ; Yes, exit
    TEST AL,0FH ; End of line?
    JNZ  PRINT  ; No, next character
    PUSH AX     ; Save current character
    MOV  AL,0AH ; Print CR+LF
    INT  29H
    MOV  AL,0DH
    INT  29H
    POP  AX     ; Restore current character
    JMP  PRINT  ; Next character
DONE:
    RET

END MAIN
ENDS
\$\endgroup\$
4
  • \$\begingroup\$ You can save 3 bytes by changing INC DL to INC DX and replacing the XCHGs with PUSH and POP. \$\endgroup\$
    – Deadcode
    Jun 30 at 6:47
  • \$\begingroup\$ Filling a buffer and printing that is another approach; 27 bytes for that as a Linux 32-bit executable. (Perhaps less as a function). Might be possible with xchg ax,dx / stosw to store a 2-byte newline. But without being sure you have some stack space above you can overwrite (which would break ret), it's less appealing. \$\endgroup\$ Jul 1 at 14:55
  • \$\begingroup\$ Very cool optimization of using the undocumented INT 29h for output. It's worth noting that it prints directly to the screen and can't be redirected (unlike INT 21h.02h which uses stdout). And it really was undocumented; it's not present in my 1991 copy of The Programmer's PC Sourcebook. \$\endgroup\$
    – Deadcode
    Jul 2 at 2:22
  • \$\begingroup\$ @Deadcode I find that Ralf Brown's Interrupt List is pretty useful for stuff like this. \$\endgroup\$
    – ErikF
    Jul 2 at 4:50
6
\$\begingroup\$

Piet + ascii-piet, 87 82 bytes (3×28=84 codels)

Thanks @Bubbler for -5 bytes by changing 4 dup * 2 * to a more space efficient 8 4 *

eeeumtqcsqrrjlvuddtrjcqdjes_eeeu ?????rr?jujrnvmsjiqqc _eeuu kdvtrbbbbb???vv   qq?

Try Piet online!

Might add a more detailed explanation later if I feel like to, but here's an explanation image generated by Bubbler's Piet interpreter for now. Can 100% be golfed, but I'm too lazy to do that right now lol.

Explanation image

The basic algorithm is to initially push 32 to the stack, then keep incrementing and outputting the character until 127, after which the code stops. At each iteration, it checks if the number+1 is a multiple of 16, and prints a newline if it is.

Longer explanation

Here's the ascii piet version of the code, with newlines added for clarity:

eeeumtqcsqrrjlvuddtrjcqdjes_
eeeu ?????rr?jujrnvmsjiqqc _
eeuu kdvtrbbbbb???vv   qq?

I'll be going over the code section by section.

Initialization:

eeeum
eeeu
eeuu

Push 8, Push 4, multiply. This puts 32 onto the stack (the codepoint for space)

Top half of the loop:

     tqcsqrrjlvuddtrjcqdje


What it does:

Commands                              Stack          DP,     CC
dup                                   [32,32]        right   left
out (char)                            [32]           right   left
1 + Dup                               [33,33]        right   left
4 dup * dup * 2 / 1 -                 [33,33,127]    right   left
- ! !                                 [33,1]         right   left
DP+                                   [33]           down    left

Basically, it adds 1 to the current codepoint and checks if it is equal to 127. If it is, then DP+ will turn the pointer 0 times and terminate the code. Otherwise, DP+ will turn the pointer 1 time and continue the loop.

Bottom right portion of the loop:


            ?jujrnvmsjiqqc
               ???vv   qq?

What it does:

Command                              Stack          DP,     CC
dup                                  [33,33]        down    left
4 dup *                              [33,33,16]     left    right
%                                    [33,1]         left    right
! 3 *                                [33,0]         left    right
1 CC+                                [33,0]         left    left
DP+                                  [33]           left    right

This checks if the current codepoint is a multiple of 16 (remember that we added 1 to the codepoint in the top half of the loop). If it is a multiple of 16, then DP+ will turn the DP to face downwards. Otherwise, the DP stays facing left. This is based on the observation that all the characters before a newline all have codepoints that are 1 less than a multiple of 16.

For example, let's say that at the beginning of this portion, the stack is [48]. This means that the ascii 47, or /, just got printed, and then that value was incremented by 1 from the top half of the loop. After taking this value modulo 16 and applied ! on the value, the stack becomes [48,1]. The 1 on the stack is then multiplied by 3 which causes DP+ to turn the DP 3 times, resulting in the DP facing down.

Bottom branch of the loop:

     t
     ?
     kdvtrbbbbb

What it does:

Command                              Stack          DP,     CC
1 5 dup +                            [33,1,10]      left    right
out (char) pop                       [33]           left    right

Basically just prints out a newline.

Top branch of the loop:

     t    rr
     ?????rr?

Nothing actually happens here. The code just passes through and enters back into the loop. One thing to note is that the reason why we did CC+ earlier was to get through the r block. Before the CC+, the CC was facing right, but that poses a problem when we go through the r block, because the code will continue execution through the top left of the block, which will break the entire code. Instead, we toggle the CC once to switch it to the left, which causes the code to exit out of the block from the bottom left.

Once the top half is entered again, dup out (char) is ran, printing out another character, and the loop continues.

Loop exit:

                          s_
                           _

Once the loop reaches 127, the loop is exited. s is essentially a noop that does nothing, and the program terminates in the _ block.

\$\endgroup\$
2
  • \$\begingroup\$ 8 4 * (or 4 8 *) can certainly utilize the black area better. \$\endgroup\$
    – Bubbler
    Jul 1 at 10:07
  • \$\begingroup\$ @Bubbler Yep thanks for the suggestion, I was originally planning to do two rows so I wrote it like that, but I couldn't fit everything in. \$\endgroup\$
    – Aiden Chow
    Jul 1 at 19:18
5
\$\begingroup\$

Python 3, 71 bytes

-2 bytes thanks to @pxeger

for i in range(6):print(''.join(chr(j+i*16+32)for j in range(16-i//5)))

Try it online!

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

Python 2, 66 bytes

for i in range(6):print bytearray(j+i*16+32for j in range(16-i/5))

Attempt This Online!

Based on @mousetail's solution; submitted as my own answer by their suggestion.

\$\endgroup\$
5
\$\begingroup\$

Rust, 74 72 70 64 bytes

(' '..'').any(|i|print!("{i}")>if i as u8%16>14{print!("
")});

Text contains non-printable characters so might not render correctly. @Antiip saved me some bytes.

Attempt This Online!

\$\endgroup\$
3
  • 2
    \$\begingroup\$ The Rust version on TIO is too old for using chars in ranges. You may use ATO instead, which also supports the new syntax print!("{i}"). \$\endgroup\$
    – alephalpha
    Jun 29 at 8:54
  • 1
    \$\begingroup\$ You can abuse all for -5 bytes: (' '..='~').all(|i|print!("{i}")==if(i as u8)%16>14{print!(" ")}); \$\endgroup\$
    – AnttiP
    Jun 29 at 9:06
  • \$\begingroup\$ You can use the official Rust Playground: bit.ly/3zzZUXZ \$\endgroup\$
    – Eric Xue
    Jul 27 at 23:10
5
\$\begingroup\$

Whitespace, 110 100 bytes

[S S S T    T   T   T   T   N
_Push_31][N
S S N
_Create_Label_LOOP][S S S T N
_Push_1][T  S S S _Add][S N
S _Duplicate][S S S T   T   T   T   T   T   T   N
_Push_127][T    S S T   _Subtract][N
T   S T N
_If_0_Jump_to_undefined_Label][S N
S _Duplicate][T N
S S _Print_as_character][S N
S _Duplicate][S S S T   S S S S N
_Push_16][T S T T   _Modulo][S S S T    T   T   T   N
_Push_15][T S S T   _Subtract][N
T   T   N
_If_neg_Jump_to_Label_LOOP][S S S T S T S N
_Push_10_\n][T  N
S S _Print_as_character][N
S N
N
_Jump_to_Label_LOOP]

Letters S (space), T (tab), and N (new-line) added as highlighting only.
[..._some_action] added as explanation only.

Try it online (with raw spaces, tabs and new-lines only).

Explanation in pseudo-code:

Integer n = 31
Start LOOP:
  n = n + 1
  If (n==127):
    Stop program with error by jumping to undefined Label
  Print n as character to STDOUT
  If (n modulo 16 < 15):
    Go to next iteration of LOOP
  Print '\n'
  Go to next iteration of LOOP
\$\endgroup\$
5
\$\begingroup\$

brainfuck, 64 86 bytes

+++++[>++>++++++>+<<<-]>>++>+[-[>+<[->>+<<]]>>[-<<+>>]<+++++++++++++++[<<.+>>-]<<<.>>]

Try it online!

No longer prints 0x7f as the last character.

With many thanks to @Jiří for the fix.

\$\endgroup\$
6
  • 2
    \$\begingroup\$ This includes 0x7F. It needs to stop at 0x7E. \$\endgroup\$
    – Ray
    Jun 29 at 17:29
  • \$\begingroup\$ Here is my way to fix it, but it comes at cost of 22 bytes: +++++[>++>++++++>+<<<-]>>++>+[-[>+<[->>+<<]]>>[-<<+>>]<+++++++++++++++[<<.+>>-]<<<.>>] \$\endgroup\$
    – Jiří
    Jun 30 at 0:57
  • \$\begingroup\$ @Ray interesting point. The rules state that "The output should be exactly like shown above, but trailing whitespace is OK.". I interpret that as meaning that 0x7F being a non printable character (and therefore not affecting the display at least not on TIO) can be seen as a trailing whitespace. I'll leave it to OP to comment if I am wrong. \$\endgroup\$
    – ElPedro
    Jun 30 at 7:37
  • \$\begingroup\$ TIO was showing a (a character containing the hex values) for me (but stackexchange wouldn't let me include it in a comment). (And 0x00-0x19 are also (mostly) non-printable characters, but presumably nobody's printing those.) \$\endgroup\$
    – Ray
    Jun 30 at 14:13
  • 2
    \$\begingroup\$ OP already said otherwise. See comment under question where someone is asking if the bottom corner can be DEL character (this is character 0x7F). Answer to this question was no. \$\endgroup\$
    – Jiří
    Jun 30 at 18:20
4
\$\begingroup\$

x86-32 machine code (Linux executable) 27 bytes

cut-down NASM listing: Address | machine code | source

                   global _start
                   _start:            ; Linux processes (and thus static executables) start with registers zeroed, except ESP
                   asciitable:
 00 B020            mov al, ' '
 02 B20A            mov dl, 0xa
 04 89E7            mov edi, esp      ; space above ESP on the stack is argc, argv[] and env[] array elements, and the env strings.  We overwrite that.
                   .loop:
 06 AA              stosb
 07 40              inc  eax            ; there is no branch condition for AF, the half-carry flag :/
 08 A88F            test al, 0x8f       ; detect mod16 and when we've gone past printable
 0A 7503            jnz .nonewline
 0C 92              xchg  eax, edx
 0D AA              stosb
 0E 92              xchg  eax, edx
                   .nonewline:
                    ; FLAGS still set from earlier TEST
 0F 79F5            jns  .loop               ; stop at 0x80, beyond what the syscall uses
                     ; mov [edi-1], 0xa      ; no trailing newline
                   
 11 B004            mov  al, 4   ; __NR_write
                    ; ebx=0 from process startup; writing to stdin happens to work on a terminal
 13 89E1            mov  ecx, esp
 15 8D5060          lea  edx, [eax-4 + 0x7f-0x20 + 5]  ; exclusive range, 5 newlines; final line does not end with newline as whitespace isn't required
 18 CD80            int  0x80    ; write(0, ecx, 100)
                   
                   ; mov  eax,1      ; exit(ebx)
                   ; int  0x80
 1A CC              int3  ; abort program

Fill bytes into a buffer (overwriting stack memory above ESP, starting with argc, argv[], and into env[]). We go a bit beyond 0x7e because that makes the stop condition cheaper, but those bytes aren't printed: we have to generate an explicit length in EDX anyway, so we just omit it.

We make one write(0, buf, 100) system call. 0 is STDIN_FD, but on a normal xterm/konsole/gnome_terminal, FD 0,1, and 2 are all read+write duplicates of the same file description. So we save 1 byte for inc ebx. If you want to pipe the output into something to hexdump for example, ./asciitable 0>&1 | hexdump -C

Instead of existing cleanly, we use int3 to raise a debug exception, resulting in the OS delivering SIGTRAP, killing the process. A typical shell will then print Trace/breakpoint trap (core dumped), but that's the shell, not this program. This saves 3 bytes vs. mov al, 1 / int 0x80 (the upper bytes of EAX are zeroed, unless write returned an error).

I considered letting execution just fall off the end (to probably 00 00 padding added by the linker, which decodes as add [eax], al and will segfault), but we're already stretching things a bit by only counting the .text section of the executable, not the whole file size. (Unlike a DOS .com, there is metadata)

Our output doesn't end with a newline; as the question says, no trailing whitespace is required after the 0x7e ~ character.

The mod16 detection via checking the low bits 4 of AL is fairly straightforward, but was borrowed from ErikF's the x86-16 MS-DOS answer which I read first before thinking about how I'd do it.

But to enable a jns as the loop branch without a separate cmp, we also set the MSB in our mask for test. That's not a spot we wanted a newline anyway. I'd hoped to be able to branch on FLAGS from inc al (2 bytes), but since we'd also need something for newlines, this is even better: we can now use inc eax (1 byte) and still branch on the MSB of AL. Using mov dl, 0xa (2B) / xchg/stosb/xchg (1B each) instead of mov byte [edi], 0xa (3 bytes) / inc edi (1 byte but clobbers FLAGS) was the key to that, saving another test or cmp for a net saving of 1 byte.

Demo:

$ nasm -felf32 asciitable.asm
$ ld -melf_i386 -o asciitable asciitable.o
$ ./asciitable
 !"#$%&'()*+,-./
0123456789:;<=>?
@ABCDEFGHIJKLMNO
PQRSTUVWXYZ[\]^_
`abcdefghijklmno
pqrstuvwxyz{|}~Trace/breakpoint trap (core dumped)

$ ./asciitable 0>&1 | cat  # suppresses signal diagnostic from shell
 !"#$%&'()*+,-./
0123456789:;<=>?
@ABCDEFGHIJKLMNO
PQRSTUVWXYZ[\]^_
`abcdefghijklmno
pqrstuvwxyz{|}~peter@volta:/tmp$

$ ./asciitable 0>&1 | hexdump -C
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

$ strace ./asciitable 0>/dev/null
execve("./asciitable", ["./asciitable"], 0x7ffc63d167c0 /* 55 vars */) = 0
[ Process PID=2670503 runs in 32 bit mode. ]
strace: WARNING: Proper structure decoding for this personality is not supported, please consider building strace with mpers support enabled.
write(0, " !\"#$%&'()*+,-./\n0123456789:;<=>"..., 100) = 100
--- SIGTRAP {si_signo=SIGTRAP, si_code=SI_KERNEL} ---
+++ killed by SIGTRAP (core dumped) +++
Trace/breakpoint trap (core dumped)

Try it online! with an inc ebx added so it writes to stdout and thus shows up in the tio.run output pane. IDK why it didn't show in the debug pane. (32-bit code supported by having FASM make an executable directly, instead of NASM.)

TODO: a function instead of program, filling a buffer

We'd obviously save the syscall code, but could no longer write past the end of the actual stop point. So would need maybe 1 more byte in the loop to go back to cmp al, 0x7e / jne as the loop condition.

\$\endgroup\$
5
  • \$\begingroup\$ I really wanted to do a jns for the loop condition as well, but with the codepoint ending at 0x7E not 0x7F that made it not really work out. \$\endgroup\$
    – 640KB
    Jul 1 at 15:06
  • \$\begingroup\$ @640KB: Yeah, that's part of why I went with filling a buffer, so I could go past the end but not print that part. Also that Linux doesn't have a putchar system call so the byte(s) have to be in memory. \$\endgroup\$ Jul 1 at 15:09
  • \$\begingroup\$ I suppose I could have mine write to a buffer too and save 3 bytes by using stosb instead of int 29h. Great idea! \$\endgroup\$
    – 640KB
    Jul 1 at 15:11
  • \$\begingroup\$ @640KB: As I suggested for ErikF's DOS answer, you could xchg/stosw/xchg to store a 2-byte newline similar to how I'm doing it here. \$\endgroup\$ Jul 1 at 15:12
  • \$\begingroup\$ Ha, I actually did that when I was editing my answer for the output to buffer! \$\endgroup\$
    – 640KB
    Jul 1 at 15:28
4
\$\begingroup\$

x86-16 machine code, PC DOS, 24 19 bytes

00000000: b020 bb0a 0daa 40a8 0f75 0393 ab93 3c7e  . ....@..u....<~
00000010: 7ef3 c3                                  ~..

Listing:

B0 20           MOV   AL, 20H       ; starting codepoint
BB 0D0A         MOV   BX, 0D0AH     ; CR/LF chars
            CP_LOOP: 
AA              STOSB               ; write AL to buffer
40              INC   AX            ; increment to next char
A8 0F           TEST  AL, 0FH       ; is end of line?
75 03           JNZ   CP_NEXT       ; jump if so
93              XCHG  AX, BX        ; save current codepoint
AB              STOSW               ; write CR/LF to buffer
93              XCHG  AX, BX        ; restore codepoint
            CP_NEXT: 
3C 7E           CMP   AL, 07EH      ; <= 7EH? 
7E F3           JLE   CP_LOOP       ; if so, keep looping 
C3              RET                 ; return to caller

enter image description here

Using @PeterCordes's suggestion to write to an output buffer instead of direct to console.

Callable function, output to string buffer ES:[DI].

\$\endgroup\$
1
  • 1
    \$\begingroup\$ You mean codepoint, not codepage, I think. (BTW, I posted a Linux x86-32 version just a few minutes after this.) \$\endgroup\$ Jul 1 at 14:59
4
\$\begingroup\$

K (ngn/k), 21 17 bytes

-4bytes thanks to Traws!

`0:`c$6 16#32+!95

It's my first answer in K! So there might be some optimizations ^^

`0:`c$6 16#32+!95
           32+!95 / Creates an array from 32 to 126
      6 16#       / Reshapes it to 16 columns and 6 lines (16 can me replaced by 0N)
   `c$            / For each elements of this array/matrix, convert the int to a char
`0:               / Print the result whitout ( and "

Try it online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ nice first answer. you don't need the lambda and each for the conversion, just `c$ is enough to convert the whole array. \$\endgroup\$
    – Traws
    Jul 10 at 13:43
  • \$\begingroup\$ @Traws Fixed! Thanks :D \$\endgroup\$
    – TKirishima
    Jul 10 at 18:46
3
\$\begingroup\$

05AB1E, 10 bytes

Without builtin:

₃L31+çJ6ä»

Try it online.

With builtin (5 bytes):

žQ6ä»

Try it online.

Explanation:

₃L          # Push a list in the range [1,95]
  31+       # Add 31 to each
     ç      # Convert the codepoint-integers to ASCII characters
      J     # Join the list together to a string
       6ä   # Split it into 6 parts
         »  # Join by newlines
            # (after which the result is output implicitly)

žQ          # Push a string of all ASCII characters
  6ä»       # Same as above
\$\endgroup\$
3
\$\begingroup\$

Burlesque, 18 bytes

@!~r@' +]16co)++un

Try it online!

@!~  # Push ! and ~ to stack
r@   # Range between them
' +] # Prepend " "
16co # Chunks of 16
)++  # Concat
un   # Intercalate newlines between blocks and join
\$\endgroup\$
3
\$\begingroup\$

PowerShell Core, 35 bytes

-join(' '..'~')-split'(.{16})'-ne''

Try it online!

     (' '..'~')                     # create a list of characters from <space> to ~
-join                               # join the list to a single string
               -split'(.{16})'      # split the string every 16 chars ...
                              -ne'' # ... and let only non-empty strings pass.
\$\endgroup\$
3
\$\begingroup\$

BQN, 12 bytes

6‿16⥊' '+↕95

Try it at BQN REPL

Output has a trailing space character.

BQN's affine character space is quite neat here: adding a number to a character gives another character. So: create a range from zero to 95 (↕95), add it to the space character (' '+), and reshape to 6-row, 16-column format (6‿16⥊).


BQN, 26 bytes

@+100⥊⍉(32+⍉6‿16⥊↕95)∾6⥊10

Try it at BQN REPL

Longer version with output string that is truly "exactly like shown above", written before the edit allowing trailing whitespace.
Creates a transposed array of character values (32+⍉6‿16⥊↕95), appends a newline value 10 to each column (∾6⥊10), re-transposes () & extracts the first 100 values (100⥊), and finally converts to characters (@+).

\$\endgroup\$
3
\$\begingroup\$

V (vim), 10 bytes

¬ ~5ñ16|á

Try it online!

Explanation:

¬               # Insert characters between the code points...
  ~             #   "space" and "~"
   5ñ           # 5 Times...
     16|        #   Go to the 16th character on this line
        á<cr>   #   Append a newline

Hexdump:

00000000: ac20 7e35 f131 367c e10d                 . ~5.16|..
\$\endgroup\$
3
\$\begingroup\$

Perl 5, 30 bytes

say map$/x!($_%16).chr,32..126

Try it online!

\$\endgroup\$
3
\$\begingroup\$

sed -r, 94 bytes

s/.*/ABCDEFGHIJKLMNO\nPQRSTUVWXYZ/
saa !"#$%\&'()*+,-./\n0123456789:;<=>?\n@&[\\]^_\n`\L&{|}~a

Try it online!

This is probably the best that can be done in sed, which has no functionality for ranges of characters. The main byte saving is in the fact we can generate ABCDEFGHIJKLMNOPQRSTUVWXYZ and then use \L to get the lowercase version.

\$\endgroup\$
3
\$\begingroup\$

PHP, 43 40 bytes

<?=chunk_split(join(range(' ','~')),16);

Simply outputs the expected text, without any trailing newlines.

Just run php file.php and it should produce the output.

Try it on: https://onlinephp.io/c/013ce


Thanks to Steffan for -3 bytes.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ join('',range(' ','~')) can just be join(range(' ','~')) for -3 bytes \$\endgroup\$
    – Steffan
    Aug 7 at 19:39
  • \$\begingroup\$ @Steffan Totally forgot to check if the empty string was required. Thank you. \$\endgroup\$ Aug 8 at 0:02
3
\$\begingroup\$

Vyxal 2.14.1, 9 bytes

kPð+s16ẇ⁋

Try it Online!

So turns out kP isn't actually all of printable ascii - it's missing the space character, and it isn't in the right order either, meaning that for the purposes of this challenge, it shouldn't be banned, as it doesn't print "the ascii table" and it isn't exactly "trivial" either.

(And if it isn't allowed, then that's grounds enough for VTCing this challenge as needs details or clarity, because "trivialising the challenge" isn't objectively defined - there's an argument to be made that kPð+s isn't a trivial built-in).

Explained

kPð+s16ẇ⁋
kPð+       # a string of 0-9a-Z + python's string.punctuation + space
    s      # sorted to be in printable ascii order
     16ẇ   # split into parts of length 16
        ⁋  # joined on newlines

Vyxal, 5 bytes

kP6/⁋

Try it Online!

Bug fixes make this 5 bytes in reality.

\$\endgroup\$
3
  • 5
    \$\begingroup\$ It does not output the required text which has 6 lines of 16 characters each (except the final line which has 15). Changing 5 to 6 does not do the trick either. \$\endgroup\$ Jun 29 at 16:35
  • \$\begingroup\$ 6/ should work, but it's so buggy. 16ẇ works, though. \$\endgroup\$
    – Steffan
    Jun 29 at 17:29
  • \$\begingroup\$ Bugs are fixed, you can use 6/ now. \$\endgroup\$
    – Steffan
    Aug 8 at 0:14
2
\$\begingroup\$

R, 38 bytes

intToUtf8(rbind(matrix(32:126,16),10))

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ I think that this outputs an illegal final space. \$\endgroup\$ Jun 29 at 12:44
  • \$\begingroup\$ @DominicvanEssen hmmm, seems so, indeed. Waiting for clarification. \$\endgroup\$
    – pajonk
    Jun 29 at 12:47
  • \$\begingroup\$ Looks like it's Ok now... \$\endgroup\$ Jun 29 at 16:03
2
\$\begingroup\$

APL (Dyalog Extended), 12 bytes

6 16⍴' '…'~'

Try it online!

' '…'~' inclusive range from space to tilde

6 16⍴ cyclically reshape into the required number of rows and columns

\$\endgroup\$
6
  • \$\begingroup\$ I think that this outputs an illegal final space. \$\endgroup\$ Jun 29 at 12:44
  • 2
    \$\begingroup\$ @DominicvanEssen APL is an array language. The normal way to output multiple lines is to print an orthogonal (non-ragged) matrix, padding with spaces. Furthermore, OP has now explicitly clarified that any trailing whitespace is OK. \$\endgroup\$
    – Adám
    Jun 29 at 14:35
  • 1
    \$\begingroup\$ looks like the OP has now allowed trailing spaces, so this is now Ok. But (as a newbie array programmer) surely it would otherwise be possible in APL to output multiple non-identically-long lines? It was do-able in BQN (see my answer), albeit with a substantially longer program... \$\endgroup\$ Jun 29 at 14:38
  • 1
    \$\begingroup\$ @DominicvanEssen Yes, it is possible to output multiple times, and also to output a flat character vector with line breaks in it. It just isn't the norm. \$\endgroup\$
    – Adám
    Jun 29 at 14:39
  • \$\begingroup\$ Not sure if APL has anything like J's alphabet a., but perhaps this approach could be adapted: 2}.8 16$a."_? \$\endgroup\$
    – Jonah
    Jun 29 at 17:45
2
\$\begingroup\$

MathGolf, 10 bytes

♣⌡╒T≥$y☻/n

Try it online.

Explanation:

♣           # Push 128
 ⌡          # Decrement it by 2 to 126
  ╒         # Pop and push a list in the range [1,126]
   T        # Push 31
    ≥       # Pop and remove the first 31 items from the list
     $      # Convert each codepoint-integer to a character
      y     # Join the list to a string
       ☻    # Push 16
        /   # Pop and split the string into parts of size 16
         n  # Join the list by newlines
            # (after which the entire stack is output implicitly as result)
\$\endgroup\$
2
\$\begingroup\$

jq -nr, 39 bytes

[range(32;127)]|implode|scan(".{1,16}")

Attempt This Online!

The best I can do without regex is 40 bytes:

16*range(2;8)|[.+range(16-./99)]|implode

Attempt This Online!

\$\endgroup\$
2
\$\begingroup\$

Charcoal, 12 bytes

UT⪪⪫…· ¦~ω¹⁶

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

UT

Disable automatic padding (would normally output a trailing space on the last line).

⪪⪫…· ¦~ω¹⁶

List the characters from to ~ inclusive, join them together, split into groups of 16, and implicitly print each group on its own line.

Save 6 bytes by using the builtin γ in place of ⪫…· ¦~ω. Try it online! Link is to verbose version of code.

\$\endgroup\$
1
  • \$\begingroup\$ The question has since been edited to allow any trailing whitespace, in which case save 2 bytes from both programs by removing the UT. \$\endgroup\$
    – Neil
    Jun 29 at 17:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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