25
\$\begingroup\$

Simple challenge inspired by the popularity of my previous print invisible text and print real invisible text challenges, and the same length different string challenge.

Given a string consisting of only printable characters (0x20 to 0x7E), print every printable character not present in the string.

Input

A string, or array of characters, consisting of only printable ASCII characters

Output

Every printable ASCII character not present in the input string, in any order.

Testcases

Input:  "Hello, World!"
Output: ""#$%&'()*+-./0123456789:;<=>?@ABCDEFGIJKLMNOPQRSTUVXYZ[\]^_`abcfghijkmnpqstuvwxyz{|}~"
========
Input:  "Hi!"
Output: " "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghjklmnopqrstuvwxyz{|}~"
========
Input:  ""
Output: " !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
========
Input:  " !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
Output: ""

Scoring

This is code-golf so fewest bytes in each language wins

\$\endgroup\$
9
  • \$\begingroup\$ If returning an array, can we include empty elements in place of the used characters? \$\endgroup\$
    – Shaggy
    May 31, 2017 at 14:34
  • \$\begingroup\$ @Shaggy sure, that's fine \$\endgroup\$
    – Mayube
    May 31, 2017 at 14:37
  • \$\begingroup\$ @Rod don't leak my plans D: \$\endgroup\$
    – Mayube
    May 31, 2017 at 14:54
  • \$\begingroup\$ Can the output be a Set object of strings of the characters? set( 'a', 'b', 'c' ) \$\endgroup\$ May 31, 2017 at 14:55
  • 1
    \$\begingroup\$ @MikhailV only if your language is unable to output ASCII characters \$\endgroup\$
    – Mayube
    Jun 1, 2017 at 7:46

58 Answers 58

1
2
1
\$\begingroup\$

05AB1E, 5 4 bytes

-1 thanks to Emigna

žQsK

Try it online!

žQ   # Push all printable characters
  s  # Swap input to the top
   K # Push a with no b's (remove input characters from all printable character)
\$\endgroup\$
1
  • \$\begingroup\$ @FrodCube Oops... I forgot to update the link. It should work now. TIO (empty input) \$\endgroup\$
    – Riley
    May 31, 2017 at 16:43
1
\$\begingroup\$

V, 20 bytes

òiÎflax
òcH ¬ ~@"<

Try it online!

Hexdump:

00000000: f269 ce66 1b6c 6178 0af2 6348 20ac 207e  .i.f.lax..cH . ~
00000010: 1b40 223c                                .@"<
\$\endgroup\$
1
\$\begingroup\$

Charcoal, 18 15 10 8 bytes

Fγ¿¬№θιι

Try it online! Link is to verbose version of code. Edit: Saved 3 bytes by ranging over characters instead of integers. Saved a further 5 bytes when I discovered the undocumented γ variable which holds the printable ASCII characters. Saved a further 2 bytes when @ASCII-only fixed predefined inputs in verbose mode (the answer is still valid as it stands, it's only the try it online link that wouldn't have worked at the time).

