24
\$\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\$ Apr 24 '20 at 21:42
  • 32
    \$\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\$
    – Grain Ghost
    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\$
    – Grain Ghost
    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

46 Answers 46

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

C (gcc), 159 bytes (-2 more bytes thanks to S.S. Anne and JustinCB)

main(a,b)char**b;{b++;for(a=0;a<strlen(*b);a++){if(isalnum((*b)[a])){a?putchar((*b)[a]):0;a&&a<strlen(*b)-1?putchar(32):0;a<strlen(*b)-1?putchar((*b)[a]):0;}}}

Try it online!

\$\endgroup\$
10
  • \$\begingroup\$ You can save some bytes: i;main(a,b)char**b;{b++;for(i=0;i<strlen(*b);i++){if(isalnum((*b)[i]))putchar(i?(*b)[i]:0);putchar(i&&i<strlen(*b)-1?32:0);putchar(i<strlen(*b)-1?(*b)[i]:0);}} \$\endgroup\$
    – JustinCB
    Apr 25 '20 at 15:17
  • \$\begingroup\$ The above version moves the declaration of i outside of main, allowing it to be implicitly declared as an int(saving 4 bytes) & moves the declaration of b's type after the function declaration, K&R-style, which allows a to be implicitly declared as an int(saving 2 bytes) \$\endgroup\$
    – JustinCB
    Apr 25 '20 at 15:19
  • \$\begingroup\$ Actually, for your code to work properly for the more advanced test cases, you need to wrap the putchar's in brackets, adding 2 bytes: i;main(a,b)char**b;{b++;for(i=0;i<strlen(*b);i++){if(isalnum((*b)[i])){putchar(i?(*b)[i]:0);putchar(i&&i<strlen(*b)-1?32:0);putchar(i<strlen(*b)-1?(*b)[i]:0);}}} \$\endgroup\$
    – JustinCB
    Apr 25 '20 at 15:24
  • \$\begingroup\$ Cool, thanks! I'll update the answer. \$\endgroup\$
    – sugarfi
    Apr 25 '20 at 15:36
  • \$\begingroup\$ I don't think outputting null bytes is allowed. Also, you can remove i; and use a instead. \$\endgroup\$
    – S.S. Anne
    Apr 25 '20 at 20:06
2
\$\begingroup\$

Elixir, 120 bytes

b=fn w->import String;l=replace(w,~r/[\W_]/,"");for(i<-0..String.length(l)-2,do: at(l,i)<>at(l,i+1))|>Enum.join(" ") end

Try it online!

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

Raku, 31 bytes

{@$_ Z~.skip}o{S:g/\W|_//.comb}

Try it online!

The extra requirement for stripping non-alphanumeric characters takes up more than half of the bytes.

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

J, 32 bytes

[:}:[:,/2,&' '\]-.-.&AlphaNum_j_

Try it online!

               -.-.&AlphaNum_j_   remove non-alphanumeric
       2,&' '\                    append space to each pair of adjacent chars 
     ,/                           join 
 }:                               remove trailing space
\$\endgroup\$
2
\$\begingroup\$

F#, 130 bytes

let f s=s|>Seq.filter Char.IsLetterOrDigit|>fun x->Seq.tail x|>Seq.zip x|>Seq.map(fun(a,b)->string a+string b)|>String.concat" "
\$\endgroup\$
2
\$\begingroup\$

AWK, 52 54 bytes

{gsub("\\W|_",a);for(b=$0;c=substr(b,++d,2);)$d=c}--NF

Try it online!

Fixed underscore rule goof (+2 chars), thanks to Pedro Maimere

Here's what's going on with this one...

gsub("\\W",a)

Removes all the non-alphabetic characters from the input string since $0 is the default target for gsub. Using an unitialized variable a instead of "" saves a byte.

Next the code loops through the string taking 2 character slices and assigns them to positional variables.

