9
\$\begingroup\$

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 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.

gif

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 to 0x7E.
  • 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!

\$\endgroup\$
8
  • \$\begingroup\$ Note to potential DV-ers or duplicate voters - it would be more difficult to port an answer on codegolf.stackexchange.com/q/124306/61563 to here than it would be to write your own answer. The answers over there read input and then use the input to print to the screen. Answers here have to print to the screen without input (using a different loop mechanism) and then test each inputted character for its location, then print a different character. \$\endgroup\$
    – MD XF
    Aug 2, 2017 at 17:05
  • \$\begingroup\$ Can we assume that the user presses enter after he entered 1 character? \$\endgroup\$
    – Mr. Xcoder
    Aug 2, 2017 at 17:07
  • \$\begingroup\$ @Mr.Xcoder Yes, that's fine for languages that cannot take input in realtime. \$\endgroup\$
    – MD XF
    Aug 2, 2017 at 17:09
  • \$\begingroup\$ @Mr.Xcoder See rule 1 - Your program only needs to display the printable ASCII characters, 0x20 to 0x7E \$\endgroup\$
    – MD XF
    Aug 2, 2017 at 17:10
  • 3
    \$\begingroup\$ @MDXF It's still strikingly similar to the original challenge. I just need to print the ascii characters to the correct positions, then, instead of putting the user's input in the correct spot, I just use a space instead. \$\endgroup\$ Aug 2, 2017 at 17:22

11 Answers 11

6
\$\begingroup\$

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

enter image description here

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

SOGL V0.12, 23 bytes

] ~Δ8«n"5αx2⁰³⁄¹‘→č@ŗ░T

Try it Here!

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)
\$\endgroup\$
2
\$\begingroup\$

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]=' ';}}
\$\endgroup\$
1
  • \$\begingroup\$ Welcome to PPCG! I believe you can remove the spaces after the #includes, as well as i + 0x20 -> i+0x20. I could be wrong though. \$\endgroup\$
    – Stephen
    Aug 3, 2017 at 0:09
1
\$\begingroup\$

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()," ")

Try it online!

\$\endgroup\$
1
\$\begingroup\$

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:]

Try it online!

\$\endgroup\$
4
  • \$\begingroup\$ This prints a 0x7f after the tilde, just fyi \$\endgroup\$ Aug 2, 2017 at 18:48
  • \$\begingroup\$ @ConorO'Brien Oops, fixed \$\endgroup\$ Aug 2, 2017 at 19:02
  • 1
    \$\begingroup\$ Any reason you couldn't just add [:-2] after print s instead? \$\endgroup\$
    – alleks
    Aug 3, 2017 at 0:43
  • \$\begingroup\$ @alleks that makes too much sense that's why \$\endgroup\$ Aug 3, 2017 at 8:22
1
\$\begingroup\$

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.

\$\endgroup\$
5
  • \$\begingroup\$ Save 2 bytes with O[h="innerHTML"]=a=[...Array(95)].map(). \$\endgroup\$
    – Shaggy
    Aug 3, 2017 at 8:20
  • \$\begingroup\$ And I think you can save another byte by getting rid of a completely. \$\endgroup\$
    – Shaggy
    Aug 3, 2017 at 8:26
  • 1
    \$\begingroup\$ @Shaggy Thanks, I was using the extra a variable because innerHTML was turning & into &amp;, along with some others. Switching to innerText fixed that. \$\endgroup\$ 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
    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\$ Aug 4, 2017 at 15:13
1
\$\begingroup\$

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 x\16-1,2*(x MOD 16)+1
END SUB

-8 bytes thanks to @DLosc

\$\endgroup\$
2
  • \$\begingroup\$ @DLosc - I had not even considered using a Sub there - Great solution. Unfortunately, we do have to count the End 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\$ 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
    Jul 12, 2018 at 14:33
0
\$\begingroup\$

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()," ");}}

Try it online!

\$\endgroup\$
5
  • \$\begingroup\$ 130 bytes \$\endgroup\$ 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\$ Aug 3, 2017 at 8:16
  • \$\begingroup\$ @TheLethalCoder That's why it says 138+using System; \$\endgroup\$
    – jkelm
    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\$ 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
    Aug 3, 2017 at 10:51
0
\$\begingroup\$

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())

Try it online

\$\endgroup\$
5
  • \$\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 identifier readline (not sure if it is compatible with version on TIO). You also don't need variable r at all, instead of && at the end, you can use , and rearrange parentheses. Same with the && at the beginning. Also, no need for process.stdout in readline interface, etc........... \$\endgroup\$
    – user72349
    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\$ 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
    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 returns undefined 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\$ 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
    Aug 2, 2017 at 23:33
0
\$\begingroup\$

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   #$0F       ; 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.

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

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.

\$\endgroup\$

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.