\$\endgroup\$
3
  • \$\begingroup\$ 8 bytes (unless preinitialized inputs weren't working back then) \$\endgroup\$
    – ASCII-only
    Jun 17, 2017 at 7:47
  • \$\begingroup\$ @ASCII-only They weren't working in verbose mode... they would probably have worked in succinct mode, but I like the verbose links. \$\endgroup\$
    – Neil
    Jun 17, 2017 at 10:36
  • \$\begingroup\$ It turns out this can be 6 bytes: Φγ¬№θι: simply filter out all characters from the (now document) variable γ that appear in the input. \$\endgroup\$
    – Neil
    Nov 22, 2020 at 16:51
1
\$\begingroup\$

Husk, 6 bytes

-⁰…" ~

Try it online!

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

Nim, 66 bytes

let s=stdin.readAll
for c in' '..'~':
 if c notin s:stdout.write c

Try it online!

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

k, 20 12 bytes

-8 bytes thanks to coltim.

^[`c$32+!94]

Try it online!

Explanation:

     32+!94  /list of int values of all printable characters
  `c$        /turn into characters
^[         ] /partial function application of "except"

What except ^ does is remove all instances of each of element in the right/second argument from the left/first argument.

\$\endgroup\$
1
  • \$\begingroup\$ I think this can be trimmed down to 12 bytes by using ^ except. \$\endgroup\$
    – coltim
    Nov 20, 2020 at 14:02
1
\$\begingroup\$

Vyxal, 4 bytes

kQ?F

Try it Online!

Explanation

kQ   # Printable ASCII
  ?F # Without the input
\$\endgroup\$
1
\$\begingroup\$

Nibbles, 2.5 bytes

--_"\n"

Attempt This Online!

Unfortunately, the printable characters built-in in Nibbles also includes the newline, so we have to explicitly exclude it.

Explanation

--_"\n"
-       List subtract
 -       list subtract
  _       printable characters
   "\n"   newline
         input
\$\endgroup\$
1
\$\begingroup\$

Flip, 21 bytes

'  |D '+1<D:|g DX: #

Attempt This Online!

ATO is not working right now, but I tested this locally. Contains a raw \x7F byte.

This would have been easier if I hadn't removed the J builtin, which generates an inclusive range.

Explanation

                             Push printable ASCII onto stack:

'                            Push space character
                             Loop body:
    D                            Duplicate the current char
      ' \x7f                     Push 127
          <                      Less than?
            :                    If so, mirror & do the following:
           D                         Duplicate TOS
         1
       +                             Add by 1
   |                                 Mirror the IP

                             Setwise difference w/ input:

              g              Read 1 char from the input
                D            Duplicate
                  :          Pop, is it nonzero? (i.e. not at EOF)
                             If so, mirror:
                 X               Remove all occurences of
                                 this char in the stack.
             |                   Mirror the IP back

                    #        When loop done, print entire stack as a string.
                             Terminate program.
\$\endgroup\$
1
\$\begingroup\$

Arturo, 17 bytes

$=>[--@` `..`~`&]

Try it!

Takes and returns a list of characters.

$=>[         ; a function where input is assigned to &
    --       ; set difference
    @        ; reify range
    ` `..`~` ; the range of printable ascii characters
    &        ; input
]            ; end function
\$\endgroup\$
1
\$\begingroup\$

C (gcc), 75 72 70 68 50 49 bytes

Thanks to Peter -1 byte

i;f(s){for(i=31;++i<127;index(s,i)?:putchar(i));}

Try it online!

\$\endgroup\$
5
  • 1
    \$\begingroup\$ Can you use || to make this work on "standard" C? \$\endgroup\$
    – Neil
    Jun 1, 2017 at 8:58
  • \$\begingroup\$ @Neil Yes || also works. Isn't ?: part of "standard" C? \$\endgroup\$
    – cleblanc
    Jun 1, 2017 at 13:13
  • \$\begingroup\$ I always thought it was a gcc extension. \$\endgroup\$
    – Neil
    Jun 1, 2017 at 13:16
  • \$\begingroup\$ @Neil That's correct. ?: is a GNU extension. It works as well in clang and tcc though. \$\endgroup\$
    – Dennis
    Jun 1, 2017 at 16:16
  • \$\begingroup\$ You can remove 1 byte by replacing strchr with index. \$\endgroup\$
    – Peter
    Jun 28, 2023 at 12:19
1
\$\begingroup\$

T-SQL (SQL Server 2016), 519 bytes

with X as(select 32a,char(32)b union all select a+1,char(a+1)from X where a<126),E AS(SELECT n FROM(VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0))E(n)),F AS(SELECT a.n FROM E a,E b),G AS(SELECT a.n FROM F a,F b),T AS(SELECT ROW_NUMBER()OVER(ORDER BY(SELECT NULL))n FROM G),I as(SELECT ASCII(SUBSTRING(t,n,1))a FROM T JOIN(select @i as t)S on T.n<=LEN(S.t)where n=0),R as(select b from X where a not in(select a from I))select STUFF((SELECT''+b FROM R FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)'),1,1,'')

... but this assumes the input string is in @i, therefore a runnable script will look like:

declare @i varchar(101) = 'Test';
    
with X as(select 32a,char(32)b union all select a+1,char(a+1)from X where a<126),E AS(SELECT n FROM(VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0))E(n)),F AS(SELECT a.n FROM E a,E b),G AS(SELECT a.n FROM F a,F b),T AS(SELECT ROW_NUMBER()OVER(ORDER BY(SELECT NULL))n FROM G),I as(SELECT ASCII(SUBSTRING(t,n,1))a FROM T JOIN(select @i as t)S on T.n<=LEN(S.t)where n=0),R as(select b from X where a not in(select a from I))select STUFF((SELECT''+b FROM R FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)'),1,1,'')

Try it online!

How it works

Use CTEs to split the input string into individual characters on separate rows in a result set; use a recursive CTE to generate a result set having individual characters on separate rows for all characters between ASCII values 32 and 126; select all rows from the latter where characters are not found in the former; use STUFF with FOR XML PATH to aggregate those characters (in lieu of the STRING_AGG function, which only arrived in SQL Server 2017).

Legible version

declare @input varchar(101) = 'Test';


with X as (
    select 32a, char(32)b
    union all
    select a+1, char(a+1) from X where a < 126
),
E(n) AS(
    SELECT n FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0))E(n)
),
E2(n) AS(
    SELECT a.n FROM E a, E b
),
E4(n) AS(
    SELECT a.n FROM E2 a, E2 b
),
cteTally(n) AS(
    SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) n
    FROM E4
),
INPUT_STRING as (
    SELECT ASCII( SUBSTRING(term, n, 1)) as [ASCII Code]
    FROM cteTally t
    JOIN (select @input as term) S on t.n <= LEN(S.term)
    where n = 0
),
DATA_RESULTS as (
     select b from X where a not in (select [ASCII Code] from INPUT_STRING) 
 )
 
 select STUFF( (SELECT '' + b FROM DATA_RESULTS FOR XML PATH (''),TYPE).value('(./text())[1]','VARCHAR(MAX)'), 1, 1, '' ) 
 ;

