22
\$\begingroup\$

Task

Given a string as input, generate a "blurred" version of that string.

Input

Your input will be a single-line string of ASCII characters, containing a minimum of 2 alphanumeric characters

Output

A string that is the "blurred" version of the input string.

A blurred string is one where every alphanumeric character from the original string has been paired with the ones adjacent to it, and each pair is separated by a space.

Any non-alphanumeric characters (whitespace, puncuation) in the input string must be ignored when determining adjacency of alphanumeric characters, and they must not included in the blurred string.

There must be no leading or trailing whitespace in the output string.

Examples

Ab -> Ab
Abc -> Ab bc
Abcd -> Ab bc cd
E?h? -> Eh
Blurry vision -> Bl lu ur rr ry yv vi is si io on
We're #1! -> We er re e1
I'm an example! -> Im ma an ne ex xa am mp pl le
This is _not_ legible -> Th hi is si is sn no ot tl le eg gi ib bl le
(a*b*c)+5^-x -> ab bc c5 5x
??a_%,1!=z#@ -> a1 1z


This is code-golf, so fewest bytes wins!

\$\endgroup\$
12
  • 2
    \$\begingroup\$ The non-alphanumeric characters have to be ignored or can be ignored? \$\endgroup\$ – RGS Apr 24 '20 at 21:39
  • 1
    \$\begingroup\$ @RGS Thanks for the clarification question, non-alphanumeric characters must be ignored \$\endgroup\$ – ampersandre Apr 24 '20 at 21:42
  • 30
    \$\begingroup\$ I feel like this challenge suffers from a lot of poorly motivated add-ons. For example removing certain characters from the string, or requiring no trailing whitespace. These additions don't really have a reason to exist or an internal logic, they just get in the way of writing an answer. I started to write an answer but found these extra conditions inflated my code by nearly three times, making them actually the bulk of the challenge. \$\endgroup\$ – Wheat Wizard Apr 24 '20 at 23:18
  • 3
    \$\begingroup\$ Here are some posts 1 2 where you can read more about why I disagree with these extraneous elements. \$\endgroup\$ – Wheat Wizard Apr 24 '20 at 23:21
  • 5
    \$\begingroup\$ Why no trailing whitespace? Why do we have to ignore non-alphanumeric characters? These just seem like a lot of extra requirements that make the challenge less fun. \$\endgroup\$ – S.S. Anne Apr 25 '20 at 20:15

45 Answers 45

21
\$\begingroup\$

Python 3, 57 55 bytes

lambda s:"".join((c+" "+c)*c.isalnum()for c in s)[2:-2]

Try it online!

How:

  • For each alpha-numeric character c in the string, replace it with c+" "+c.
    E.g: "abcd" -> "a ab bc cd d"

  • Remove the redundant first and last 2 characters:
    E.g: "a ab bc cd d" -> "ab bc cd"

\$\endgroup\$
2
  • 1
    \$\begingroup\$ I like this answer because it's elegant, and, esoterically, very useful. I might use this if I, for some reason, decide to add bluriness (how do you even type that?) to some program. \$\endgroup\$ – mazunki Apr 25 '20 at 20:41
  • 7
    \$\begingroup\$ @mazunki bl lu ur rr ri in ne es ss \$\endgroup\$ – S.S. Anne Apr 26 '20 at 2:15
12
\$\begingroup\$

Husk, 5 bytes

wX2f□

Try it online!

Explanation

   f   Keep all items that
    □  Is an alphanumeric character.
 X     Pick all sublists
  2    With a length of 2.
w      Join the output list by spaces.
\$\endgroup\$
7
\$\begingroup\$

K (ngn/k), 27 24 22 bytes

" "/2'(2!+/"/9@Z`z"<)#

Try it online!

( )# filter

  • "/9@Z`z"< which of these characters is the argument greater than?

  • +/ sum

  • 2! mod 2

2' pairs of adjacent chars

" "/ join with spaces

\$\endgroup\$
7
\$\begingroup\$

05AB1E, 8 7 bytes

-1 byte thanks to @CommandMaster

žKÃüJðý

Try it online!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ 7 bytes: žKÃüJðý \$\endgroup\$ – Command Master Apr 26 '20 at 5:45
7
\$\begingroup\$

Jelly, 6 bytes

fØB;ƝK

A monadic Link accepting a list of characters which yields a list of characters.

Try it online!

How?

