Undress a string

48

2

We already now how to strip a string from its spaces.

However, as proper gentlemen/ladies, we should rather undress it.


Undressing a string is the same as stripping it, only more delicate. Instead of removing all leading and trailing spaces at once, we remove them one by one. We also alternate between leading and trailing, so as not to burn steps.

Example, starting with " codegolf " (five leading and trailing spaces):

     codegolf     
    codegolf     
    codegolf    
   codegolf    
   codegolf   
  codegolf   
  codegolf  
 codegolf  
 codegolf 
codegolf 
codegolf

  1. First output the string unchanged. Then, output every step. Begin by removing a leading space (if applicable - see rule #2).

  2. The input may have a different number of leading and trailing spaces. If you run out of spaces on one side, keep undressing the other until the string is bare.

  3. The input may have no leading nor trailing spaces. If that's the case, output it as-is.

  4. Use PPCG's default I/O methods. PPCG Default loopholes are forbidden.

  5. Undefined behaviour on empty input, or input that only contains spaces, is OK.

  6. You can assume that the string will only contain characters from the ASCII printable space (0x20 to 0x7E).


Examples - spaces are replaced by dots . for better readability:

4 leading spaces, 5 trailing: "....Yes, Sir!....."
....Yes, Sir!.....
...Yes, Sir!.....
...Yes, Sir!....
..Yes, Sir!....
..Yes, Sir!...
.Yes, Sir!...
.Yes, Sir!..
Yes, Sir!..
Yes, Sir!.
Yes, Sir!

6 leading, 3 trailing: "......Let's go golfing..."
......Let's go golfing...
.....Let's go golfing...
.....Let's go golfing..
....Let's go golfing..
....Let's go golfing.
...Let's go golfing.
...Let's go golfing
..Let's go golfing
.Let's go golfing
Let's go golfing

0 leading, 2 trailing: "Hello.."
Hello..
Hello.
Hello

0 leading, 0 trailing: "World"
World

21 leading, 5 trailing: ".....................a....."
.....................a.....
....................a.....
....................a....
...................a....
...................a...
..................a...
..................a..
.................a..
.................a.
................a.
................a
...............a
..............a
.............a
............a
...........a
..........a
.........a
........a
.......a
......a
.....a
....a
...a
..a
.a
a

A gentleman/lady is concise, so the shortest answer in bytes wins.

Nathan.Eilisha Shiraini

Posted 2017-09-21T09:19:05.853

Reputation: 561

From Sandbox: https://codegolf.meta.stackexchange.com/a/13765/71426

– Nathan.Eilisha Shiraini – 2017-09-21T09:19:15.097

Can we assume that there will be at least one non-space character? – Martin Ender – 2017-09-21T09:34:23.883

@MartinEnder Yes – Nathan.Eilisha Shiraini – 2017-09-21T10:23:31.623

Can a test string contain new-lines or tabs? (Or more precisely, will the spaces have the lowest decimal value 32 in the strings?) – Kevin Cruijssen – 2017-09-21T10:47:10.683

2@KevinCruijssen You only have to handle ASCII characters in the printable space (0x20 to 0x7E). The other ones are Undefined Behavior. – Nathan.Eilisha Shiraini – 2017-09-21T10:54:26.537

@Nathan.EilishaShiraini Ok, so a test case like " \ntest " or " \t test " isn't possible (\n being a line-feed; \t being a tab)? – Kevin Cruijssen – 2017-09-21T10:55:46.120

1@KevinCruijssen Yes, there will be no test case like this. There will be no things like " test\r " or " \v test" either. – Nathan.Eilisha Shiraini – 2017-09-21T10:57:16.653

@Nathan.EilishaShiraini LOL! Thank you for this idea :) – frarugi87 – 2017-09-21T12:12:37.893

do we need to output as 1 line for each step or can we return a list of strings with all the steps? – Felipe Nardi Batista – 2017-09-21T12:52:40.523

1Is this a valid test case ".....................a....."? If so I suggest to add it since some answers seems to fail this kind of test. (dots are for better readability of course) – Cinaski – 2017-09-21T13:54:27.267

@FelipeNardiBatista I thought list of string instead of multiline string was implicitely allowed as part of the standard I/O methods. Now: it is explicitely valid. – Nathan.Eilisha Shiraini – 2017-09-21T14:48:18.697

Added @Cinaski 's suggested test case. Thanks! – Nathan.Eilisha Shiraini – 2017-09-21T14:59:25.137

After testing the answers with Cinaski's test case, I found that some of them inconsistently add a trailing empty line. Since they are already there, and upvoted, I will allow this in order to leave these answers valid. – Nathan.Eilisha Shiraini – 2017-09-21T15:20:25.880

Somehow the terminology feels backwards to me. In my mind, undressing is something that happens relatively quickly, usually done by yourself, whereas stripping is often about making it take as long as possible to turn it into a proper show. – Trejkaz – 2017-09-25T05:23:29.333

Answers

11

Retina, 26 bytes

{m`^ (.+)\z
$&¶$1
 $
 ¶$%`

Try it online! (Test suite uses periods for clarity. The footer and header convert them to and from spaces for the main code.)

Explanation

It would be nice if we could just alternate between dropping a leading and a trailing space and printing the intermediate result each time. The problem is that currently Retina can't print conditionally, so it would even print this intermediate result if there are no leading or no trailing spaces left, generating duplicates. (Retina 1.0 will get an option that only prints the result if the string was changed by the operation, but we're not there yet...)

So instead, we're building up a single string containing all intermediate results and printing that at the end.

