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
First output the string unchanged. Then, output every step. Begin by removing a leading space (if applicable - see rule #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.
The input may have no leading nor trailing spaces. If that's the case, output it as-is.
Use PPCG's default I/O methods. PPCG Default loopholes are forbidden.
Undefined behaviour on empty input, or input that only contains spaces, is OK.
You can assume that the string will only contain characters from the ASCII printable space (
0x20
to0x7E
).
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.
41 Answers 41
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, (削除) 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
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)
-
\$\begingroup\$ Using
s=input()
instead of a function would take less bytes. \$\endgroup\$Jonathan Frech– Jonathan Frech2017年09月21日 10:23:41 +00:00Commented Sep 21, 2017 at 10:23 -
\$\begingroup\$ Refering to
5. Undefined behaviour on empty input, or input that only contains spaces, is OK.
, 98 bytes. \$\endgroup\$Jonathan Frech– Jonathan Frech2017年09月21日 10:42:17 +00:00Commented Sep 21, 2017 at 10:42 -
\$\begingroup\$ Python 3 saves a byte. \$\endgroup\$LyricLy– LyricLy2017年09月21日 10:42:32 +00:00Commented Sep 21, 2017 at 10:42
-
\$\begingroup\$ @JonathanFrech I hadn't seen that; thanks :) \$\endgroup\$TFeld– TFeld2017年09月21日 10:49:07 +00:00Commented Sep 21, 2017 at 10:49
-
2
Perl 6, 55 bytes
Saved 3 bytes thanks to @nwellnhof.
{($_,{$++%2??S/" "$//!!S/^" "//}...*)[^.comb*2].unique}
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.
-
\$\begingroup\$
[^.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. \$\endgroup\$nwellnhof– nwellnhof2017年09月21日 13:50:02 +00:00Commented Sep 21, 2017 at 13:50 -
\$\begingroup\$ 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... \$\endgroup\$Ramillies– Ramillies2017年09月21日 14:08:46 +00:00Commented Sep 21, 2017 at 14:08
05AB1E, (削除) 21 (削除ここまで) 15 bytes
=v¬ðQi¦=}¤ðQi ̈=
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
-
\$\begingroup\$ 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. :-) \$\endgroup\$scottinet– scottinet2017年09月21日 14:17:56 +00:00Commented Sep 21, 2017 at 14:17
-
1\$\begingroup\$ @scottinet: I just found a way to get around the end-check :) \$\endgroup\$Emigna– Emigna2017年09月21日 15:00:52 +00:00Commented Sep 21, 2017 at 15:00
-
\$\begingroup\$ 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 :-) \$\endgroup\$scottinet– scottinet2017年09月21日 15:10:17 +00:00Commented Sep 21, 2017 at 15:10
-
1\$\begingroup\$ @scottinet: Yeah. It's obvious when you think about it, but sometimes it's easy to miss those things :P \$\endgroup\$Emigna– Emigna2017年09月21日 15:27:00 +00:00Commented Sep 21, 2017 at 15:27
-
\$\begingroup\$ TFW the clunky redundant answer gets the lead... \$\endgroup\$Erik the Outgolfer– Erik the Outgolfer2017年09月21日 16:36:04 +00:00Commented Sep 21, 2017 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);}
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);}
-
2\$\begingroup\$ 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. \$\endgroup\$Jonathan Frech– Jonathan Frech2017年09月21日 14:20:33 +00:00Commented Sep 21, 2017 at 14:20 -
\$\begingroup\$ What does the
++k+
do? \$\endgroup\$Jonathan Frech– Jonathan Frech2017年09月21日 14:36:58 +00:00Commented Sep 21, 2017 at 14:36 -
\$\begingroup\$ @JonathanFrech It pre-increments
k
and adds one, which is equivalent tok = k + 1; i = k + 1;
ori = k + 2; k = k + 1
. \$\endgroup\$2017年09月21日 14:37:45 +00:00Commented Sep 21, 2017 at 14:37 -
\$\begingroup\$ Technically
i=k+++2
works too which I would have used because the+++
looks weird :P \$\endgroup\$2017年09月21日 14:38:12 +00:00Commented Sep 21, 2017 at 14:38 -
\$\begingroup\$ @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. \$\endgroup\$Jonathan Frech– Jonathan Frech2017年09月21日 14:42:08 +00:00Commented Sep 21, 2017 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=
(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>
-
\$\begingroup\$ You could save a byte by checking for space with
<'!'
. To make your snippet still work you canreplace
periods with spaces before passing to your function. \$\endgroup\$Justin Mariner– Justin Mariner2017年09月21日 15:16:03 +00:00Commented Sep 21, 2017 at 15:16 -
\$\begingroup\$ @JustinMariner ok now, because OP stated no char expected less than ' '. Thanks \$\endgroup\$edc65– edc652017年09月21日 15:56:58 +00:00Commented Sep 21, 2017 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
-
\$\begingroup\$ Doesn't work correctly for strings without trailing spaces. \$\endgroup\$nwellnhof– nwellnhof2017年09月21日 13:35:55 +00:00Commented Sep 21, 2017 at 13:35
-
\$\begingroup\$
print;s/^ //&&print,s/ $//&&print while/^ | $/
works with-n
flag, also-l
is not needed \$\endgroup\$Nahuel Fouilleul– Nahuel Fouilleul2017年09月21日 15:56:36 +00:00Commented Sep 21, 2017 at 15:56 -
\$\begingroup\$ @nwellnhof fixed. \$\endgroup\$primo– primo2017年09月23日 11:54:24 +00:00Commented Sep 23, 2017 at 11:54
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;}
-
\$\begingroup\$ 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)
\$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2017年09月21日 10:42:40 +00:00Commented Sep 21, 2017 at 10:42 -
\$\begingroup\$ I've thought about second one, but what if the test string contains newlines? \$\endgroup\$the default.– the default.2017年09月21日 10:44:29 +00:00Commented Sep 21, 2017 at 10:44
-
\$\begingroup\$ 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
to0x7E
)." \$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2017年09月21日 10:58:39 +00:00Commented Sep 21, 2017 at 10:58
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
-
1\$\begingroup\$ You can use
s=f+s.charAt(0)<33
instead of(f<1&s.charAt(0)<33)
(-4 bytes). \$\endgroup\$Nevay– Nevay2017年09月21日 12:01:54 +00:00Commented Sep 21, 2017 at 12:01 -
1\$\begingroup\$ You can use
s!=s.trim()
instead of!s.trim().equals(s);
(-8 bytes). \$\endgroup\$Nevay– Nevay2017年09月21日 12:24:01 +00:00Commented Sep 21, 2017 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);}
Jelly, 16 bytes
Ḋ=6Ḣ$¡UμÐL·1Ṛƭ€QY
-2 bytes thanks to Erik the Outgolfer
-1 byte thanks to miles
Explanation
Ḋ=6Ḣ$¡UμÐL·1Ṛƭ€QY Main link
μÐL· While the results are unique (collecting intermediate results), apply the last link (`μ` creates a new monadic link):
Ḋ=6Ḣ$¡ Remove a space from the beginning if there is one
=6Ḣ$ If the first character is a space, then 1, else 0
= Compare each character to
6 ' '
Ḣ 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:
1 Identity (do nothing), and
Ṛ Reverse
1Ṛƭ€ 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
-
\$\begingroup\$
ḣ1Ḣ=6
->=6Ḣ
\$\endgroup\$Erik the Outgolfer– Erik the Outgolfer2017年09月21日 14:09:49 +00:00Commented Sep 21, 2017 at 14:09 -
\$\begingroup\$ @EriktheOutgolfer Thanks, edit coming. \$\endgroup\$2017年09月21日 14:10:58 +00:00Commented Sep 21, 2017 at 14:10
-
\$\begingroup\$ Cool idea with the alternating commands of reverse/identity! \$\endgroup\$Emigna– Emigna2017年09月21日 15:02:22 +00:00Commented Sep 21, 2017 at 15:02
-
\$\begingroup\$ @Emigna Thanks! :D I mostly just wanted an excuse to use the new quick... heh :P \$\endgroup\$2017年09月21日 17:21:03 +00:00Commented Sep 21, 2017 at 17:21
-
\$\begingroup\$
ƭ
only needs a nilad if the chain is longer than two.¹Ṛƭ
works fine here. \$\endgroup\$miles– miles2017年09月22日 11:26:58 +00:00Commented Sep 22, 2017 at 11:26
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;}
-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;
}
-
1\$\begingroup\$ Hehe, I saw your deleted answer and was wondering when you were below my 150 bytes and would undelete it. ;) \$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2017年09月21日 11:49:07 +00:00Commented Sep 21, 2017 at 11:49
-
1\$\begingroup\$ 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)
\$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2017年09月21日 11:53:36 +00:00Commented Sep 21, 2017 at 11:53 -
\$\begingroup\$ @KevinCruijssen Won't work,
k
is0
every second iteration. \$\endgroup\$Nevay– Nevay2017年09月21日 12:00:38 +00:00Commented Sep 21, 2017 at 12:00 -
1\$\begingroup\$ 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
tok
forv
. I'm confused why it works though, sincek
will indeed become0
afterk=~k
.. :S \$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2017年09月21日 12:05:47 +00:00Commented Sep 21, 2017 at 12:05 -
1\$\begingroup\$ @KevinCruijssen For the
k=0
scenario: If left has spaces left, thenu
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 ofu
does not matter (-1|x==-1
). \$\endgroup\$Nevay– Nevay2017年09月21日 12:56:02 +00:00Commented Sep 21, 2017 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
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
-
\$\begingroup\$ 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. \$\endgroup\$Emigna– Emigna2017年09月21日 13:34:32 +00:00Commented Sep 21, 2017 at 13:34
-
\$\begingroup\$ 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. \$\endgroup\$scottinet– scottinet2017年09月21日 13:51:54 +00:00Commented Sep 21, 2017 at 13:51 -
\$\begingroup\$ 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... \$\endgroup\$Emigna– Emigna2017年09月21日 14:00:36 +00:00Commented Sep 21, 2017 at 14:00
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}
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
}
-
\$\begingroup\$ can't you use
C(s<-sub(),\n)
instead of a separate print statement? Ah, no, because ofsep=" "
\$\endgroup\$Giuseppe– Giuseppe2017年09月21日 13:38:54 +00:00Commented Sep 21, 2017 at 13:38 -
\$\begingroup\$ @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! \$\endgroup\$user2390246– user23902462017年09月21日 13:45:00 +00:00Commented Sep 21, 2017 at 13:45 -
-
\$\begingroup\$ @Giuseppe Very elegant! \$\endgroup\$user2390246– user23902462017年09月21日 14:55:04 +00:00Commented Sep 21, 2017 at 14:55
-
\$\begingroup\$ Could you just set
L=s
and return a vector of strings? \$\endgroup\$Giuseppe– Giuseppe2017年09月21日 15:14:15 +00:00Commented Sep 21, 2017 at 15:14
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))));}
-
\$\begingroup\$ 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)));}
\$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2017年09月21日 13:36:38 +00:00Commented Sep 21, 2017 at 13:36 -
\$\begingroup\$ This currently does not "... output the string unchanged" and fails for input with leading spaces and no trailing spaces. \$\endgroup\$Nevay– Nevay2017年09月21日 14:39:21 +00:00Commented Sep 21, 2017 at 14:39
-
1\$\begingroup\$ Maybe 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). \$\endgroup\$Nevay– Nevay2017年09月21日 14:54:38 +00:00Commented Sep 21, 2017 at 14:54
MATL, (削除) 21 (削除ここまで) 16 bytes
tnE:"t@o&)w46-?x
This uses dots instead of spaces for greater clarity. For spaces replace 46
by 32
.
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§↑L`G`I¢e1ȯ↔1↔
?tI<"!
Thanks to Leo for -1 byte.
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¢e1ȯ↔1↔ Main function.
e List containing
1 the helper function
ȯ↔1↔ 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.
-
\$\begingroup\$ 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/… \$\endgroup\$Leo– Leo2017年09月21日 21:54:11 +00:00Commented Sep 21, 2017 at 21:54
-
\$\begingroup\$ @Leo Thanks! Using
?
seems obvious in hindsight... \$\endgroup\$Zgarb– Zgarb2017年09月23日 20:27:33 +00:00Commented Sep 23, 2017 at 20:27
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
-
\$\begingroup\$ You may be able to replace
==32
with<33
. \$\endgroup\$Jonathan Frech– Jonathan Frech2017年09月21日 12:56:40 +00:00Commented Sep 21, 2017 at 12:56 -
\$\begingroup\$ I am no C++ master, though is
#include<string>
really necessary? \$\endgroup\$Jonathan Frech– Jonathan Frech2017年09月21日 13:00:17 +00:00Commented Sep 21, 2017 at 13:00 -
\$\begingroup\$
if(...){...;D;}
->if(...)...,D;
. \$\endgroup\$Jonathan Frech– Jonathan Frech2017年09月21日 13:04:49 +00:00Commented Sep 21, 2017 at 13:04 -
\$\begingroup\$ @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. \$\endgroup\$HatsuPointerKun– HatsuPointerKun2017年09月21日 13:09:17 +00:00Commented Sep 21, 2017 at 13:09
-
\$\begingroup\$
#define R ...<33
,||R){
andif(R){
->#define R ...<33)
,||R{
andif(R{
. \$\endgroup\$Jonathan Frech– Jonathan Frech2017年09月21日 13:10:23 +00:00Commented Sep 21, 2017 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();}}}
This is an alternative to @someone's answer, and just outputs the strings directly.
-
\$\begingroup\$ Your program doesn't output the string unmodified before removing spaces. \$\endgroup\$Nathan.Eilisha Shiraini– Nathan.Eilisha Shiraini2017年09月21日 15:18:38 +00:00Commented Sep 21, 2017 at 15:18
-
\$\begingroup\$ @Nathan.EilishaShiraini I corrected that mistake and golfed a few bytes to reduce the byte count anyway. \$\endgroup\$BgrWorker– BgrWorker2017年09月21日 15:26:13 +00:00Commented Sep 21, 2017 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
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>
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
-
\$\begingroup\$ Very nice. "Anyway, see if you can remove a couple of bytes" :-P \$\endgroup\$Stewie Griffin– Stewie Griffin2017年09月22日 10:42:43 +00:00Commented Sep 22, 2017 at 10:42
-
\$\begingroup\$ @StewieGriffin I meant in your answer... :-D Good idea, thanks! \$\endgroup\$Luis Mendo– Luis Mendo2017年09月22日 10:48:36 +00:00Commented Sep 22, 2017 at 10:48
-
\$\begingroup\$ I might delete mine... It's so uninspired compared to this... \$\endgroup\$Stewie Griffin– Stewie Griffin2017年09月22日 10:54:30 +00:00Commented Sep 22, 2017 at 10:54
-
\$\begingroup\$ @StewieGriffin Here's an idea to remove two bytes. Pity that
min
is needed because ofs
being dynamically shrunk \$\endgroup\$Luis Mendo– Luis Mendo2017年09月22日 11:06:39 +00:00Commented Sep 22, 2017 at 11:06
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
-
\$\begingroup\$
sys_write()
makeseax
non-zero (specifically1
, the number of characters written, assuming it's not-errno
), So willprint
if you don'tpop eax
at the end. You could justxor eax,eax
before thecmp byte [edi], ' '
and save themov al,1
, and maybe someeax
save/restore. Although you don't actually save it until after clobbering withSYS_WRITE
. Hmm, instead of0
, you could useSYS_WRITE
vs.1
, sincecmp al, imm8
is the same size astest al,al
. \$\endgroup\$Peter Cordes– Peter Cordes2017年09月24日 22:23:49 +00:00Commented Sep 24, 2017 at 22:23 -
\$\begingroup\$ Can you put a
'\n'
into the array withmov byte [ecx + edx], '\n'
instead of doing the 2ndwrite()
? (And decrement the length after printing?) Might save you a few instructions. \$\endgroup\$Peter Cordes– Peter Cordes2017年09月24日 22:29:16 +00:00Commented Sep 24, 2017 at 22:29 -
\$\begingroup\$ Actually,
print()
currently leaves'\n'
ineax
, which is different fromSYS_WRITE
, so you could still check that. I thought you were saving/restoringeax
, 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 usingmov al, SYS_WRITE
. \$\endgroup\$Peter Cordes– Peter Cordes2017年09月24日 23:05:08 +00:00Commented Sep 24, 2017 at 23:05 -
\$\begingroup\$ @PeterCordes actually yes,
mov al, 1
was extraneous. -2 bytes now, thanks. \$\endgroup\$Ruslan– Ruslan2017年09月25日 06:07:58 +00:00Commented Sep 25, 2017 at 6:07 -
\$\begingroup\$ 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. \$\endgroup\$Peter Cordes– Peter Cordes2017年09月25日 12:41:00 +00:00Commented Sep 25, 2017 at 12:41
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))."
";}
-
1\$\begingroup\$ Using your method 6 bytes can be reduced: Try it online! \$\endgroup\$Night2– Night22019年08月27日 10:04:34 +00:00Commented Aug 27, 2019 at 10:04
-
1\$\begingroup\$ 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. \$\endgroup\$Night2– Night22019年08月27日 10:07:14 +00:00Commented Aug 27, 2019 at 10:07
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.
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[])
The test suit replaces "."
with " "
before calling the function and replaces " "
back to "."
before printing the results for clarity.
-
\$\begingroup\$
'!'*i and
->i*'!'and
. \$\endgroup\$Jonathan Frech– Jonathan Frech2017年09月21日 12:12:41 +00:00Commented Sep 21, 2017 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!
-
\$\begingroup\$ Welcome to PPCG! \$\endgroup\$Laikoni– Laikoni2017年09月22日 19:06:09 +00:00Commented Sep 22, 2017 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
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 ...
-
\$\begingroup\$ Is it valid to output with
s = ...
? (The usual question, I know) \$\endgroup\$Luis Mendo– Luis Mendo2017年09月21日 23:24:43 +00:00Commented Sep 21, 2017 at 23:24 -
\$\begingroup\$ Anyway, see if you can remove a couple of bytes :-P \$\endgroup\$Luis Mendo– Luis Mendo2017年09月21日 23:36:12 +00:00Commented Sep 21, 2017 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
0x20
to0x7E
). The other ones are Undefined Behavior. \$\endgroup\$" test\r "
or" \v test"
either. \$\endgroup\$".....................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) \$\endgroup\$