fØB;ƝK - Link: list of characters, S
 ØB    - base-62 characters = "01...89AB...YZab...yz"
f      - (S) filter keep if in (that)
    Ɲ  - for neighbours:
   ;   -   concatenate
     K - join with spaces
\$\endgroup\$
7
\$\begingroup\$

[sed] -E (C locale), 46 33 23 bytes

s/\W|_//g;s/\B.\B/& &/g

Try it online!

Thanks to pizzapants184 for a 13-byte improvement.

10 more bytes off thanks to Dom Hastings.


Input on stdin, and output on stdout.

If your locale isn't set to C, you can set it with: export LC_ALL=C

\$\endgroup\$
5
  • 1
    \$\begingroup\$ I think you can replace s/\B(.)\B/\1\1 /g;s/(.) / \1/g with s/\B(.)\B/\1 \1/g for 33 bytes \$\endgroup\$ – pizzapants184 Apr 25 '20 at 5:28
  • \$\begingroup\$ @pizzapants184 Thank you -- I thought I had tried that :) . \$\endgroup\$ – Mitchell Spector Apr 25 '20 at 5:51
  • \$\begingroup\$ You can drop this to 23 bytes with a couple of minor tweaks: Try it online! \$\endgroup\$ – Dom Hastings May 10 '20 at 13:38
  • \$\begingroup\$ It's almost a polyglot with Perl too, if the replacement string is $& $& instead of & &! \$\endgroup\$ – Dom Hastings May 10 '20 at 13:39
  • 1
    \$\begingroup\$ @DomHastings Thank you! \$\endgroup\$ – Mitchell Spector May 10 '20 at 20:29
6
\$\begingroup\$

Pyth, 14 bytes

jd.::Q"\W|_"k2

Try it online!

  • :Q"\W|_"k replaces each non-alphanumeric character of the input with the empty string by matching each character against the regex \W|_

  • .: --- 2 finds all substrings of length 2

  • jd joins the substrings using spaces

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

MATL, 17 16 bytes

t8Y2m)2YC!Z{0&Zc

Try it online! Or verify all test cases.

Explanation

Consider input 'Blurry vision'.

t      % Implicit input. Duplicate
       % STACK: 'Blurry vision', 'Blurry vision'
8Y2    % Push '012...9ABC...Zabc...z' (predefined literal)
       % STACK: 'Blurry vision', 'Blurry vision', '012...9ABC...Zabc...z'
m      % Ismember: true for chars of the first string that are in the second
       % STACK: 'Blurry vision', [1 1 1 1 1 1 0 1 1 1 1 1 1]
)      % Use as logical index. This keeps only letters and numbers in the input
       % STACK: 'Blurryvision'
2YC    % Character matrix with sliding blocks of length 2 as columns
       % STACK: ['Blurryvisio';
                 'lurryvision']
!      % Transpose
       % STACK: ['Bl';
                 'lu';
                 ...
                 'on']