{m`^ (.+)\z
$&¶$1

The { wraps both stages of the program in a loop which repeats until the string stops changing (which means there are no leading/trailing spaces left). The stage itself matches a leading space on the final line of the string, and that final line, and then writes back the match, as well as the stuff after the space on a new line (thereby dropping the leading space in the copy).

 $
 ¶$%`

Removing the trailing space is a bit easier. If we just match the final space, we can access the stuff in front of it (on the same line) with $%` which is a line-aware variant of the prefix substitution $`.

Martin Ender

Posted 2017-09-21T09:19:05.853

Reputation: 184 808

11

Python 2, 122 107 103 102 98 95 93 91 90 88 87 bytes

s=input()+' '
a=0
while-a*s!=id:
 if a:id=s
 a=~a
 if'!'>s[a]:s=s[1+a:len(s)+a];print s

Try it online!


Python 3, 97 95 93 90 bytes

s=input()
a=p=print
p(s)
while s!=a:
 a=s
 if'!'>s:s=s[1:];p(s)
 if'!'>s[-1]:s=s[:-1];p(s)

Try it online!

TFeld

Posted 2017-09-21T09:19:05.853

Reputation: 19 246

Using s=input() instead of a function would take less bytes. – Jonathan Frech – 2017-09-21T10:23:41.257

Refering to 5. Undefined behaviour on empty input, or input that only contains spaces, is OK., 98 bytes.

– Jonathan Frech – 2017-09-21T10:42:17.937

Python 3 saves a byte.

– LyricLy – 2017-09-21T10:42:32.107

@JonathanFrech I hadn't seen that; thanks :) – TFeld – 2017-09-21T10:49:07.903

95 bytes. – Jonathan Frech – 2017-09-21T10:59:04.487

2

You can further golf the Python 2 code by replacing a with the built-in function id to save having to define it at the start. -2 bytes.

– LyricLy – 2017-09-21T11:00:19.430

91 bytes. – Jonathan Frech – 2017-09-21T11:07:24.580

I came up with a cute exec-free 92B variation… I’m not sure if it can be golfed down more: https://tio.run/##LYxBCgIxEATveUXvKYoKrsdIfIIfkD0Ek7gDy0zYiYivjxGtS0PRVHnXWfjUmnri8qybrSkrcYWa10xLgg6eojOg6NUgy4oAYhz3h7FbULaDvegtTE59n93oAvrpKpym8z/VmsWXu8T0kCXjh/0A

– Lynn – 2017-09-21T11:45:43.683

in your python3, '!'>s[0] to '!'>s – Felipe Nardi Batista – 2017-09-21T13:17:33.380

@FelipeNardiBatista Thanks :) – TFeld – 2017-09-21T13:19:33.507

@Lynn Thanks :) I got it down to 88 bytes using your slicing – TFeld – 2017-09-22T14:03:42.927

While it's not required, it's common practice (and courtesy ;)) to credit the users that have helped you golf an answer. That would also let me remove all of these comments. – Martin Ender – 2018-02-20T10:20:05.863

7

05AB1E, 21 15 bytes

=v¬ðQi¦=}¤ðQi¨=

Try it online!

Explanation^

=                 # print input
 v                # for each character in input
  ¬ðQi  }         # if the first char in the current string is a space
      ¦=          # remove it and print without popping
         ¤ðQi     # if the last char in the current string is a space
             ¨=   # remove it and print without popping

Emigna

Posted 2017-09-21T09:19:05.853

Reputation: 50 798

Dang, I tried something similar but for some reason I was sure head/tail didn't work on strings, and I was about to raise an issue about it on github. Must have read the debug logs wrong. :-) – scottinet – 2017-09-21T14:17:56.390

1@scottinet: I just found a way to get around the end-check :) – Emigna – 2017-09-21T15:00:52.227

oh... why didn't we think about that before? since we print conditionally there is no need to loop exactly the right number of times, we only need to loop over enough times. I'm borrowing that idea to improve my answer :-) – scottinet – 2017-09-21T15:10:17.847

1@scottinet: Yeah. It's obvious when you think about it, but sometimes it's easy to miss those things :P – Emigna – 2017-09-21T15:27:00.307

TFW the clunky redundant answer gets the lead... – Erik the Outgolfer – 2017-09-21T16:36:04.593

7

Perl 6, 55 bytes

Saved 3 bytes thanks to @nwellnhof.

