# Bl lu ur rr ry yv vi is si io on - Blur the text

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!

• The non-alphanumeric characters have to be ignored or can be ignored?
– RGS
Apr 24 '20 at 21:39
• @RGS Thanks for the clarification question, non-alphanumeric characters must be ignored Apr 24 '20 at 21:42
• 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. Apr 24 '20 at 23:18
• Here are some posts 1 2 where you can read more about why I disagree with these extraneous elements. Apr 24 '20 at 23:21
• 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. Apr 25 '20 at 20:15

# 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"

• 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. Apr 25 '20 at 20:41
• @mazunki bl lu ur rr ri in ne es ss Apr 26 '20 at 2:15

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


# 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

# 05AB1E, 8 7 bytes

-1 byte thanks to @CommandMaster

žKÃüJðý


Try it online!

• 7 bytes: žKÃüJðý Apr 26 '20 at 5:45

# 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


# [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

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

# K (ngn/k), 27 24 22 20 bytes

" "/2'(2!"/9@Zz"')_


Try it online!

"/9@Zz"' binary search in the given string

2! mod 2

(2!"/9@Zz"')_ drop non-alphanumeric chars

2' make a list of pairs of adjacent chars

" "/ join with spaces

# MATL, 17 16 bytes

t8Y2m)2YC!Z{0&Zc


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

• This doesn't seem to properly handle input strings that contain numbers Apr 25 '20 at 0:30
• @mathjunkie Thanks for pointing that out. I have corrected it Apr 25 '20 at 1:50
• Save a byte: "@32v! Apr 25 '20 at 11:47
• @Sanchises Thanks! But that produces a trailing space, which is not allowed Apr 25 '20 at 11:54
• Oh yes overlooked the overly restrictive spec Apr 25 '20 at 16:52

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

• $& is the default output for L so no need to use $. (But I didn't know you could omit the ' after L|.)
– Neil
Apr 24 '20 at 22:57
• @Neil Thanks for the tip - first Retina answer so still learning and madly skimming the documentation! Apr 24 '20 at 23:26
• (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.)
– Neil
Apr 25 '20 at 9:23

# 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!

• 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! Apr 26 '20 at 1:21
• I'm also realizing that char is way more powerful than I originally thought. There's no need to do the String -> char -> String Apr 26 '20 at 1:26

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

• Another 17-byte solution, slightly different approach: Try it online! Apr 24 '20 at 23:19
• @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.
– Neil
Apr 24 '20 at 23:28

# JavaScript (ES6), 57 bytes

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


Try it online!

• The approach looks promising so far. Apr 25 '20 at 23:54

# Factor, 51 bytes

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


Try it online!

Unbelievably Factor is competitive with Python and JavaScript :)

# APL (Dyalog Unicode), 32 bytes (SBCS)

Port of Surculose Sputum's Python answer.

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


Try it online!

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

# 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!

# 05AB1E, 2319 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.

ž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

• – user92069
Apr 25 '20 at 3:31
• 18 bytes Apr 26 '20 at 6:24

# TEX (INITEX), 372 bytes

\catcode~13\let~\catcode~{1~}2~#6~\ 12~|13\let|\expandafter\def\z{}\def\f#1{#1}\def\i#1{}\def\b#1#2{\ifx#2\e|||\i|\i\else|\f\fi{\ifcat#1a|\f\else|||\b|||#2|\i\fi}{\ifcat#2a #1#2|\b|#2\else|\b|#1\fi}}\def\t{~011~111~211~311~411~511~611~711~811~911~\|12~\~12~\#12~\{12~\}12~127=12~\%12~\\12\read16to\x\edef\r{|\b\x\e}\immediate\write16{|\i\r\z}\end}\t


For example, the program being saved in a file named "codegolf.tex", provided with input ??a_%,1!=\z#@, initex codegolf.tex outputs:

