9
\$\begingroup\$

A space cleaner is a special character which removes all spaces between it and the first non space character to its left and it is represented by a '!' character. If it reaches the beginning of the string it stops.

Given a string output the string in any reasonable format after the cleaning process.

Trailing spaces at the end of the string must be still be in the output.

Remember that space cleaners remain after their job.

Input will only consist of printable ASCII characters.

This is code-golf, so least number of bytes win.

Test Cases

" ! a! !b c!d !" => "! a!!b c!d!"
"a    !" => "a!"
"!    a" => "!    a"
"!    !    !" => "!!!"
"! " => "! "
\$\endgroup\$
17
  • 8
    \$\begingroup\$ Some test cases would be good. I assume that the cleaners are represented by !s, since it isn't quite clear. So basically, this boils down to "remove any spaces before a space cleaner", correct? \$\endgroup\$
    – Jo King
    Sep 10, 2019 at 6:07
  • 2
    \$\begingroup\$ Can we get some examples? What is the minimum string length? What do we do with the input string !? This looks like it would be trivially solved by a regex looking for any number of spaces followed by a bang? \$\endgroup\$
    – mkst
    Sep 10, 2019 at 6:08
  • 1
    \$\begingroup\$ May we choose which character to use as the "pipe cleaner"? \$\endgroup\$
    – Shaggy
    Sep 10, 2019 at 7:00
  • 3
    \$\begingroup\$ Suggested test case "! " => "! " \$\endgroup\$
    – Jitse
    Sep 10, 2019 at 8:05
  • 1
    \$\begingroup\$ @AZTECCO Test case added. For the question, nope. \$\endgroup\$
    – null
    Sep 10, 2019 at 9:56

27 Answers 27

8
\$\begingroup\$

05AB1E, 5 bytes

„ !¤:

Try it online!


Explanation

„ !                  # 2 char string " !"
   ¤                 # Push the tail of that (so "!") 
    :                # Infinite replacement
\$\endgroup\$
0
5
\$\begingroup\$

Retina, 5 bytes

 +!
!

Try it online.

Not much to say. Simply removes all spaces in front of every ! with a simple replace.