{($_,{$++%2??S/" "$//!!S/^" "//}...*)[^.comb*2].unique}

Try it online!

Explanation: ($_,{$++%2??S/" "$//!!S/^" "//}...*) is a recursive infinite sequence that starts with the original string ($_) and the next element is given by the block called on the previous element.

The block itself gets the string in the $_ variable. The operator S/(regex)/(string)/ will search for the first occurence of (regex) in $_, replaces it with (string), and returns the result. If there is no match, it returns the content of $_ unchanged. We use the ternary operator ?? !! with the condition $++%2, which alternates between False and True ($ is a free variable that conserves its contents across calls to the block.)

In the worst case (all spaces on one side and 1 other character), we remove 1 space every 2 steps. So we can be sure that in 2*(length of the string) steps, all spaces will have been removed. We take that many elements from the recursive sequence with [^.comb*2] and finally discard duplicates (which occur whenever a space should have been removed but it isn't there) with .unique. This returns the list of strings, progressively stripped of spaces.

Ramillies

Posted 2017-09-21T09:19:05.853

Reputation: 1 923

[^.comb*2] saves 2 bytes. For some reason this works, but [^2*.comb] doesn't. No idea why. Using a ternary ?? !! to select the regex saves another byte. – nwellnhof – 2017-09-21T13:50:02.337

Thanks! I tried [^2*.comb] and it didn't work, so I just used [0..2*.comb]. And thanks for the ternary, I just thought it's too expensive and it didn't occur to me that I replaced it with something even more expensive... – Ramillies – 2017-09-21T14:08:46.457

7

C (gcc), 89 84 bytes

Recursive version is shorter ;-)

j;f(char*s){puts(s);*s^32||puts(++s);s[j=strlen(s)-1]<33?s[j]=0,f(s):*s^32||f(s+1);}

Try it online!

C (gcc), 107 102 101 100 99 bytes

Saved 2 bytes thanks to @Jonathan Frech using spaces and ~

i,j,k;f(char*s){for(i=~++k,puts(s);i^k;k=s[j=strlen(s)-1]<33?s[j]=0,puts(s):0)*s^32?i=0:puts(++s);}

Try it online!

cleblanc

Posted 2017-09-21T09:19:05.853

Reputation: 3 360

2I think the question really wants you to remove spaces rather than dots. There is even an advantage to using spaces; you can replace ==46 with <33 as the space is the smallest printable character and you only have to handle those. – Jonathan Frech – 2017-09-21T14:20:33.040

What does the ++k+ do? – Jonathan Frech – 2017-09-21T14:36:58.453

@JonathanFrech It pre-increments k and adds one, which is equivalent to k = k + 1; i = k + 1; or i = k + 2; k = k + 1. – HyperNeutrino – 2017-09-21T14:37:45.930

Technically i=k+++2 works too which I would have used because the +++ looks weird :P – HyperNeutrino – 2017-09-21T14:38:12.197

@HyperNeutrino Yeah, I know what the pre-increment operator does; though I do not get how the code works without it. So really I was asking what role it plays, rather than how it is defined.

– Jonathan Frech – 2017-09-21T14:42:08.483

@JonathanFrech That's really odd... I'd have to take a better look at that. Good observation though. – HyperNeutrino – 2017-09-21T14:48:32.787

@JonathanFrech k is true if there are leading spaces and i is true if there are trailing spaces. I needed them to have different values so I could use ^ in the loop condition. – cleblanc – 2017-09-21T14:54:01.677

Ah, I think I get it. If so, I would propose ++k+1 -> ~++k. – Jonathan Frech – 2017-09-21T14:57:24.460

6

JavaScript (ES6) 92

@Upvoters: have a look at the other JS answer down below that is 76 bytes long

(s,q,l=2,p=0)=>{for(alert(s);l--;p=!p)s[+p&&s.length-p]<'!'&&alert(s=s.slice(!p,-p||q,l=2))}

A loop looking for a space at front or at end. If found, remove space and output string. If no space found 2 times, stop.

F=
(s,q,l=2,p=0)=>{for(alert(s);l--;p=!p)s[+p&&s.length-p]<'!'&&alert(s=s.slice(!p,-p||q,l=2))}

// some trick to show dots instead of spaces, for test
alert=x=>console.log(x
  .replace(/^ +/g,z=>'.'.repeat(z.length))
  .replace(/ +$/g,z=>'.'.repeat(z.length))
)

function go() {F(I.value.replace(/\./g,' '))}

go()
<input ID=I value='....yes Sir!....'> (use dot instead of space)
<button onclick='go()'>Go</button>

edc65

Posted 2017-09-21T09:19:05.853

Reputation: 31 086

You could save a byte by checking for space with <'!'. To make your snippet still work you can replace periods with spaces before passing to your function. – Justin Mariner – 2017-09-21T15:16:03.650

@JustinMariner ok now, because OP stated no char expected less than ' '. Thanks – edc65 – 2017-09-21T15:56:58.663

6

Perl 5, 32 bytes

Saved 4 bytes due to @Abigail.

1while s/^ /!say/e+s/ $/!say/e

Requires -pl counted as 2, invoked with -E.

Sample Usage

$ echo '   test   ' | perl -plE'1while s/^ /!say/e+s/ $/!say/e'
   test   
  test   
  test  
 test  
 test 
test 
test

Try it online!

primo

Posted 2017-09-21T09:19:05.853

Reputation: 30 891

Doesn't work correctly for strings without trailing spaces. – nwellnhof – 2017-09-21T13:35:55.890

print;s/^ //&&print,s/ $//&&print while/^ | $/ works with -n flag, also -l is not needed – Nahuel Fouilleul – 2017-09-21T15:56:36.347

@nwellnhof fixed. – primo – 2017-09-23T11:54:24.003

5

C# (.NET Core), 192 183 182 181 179 178 bytes

-3 bytes thanks to Kevin Cruijssen

n=>{var o=n+"\n";for(var e=1;n.Trim()!=n;){if(1>(e^=1))if(n[0]<33)n=n.Remove(0,1);else continue;else if(n.TrimEnd()!=n)n=n.Remove(n.Length-1);else continue;o+=n+"\n";};return o;}

Try it online!

my pronoun is monicareinstate

Posted 2017-09-21T09:19:05.853

Reputation: 3 111

Some things to golf: var e=1;while(n.Trim()!=n) -> for(var e=1;n.Trim()!=n;); if(n[0]==' ') -> if(n[0]<33) – Kevin Cruijssen – 2017-09-21T10:42:40.020

I've thought about second one, but what if the test string contains newlines? – my pronoun is monicareinstate – 2017-09-21T10:44:29.507

Ok, <33 is possible due to OP's newly added rule: "You can assume that the string will only contain characters from the ASCII printable space (0x20 to 0x7E)." – Kevin Cruijssen – 2017-09-21T10:58:39.537

5

Java 8, 150 146 145 137 bytes

s->{String r=s;for(int f=0;s!=s.trim();f^=1)r+="\n"+(s=f+s.charAt(0)<33|!s.endsWith(" ")?s.substring(1):s.replaceAll(" $",""));return r;}

-4 bytes thanks to @Nevay changing (f<1&s.charAt(0)<33) to f+s.charAt(0)<33.
-1 byte by using the !s.trim().equals(s) trick from @someone's C# .NET answer instead of s.matches(" .*|.* ").
-8 bytes thanks to @Nevay again by changing !s.trim().equals(s) to s!=s.trim(), because String#trim will return "A copy of this string with leading and trailing white space removed, or this string if it has no leading or trailing white space", thus the reference stays the same and != can be used to check if they are the same reference, instead of .equals to check the same value.

Explanation:

Try it here (or try a more visual version here with # instead of spaces).

s->{                               // Method with String as both parameter and return-type
  String r=s;                      //  Result-String (starting at the input)
  for(int f=0;                     //  Flag-integer (starting at 0)
      s!=s.trim();                 //  Loop as long as `s` contains leading/trailing spaces
      f^=1)                        //    And XOR(1) `f` after every iteration (0->1; 1->0)
    r+="\n"                        //   Append the result with a new-line
       +(                          //    Followed by:
         s=f+                      //     If `f` is 0,
             s.charAt(0)<33        //     and `s` starts with a space
           |!s.endsWith(" ")?      //     Or doesn't end with a space
            s.substring(1)         //      Remove the first leading space
           :                       //     Else:
            s.replaceAll(" $",""));//      Remove the last trailing space
                                   //  End of loop (implicit / single-line body)
  return r;                        //  Return the result-String
}                                  // End of method

Kevin Cruijssen

Posted 2017-09-21T09:19:05.853

Reputation: 67 575

1You can use s=f+s.charAt(0)<33 instead of (f<1&s.charAt(0)<33) (-4 bytes). – Nevay – 2017-09-21T12:01:54.023

1You can use s!=s.trim() instead of !s.trim().equals(s); (-8 bytes). – Nevay – 2017-09-21T12:24:01.940

4

Jelly, 16 bytes

Ḋ=⁶Ḣ$¡UµÐĿ¹Ṛƭ€QY

Try it online!

-2 bytes thanks to Erik the Outgolfer
-1 byte thanks to miles

Explanation

Ḋ=⁶Ḣ$¡UµÐĿ¹Ṛƭ€QY  Main link
       µÐĿ        While the results are unique (collecting intermediate results), apply the last link (`µ` creates a new monadic link):
Ḋ=⁶Ḣ$¡            Remove a space from the beginning if there is one
 =⁶Ḣ$             If the first character is a space, then 1, else 0
 =                Compare each character to
  ⁶               ' '
   Ḣ              Get the first comparison
Ḋ                 Then Dequeue the string (s -> s[1:])
    ¡             That many times
     U            And reverse the string (the next time this is called, it will remove spaces from the end instead)
             €    For each string
            ƭ     Alternate between two commands:
          ¹       Identity (do nothing), and
           Ṛ      Reverse
          ¹Ṛƭ€    Correct all strings that are reversed to remove the trailing space
              Q   Remove duplicates (where there was no space to remove)
               Y  Join on newlines

HyperNeutrino

Posted 2017-09-21T09:19:05.853

Reputation: 26 575

ḣ1Ḣ=⁶ -> =⁶Ḣ – Erik the Outgolfer – 2017-09-21T14:09:49.930

@EriktheOutgolfer Thanks, edit coming. – HyperNeutrino – 2017-09-21T14:10:58.347

Cool idea with the alternating commands of reverse/identity! – Emigna – 2017-09-21T15:02:22.203

@Emigna Thanks! :D I mostly just wanted an excuse to use the new quick... heh :P – HyperNeutrino – 2017-09-21T17:21:03.360

ƭ only needs a nilad if the chain is longer than two. ¹Ṛƭ works fine here. – miles – 2017-09-22T11:26:58.433

@miles Oh cool! Thanks! :D – HyperNeutrino – 2017-09-22T15:23:57.357

4

C, 91 90 bytes

i,l;f(char*s){for(i=puts(s);i;i=(s[l=strlen(s)-1]*=s[l]>32)?i:puts(s))i=*s<33&&puts(++s);}

Try it online!

Steadybox

Posted 2017-09-21T09:19:05.853

Reputation: 15 798

3

Java (OpenJDK 8), 161 147 146 bytes

x->{for(int l=0,r=x.length(),k=-1,u,v;((u=32-x.charAt(l)>>k)*(v=32-x.charAt(r-1)>>-1))<1;x+="\n"+x.substring(l-=k&~u|v,r+=(k=~k)&~v|u));return x;}

Try it online!

-1 byte thanks to @Kevin Cruijssen!

x -> {
    /*
     * l: left index (inclusive)
     * r: right index (exclusive)
     * k: side to remove from, -1:=left, 0:=right
     * u: left character   0:=space, <0:=no space (-1 if k is left side)
     * v: right character  0:=space, -1:=no space
     */
    for (int l = 0, r = x.length(), k = -1, u, v;
            ((u = 32 - x.charAt(l) >> k)
           * (v = 32 - x.charAt(r - 1) >> -1)) < 1; // loop while left or right has space(s)
            x += "\n" + x.substring(                // append newline and substring
                    l -= k & ~u | v,                // inc. left  if k is left side
                                                    //               and left has space
                                                    //            or right has no space
                    r += (k = ~k) & ~v | u));       // dec. right if k is right side
                                                    //               and right has space
                                                    //            or left has no space
    return x;
}

Nevay

Posted 2017-09-21T09:19:05.853

Reputation: 421

1Hehe, I saw your deleted answer and was wondering when you were below my 150 bytes and would undelete it. ;) – Kevin Cruijssen – 2017-09-21T11:49:07.110

1I'm not entirely sure, but I think you can golf a byte by changing (u=32-x.charAt(l)>>-1) to (u=32-x.charAt(l)>>k) – Kevin Cruijssen – 2017-09-21T11:53:36.677

@KevinCruijssen Won't work, k is 0 every second iteration. – Nevay – 2017-09-21T12:00:38.077

1

Yes, but the weird part is that the TIO works and gives the correct result for all test cases with this change for u. It doesn't when I also change -1 to k for v. I'm confused why it works though, since k will indeed become 0 after k=~k.. :S

– Kevin Cruijssen – 2017-09-21T12:05:47.047

1@KevinCruijssen For the k=0 scenario: If left has spaces left, then u has the same value as before (0); if left has no spaces left, then (k=~k)&~v|u evaluates to -1|u (~0&-1|u), thus the undefined (negative) value of u does not matter (-1|x==-1). – Nevay – 2017-09-21T12:56:02.517

3

05AB1E, 25 17 bytes

-8 bytes by borrowing the no-need-for-an-end-check idea from Emigna

,v2F¬ðQi¦DNiR},}R

Try it online!

I'm pretty sure a less straightforward approach can beat that solution easily. For now...

Explanations:

,v2F¬ðQi¦DNiR},}R           Full Programm
,                           Print the input string
 v                          For each char of the string
                               (we don't really care, we only need to loop
                                enough times to accomplish our task, since
                                we print conditionally we can loop more
                                times than necessary)
  2F...........}            Two times...
    ¬õQi                       Is 1st item a space?
        ¦D                        Remove 1st item + duplicate
          NiR}                    If on the second pass: reverse the list
              ,                   Pop & print with newline
               }               End If
                 R          Reverse the list

