Re: golf anyone? (taking first field)
by Aristotle (Chancellor) on Jan 07, 2003 at 10:44 UTC
|
Update: 'tis broken. See sauoq's reply.
Do you really just want the first word, even if there are several before the colon? In that case, 21.
# 1 2
#23456789012345678901
map/^([^:\s]+)/,@list
If you want to allow optional whitespace at the start of a line, 24.
# 1 2
#23456789012345678901234
map/^\s*([^:\s]+)/,@list
Makeshifts last the longest. | [reply] [Watch: Dir/Any] [d/l] [select] |
Re: golf anyone? (taking first field)
by sauoq (Abbot) on Jan 08, 2003 at 02:09 UTC
|
# 1 2
#1234567890123456789012345678
map/(^\s*[^:]*[^:\s])/,@list
Specifically, remove blank lines, and truncate each line at the first : (if present) and get rid of trailing whitespace after the xxxxx part (including the possible "\n".
Of all the solutions that were submitted, only this one and blokhead's (36) took into account that the 'xxxxxx' portion might itself contain whitespace. (Well, to be fair, busunsl's did too, but it didn't properly remove newlines. Update: So did Arien's as he kindly pointed out to me but his breaks by being too liberal in what it accepts/returns.)
This is what I used to test:
This is the output:
-sauoq
"My two cents aren't worth a dime.";
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
map/(^\s*[^:]*[^:\s])/,@list
Is beautifully clear and simple, not just short because of fancy tricks. Read all the leading whitespace, read up to the first : or to the end, finally back off any whitespace. (actually, will read over consecutive :'s, not the first. But it's the first =occurance=.)
In general, the x*y regex idiom, where y is a union of x and w, will take internal w but not trailing w. This triggers backtracking to literally "back off" if it happened to end in w.
Furthermore, it works with only the most common regex features, not using rare backslash chars or extensions. It can be grocked by anyone with a little regex experience.
The fact that the blank lines and blank-after-truncating lines are purged without special case logic means that the algorithm to "find the interesting part" matches neatly what the defining characteristic of that interesting part is. The desired behavior of blanks and empty lines is a natural concequence of that fundimental idea, not arbitrary rules designed to make it harder (like a putt-putt course's windmill?).
Well done. I think you hit the sweet spot on that one.
—John | [reply] [Watch: Dir/Any] [d/l] [select] |
Re: golf anyone? (taking first field)
by Arien (Pilgrim) on Jan 07, 2003 at 07:56 UTC
|
# 1 2
#2345678901234567890123456
map/(.+?)\s*(?>:|$)/,@list
Update: Also eliminating lines that contain just a colon and optional whitespace. 28 strokes:
# 1 2
#234567890123456789012345678
map/(.+?)\b\s*(?>:|$)/,@list
— Arien | [reply] [Watch: Dir/Any] [d/l] [select] |
|
| [reply] [Watch: Dir/Any] |
Re: golf anyone? (taking first field)
by jmcnamara (Monsignor) on Jan 07, 2003 at 09:16 UTC
|
The following should do what you require:
@a = map{(split)[0]}@a;
As an un-golfed one-liner I would write it like this:
perl -lane 'print $F[0] if @F' file
Update: I see that you added a specific requirement for lines that begin with ":" in one of your follow ups. In Golf that's not fair since it means that we would have to have read all of the other posts before posting a reply.
Anyone interested in posting a Golf challenge should read Tips on Writing a Golf Challenge.
The following handles the special case (the ^ is probably optional):
@a = grep!/^:/,map+(split)[0],@a;
--
John.
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: golf anyone? (taking first field)
by blokhead (Monsignor) on Jan 07, 2003 at 06:51 UTC
|
Here's my shot (37 chars):
map{/([^:]*?)(\s*\n|\s*:)/&&$1}@list;
# silly me ... distributive property! update: 34 chars:
map{/([^:]*?)\s*(\n|:)/&&$1}@list;
I tested it with the following data and it seemed to work correctly:
__DATA__
123 : oain:b:okfbd
456
foo bar : df a dsaf asdf
111 :
It doesn't work when the input line contains only whitespace, but it does work for blank (other than the \n) lines. It returns empty string when the colon is the first non-whitespace. I don't know if this is correct behavior or not, though! This is my first golf attempt, so I may have missed some regex shortening tricks.
Update: Here's a slightly different approach that's the same 34 chars, although it behaves differently. This one does ignore lines of complete whitespace. It still gives empty string when a colon is the first non-whitespace in the line.
map{(split/\s*(:|\n|$)/)[0]}@list;
blokhead | [reply] [Watch: Dir/Any] [d/l] [select] |
|
If the colon begins the line, it should be the same as an empty line. That is, remove the '' from the output list.
| [reply] [Watch: Dir/Any] |
|
map{/([^:]*?)\s*(:|$)/;$1||()}@list;
Back to 36 chars. ;)
blokhead | [reply] [Watch: Dir/Any] [d/l] |
|
Re: golf anyone? (taking first field)
by busunsl (Vicar) on Jan 07, 2003 at 07:33 UTC
|
36 chars and handles blank lines, empty lines and lines starting with a colon:
@list = (
"123 : oain:b:okfbd",
"",
"456",
"foo bar : df a dsaf asdf",
"111 :",
": adf",
" "
);
$, = "\n";
print map{/(.*?)(\s*:|\s*$)/;$1||()}@list;
Chokes if the values in front of the colon is '0'.
Update:
33 chars (destructive):
map{s/\s*:.*|\s*$//;$_||()}@list;
Update:
32 chars (destructive):
map{s/\s*(:.*|$)//;$_||()}@list;
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: golf anyone? (taking first field)
by CountZero (Bishop) on Jan 07, 2003 at 07:23 UTC
|
use strict;
my @list=('xxxxxa : yyyyy blah blah','xxxxxb : yyyyy blah blah',' ',
+'xxxxxc : yyyyy blah blah',': this is strange','xxxxxd : yyyyy blah b
+lah',"\n",'xxxxxe : yyyyy blah blah');
my @result = map {m/(.*?)\s+:/} @list;
print join("\n",@result);
It throws out blank lines, lines with only a trailing newline and lines which start with a colon. The operative part counts 24 characters. CountZero
Update:Added ? to make the match non-greedy (see blokhead's remarks)
Update 2:The operative part could be written as map/(.*?)\s+:/,@list and is then only 20 characters long.
"If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law | [reply] [Watch: Dir/Any] [d/l] [select] |
|
On inputs " : space before colon\n" it returns the spaces (minus one), and "xxxxx: no space between data and colon", it returns an empty list.
blokhead
| [reply] [Watch: Dir/Any] |
|
By adding a ? to the regex code my @result = map {m/(.*?)\s+:/} @list; I think it now works: - the delimiter is space before colon, hence "xxxxx: no space between data and colon" returns nothing as there is no valid delimiter
- and on " : space before colon\n" it now returns the empty list as there is a valid delimiter and all spaces are stripped from the result, so nothing remains. Please, note that this is different from having an empty line to start with, which is to be dropped.
CountZero "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law
| [reply] [Watch: Dir/Any] [d/l] |