This is TeX, Version 3.14159265 (TeX Live 2019/dev/Debian) (INITEX)
(./codegolf.tex
\x=??a_%,1!=\z#@
a1 1z
)
No pages of output.
Transcript written on codegolf.log.


In the case of a degraded input, for example the strings ??, ?a, or a?, this implementation does not print any pair.

# Explanation

## Basis for a TEX program

\read16


Per this Meta answer, the input of a program written in TEX should come from standard input, which is the in register number 16.

\immediate\write16


The TEX Codegolf community prefers to output to DVI or PDF, because it is simpler than writing to the terminal. However, this requires a valid \output routine, which either requires a format (with more category codes to alter1) or is longer to define. So I write to the terminal. (\message could also have been used, but I don't like how the output is surrounded by TEX chat on the same line).

Because I output to the terminal, I also feel that no DVI file should get produced, so \immediate is required2.

\end


This is a complete program, so it must end with \end to run cleanly.

## Category codes

Running on alphanumerics and ignoring punctuation is a trivial matter for TEX. All I have to do is to customize the category codes of those characters.

For this subject, I will use category code 11 ("letter") for characters that need to be blurred, and category code 12 ("other") for characters that are to be dropped. That choice comes from the defaults of (ini)TEX, where letters are already set to 11 and most of the other characters to 12.

\catcode~13\let~\catcode


To save bytes, I make ~ an active character and set its meaning to \catcode. In the rest of the explanation, that alias will be ungolfed.

\catcode{=1 \catcode}=2 \catcode#=6 \catcode\ =12


These are required for INITEX to interpret my program correctly: { is now the begin-group character, } the end-group, # the macro argument, and is considered a normal character (so that the first spurious space of output can be removed). These choices are widely used in the TEX world and do not cost bytes3.

\catcode|=13 \let|=\expandafter


This is an useful alias for later.

\def\t{\catcode0=11 ... \end}
\t


This is a TEX design pattern that fools TEX's eyes. Everything that is written in the \todo macro definition will get a category code assigned, and this category code will not be reconsidered when TeX expands the macro. Most notably:

\catcode\\=12


This makes the escape character \ a normal character when read from the user input.

\read16to\x \edef\r{|\b\x\e} \immediate\write16{|\i\r\z} \end


When reading the macro definition, TEX has decided that these were control words, and TEX will not reconsider this choice after the macro has been expanded, even if \ has lost its special meaning in the meantime.

\catcode127=12


The DEL character is contained in ASCII, so it should be valid input per the subject's rules. But in order to change its category code to 12, the DEL character has to be written, and the most efficient4 way to input it in TEX is to name it by its code point.

\catcode0=11 ... \catcode\\=12


Here are three groups of category code assignments: make the digits like letters, revert the changes made at the beginning of the program, and cancel other INITEX defaults (DEL, %, \, but not the new line because the subject emits the hypothesis:)

Your input will be a single-line string

## The blurring command

Because I opted for terminal output, and because \write does not executes its argument (only expands it), I am forced to write the \blur macro as fully expandable.

\def\z{} \def\firstofone#1{#1} \def\ignore#1{}


As a prolog, I define three macros, which are commonly used in various fully-expandable design patterns. The first one is the empty macro, the second one is the identity macro, and the third one is the zero macro.

\def\blur#1#2{ ... }


The \blur macro is recursive5. It takes two characters at a time (because the rules say that the input is longer than two). Its definition is made of three parts.

\ifx#2\e \expandafter\expandafter \expandafter\ignore \expandafter\ignore
\else    \expandafter\firstofone
\fi


is the recursion condition: if the end-of-string marker (the undefined command \e6) is found, ignore the two other parts. (More precisely, drop the unused portion of the conditional \else...\fi at \expandafter level 0, then ignore the second part at \expandafter level 1, then ignore the third part at \expandafter level 2.) Otherwise, close the conditional and interpret the second part.

\ifcat#1a \expandafter\firstofone
\else \expandafter\expandafter \expandafter\blur
\expandafter\expandafter \expandafter#2
\expandafter             \ignore
\fi


handles the first character. If it is a letter or digit, go analysing a second character. Otherwise, skip the remaining of the conditional, ignore the third part, and call \blur recursively with #1 being dropped and #2 as the first character7 (an other one will get extracted from input).

\ifcat#2a ␣#1#2 \expandafter\blur \expandafter#2
\else \expandafter\blur \expandafter#1
\fi


handles the second character. If it is a letter or digit, output a space then the first part of the blur, then forget about #1 and call \blur recursively on #27. Otherwise, forget about it and call \blur recursively on #17.

## Calling the blurring command on real input

\read16 to \x


will store the input into an (expandable) macro \x.

\expandafter\blur \x \e


This is how the \blur macro is called. Because \blur acts on tokens, the input contained in \x must be expanded first. The end-of-string marker follows.

\edef\result{\expandafter\blur \x \e}


The result of the expansion, including the whitespace at front, is stored into the \result macro.

\expandafter\ignore \result \z


Inside the \write16 command, the \result macro is first expanded. Then, \ignore eliminates the first token of output: the first space if the output is non-empty, or the \z macro call if the output is empty. In the first case, the \z macro will survive; but \write16 will finally expand it, and its expansion is a no-op. This is the most efficient way of handling the “no trailing space” requirement, even if it requires 24 bytes (the definition and call of \z and \return); suppressing a space at the end of the output would have been nearly impossible.

## ☡ Footnotes

1. $, &, ^, _, NUL, SPC, TAB, ~ for plain TEX; 5 bytes each = 40 bytes. 2. Without \immediate, \write adds its content to a whatsit box, thus generating a page of output. 3. Because there are only three category code changes, it is not worth putting them in a group to save the reverting. 4. Decimal: 127= (4); Hexadecimal: "7F= (4, harder to read); Octal: '199= (5); Escape sequence: \^^? (5, plus \catcode^7 and revert) 5. It is even tail-recursive, which in TEX has the meaning of "it does not add tokens after the recursive call", and by doing so is more memory-friendly. 6. Because all input other than my program does not get interpreted, the \e command cannot be defined later. 7. This would fail if #2 was a simple group of arguments, but fortunately the input cannot contain simple groups, because no character has category code 1 nor 2. # 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)) • @tsh, yep, nice. I removed +, but forgot about braces. Apr 28 '20 at 7:42 # 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(" ")}  # Charcoal, 26 bytes ≔ΦＳ№⁺α⁺β⭆χλιθ⪫Ｅ⊖Ｌθ✂θι⁺²ι¹  Try it online! Link is to verbose version of code. Explanation: ≔ΦＳ№⁺α⁺β⭆χλιθ  Filter out any character that can't be found in the upper or lower case alphabet and isn't a digit. ⪫Ｅ⊖Ｌθ✂θι⁺²ι¹  Extract all substrings of length 2 and join them together on spaces. # Icon, 92 bytes procedure f(s) t:="" find(k:=!s,&letters++&digits--'_')&t||:=k||' '||k&\z return t[3:-2] end  Try it online! # Japt v2.0a0 -S, 6 bytes r\W ä+  Try it # 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 " "  # 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! # 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! • 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 :) Apr 25 '20 at 20:34 • @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. Apr 25 '20 at 20:55 • You can save 2 bytes with .join  Aug 9 at 7:06 # 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  # [C#], 163155133128127128114112133 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 • 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. – Neil Apr 25 '20 at 9:37 • Actually you don't use j or p, so they can go too, so with the other changes you're still ahead overall. – Neil Apr 25 '20 at 9:38 • 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; :( Apr 25 '20 at 10:09 • Ah Neil, thanks, I will change it. Apr 26 '20 at 0:59 • @ my pronoun is monicareinstate do you have a link for more info on that rule? Thanks Apr 26 '20 at 1:02 # 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!

import Data.Char

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