scottinet

Posted 2017-09-21T09:19:05.853

Reputation: 981

I like your approach with the loop :) I've been trying to figure out a way to do everything in one pass without multiple ifs, but I haven't figured it out yet. Also, your explanation seem to have an empty string instead of a space. – Emigna – 2017-09-21T13:34:32.213

Thanks! I fixed the explanation, I forgot to edit the "is empty" part when I golfed my code, using S instead of # (-1 byte). The loop... well... it saves a whopping 1 byte compared to a straightforward approach. I'm currently looking for a shorter way to detect the end of the task (5 bytes for this is a lot), and I'm also considering a different approach altogether. I do think there is a more clever way to solve this challenge. – scottinet – 2017-09-21T13:51:54.237

If you try and do everything in one pass (as I'm currently looking into), the best check I have for exiting the loop is 8 bytes... – Emigna – 2017-09-21T14:00:36.040

3

Ruby, 63 bytes

->s{*x=s;(s=~/^ /&&x<<s=$';s=~/ $/&&x<<s=$`)while s=~/^ | $/;x}

Try it online!

G B

Posted 2017-09-21T09:19:05.853

Reputation: 11 099

3

R, 145 133 111 bytes

-12 bytes thanks to @Giuseppe, by storing the result of sub in a new variable and testing for whether it has changed

-22 bytes by returning a vector of strings rather than a string with newlines

function(s){L=s
while(grepl("^ | $",s)){if((x=sub("^ ","",s))!=s)L=c(L,x)
if((s=sub(" $","",x))!=x)L=c(L,s)}
L}

Try it online!

Explanation on a partially ungolfed version:

function(s){
  L=s                          # Initialise a vector with the original string
  while(grepl("^ | $",s)){     # While there are leading or trailing spaces...
    if((x=sub("^ ","",s))!=s){ # Check whether we can remove a leading space
      L=c(L,x)                 # If so, add the shortened string to the vector
    }
    if((s=sub(" $","",x))!=x){ # Check whether we can remove a trailing space
      L=c(L,x)                 # If so, add the shortened string to the vector
    }
  }
  L                            # Return the vector
}                              

user2390246

Posted 2017-09-21T09:19:05.853

Reputation: 1 391

can't you use C(s<-sub(),\n) instead of a separate print statement? Ah, no, because of sep=" " – Giuseppe – 2017-09-21T13:38:54.713

@Giuseppe Yes, I think it works out slightly longer to include it all in a single statement because of the need to add sep="". In most challenges the extra trailing space would not matter, but here unfortunately it does! – user2390246 – 2017-09-21T13:45:00.650

133 bytes -- something about your using sub just suggested this, IDK why – Giuseppe – 2017-09-21T14:26:44.177

@Giuseppe Very elegant! – user2390246 – 2017-09-21T14:55:04.453

Could you just set L=s and return a vector of strings? – Giuseppe – 2017-09-21T15:14:15.957

@Giuseppe I guess so! – user2390246 – 2017-09-21T15:26:18.250

3

Husk, 23 22 bytes

u§↑L`G`I¢e₁ȯ↔₁↔
?tI<"!

Thanks to Leo for -1 byte.

Try it online!

Explanation

The function `G`I should really be a built-in...

?tI<"!  Helper function: remove initial space.
?  <"!  If less than the string "!",
 t      remove first character,
  I     else return as is.
u§↑L`G`I¢e₁ȯ↔₁↔  Main function.
         e       List containing
          ₁      the helper function
           ȯ↔₁↔  and the composition reverse-helper-reverse.
        ¢        Repeat it cyclically.
    `G`I         Cumulative reduce from left by function application
                 using input string as initial value.
 §↑L             Take first length(input) values.
u                Remove duplicates.

Zgarb

Posted 2017-09-21T09:19:05.853

Reputation: 39 083

Nice! Indeed we would need more builtins for applying functions cyclically... btw I've found a sligthly shorter way to remove the first space: https://tio.run/##yygtzv7/v/TQ8kdtE30S3BM8Dy1KfdTUeGL9o7YpQBpIctmXeNooKf7//19JAQgiU4t1FIIzixRBHAUlAA

– Leo – 2017-09-21T21:54:11.873

@Leo Thanks! Using ? seems obvious in hindsight... – Zgarb – 2017-09-23T20:27:33.563

3

C++, 196 193 189 186 183 bytes

-10 bytes thanks to Jonathan Frech
-3 bytes thanks to Zacharý

#include<iostream>
#include<string>
#define D std::cout<<s<<'\n'
#define R ~-s.size()
auto u=[](auto s){D;while(s[0]<33||s[R]<33){if(s[0]<33)s.erase(0,1),D;if(s[R]<33)s.erase(R),D;}};

Compilation with MSVC requires the un-activation of SDL checks

HatsuPointerKun

Posted 2017-09-21T09:19:05.853

Reputation: 1 891

You may be able to replace ==32 with <33. – Jonathan Frech – 2017-09-21T12:56:40.027

I am no C++ master, though is #include<string> really necessary?

– Jonathan Frech – 2017-09-21T13:00:17.123

if(...){...;D;} -> if(...)...,D;. – Jonathan Frech – 2017-09-21T13:04:49.680

@JonathanFrech What you did there was compiler specific, not guarranted by the standard. VC++ can't find a definition of the << operators without the explicit inclusion of string. – HatsuPointerKun – 2017-09-21T13:09:17.803

#define R ...<33, ||R){ and if(R){ -> #define R ...<33), ||R{ and if(R{. – Jonathan Frech – 2017-09-21T13:10:23.690

184 bytes. – Jonathan Frech – 2017-09-21T13:20:13.803

void -> int. – Jonathan Frech – 2017-09-21T13:24:00.480

@JonathanFrech 1.) C++11 requires whitespace after the macro name. ( and i compile with C++17 norm ) 2.) Sticking 2 includes each other on the same lines cause the second token to be ignored. 3.) Declaring a return value in a function that doesn't return a value is undefined behavior

