In Map inputted ASCII characters, I asked you to .. map inputted ASCII characters. This time, you will do the opposite, by immediately mapping all ASCII characters, and then mapping spaces over them.
This program will have practical uses, such as seeing what characters you have left in a restricted-source challenge submission.
Challenge
Your job is to write a program that un-maps inputted ASCII characters. As soon as the program is run, it will display this exact map (except color, font, size, etc.):
step 1
Each time the user inputs a printable ASCII character, you will print a space over it.
Rules
- The initial output must be exactly as shown in the first image above: a 6x16 grid with ASCII characters in their respective positions, with the space (32) at the top left and the tilde (126) at one character left from the bottom right.
- Your program only needs to display the printable ASCII characters,
0x20
to0x7E
. - Your program must not terminate and continue to print spaces over characters until all printable ASCII characters have been overwritten. From here, your program can either terminate or run off into Neverland.
- Your reverse map must be updated in realtime (as soon as it receives user input).
- If your program does not read input silently, it must put the cursor out of the way, so the text won't get in the way of the map.
Here's a useful ASCII table for reference.
Scoring
The answer with the least bytes in each language wins. Have fun!
11 Answers 11
x86-16 Machine Code, 62 bytes
Hex dump:
BC0100B101B07EBAFE0581EAE00080EA02B402CD1085E4750830E439C5750A30C0B40ACD1084C074094884D275E085D275D831C031E4CD1630E489C5EBC7
Assembly:
mov sp, 0x0001 ; Stack pointer is used as a flag; 0 - Print all characters, 1 - Delete specific character
mov cl, 0x01 ; Number of characters to print per interrupt call
printString:
mov al, 0x7E ; Last character to print
mov dx, 0x05FE ; Row: 0x05, Collumn: 0xFE
printRow:
sub dx, 0x00E0 ; Decrement row number + 2 extra characters
printChar:
sub dl, 0x02 ; Decrement collumn index + 1 space
mov ah, 0x02 ; Prepare for interrupt call, 0x02 - Set cursor position
int 0x10 ; BIOS interrupt
test sp, sp ; Are we printing all characters or removing specific character
jnz print ; In first case just print it and go on
xor ah, ah ; Otherwise reset the upper byte of ax (shorter than "and ax, 0x00FF")
cmp bp, ax ; Is the current character same as the input character
jne after ; If no, continue searching
xor al, al ; If yes, remove it
print:
mov ah, 0x0A ; Prepare for print
int 0x10 ; Print
test al, al ; If we found target character
jz loop ; then stop searching
after:
dec ax ; Shorter than "dec, al"
test dl, dl ; Is it the last character in the row
jnz printChar ; If no, continue searching
test dx, dx ; Is it last char
jnz printRow ; If no, go to next row
loop:
xor ax, ax ; Remove "ah" cache
xor sp, sp ; Reset sp (it will never become 1 again)
int 0x16 ; BIOS interrupt for reading keyboard input
xor ah, ah ; Again reset "ah", because BIOS may change it
mov bp, ax ; Save it in stack base pointer
jmp printString ; Remove the character from the list
SOGL V0.12, 23 bytes
] ~Δ8«n"5αx203⁄1‘→č@ŗ░T
Takes input in the input box. I hope that it isn't too big of an issue that characters can be deleted :p
Explanation:
] do.. while (popping (which makes the stack not blow up luckily :D))
~Δ push the ascii characters (range("~"))
8«n split into lines of length 16
"...‘ push "inputs.value" (could be 2 bytes less if my dictionary contained the word "inputs". I even added "input", but only now realise that the input box is id=inputs :/)
→ evaluate as JavaScript, then push the result
č chop into characters
@ŗ replace each of the characters in the array with space
░ clear the output
T output without popping (so do..while continues looping)
C++ (Visual C++), 253 (@Step Hen) (削除) 261 (削除ここまで) bytes
#include<cstdlib>
#include<iostream>
#include<conio.h>
int main(){char a[0x5E];for(int i=0;i<0x5E;i++)a[i]=(char)(i+0x20);while(true){system("cls");for(int i=0;i<0x5E;i++)if(i&&!(i%16))printf("\n%c ",a[i]);else printf("%c ",a[i]);a[_getch()-0x20]=' ';}}
-
\$\begingroup\$ Welcome to PPCG! I believe you can remove the spaces after the
#include
s, as well asi + 0x20
->i+0x20
. I could be wrong though. \$\endgroup\$Stephen– Stephen2017年08月03日 00:09:56 +00:00Commented Aug 3, 2017 at 0:09
Python 3, 116 bytes
o='\n'.join(''.join(map(chr,range(i,16+i)))for i in range(32,124,16))[:-1]
while 1:print(o);o=o.replace(input()," ")
Python 2, 132 bytes
Saved 4 bytes thanks to @alleks!
s=''
for i in range(32,128,16):s+=' '.join(map(chr,range(i,i+16)))+'\n'
while 1:print s[:-2];i=2*ord(input())-64;s=s[:i]+' '+s[i+1:]
-
\$\begingroup\$ This prints a 0x7f after the tilde, just fyi \$\endgroup\$Conor O'Brien– Conor O'Brien2017年08月02日 18:48:04 +00:00Commented Aug 2, 2017 at 18:48
-
\$\begingroup\$ @ConorO'Brien Oops, fixed \$\endgroup\$musicman523– musicman5232017年08月02日 19:02:13 +00:00Commented Aug 2, 2017 at 19:02
-
1\$\begingroup\$ Any reason you couldn't just add
[:-2]
afterprint s
instead? \$\endgroup\$alleks– alleks2017年08月03日 00:43:41 +00:00Commented Aug 3, 2017 at 0:43 -
\$\begingroup\$ @alleks that makes too much sense that's why \$\endgroup\$musicman523– musicman5232017年08月03日 08:22:44 +00:00Commented Aug 3, 2017 at 8:22
JavaScript (ES6) + HTML, (削除) 139 (削除ここまで) (削除) 136 (削除ここまで) 116 + (削除) 10 (削除ここまで) 16 = 132 bytes
-3 bytes thanks to @Shaggy.
-14 bytes inspired by @Arnauld.
for(i=32;i<127;)O[h="innerText"]+=String.fromCharCode(i++)+(i%16?" ":`
`);onkeypress=e=>O[h]=O[h].replace(e.key," ")
<pre id=O></pre>
Closing pre
tag is required in this case, since we need the innerText
value to start totally empty.
-
\$\begingroup\$ Save 2 bytes with
O[h="innerHTML"]=a=[...Array(95)].map()
. \$\endgroup\$Shaggy– Shaggy2017年08月03日 08:20:10 +00:00Commented Aug 3, 2017 at 8:20 -
\$\begingroup\$ And I think you can save another byte by getting rid of
a
completely. \$\endgroup\$Shaggy– Shaggy2017年08月03日 08:26:55 +00:00Commented Aug 3, 2017 at 8:26 -
1\$\begingroup\$ @Shaggy Thanks, I was using the extra
a
variable becauseinnerHTML
was turning&
into&
, along with some others. Switching toinnerText
fixed that. \$\endgroup\$Justin Mariner– Justin Mariner2017年08月03日 10:20:27 +00:00Commented Aug 3, 2017 at 10:20 -
\$\begingroup\$ You can move
i
to the global scope to save 2 bytes:map(_=>String.fromCharCode(i++)+(i%16?...),i=32)
\$\endgroup\$Arnauld– Arnauld2017年08月04日 09:58:13 +00:00Commented Aug 4, 2017 at 9:58 -
\$\begingroup\$ @Arnauld Using that idea, I could just remove the whole array mapping and use a for loop instead. Thanks! \$\endgroup\$Justin Mariner– Justin Mariner2017年08月04日 15:13:49 +00:00Commented Aug 4, 2017 at 15:13
QBasic, 107 bytes
An anonymous function that takes as keystrokes, and erases an ASCII table
FOR x=32TO 126
L x
?CHR$(x)
NEXT
DO
L ASC(Input$(1))
?" "'<- `"` included for highlighting only
LOOP
SUB L(x)
LOCATE x16円-1,2*(x MOD 16)+1
END SUB
-8 bytes thanks to @DLosc
-
\$\begingroup\$ @DLosc - I had not even considered using a
Sub
there - Great solution. Unfortunately, we do have to count theEnd Sub
as the community has decided that autocompletion is not valid (at least with VBA, but I am sure that it applies here as well) \$\endgroup\$Taylor Raine– Taylor Raine2018年07月10日 17:27:29 +00:00Commented Jul 10, 2018 at 17:27 -
\$\begingroup\$ Huh, that's interesting--I hadn't realized there was a distinction between autoformatting and autocompletion. Good to know. \$\endgroup\$DLosc– DLosc2018年07月12日 14:33:36 +00:00Commented Jul 12, 2018 at 14:33
C# (.NET Core), (138 + using System;) 151 bytes
()=>{var j="";for(int i=32;i<127;i++){if(i%16<1)j+='\n';j+=(char)i+" ";}while(1>0){Console.Write(j);j=j.Replace(Console.ReadLine()," ");}}
-
\$\begingroup\$ 130 bytes \$\endgroup\$TheLethalCoder– TheLethalCoder2017年08月03日 08:12:00 +00:00Commented Aug 3, 2017 at 8:12
-
\$\begingroup\$ Oh but you need to include
using System;
into your byte count if you haven't already (I forgot to add it into the count above). \$\endgroup\$TheLethalCoder– TheLethalCoder2017年08月03日 08:16:20 +00:00Commented Aug 3, 2017 at 8:16 -
\$\begingroup\$ @TheLethalCoder That's why it says 138+using System; \$\endgroup\$jkelm– jkelm2017年08月03日 10:46:22 +00:00Commented Aug 3, 2017 at 10:46
-
\$\begingroup\$ I mainly meant it because I forgot to add in the using into my byte count above. \$\endgroup\$TheLethalCoder– TheLethalCoder2017年08月03日 10:49:18 +00:00Commented Aug 3, 2017 at 10:49
-
\$\begingroup\$ Oh. Didn't see your first comment there. I like the abuse of the infinite for loop there :) \$\endgroup\$jkelm– jkelm2017年08月03日 10:51:00 +00:00Commented Aug 3, 2017 at 10:51
Node.js (削除) 233 (削除ここまで) 212 bytes
Saved 21 bytes thanks to @thePirateBay
This works, I'm still trying to find an online option as all the repls I've found hijack stdin.
a=[];l=_=>console.log(a.join``);for(i=32;i<127;i++)(x=String.fromCharCode(i)),a.push(i%16?x:x+'\n');l();b=require('readline');b.createInterface(process.stdin).on('line',c=>(a=a.join``.replace(c,' ').split``),l())
-
\$\begingroup\$ Online version can be found on TIO. Just a few notes: you can save more than 30 bytes by rearranging your identifiers and removing unnecesary parts. You don't need variable
b
at all, and you are also using uninitialized identifierreadline
(not sure if it is compatible with version on TIO). You also don't need variabler
at all, instead of&&
at the end, you can use,
and rearrange parentheses. Same with the&&
at the beginning. Also, no need forprocess.stdout
inreadline
interface, etc........... \$\endgroup\$user72349– user723492017年08月02日 23:17:27 +00:00Commented Aug 2, 2017 at 23:17 -
\$\begingroup\$ @ThePirateBay without
process.stdout
it throws (at least on my version of node). The readline thing was a typo (hit ctrl-z too many times). I'll change the&&
s. \$\endgroup\$Jared Smith– Jared Smith2017年08月02日 23:21:58 +00:00Commented Aug 2, 2017 at 23:21 -
\$\begingroup\$ Readline module doesn't require
process.stdout
. You can read the specification. It may throw an error if you messed something up with the rest of your code or if you are using old/inconsistent version of Node.js. \$\endgroup\$user72349– user723492017年08月02日 23:23:51 +00:00Commented Aug 2, 2017 at 23:23 -
\$\begingroup\$ @thePirateBay Must be my node, I'm 6.9.1 on MacOS... just tried it again and
createInterface
apparently returnsundefined
if you omit the second param. I went ahead and removed it though per the docs you linked. As far as TIO goes, how do you make it interactive? \$\endgroup\$Jared Smith– Jared Smith2017年08月02日 23:26:58 +00:00Commented Aug 2, 2017 at 23:26 -
\$\begingroup\$ Here is using only 191 bytes, but I am sure at least 10 more bytes can be saved. Sorry, im too bored now to continue golfing this:
for(a=[],l=_=>console.log(a.join``),i=32;i<127;x=String.fromCharCode(i++),a.push(i&15?x:x+'\n'));l();require('readline').createInterface(process.stdin).on('line',c=>(a[a.indexOf(c)]=' ',l)())
\$\endgroup\$user72349– user723492017年08月02日 23:33:21 +00:00Commented Aug 2, 2017 at 23:33
65c02 machine code + Apple //e ROM, 52 (47?) bytes
Hex dump:
8000- 20 58 FC A9 A0 20 20 80
8008- 20 ED FD 1A C9 FF D0 F5
8010- AD 00 C0 10 FB 8D 10 C0
8018- 20 20 80 20 57 DB 80 F0
8020- 48 38 E9 A0 48 29 0F 0A
8028- 85 24 68 4A 4A 4A 4A 20
8030- 5B FB 68 60
Commented assembly:
1 HTAB = 24ドル ; HORIZONTAL POSITION OF CURSOR
2 SETVTAB = $FB5B ; SETS VERTICAL POSITION OF CURSOR FROM ACC
3 COUT = $FDED ; OUTPUTS CHARACTER IN ACC
4 HOME = $FC58 ; CLEARS SCREEN
5 OUTSP = $DB57 ; APPLESOFT ROUTINE THAT OUTPUTS A SPACE
6 KBD = $C000 ; KEY LAST PRESSED
7 KBSTROBE = $C010 ; ACCESS TO RESET "NEW KEY PRESSED" INDICATOR
8 ORG 8000ドル
9 JSR HOME
10 * PRINT INITIAL CHARACTER MAP
11 LDA #" "
12 LOOP JSR CHARPOS
13 JSR COUT
14 INC ; INCREMENT ACCUMULATOR
15 CMP #"~"+1
16 BNE LOOP
17 * WAIT FOR KEYPRESS
18 GETCH LDA KBD ; GET LAST KEY PRESSED
19 BPL GETCH ; READ AGAIN IF KEYPRESS IS NOT NEW
20 STA KBSTROBE ; RESET "NEW KEYPRESS" INDICATOR
21 JSR CHARPOS
22 JSR OUTSP
23 BRA GETCH
24 * SUBROUTINE TO POSITION CURSOR TO PRINT OVER CHARACTER IN ACCUMULATOR
25 CHARPOS PHA ; PRESERVE ACC
26 SEC ; MAKE SURE CARRY IS SET TO SUBTRACT
27 SBC #" " ; SUBTRACT CHAR CODE OF SPACE
28 PHA ; SAVE ACC
29 AND #0ドルF ; GET LOWER 4 BITS TO GET CURSOR X POSITION
30 ASL ; SHIFT LEFT TO MAKE SPACES BETWEEN CHARS
31 STA HTAB
32 PLA ; GET OLD ACC
33 LSR ; SHIFT HIGH NIBBLE
34 LSR ; INTO LOW NIBBLE
35 LSR ; TO GET CURSOR Y POSITION
36 LSR
37 JSR SETVTAB
38 PLA ; RESTORE ACC
39 RTS
This has no cursor whatsoever. I also have a 47 byte version which might be valid, depending on what is meant by "put the cursor out of the way, so the text won't get in the way of the map":
8000- 20 58 FC A9 A0 20 1B 80
8008- 20 ED FD 1A C9 FF D0 F5
8010- 20 0C FD 20 1B 80 20 57
8018- DB 80 F5 48 38 E9 A0 48
8020- 29 0F 0A 85 24 68 4A 4A
8028- 4A 4A 20 5B FB 68 60
This puts a cursor at the character after the character you type (which is the space between characters), so it won't overwrite any of the actual characters in the map. Whether this is valid or not is up to the creator of the challenge.
Python 2, 96 bytes
from textwrap import*
a=fill(str(bytearray(range(32,127))),16)
while 1:a=a.replace(input(a),' ')
Try it online! Output looks iffy on TIO (because input is passed from a file), but it’s fine interactively. I hope 'A'\n
, 'B'\n
etc is an okay input format.
Your program only needs to display the printable ASCII characters, 0x20 to 0x7E
\$\endgroup\$