Why?

Because I can.

Can it be shorter?

Almost certainly!

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

Mathematica, 35 bytes

20~CharacterRange~126~Complement~#&

Anonymous function. Takes a list of characters as input and returns a list of characters as output.

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

Lua, 78 bytes

s=io.read()for i=32,126 do c=string.char(i)io.write(s:find(c,1,1)and""or c)end
\$\endgroup\$
0
\$\begingroup\$

shortC, 33 bytes

i;AOi=31;++i<'~';strchr(*@,i)?:Pi

Conversions made in this program:

  • A -> int main(int argc, char **argv) {
  • O -> for(
  • @ -> argv
  • P -> putchar
  • Auto-inserted closing ));}

The resulting program looks like:

i;int main(int argc, char **argv){for(i=31;++i<'~';strchr(*argv,i)?:putchar(i));}

Try it online!

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

Pyth, 17 bytes

Vr32 127I!}CNzpCN

The naive approach.

Explanation:

Vr32 127I!}CNzpCN
Vr32 127             For N in [32, 127[
           CN        Get the ASCII character for the code N
        I!}  z       If it is in the input string...
              pCN    ...then print it

Test it online!

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

Clojure, 60 or 49 bytes

#(apply str(sort(apply disj(set(map char(range 32 127)))%)))

These "apply"s are killing me :/ Oh, if returning a list is fine then this is a bit shorter.

#(sort(apply disj(set(map char(range 32 127)))%))
\$\endgroup\$
0
\$\begingroup\$

Aceto, 38 bytes

cC|d
dXpc
=`I&
LM-1I
d@7F&
€92-
r4*2

Explanation

We first read the input string and explode it (, put the characters on the stack). Next, we push the numbers 34 (94*2-) and 127 (27F1-). The second value is then removed from the stack and memorized (M):

 M-1
  7F
€92-
r4*2

We then first set a catch mark so we can jump back to this place, and then duplicate the number on the stack (the 34). We load the 126 from the quick memory and test for equality, in which case we exit:

 X
=`
L
d@

Otherwise, we duplicate the value again, convert it to a character of that number and check whether that character is already on the stack (dcC). If it is, we mirror to the right side:

cC|
d

Otherwise, we duplicate the value and convert it to a character again, print that character, increment the value and raise an exception, jumping back to the catch mark.

   d
  pc
  I&

If we mirrored, we just increment and raise an exception, too (I&).

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

JavaScript (ES6), 73 72 bytes

f=(s,i=95)=>i?f(s,i-1)+(s.includes(c=String.fromCharCode(i+31))?'':c):''

This builds the string recursively, excluding characters found in the input.

Snippet:

f=(s,i=95)=>i?f(s,i-1)+(s.includes(c=String.fromCharCode(i+31))?'':c):''

console.log(f('Hello, World!'));
console.log(f('Hi'));
console.log(f(''));
console.log(f(' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'));

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

QBIC, 32 bytes

[32,126|X=chr$(a)~instr(;,X)|\?X

Time to implement chr$ and instr in QBIC...

[32,126|    Loop from 32 to 126
X=chr$(a)   Make X$ to be the character with Ascii value a (a is our loop counter)
~instr(;,X) If our input string (read from cmd line) contains cjar X$
|           THEN (empty, no-op)
\?X         ELSE, print char X$
\$\endgroup\$
0
\$\begingroup\$

Retina, 48 45 bytes

^
95$*~¶
+T`p`_p`(.)(?=\1)
s`(.)(?=.*\1)|¶.*

Try it online! Includes test cases. Works by prepending a line of 95 ~s, translating them into the printable ASCII characters, then deleting duplicate characters and the original input. Edit: Saved 3 bytes by matching the characters to be translated individually.

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

Java 8, 68 bytes

s->{for(char c=31;++c<127;System.out.print(s.contains(c+"")?"":c));}

Try it here.

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

Pyke, 4 bytes

~KR-

Try it here!

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

C, 57 bytes

i=32;f(char*s){for(;i<127;i++)!strchr(s,i)?putchar(i):0;}

How it works:

  • Initially sets i to 32, the ASCII character code for the space (the first printable ASCII character).
  • The function f takes a string s, the "input".
  • Loops, incrementing i until it reaches ~ (126), the last printable ASCII character.
  • !strchr(s,i) checks if i is not in s. If i is not in s, print i. Otherwise, do nothing.

I'm sure this can be golfed.

\$\endgroup\$
2
  • \$\begingroup\$ +1 to neutralize the downvoter, but isn't it currently excluding the ~? Shouldn't it be <='~' or (not sure if this is possible in C) i<127)? \$\endgroup\$ Jun 1, 2017 at 11:09
  • \$\begingroup\$ @KevinCruijssen Oh huh, missed that! Thanks! \$\endgroup\$
    – MD XF
    Jun 1, 2017 at 14:31
0
\$\begingroup\$

Python 3, 52 bytes

I feel like there ought to be a shorter way to grab all the unicode characters than this set comprehension, but I haven't found it yet.

lambda s:''.join({chr(i+34)for i in range(93)}-set(s))
\$\endgroup\$
0
\$\begingroup\$

PowerShell, 44 Bytes

[char[]](32..126|?{$_-notin[char[]]"$args"})

creates an array of the numbers 32 through 126 (printable char codes)

finds the char codes not present in the input $args and then converts them back to a char array.

apparently the 1..5 -gt 3 trick doesn't work for -in or -notin, which would save a few bytes.

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

Common Lisp, 79 bytes

(defun f(s)(dotimes(x 95)(let((y(code-char(+ 32 x))))(or(find y s)(princ y)))))

Very straightforward code.

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

Japt, 5 bytes

;EkU1

Try it - includes all test cases

Note that quotation marks in input strings cannot be escaped in Japt and %s must be escaped with %%.

\$\endgroup\$
1
2

Your Answer

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

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