– HatsuPointerKun – 2017-09-21T14:38:44.783

Would using C++14 and auto instead of std::string, and have u be called like u(std::string(" SOMETHING ")) work? – Zacharý – 2017-09-24T15:06:22.650

@Zacharý No, since it's not a lambda. But i can replace it by a lambda and save a few bytes – HatsuPointerKun – 2017-09-30T22:07:08.167

3

Java (OpenJDK 8), 137 125 121 120 124 bytes

s->{int i=1;do System.out.println(s);while(s!=(s=s.substring(s.charAt(0)<33?i:(i=0),s.length()-(s.endsWith(" ")?i^=1:0))));}

Try it online!

Roberto Graham

Posted 2017-09-21T09:19:05.853

Reputation: 1 305

Nice answer! Just as short as my answer of 137 bytes, but you can still golf 12 bytes like this: s->{for(int i=0;s!=s.trim();)System.out.println(s=s.substring(s.charAt(0)<33?1-i%2:0,s.length()-(s.endsWith(" ")?i++%2:0)));}

– Kevin Cruijssen – 2017-09-21T13:36:38.813

This currently does not "... output the string unchanged" and fails for input with leading spaces and no trailing spaces. – Nevay – 2017-09-21T14:39:21.957

1Maybe you can use s->{int i=1;do System.out.println(s);while(s!=(s=s.substring(s.charAt(0)<33?i:(i=0),s.length()-(s.endsWith(" ")?i^=1:0))));} (124 bytes) (seems to be correct but didn't test much). – Nevay – 2017-09-21T14:54:38.947

3

MATL, 21 16 bytes

tnE:"t@o&)w46-?x

This uses dots instead of spaces for greater clarity. For spaces replace 46 by 32.

Try it online!

Explanation

tn      % Input (implicit). Duplicate and push length, say L
E       % Multiply by 2
:       % Push range [1 2 ... 2*L]
"       % For each k in that array
  t     %   Duplicate the string at the top of the stack
  @     %   Push k
  o     %   Parity: gives 1 or 0
  &)    %   Two-ouput indexing. Pushes the k-th entry of the string and then
        %   the rest of the string. The 1-st output is the first, the 0-th
        %   is the last (indexing is 1-based dand modular)
  w     %   Swap
  46-   %   Subtract 46, which ias ACII for '.'
  ?     %   If non-zero
    x   %     Delete sub-string that was obained by removing that entry
        %   End (implicit)
        % End (implicit)
        % Display stack (implicit)

