# Undress a string

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

Hello..
Hello.
Hello

World

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


• From Sandbox: codegolf.meta.stackexchange.com/a/13765/71426 Sep 21 '17 at 9:19
• Can we assume that there will be at least one non-space character? Sep 21 '17 at 9:34
• @KevinCruijssen You only have to handle ASCII characters in the printable space (0x20 to 0x7E). The other ones are Undefined Behavior. Sep 21 '17 at 10:54
• @KevinCruijssen Yes, there will be no test case like this. There will be no things like " test\r " or " \v test" either. Sep 21 '17 at 10:57
• Is 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) Sep 21 '17 at 13:54

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

# Python 2, 122107103102989593919088 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, 979593 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!

• Using s=input() instead of a function would take less bytes. Sep 21 '17 at 10:23
• Refering to 5. Undefined behaviour on empty input, or input that only contains spaces, is OK., 98 bytes. Sep 21 '17 at 10:42
• Python 3 saves a byte. Sep 21 '17 at 10:42
• @JonathanFrech I hadn't seen that; thanks :) Sep 21 '17 at 10:49
• 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. Sep 21 '17 at 11:00

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

• [^.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. Sep 21 '17 at 13:50
• 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... Sep 21 '17 at 14:08

# 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

• 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. :-) Sep 21 '17 at 14:17
• @scottinet: I just found a way to get around the end-check :) Sep 21 '17 at 15:00
• 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 :-) Sep 21 '17 at 15:10
• @scottinet: Yeah. It's obvious when you think about it, but sometimes it's easy to miss those things :P Sep 21 '17 at 15:27
• TFW the clunky redundant answer gets the lead... Sep 21 '17 at 16:36

# 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), 107102101100 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!

• I 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. Sep 21 '17 at 14:20
• What does the ++k+ do? Sep 21 '17 at 14:36
• @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. Sep 21 '17 at 14:37
• Technically i=k+++2 works too which I would have used because the +++ looks weird :P Sep 21 '17 at 14:38
• @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. Sep 21 '17 at 14:42

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

// some trick to show dots instead of spaces, for test
.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> • 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. Sep 21 '17 at 15:16 • @JustinMariner ok now, because OP stated no char expected less than ' '. Thanks Sep 21 '17 at 15:56 # 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!

• Doesn't work correctly for strings without trailing spaces. Sep 21 '17 at 13:35
• print;s/^ //&&print,s/ $//&&print while/^ |$/ works with -n flag, also -l is not needed Sep 21 '17 at 15:56
• @nwellnhof fixed. Sep 23 '17 at 11:54

# C# (.NET Core), 192183182181179 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!

• 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) Sep 21 '17 at 10:42
• I've thought about second one, but what if the test string contains newlines? Sep 21 '17 at 10:44
• 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)." Sep 21 '17 at 10:58

# Java 8, 150146145 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

• You can use s=f+s.charAt(0)<33 instead of (f<1&s.charAt(0)<33) (-4 bytes). Sep 21 '17 at 12:01
• You can use s!=s.trim() instead of !s.trim().equals(s); (-8 bytes). Sep 21 '17 at 12:24

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

Ḋ=⁶Ḣ$¡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

• ḣ1Ḣ=⁶ -> =⁶Ḣ Sep 21 '17 at 14:09
• @EriktheOutgolfer Thanks, edit coming. Sep 21 '17 at 14:10
• Cool idea with the alternating commands of reverse/identity! Sep 21 '17 at 15:02
• @Emigna Thanks! :D I mostly just wanted an excuse to use the new quick... heh :P Sep 21 '17 at 17:21
• ƭ only needs a nilad if the chain is longer than two. ¹Ṛƭ works fine here. Sep 22 '17 at 11:26

# Ruby, 63 bytes

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


Try it online!

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

• Hehe, I saw your deleted answer and was wondering when you were below my 150 bytes and would undelete it. ;) Sep 21 '17 at 11:49
• I'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) Sep 21 '17 at 11:53
• @KevinCruijssen Won't work, k is 0 every second iteration. Sep 21 '17 at 12:00
• 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 Sep 21 '17 at 12:05
• @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). Sep 21 '17 at 12:56

# 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

• 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. Sep 21 '17 at 13:34
• 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. Sep 21 '17 at 13:51
• 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... Sep 21 '17 at 14:00

# R, 145133 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
}

• can't you use C(s<-sub(),\n) instead of a separate print statement? Ah, no, because of sep=" " Sep 21 '17 at 13:38
• @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! Sep 21 '17 at 13:45
• 133 bytes -- something about your using sub just suggested this, IDK why Sep 21 '17 at 14:26
• @Giuseppe Very elegant! Sep 21 '17 at 14:55
• Could you just set L=s and return a vector of strings? Sep 21 '17 at 15:14

# Java (OpenJDK 8), 137125121120 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!

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


# Husk, 23 22 bytes

u§↑LGI¢e₁ȯ↔₁↔
?tI<"!


Thanks to Leo for -1 byte.

Try it online!

## Explanation

The function GI 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§↑LGI¢e₁ȯ↔₁↔  Main function.
e       List containing
₁      the helper function
ȯ↔₁↔  and the composition reverse-helper-reverse.
¢        Repeat it cyclically.
GI         Cumulative reduce from left by function application
using input string as initial value.
§↑L             Take first length(input) values.
u                Remove duplicates.

• Nice! Indeed we would need more builtins for applying functions cyclically... btw I've found a sligthly shorter way to remove the first space: tio.run/##yygtzv7/v/…
– Leo
Sep 21 '17 at 21:54
• @Leo Thanks! Using ? seems obvious in hindsight... Sep 23 '17 at 20:27

## C++, 196193189186 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

• You may be able to replace ==32 with <33. Sep 21 '17 at 12:56
• I am no C++ master, though is #include<string> really necessary? Sep 21 '17 at 13:00
• if(...){...;D;} -> if(...)...,D;. Sep 21 '17 at 13:04
• @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. Sep 21 '17 at 13:09
• #define R ...<33, ||R){ and if(R){ -> #define R ...<33), ||R{ and if(R{. Sep 21 '17 at 13:10

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

• Your program doesn't output the string unmodified before removing spaces. Sep 21 '17 at 15:18
• @Nathan.EilishaShiraini I corrected that mistake and golfed a few bytes to reduce the byte count anyway. Sep 21 '17 at 15:26

# 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

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>

";if($s[-1]==" ")echo($s=substr($s,0,-1))." ";}  Try it online! • Using your method 6 bytes can be reduced: Try it online! Aug 27 '19 at 10:04 • You 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. Aug 27 '19 at 10:07 # Pyth, 28 bytes QW<lrKQ6lQ=hZ?&%Z2qdhQ=tQ=PQ  # 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.  # 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. • '!'*i and -> i*'!'and. Sep 21 '17 at 12:12 # 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! • Welcome to PPCG! Sep 22 '17 at 19:06 # 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 ... • Is it valid to output with s = ...? (The usual question, I know) Sep 21 '17 at 23:24 • Anyway, see if you can remove a couple of bytes :-P Sep 21 '17 at 23:36 # 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