Z{     % Cell array of matrix rows
       % STACK: {'Bl' 'lu ... 'on'}
0&Zc   % Join with character 0 (which will be displayed as space)
       % STACK: 'Bl lu ur rr ry yv vi is si io on'
       % Implicit display
\$\endgroup\$
5
  • \$\begingroup\$ This doesn't seem to properly handle input strings that contain numbers \$\endgroup\$ – math junkie Apr 25 '20 at 0:30
  • 1
    \$\begingroup\$ @mathjunkie Thanks for pointing that out. I have corrected it \$\endgroup\$ – Luis Mendo Apr 25 '20 at 1:50
  • \$\begingroup\$ Save a byte: "@32v! \$\endgroup\$ – Sanchises Apr 25 '20 at 11:47
  • \$\begingroup\$ @Sanchises Thanks! But that produces a trailing space, which is not allowed \$\endgroup\$ – Luis Mendo Apr 25 '20 at 11:54
  • 1
    \$\begingroup\$ Oh yes overlooked the overly restrictive spec \$\endgroup\$ – Sanchises Apr 25 '20 at 16:52
4
\$\begingroup\$

Retina, 13 bytes

\W|_

Lw| `..

Try it online!

Explanation

\W|_ Replace each character NOT in the regex group \W (which is A-Z,a-z,0-9,_) or a _ with nothing

Lw| `.. Compute lists (L) for each set of two characters (..) starting at all positions in the string (w) and separate the lists with a space (| )

\$\endgroup\$
3
  • 1
    \$\begingroup\$ $& is the default output for L so no need to use $. (But I didn't know you could omit the ' after L|.) \$\endgroup\$ – Neil Apr 24 '20 at 22:57
  • \$\begingroup\$ @Neil Thanks for the tip - first Retina answer so still learning and madly skimming the documentation! \$\endgroup\$ – Jarmex Apr 24 '20 at 23:26
  • \$\begingroup\$ (Technically w allows the match to start and end at all positions in the string while v only allows the longest possible matches starting at all positions. Of course it makes no difference in a case like this where there is only one possible match per position.) \$\endgroup\$ – Neil Apr 25 '20 at 9:23
4
\$\begingroup\$

C# (Visual C# Interactive Compiler), 74 bytes

This ended up very similar to the Python answer. I was trying something noticeably more interesting with Aggregate, but the terrible no trailing whitespace requirement made it too long.

s=>s.SelectMany(c=>char.IsLetterOrDigit(c)?c+" "+c:"").Skip(2).SkipLast(2)

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ This is really great - I love seeing C# answers. I originally thought of flattening the list with SelectMany, but decided not to. I ended up utilizing the c+" "+c pattern as well. I need to utilize SkipLast! \$\endgroup\$ – Kale_Surfer_Dude Apr 26 '20 at 1:21
  • \$\begingroup\$ I'm also realizing that char is way more powerful than I originally thought. There's no need to do the String -> char -> String \$\endgroup\$ – Kale_Surfer_Dude Apr 26 '20 at 1:26
3
\$\begingroup\$

Retina 0.8.2, 17 16 bytes

\W|_

M&!`..
¶
 

Try it online! Link includes test cases. Explanation: Now basically a port of @Jarmex's Retina 1 solution, except that M! always joins with newlines, so I have explicitly change them to spaces. Previous 17-byte approach:

\W|_

\B.\B
$& $&

Try it online! Link includes test cases. Explanation:

\W|_

Delete any non-word character and any underscore (which is the only non-alphanumeric character that counts as a word character).

\B.\B
$& $&

Duplicate each inner character and space separate the results.

\$\endgroup\$
2
  • \$\begingroup\$ Another 17-byte solution, slightly different approach: Try it online! \$\endgroup\$ – math junkie Apr 24 '20 at 23:19
  • 1
    \$\begingroup\$ @mathjunkie Actually I was just working on that approach myself, although I had it as 16 bytes because I used a pilcrow instead of \n. \$\endgroup\$ – Neil Apr 24 '20 at 23:28
3
\$\begingroup\$

JavaScript (ES6), 57 bytes

s=>s.replace(/\W|_|(.)/g,(_,c)=>c?c+' '+c:'').slice(2,-2)

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ The approach looks promising so far. \$\endgroup\$ – Robert Apr 25 '20 at 23:54
3
\$\begingroup\$

Factor, 51 bytes

: b ( s -- s ) [ alpha? ] filter 2 clump " " join ;

Try it online!

Unbelievably Factor is competitive with Python and JavaScript :)

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

APL (Dyalog Unicode), 32 bytes (SBCS)

Port of Surculose Sputum's Python answer.

{¯2↓2↓⊃,/{⍵' '⍵}¨⍵∩⎕A,819⌶⎕A,⎕D}

Try it online!

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

QuadR, 18 bytes

1↓∊' ',¨2,/⍵
\W|_

Try it online!

Replaces all non-word characters and underscores (\W|_) with nothing , and then:

2,/⍵ adjacent pairs

' ',¨ prepend a space to each pair

ϵnlist (flatten)

1↓ drop the first space

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

C (gcc), 80 bytes

p,b;f(char*s){for(p=b=0;*s;s++)isalnum(*s)?p&&printf(" %c%c"+!b--,p,*s),p=*s:0;}

Try it online!

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

05AB1E, 23 19 18 bytes

žKég<F®Nè?®N>è?ð?

Try it online!

This probably could be really shorter, but I just wasn't able to find the right tools for the job. -4 bytes thanks to petStorm and a further byte thanks to Command Master.

Old Answer Explained

žj'_ммм©g<F®Nè?®N>è?' ?
žj                      # Push [a-zA-Z0-9_]
  '_м                   # Remove the "_" from the above string
     м                  # Remove all alphanum characters from the input, leaving non-alphanum chars
      м                 # Remove those non-alphanum chars from the input, leaving alphanum chars
       ©                # Put this string into the register
        g<F             # For N in range(0, len(input) - 1):
           ®Nè?         #   Index the string at position N and print
               ®N>è?    #   Index the string at position N + 1 and print
                    ' ? #   Print a space
\$\endgroup\$
2
  • \$\begingroup\$ 19 bytes. \$\endgroup\$ – user92069 Apr 25 '20 at 3:31
  • \$\begingroup\$ 18 bytes \$\endgroup\$ – Command Master Apr 26 '20 at 6:24
3
\$\begingroup\$

Javascript ES6, 55 54 chars

s=>s.replace(/\W|_/g,"").replace(/.(?=(.).)/g,"$&$1 ")

Test:

f=s=>s.replace(/\W|_/g,"").replace(/.(?=(.).)/g,"$&$1 ")

console.log(`Ab -> Ab
Abc -> Ab bc
Abcd -> Ab bc cd
E?h? -> Eh
Blurry vision -> Bl lu ur rr ry yv vi is si io on
We're #1! -> We er re e1
I'm an example! -> Im ma an ne ex xa am mp pl le
This is _not_ legible -> Th hi is si is sn no ot tl le eg gi ib bl le
(a*b*c)+5^-x -> ab bc c5 5x
??a_%,1!=z#@ -> a1 1z`.split`
`.map(s=>s.split` -> `).map(([s,k])=>f(s)==k).every(x=>x))

\$\endgroup\$
1
  • \$\begingroup\$ @tsh, yep, nice. I removed +, but forgot about braces. \$\endgroup\$ – Qwertiy Apr 28 '20 at 7:42
3
\$\begingroup\$

Kotlin, 77 76 bytes

{it.filter{it.isLetterOrDigit()}.zipWithNext{a,b->"$a$b"}.joinToString(" ")}

Old solution

{it.replace("\\W|_".toRegex(),"").zipWithNext{a,b->"$a$b"}.joinToString(" ")}
\$\endgroup\$
2
\$\begingroup\$

Charcoal, 26 bytes

≔ΦS№⁺α⁺β⭆χλιθ⪫E⊖Lθ✂θι⁺²ι¹ 

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

≔ΦS№⁺α⁺β⭆χλιθ

Filter out any character that can't be found in the upper or lower case alphabet and isn't a digit.

⪫E⊖Lθ✂θι⁺²ι¹ 

Extract all substrings of length 2 and join them together on spaces.

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

Icon, 92 bytes

procedure f(s)
t:=""
find(k:=!s,&letters++&digits--'_')&t||:=k||' '||k&\z
return t[3:-2]
end

Try it online!

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

Japt v2.0a0 -S, 6 bytes

r\W ä+

Try it

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

Q/KDB+, 38 bytes

Solution:

{" "sv -2_2#'next\[x inter .Q.an _52]}

Examples:

q){" "sv -2_2#'next\[x inter .Q.an _52]}"Ab"
"Ab"
q){" "sv -2_2#'next\[x inter .Q.an _52]}"Abc"
"Ab bc"
q){" "sv -2_2#'next\[x inter .Q.an _52]}"E?h?"
"Eh"
q){" "sv -2_2#'next\[x inter .Q.an _52]}"This is _not_ legible"
"Th hi is si is sn no ot tl le eg gi ib bl le"

Explanation:

{" "sv -2_2#'next\[x inter .Q.an _52]} / solution
{                                    } / lambda taking implicit x
                           .Q.an       / "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789"
                                 _52   / drop element at index 52
                   x inter             / intersection of x and alphanumerics
             next\[                 ]  / scan along input
          2#'                          / take first 2 characters of each
       -2_                             / drop final two items
 " "sv                                 / join (sv) with " "
\$\endgroup\$
2
\$\begingroup\$

Red, 130 bytes

func[s][a: charset[#"0"-#"9"#"A"-#"Z"#"a"-#"z"]parse s[any[p: change
a(rejoin[p/1" "p/1])| remove skip]]take/part/last s 2 at s 3]

Try it online!

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

JavaScript (ES6), 54 76 bytes

a=>[...a.replace(/[\W_-]/g,'')].map((a,b,c)=>a+c[b+1]).slice(0,-1).join(' ')

Try it online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Hello and welcome to CGCC! Looks like this code isn't ignoring special characters as the spec requires (eg. ??a_%,1!=z#@ should become a1 1z). Hopefully it's an easy fix :) \$\endgroup\$ – math junkie Apr 25 '20 at 20:34
  • \$\begingroup\$ @mathjunkie Sorry, completely missed the comment saying that non-alphanumeric characters must be removed, it's fixed but it makes my answer a lot less competitive. \$\endgroup\$ – Kryštof Píštěk Apr 25 '20 at 20:55
2
\$\begingroup\$

Stax, 6 bytes

£Q·H°·

Run and debug it at staxlang.xyz!

Unpacked (7 bytes) and explanation:

VL|&2BJ
VL         Push string of all alphanumeric characters.
  |&       Remove from the input all letters not in this string.
    2B     All length-2 substrings
      J    Join with spaces
\$\endgroup\$
2
\$\begingroup\$

[C#], 163 155 133 128 127 128 114 112 133 98 bytes

i=>{var b=i.Where(char.IsLetterOrDigit);return b.Select((n,i)=>i==0|i==b.Count()-1?n+"":n+" "+n);}

Run it

Have not used a Regex yet in a Codegolf, so very excite. Regex uses way too many characters. No longer excite.

  • 127 bytes: removed a "." in the regex string
  • 126 bytes: replaced String.Join("" with String.Concat
  • 114 bytes: changed || to |, removed the ( ) { return; } from inside the Select
  • 112 bytes: Removed + from regex
  • 128 bytes: Reverting back to older solution. Entry now legal (thanks to @Neil and @my pronoun is monicareinstate)
  • 98 bytes: Realization that char is way more powerful than I thought (thanks to @my pronoun is monicareinstate's C# solution), removed the string -> char -> string conversions
\$\endgroup\$
5
  • 1
    \$\begingroup\$ Under standard rules this is a snippet rather than a function so you should include the (i,j,p)=>{} to make it legal, but you can at least copy the "\\W|_" that everyone else is using (with two backslashes because it's inside a string literal). Also I think i==0 can be i<1 to save another byte. \$\endgroup\$ – Neil Apr 25 '20 at 9:37
  • \$\begingroup\$ Actually you don't use j or p, so they can go too, so with the other changes you're still ahead overall. \$\endgroup\$ – Neil Apr 25 '20 at 9:38
  • \$\begingroup\$ Besides, for some weird reason you have to count using directives. While the awesome interactive compiler imports several, you still have to count using System.Text.RegularExpressions; :( \$\endgroup\$ – the default. Apr 25 '20 at 10:09
  • \$\begingroup\$ Ah Neil, thanks, I will change it. \$\endgroup\$ – Kale_Surfer_Dude Apr 26 '20 at 0:59
  • \$\begingroup\$ @ my pronoun is monicareinstate do you have a link for more info on that rule? Thanks \$\endgroup\$ – Kale_Surfer_Dude Apr 26 '20 at 1:02
2
\$\begingroup\$

C (gcc), 123 \$\cdots\$ 117 116 bytes

i;f(char*s){char*t=s;for(i=0;t[i+=!!isalnum(*s++)]=*s;);for(putchar(*t++);t[1];)printf("%c %1$c",*t++);putchar(*t);}

Try it online!

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

Haskell, 86 74 bytes

-12 bytes thanks to Khuldraeseth na'Barya

import Data.Char
unwords.map(\(x,y)->[x,y]).(zip<*>tail).filter isAlphaNum

Try it online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ \x->zip x$tail x is zip<*>tail for four bytes of savings. \$\endgroup\$ – Khuldraeseth na'Barya Apr 25 '20 at 23:02
  • \$\begingroup\$ uncurry$(.pure).(:) is \(a,b)->[a,b] for another six. \$\endgroup\$ – Khuldraeseth na'Barya Apr 25 '20 at 23:03
2
\$\begingroup\$

J, 42 bytes

1}.[:,/2' '&,\]#~'/9@Z`z'(2|I."#.)&(3&u:)]

Try it online!

Inspired by ngn's ngn/k solution

Explanation

                                   (3&u:)     convert to integer both
                                         ]    the input
                 '/9@Z`z'                     and the symbols surrounding the digits, 
                                              uppercas and lowercase letters
                         (2|I."#.)&           and find in which interval lies each char
                                              then check if it's an odd one
              ]#~                             use the above to filter the input
       2' '&,\                                prepend each pair of adjacent chars
                                              with a space
   [:,/                                       flatten the result 
1}.                                           and drop the leading space 
\$\endgroup\$

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.