Luis Mendo

Posted 2017-09-21T09:19:05.853

Reputation: 87 464

2

C# (.NET Core), 176 170 bytes

using System;s=>{Action o=()=>Console.WriteLine(s);o();Func<int>l=()=>s.Length-1;while(s!=s.Trim()){if(s[0]<33){s=s.Remove(0,1);o();}if(s[l()]<33){s=s.Remove(l());o();}}}

Try it online!

This is an alternative to @someone's answer, and just outputs the strings directly.

BgrWorker

Posted 2017-09-21T09:19:05.853

Reputation: 351

Your program doesn't output the string unmodified before removing spaces. – Nathan.Eilisha Shiraini – 2017-09-21T15:18:38.453

@Nathan.EilishaShiraini I corrected that mistake and golfed a few bytes to reduce the byte count anyway. – BgrWorker – 2017-09-21T15:26:13.700

2

JavaScript (ES6), 76 bytes

f=(s,r,n,l=s.length)=>s[r?--l:0]<"!"?s+`
`+f(s.slice(!r,l),!r):n?s:f(s,!r,1)

Outputs as a multiline string.

Test Cases

Using dots instead of spaces, as most answers are doing.

f=(s,r,n,l=s.length)=>s[r?--l:0]<"!"?s+`
`+f(s.slice(!r,l),!r):n?s:f(s,!r,1)

// converting to and from dots and spaces
let dots=s=>s.replace(/^\.+|\.+$/gm,x=>" ".repeat(x.length));
let spaces=s=>s.replace(/^ +| +$/gm,x=>".".repeat(x.length));

["....Yes, Sir!.....", "......Let's go golfing...", "Hello..", "World", ".....................a....."]
.forEach(test=>O.innerHTML+=spaces( f(dots(test)) ) + "\n\n");
<pre id=O></pre>

Justin Mariner

Posted 2017-09-21T09:19:05.853

Reputation: 4 746

2

Sed, 24 bytes

p;:s s/ //p;s/ $//p;ts;D

Try It Online !

zeppelin

Posted 2017-09-21T09:19:05.853

Reputation: 7 884

2

Octave, 88 83 bytes

5 bytes off thanks to Stewie Griffin!

x=[input('') 0];for p=mod(1:sum(x),2)if x(~p+end*p)<33,disp(x=x(2-p:end-p)),end,end

Try it online!

Luis Mendo

Posted 2017-09-21T09:19:05.853

Reputation: 87 464

Very nice. "Anyway, see if you can remove a couple of bytes" :-P

– Stewie Griffin – 2017-09-22T10:42:43.760

@StewieGriffin I meant in your answer... :-D Good idea, thanks! – Luis Mendo – 2017-09-22T10:48:36.083

I might delete mine... It's so uninspired compared to this... – Stewie Griffin – 2017-09-22T10:54:30.977

@StewieGriffin Here's an idea to remove two bytes. Pity that min is needed because of s being dynamically shrunk

– Luis Mendo – 2017-09-22T11:06:39.310

2

x86 machine code for Linux, 60 bytes

e8 1f 00 00 00 31 c0 80 3f 20 75 09 47 4d 74 10
e8 0f 00 00 00 80 7c 2f ff 20 74 05 84 c0 75 e5
c3 4d eb dc 6a 04 58 50 31 db 43 89 f9 89 ea cd
80 58 6a 0a 89 e1 89 da cd 80 58 c3

This is a function for Linux x86. It takes as input pointer to the string in edi and string length in ebp.

Ungolfed, with some infrastructure to test (compile with FASM, run with the string as program argument; look for undress: label for actual function code):

format ELF executable
segment executable
SYS_WRITE = 4
    jmp     callUndress
; -------------------- the function itself --------------------------------
; Input:
;   edi=string
;   ebp=length
undress:
undressLoopPrint:
    call    print
undressLoop:
    xor     eax, eax    ; flag of having printed anything on this iteration
    cmp     byte [edi], ' '
    jne     startsWithoutSpace
    inc     edi
    dec     ebp
    jz      quit
    call    print
startsWithoutSpace:
    cmp     byte [edi+ebp-1], ' '
    je      endsWithSpace
    test    al, al      ; if print has been called, then we have 0x0a in eax
    jnz     undressLoop
quit:
    ret
endsWithSpace:
    dec     ebp
    jmp     undressLoopPrint
print:
    push    SYS_WRITE
    pop     eax
    push    eax
    xor     ebx, ebx
    inc     ebx ; STDOUT
    mov     ecx, edi
    mov     edx, ebp
    int     0x80
    pop     eax
    push    0x0a    ; will print newline
    mov     ecx, esp
    mov     edx, ebx ; STDOUT=1, which coincides with the length of newline
    int     0x80
    pop     eax
    ret
; --------------------- end undress ---------------------------------------
SYS_EXIT = 1
STDERR = 2
callUndress:
    pop     eax     ; argc
    cmp     eax, 2
    jne     badArgc
    pop     eax     ; argv[0]
    pop     edi
    mov     al, 0
    cld
    mov     ecx, -1
    repne   scasb
    lea     edi, [edi+ecx+1] ; argv[1]
    neg     ecx
    sub     ecx, 2
    mov     ebp, ecx     ; strlen(argv[1])
    call    undress
    xor     ebx, ebx
exit:
    mov     eax, SYS_EXIT
    int     0x80
    ud2
badArgc:
    mov     esi, eax
    mov     eax, SYS_WRITE
    mov     ebx, STDERR
    mov     ecx, badArgcMsg
    mov     edx, badArgcMsgLen
    int     0x80
    mov     ebx, esi
    neg     ebx
    jmp     exit
badArgcMsg:
    db      "Usage: undress YourString",0x0a,0
badArgcMsgLen = $-badArgcMsg
segment readable writable
string:
    db      100 dup(0)
    stringLen = $-string

Ruslan

Posted 2017-09-21T09:19:05.853

Reputation: 1 283