for(b=$0;

The setup has to save $0 to another variable, since changing the positional variables impacts the collected input in $0 as well.

c=substr(b,++d,2);

The "test" at the top of the loop does a couple of things in one statement:

  • increments d, the "current character" pointer
  • sets variable c to the next 2 character slices of the input
  • the true/false test simple has the code looping until we run off the string and get a null

The body of the loop sets the next positional variable to the slice we just took.

$d=c

After all the positional variables have been set, there's one "garbage" entry on the end with one character. So the test:

--NF

effectively drops that last positional variable and triggers the default action, which prints all the positional variables separated by a space.

\$\endgroup\$
3
  • 2
    \$\begingroup\$ Great explanation, again. \$\endgroup\$ Mar 2 at 10:20
  • 1
    \$\begingroup\$ Nice piece of code! According to the question's examples, underscores (_) are meant to be erased. Unfortunately, gawk's \W is the same as [^[:alnum:]_], so the underscores are not erased. Thus, the regex would become "\\W|_". \$\endgroup\$ Jun 5 at 0:54
  • 1
    \$\begingroup\$ Nice catch! I'll update the code to add the underscore. \$\endgroup\$
    – cnamejj
    Jun 5 at 1:05
1
\$\begingroup\$

Erlang (escript), 110 bytes

Port of the Python answer.

f(X)->R=lists:flatten([[I]++" "++[I]||I<-X,re:run([I],"[A-Za-z0-9]")/=nomatch]),string:slice(R,2,length(R)-4).

Try it online!

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

Swift, 141 bytes

{let a=$0.unicodeScalars.filter{CharacterSet.alphanumerics.contains($0)};return zip(a,a.dropFirst()).map{"\($0)\($1)"}.joined(separator:" ")}

Ungolfed:

let ungolfed: (String) -> String = { input in
    let unicodeScalars = input.unicodeScalars.filter { char in CharacterSet.alphanumerics.contains(char) }
    return zip(unicodeScalars, unicodeScalars.dropFirst())
        .map { "\($0)\($1)" }
        .joined(separator: " ")
}

Test case runner:

import Foundation

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

for (input, expectedOutput) in testCases {
    let actualOutput = f(input)
    assert(actualOutput == expectedOutput, """
    Wrong answer.
        input: '\(input)'
        actualOutput: '\(actualOutput)'
        expectedOutput: '\(expectedOutput)'

    """)
}
```
\$\endgroup\$
1
\$\begingroup\$

Python 3, 82 chars

a=[c for c in input() if c.isalnum()]
print(' '.join(a+b for a,b in zip(a,a[1:])))

Try it: https://ideone.com/dxJU8e

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

Java (JDK), 59 bytes

s->s.replaceAll("\\W|_","").replaceAll(".(?=(.).)","$0$1 ")

Try it online!

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

Vyxal S, 26 15 7 bytes

kr↔2lvṅ

Try it Online!
-6 thanks to @astonearachnid
-5 from some of my tricks.
-8 thanks to lyxal.

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

R, 98 bytes

function(x,y=grep("[a-z0-9]",el(strsplit(x,"")),T,,T))for(i in seq(y)[-1])cat(y[i-1:0],' ',sep='')

Try it online!

Unusually for R, a for loop is significantly shorter than a matrix-based approach, mainly because it allows us to just use cat instead of the much-more-verbose Reduce(paste vectorized way to build a text string from a list of characters.

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

PowerShell Core, 56 bytes

$n=$args|% t*y|%{$_+" "+$_}
-join$n[0..($n.length-2)+-1]

Try it online!

-20 bytes for @mazzy

\$\endgroup\$
3
  • \$\begingroup\$ nice. you don't need $s. see Try it online! \$\endgroup\$
    – mazzy
    Mar 2 at 10:06
  • \$\begingroup\$ @mazzy thanks for it! \$\endgroup\$
    – wasif
    Mar 2 at 10:07
  • \$\begingroup\$ Wasif, I think improvements are needed here. See test case Blurry vision \$\endgroup\$
    – mazzy
    Mar 2 at 10:11
0
\$\begingroup\$

PowerShell Core, 48 47 bytes

''+($args-match'[a-z\d]'|%{,"$p$_"*!!$p;$p=$_})

Try it online!

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

APL (NARS2000 dialect) 24 bytes

{¯1↓1↓⍕2,/⍵/⍨⍵∊A←⎕a,⎕A,⎕D}
\$\endgroup\$
1
  • \$\begingroup\$ Thank you for format editing, @ppery \$\endgroup\$
    – turnip
    Mar 3 at 17:08
1
2

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.