\$\endgroup\$
4
  • \$\begingroup\$ 4th test case ! ! ! -> !!! why not ! !! ? \$\endgroup\$ Sep 10, 2019 at 7:12
  • 4
    \$\begingroup\$ @NahuelFouilleul Why not? I assume all space cleaners 'walk' simultaneously, so eventually they'll reach the start of the string for that test case. OP never stated the left one walks first, only that all space cleaners travel left. \$\endgroup\$ Sep 10, 2019 at 7:17
  • 1
    \$\begingroup\$ maybe the OP should clarify \$\endgroup\$ Sep 10, 2019 at 7:21
  • 1
    \$\begingroup\$ The assumption is correct. (Which, if I'm not mistaken, is equivalent to "the left ones first".) \$\endgroup\$
    – null
    Sep 10, 2019 at 9:48
5
\$\begingroup\$

JavaScript (ES6), 24 bytes

Thanks to @Nick Kennedy for the TIO link and -2 bytes, since I could omit the function name f=

_=>_.replace(/ +!/g,'!')

Try It Online

Nothing special, same regex as other answers. New to codegolf, was a simple one to translate to js. If anyone can think of improvements I'd love to see them.

\$\endgroup\$
4
  • 2
    \$\begingroup\$ Welcome to the site! \$\endgroup\$
    – Wheat Wizard
    Sep 11, 2019 at 16:58
  • 1
    \$\begingroup\$ Welcome to the site! I like the underline obfuscation LOL. \$\endgroup\$
    – null
    Sep 12, 2019 at 5:35
  • \$\begingroup\$ Welcome! Would suggest having a Try it online link with a working example. Also you can move the naming of the lambda to a header and remove it from the byte count. e.g. tio.run/##BcExDoAgDADAr7QsQFRYXfArBCsQDREChu/… \$\endgroup\$ Sep 12, 2019 at 13:38
  • \$\begingroup\$ @NickKennedy Thanks! I wasn't sure about the function naming, good to know. I considered the TIO link but figured it's easy enough to test JS with browser console. Although, I will edit it into my post. \$\endgroup\$
    – Matsyir
    Sep 12, 2019 at 13:52
4
\$\begingroup\$

PHP, 35 bytes

<?=preg_replace('/ +!/','!',$argn);

Try it online!

Just a simple RegEx replace.

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

R, 25 bytes

gsub(" +!","!",scan(,''))

Straightforward enough with a simple regex substitution!

Try it online!

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

Haskell, 48 42 bytes

-6 bytes thanks to H.PWiz!

g(' ':b)|'!':_<-g b=g b
g(a:b)=a:g b
g a=a

Try it online!

Explanation:

g(' ':b)                 -- Given a string starting with space
        |'!':_           -- Check if '!' is the first element of
              <-g b      -- The function applied to the rest of it
                   =g b  -- Return the function applied to the rest of it
g(a:b)=a:g b             -- Otherwise just apply the function recursively
g a=a                    -- Until the string is empty
\$\endgroup\$
1
  • 1
    \$\begingroup\$ You don't need parens around g b. Also, you can replace g b!!0=='!' with '!':_<-g b \$\endgroup\$
    – H.PWiz
    Sep 12, 2019 at 1:42
3
\$\begingroup\$

Python 3, 50 bytes

f=lambda s:' !'in s and f(s.replace(' !','!'))or s

Try it online!

Port of Expired Data's 05AB1E answer, so make sure to upvote him!


Original answer:

Python 3, 63 bytes

lambda s:'!'.join(i.rstrip(' ')for i in(s+'_').split('!'))[:-1]

Try it online!

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

brainfuck, 66 bytes

,[<<++++[->++++++++<]>>[-<-<+>>]<[+[[+]<<[.<]>[>]]<.>>]>>,]<<<[.<]

Try it online!

It's funny how much space is just taken up by constants, in this case making a space takes up more than a quarter of the code.

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

Haskell, 34 bytes

foldr(%)""
' '%r@('!':_)=r
c%s=c:s

Try it online!

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

ksh, 18 bytes

try it online!

echo ${1//+( )!/!}

zsh, 32 bytes
Since there's another zsh answer I changed to ksh. Thanks to @Gilles at unix.se for zsh help. try it online!
setopt ksh_glob;<<<${1//+( )!/!}

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

///, 6 bytes

/ !/!/

Try it online!

Replaces every occurrence of ! with ! until it eats up all the spaces in front of the exclamation marks.

The language is a perfect match because it's built on find/replace. That's the only command you're given, and not a single special character or wild card to use in your patterns, except the \ which only serves to escape the /. Yet, it's Turing complete. It's really elegant!

The language is read by slash triplets, hence the name. Each one couches a find pattern and replace pattern. We have one such pattern here doing precisely what it says at the top. The first pair of slashes says to find all ! and the second pair says to replace them with !.

\$\endgroup\$
1
  • \$\begingroup\$ What I intended. But input: / :( \$\endgroup\$
    – null
    Jul 26, 2021 at 16:07
2
\$\begingroup\$

Perl 5 (-p), 9 bytes

s/ *!/!/g

TIO

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

PowerShell, 22 bytes

$args-replace' +!','!'

Try it online!

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

Jelly, 11 bytes

œṣ⁾ !j”!µÐL

Try it online!

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

Python 3, 38 bytes

lambda s:re.sub(' +!','!',s)
import re

A simple regex substitution. Replaces any amount of space plus an exclamation mark with just an exclamation mark.

\$\endgroup\$
2
  • \$\begingroup\$ Why using a raw string? lambda s:re.sub(' *!','!',s) is a byte shorter. \$\endgroup\$
    – Skillmon
    Sep 13, 2019 at 13:44
  • \$\begingroup\$ @Skillmon Man, that habit is hard to break for code golf. Thanks for pointing it out! \$\endgroup\$ Sep 13, 2019 at 14:22
2
\$\begingroup\$

Zsh with extended_glob, 14 bytes

<<<${1// #!/!}

Zsh with extended_glob is not an arbitrary whim: it's the language in which zsh completion functions are written. Inspired by roblogic's initial attempt. Try it online.

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

Charcoal, 22 bytes

≔ ηF⮌S«≡ι!≔ωη ≔ηι≔ η←ι

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

≔ η

h is a variable that specifies whether a space is being cleaned or not.

F⮌S«

Loop over the string in reverse as the spaces are cleaned to the left.

≡ι

Switch over the current character.

!≔ωη

If it's a ! then start cleaning spaces.

 ≔ηι

If it's a space then replace it with the space cleaning flag.

≔ η

Otherwise turn off space cleaning.

←ι

Print the current character leftwards.

Boring 15-byte version:

W№θ !≔⪫⪪θ !¦!θθ

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

W№θ !

Repeat while there are spaces to be cleaned.

≔⪫⪪θ !¦!θ

Clean up to one space per space cleaner.

θ

Output the result.

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

Japt, 7 bytes

Recursive replacement. Could save 2 bytes if we could choose the "cleaner" character.

e" !"'!

Try it

\$\endgroup\$
3
  • \$\begingroup\$ I didn't get how did you save bytes by changing the cleaner character. \$\endgroup\$
    – null
    Sep 10, 2019 at 13:20
  • \$\begingroup\$ @TwilightSparkle, Japt has constants for a few characters & digits (e.g., T===0), which would allow me to do something like eS+TT (where S is Japt's constant for a single space). \$\endgroup\$
    – Shaggy
    Sep 10, 2019 at 13:29
  • \$\begingroup\$ Thanks for the explanation. I choose ! just because it's next to the space in the ASCII table. \$\endgroup\$
    – null
    Sep 11, 2019 at 13:31
1
\$\begingroup\$

Perl 6, 14 bytes

{S:g/\s+\!/!/}

Try it online!

Loses bytes over other regex solutions since I can't use a literal space and I have to escape the metaoperator !

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

J, 16 bytes

(#~1-' !'E.])^:_

Try it online!

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

C (clang), 79 bytes

j,e;f(char*s){for(j=e=0;!e;e=!*s++)*s-32?s-=*s-33?j:0,j=0,*s&&putchar(*s):j++;}

Try it online!

Saved 1 thanks to @ceilingcat *s && instead of !*s ||

j is used to jump back if there is no "!" after spaces.

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

Ruby -p, 14 bytes

gsub(/ +!/,?!)

Unfortunately the 13-byte gsub / +!/,?! doesn't work because Ruby interprets the first / as division instead of the start of a regex statement.

Try it online!

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

Java 8+, 26 bytes

Yet another regex port

s->s.replaceAll(" +!","!")

TIO

\$\endgroup\$
2
  • 1
    \$\begingroup\$ I think lambdas where first introduced in Java 8. \$\endgroup\$ Sep 14, 2019 at 23:39
  • \$\begingroup\$ @JonathanFrech I had a brain short-circuit there \$\endgroup\$ Sep 15, 2019 at 13:31
1
\$\begingroup\$

Pip, 8 bytes

aRw.'!'!

Try it online!

concatenates the whitespace regex variable w with an ! character. then replaces it with a single ! in the string.

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

Husk, 8 bytes

ωσ" !""!

Try it online!

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

AWK, 16 bytes

gsub(" *!","!")1

Try it online!

Similar regex to some others that were posted, just AWK-styled. Adding a random number on the end makes sure it prints even if the input has no cleaner character.

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

Vyxal, 9 bytes

` *!`\!øṙ

Try it Online!

Another one ports the regex

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