sys_write() makes eax non-zero (specifically 1, the number of characters written, assuming it's not -errno), So will print if you don't pop eax at the end. You could just xor eax,eax before the cmp byte [edi], ' ' and save the mov al,1, and maybe some eax save/restore. Although you don't actually save it until after clobbering with SYS_WRITE. Hmm, instead of 0, you could use SYS_WRITE vs. 1, since cmp al, imm8 is the same size as test al,al. – Peter Cordes – 2017-09-24T22:23:49.860

Can you put a '\n' into the array with mov byte [ecx + edx], '\n' instead of doing the 2nd write()? (And decrement the length after printing?) Might save you a few instructions. – Peter Cordes – 2017-09-24T22:29:16.220

Actually, print() currently leaves '\n' in eax, which is different from SYS_WRITE, so you could still check that. I thought you were saving/restoring eax, but that was just saving bytes copying a constant around. For long strings, sys_write() can leave the high bytes of eax non-zero, so that unfortunately rules out just using mov al, SYS_WRITE. – Peter Cordes – 2017-09-24T23:05:08.933

@PeterCordes actually yes, mov al, 1 was extraneous. -2 bytes now, thanks. – Ruslan – 2017-09-25T06:07:58.737

A register calling convention would save you the load instructions. In code-golf, a custom calling convention is normally fair game for asm. OTOH, if you'd rather golf the standard stack-args calling convention, that's interesting too. – Peter Cordes – 2017-09-25T12:41:00.307

@PeterCordes I supposed one has to use a standard convention. Will take this into account for the future. – Ruslan – 2017-09-25T13:25:56.807

You're writing in asm, presumably for a caller written in asm. In asm, every function can have its own calling convention if you want. I try not to bend the rules too far, so I still always return in eax (or dx:ax for 16-bit addler32). Using a calling convention similar to an existing one (like MS _fastcall but with different regs), or with some dummy args to get the args in the regs you want, seems fine. Treating more regs as call-clobbered is probably also ok. Saving/restoring regs is kind of boilerplate and not the interesting part of a machine-code answer. – Peter Cordes – 2017-09-25T13:32:57.007

@PeterCordes agreed. Here goes the 10 bytes smaller version with custom calling convention. – Ruslan – 2017-09-25T13:44:09.590

If you used esi as your 2nd arg, you'd have a 32-bit version of the x86-64 System V calling convention. Not that it really matters. – Peter Cordes – 2017-09-25T13:46:39.287

2

PHP, 117 bytes

I add an extra space at the start so it will take the space out and show the original without any extra code.

Kinda new to this... would the <?php and the space at the start of the PHP file add 6 extra bytes or do I get that for free?

$s=" $argn";while($r!=$s){$r=$s;if($s[0]==" ")echo($s=substr($s,1))."
";if($s[-1]==" ")echo($s=substr($s,0,-1))."
";}

Try it online!

XMark

Posted 2017-09-21T09:19:05.853

Reputation: 141

1

Using your method 6 bytes can be reduced: Try it online!

– Night2 – 2019-08-27T10:04:34.237

1You can omit the PHP's opening tag since you can run it with a command like this: php -r "echo 1;" But if you want to use something like <?=1; you have to include the tag in bytes count. – Night2 – 2019-08-27T10:07:14.327

1

Octave, 89 bytes

s=input('');while any(s([1,end])<33)if s(1)<33,s(1)=[],end,if s(end)<33,s(end)=[],end,end

Try it online!

I'll add an explanation later, when I have the time. I might be able to golf off some bytes if I change the approach completely, but I can't see how unfortunately.

The last letters here spell out: "sendsendendend". I wish there was a way to store end as a variable and use that, but guess what ...

Stewie Griffin

Posted 2017-09-21T09:19:05.853

Reputation: 43 471

Is it valid to output with s = ...? (The usual question, I know) – Luis Mendo – 2017-09-21T23:24:43.367

Anyway, see if you can remove a couple of bytes :-P

– Luis Mendo – 2017-09-21T23:36:12.927

1

Python 2, 79 bytes

-1 byte thanks to @JonathanFrech

f=lambda s,i=1:[s]+(s>i*'!'and'!'>s[-1]and f(s[:-1])or'!'>s and f(s[1:],0)or[])

Try it online!

The test suit replaces "." with " " before calling the function and replaces " " back to "." before printing the results for clarity.

Felipe Nardi Batista

Posted 2017-09-21T09:19:05.853

Reputation: 2 345

'!'*i and -> i*'!'and. – Jonathan Frech – 2017-09-21T12:12:41.250

1

Pyth, 28 bytes

QW<lrKQ6lQ=hZ?&%Z2qdhQ=tQ=PQ

Try it here! or Verify all test cases!

Explanation

QW<lrKQ6lQ=hZ?&%Z2qdhQ=tQ=PQ   ~ Full program. Q is autoinitialized to input.

Q                              ~ Output the input.
 W<lrKQ6lQ                     ~ Loop while the condition is met.
  <                            ~ Is smaller?
   lrKQ6                       ~ The length of the original input, stripped on both sides.
        lQ                     ~ The length of the current Q.
          =hZ                  ~ Increment a variable Z, initially 0
             ?&%Z2qdhQ         ~ If Z % 2 == 1 and Q[0] == " ", then:
                      =tQ      ~ Make Q equal to Q[1:] and output, else:
                         =PQ   ~ Make Q equal to Q[:-1] and output.

Mr. Xcoder

Posted 2017-09-21T09:19:05.853

Reputation: 39 774

1

Bash, 98 94 bytes

Saved 4 bytes using subshell instead of sequences (poor performances)

r()(s=$1;[[ $s = $b ]]||([[ $s = $a ]]||echo "$s"
b=$a a=$s;((i=!i))&&r "${s# }"||r "${s% }"))

First answer

r(){ s=$1;[[ $s = $b ]]||{ [[ $s = $a ]]||echo "$s"
b=$a a=$s;((i=!i))&&r "${s# }"||r "${s% }";};}

Note the ! must be escaped in interactive mode

Nahuel Fouilleul

Posted 2017-09-21T09:19:05.853

Reputation: 5 582

1

C# - yet again, 125 bytes

while(s.Trim()!=s){if(s[0]==' '){yield return s=s.Substring(1);}if(s.Last()==' '){yield return s=s.Substring(0,s.Length-1);}}

Cheers!

Try it online!

Barodus

Posted 2017-09-21T09:19:05.853

Reputation: 43

Welcome to PPCG! – Laikoni – 2017-09-22T19:06:09.053

1

Haskell, 109 bytes

(b%e)
t=last
b(' ':s)=s
b l=l
e l|t l>' '=l|1>0=init l
(g%h)l=l:t((h%g$g l):[t$(h%g$h l):[[]|h l==l]|g l==l])

Try it online!

b removes leading space if there is a leading space

e removes trailing space if there is a trailing space

% switches between b and e

jferard

Posted 2017-09-21T09:19:05.853

Reputation: 1 764

1

Haskell, 86 bytes

(f#g)
r=reverse
f(' ':s)=s
f s=g s
g=r.f.r
(a#b)s=s:[x|last s<'!'||s<"!",x<-(b#a)$a s]

Try it online! Usage: (f#g) " test " yields a list of strings.

Explanation

  • Function f removes a leading space from a given string. If there is no leading space, it calls function g.
  • Function g reverses the string, calls f and reverses back. This removes a trailing space if there is one, and an leading space otherwise.
  • If a string has neither leading nor trailing spaces, then f and g diverge, so this needs to be checked before.
  • The main function # is initialized with f as first and g as second argument. The third argument s is the input string, which is appended to the recursively computed list of results:
    • If s has no leading or trailing spaces, then last s<'!'||s<"!" is false and the list of results empty.
    • Otherwise the function given as first argument is applied to s and # is applied recursively with f and g exchanged.

Laikoni

Posted 2017-09-21T09:19:05.853

Reputation: 23 676

1

D, 142 140 bytes

import std.stdio;void u(T)(s){s.writeln;while(s[0]<33||s[$-1]<33){if(s[0]<33){s=s[1..$];s.writeln;}if(s[$-1]<33){s=s[0..$-1];s.writeln;}}}

Try it online!

This is a port of HatsuPointerKun's C++ answer.

Zacharý

Posted 2017-09-21T09:19:05.853

Reputation: 5 710

1

Julia, 138 bytes

a(s)=' ' in s?s[1]==' '?(println(s);z(s[2:end])):z(s[1:end]):print(s)
z(s)=' ' in s?s[end]==' '?(println(s);a(s[1:end-1])):a(s[1:end]):print(s)

Not sure if there is a way to substitute another character for end, but if there was that would probably save some bytes.

spacetyper

Posted 2017-09-21T09:19:05.853

Reputation: 121

Welcome to the site! – James – 2017-09-28T19:56:02.763

0

Jq 1.5, 149 116 bytes

def G(p):if p==[]then. else sub(p[0];"")as$n|if.!=$n then.,($n|G(p|reverse))else($n|G(p[1:]))end end;G(["^ "," $"])

Expanded

def G(p):
  if p==[] then .                  # stop when no patterns remain
  else
     sub(p[0];"") as $n            # use first pattern
   | if .!=$n                      # if we removed something
     then ., ($n|G(p|reverse))     #   return result and switch patterns
     else ($n|G(p[1:]))            # otherwise remove failed pattern
     end 
  end 
;
G(["^ "," $"])

Sample Run

$ jq -MRr 'def G(p):if p==[]then. else sub(p[0];"")as$n|if.!=$n then.,($n|G(p|reverse))else($n|G(p[1:]))end end;G(["^ "," $"])' <<<'     codegolf     '
     codegolf     
    codegolf     
    codegolf    
   codegolf    
   codegolf   
  codegolf   
  codegolf  
 codegolf  
 codegolf 
codegolf 
codegolf

$ wc -c <<<'def G(p):if p==[]then. else sub(p[0];"")as$n|if.!=$n then.,($n|G(p|reverse))else($n|G(p[1:]))end end;G(["^ "," $"])'
 116

jq170727

Posted 2017-09-21T09:19:05.853

Reputation: 411

0

Kotlin, 151 150 bytes

{var v=it
var c={println(v)}
while(0<((if(v[0]<'!'){c()
v=v.substring(1)
1}else 0)+if(v.endsWith(' ')){c()
v=v.slice(0..v.length-2)
1}else 0
)){}
c()}

Beautified

{
    var v = it
    var c={println(v)}
    while ( 0 <(
            (if (v[0] < '!') {
                c()
                v = v.substring(1)
                1
            } else 0)
                    +
                    if (v.endsWith(' ')) {
                        c()
                        v = v.slice(0..v.length-2)
                        1
                    } else 0
            )){}
    c()
}

Test

/** Shows spaces, just helps viewing answer. */
fun println(i: String) {
    for (c in i) {
        if (c == ' ') {
            print('~')
        } else {
            print(c)
        }
    }
    print('\n')
}
var u: (String) -> Unit =
{var v=it
var c={println(v)}
while(0<((if(v[0]<'!'){c()
v=v.substring(1)
1}else 0)+if(v.endsWith(' ')){c()
v=v.slice(0..v.length-2)
1}else 0
)){}
c()}

fun main(args: Array<String>) {
    u("      Let's go golfing   ")
}

Edits

-1 -> x == ' ' => x < '!' Jonathan French

jrtapsell

Posted 2017-09-21T09:19:05.853

Reputation: 915

150 bytes. – Jonathan Frech – 2017-09-23T16:13:08.633

0

This is not a successful contender, because it works only for len(left whitespace) between [len(right whitespace), len(right whitespace)+1]. Anyway, just for the fun of it:

Python 3, 56 bytes:

def f(a,e=0):print(a);a[e]<'!'and f(a[e+1:e or None],~e)

tzot

Posted 2017-09-21T09:19:05.853

Reputation: 647

0

GolfScript - 46 bytes

'
'+{.(32={.1}{;.0}if\);)32={'
'+\1}{;0}if|}do

Explanation

'\n'+    Adds endline to the argument
{.       Starts do loop and duplicates the top of the stack
(32=     Is the first character a ' '?
{.1}     It is, duplicate result and push 1
{;.0}if  It isn't, remove cut string, duplicate and push 0
\        The number (0 or 1) we pushed before sinks one position
);)      Obtains the last character of the string
32=      Is it a space?    
{'\n'+\1} Add a new line, make the number we pushed before rise
          one position, and push another 1
{;0}if   Same as before
|        'Or' between the two numbers we pushed before
}do      If at least one of them was 1, repeat!

Test

It works with dots by replacing 32 with 46.

Input: ...test..

Output:

...test..
..test..
..test.
.test.
.test
test

FedeWar

Posted 2017-09-21T09:19:05.853

Reputation: 271

0

Japt -R, 18 bytes

ÈrYg"^  $"ò}hUÊN â

Try it

Shaggy

Posted 2017-09-21T09:19:05.853

Reputation: 24 623

0

Stax, 16 bytes

ùG⌐♦ò⌡╩d♪º"╪8·`;

Run and debug it

Procedure:

  • Alternate replacing regexes "^ " and " $" with "". Do this n times where n is the length of the input.
  • Remove duplicate values.

recursive

Posted 2017-09-21T09:19:05.853

Reputation: 8 616

0

Perl 5 -n, 33 bytes

(s/^ //&&say)|(s/ $//&&say)&&redo

Try it online!

Xcali

Posted 2017-09-21T09:19:05.853

Reputation: 7 671