### (tye)Re3: (Golf) Let's go bowling (113)

by tye (Sage)
 on Aug 14, 2001 at 03:29 UTC ( #104627=note: print w/replies, xml ) Need Help??

in reply to Re: (tye)Re2: (Golf) Let's go bowling (98!)
in thread (Golf) Let's go bowling

Darn. I noticed elsewhere in the thread about being sure to not count the bonus balls twice but missed the stuff about there being no good trick to tell whether X\d\d\$ is a final frame with bonus balls or just the two final frames (other than counting frames). ):

I really didn't want to hard-code the number of frames because sometimes I'll bowl a "short game" when we run out of time. So here is an entry at 113 strokes that optionally lets you specify how many frames you shortened your game (you can even pass in a negative value for "extra long games"):

```sub bowl {
(\$_,\$n)=@_;
s#(\d)(\d|/(?=(.)))|X(?=(..))|.#
(\$3.\$4?"X\$3\$4":\$1.\$2,"")[9<\$n++]#ge;
s#./#X#g;
map{(y.X.a.)x hex}split//
}

chomp( @ARGV=<DATA> ) if ! @ARGV;
for my \$line ( @ARGV ) {
print "\$line = ", 0+bowl(\$line), "\n   ";
for(  0..9  ) {
print " ",0+bowl(\$line,9-\$_);
}
print \$/;
}
__END__
81633470434/72813/62
81633470434/72813/X18
X00X00X00X00X00
00X00X00X00X00X00
X11X11X11X11X11
11X11X11X11X11X11
5/63XX7043X4/813/6
This even allowed me to add a test suite that shows the score at each frame.

- tye (but my friends call me "Tye")

Replies are listed 'Best First'.
Re: (tye)Re3: (Golf) Let's go bowling (113)
by petral (Curate) on Aug 14, 2001 at 20:41 UTC
Awesome. But, um, you can combine the last 2 lines (and return a scalar):  s#./|X#9#g+eval join'+',/./g
(and I still don't understand how that `|.' guard is working.)

Thanks! Those are much shorter ways of splitting and dealing with the 10s. My method of summing is a bit shorter, so that gets me to 105:

```sub bowl {
(\$_,\$n)=@_;
s#(\d)(\d|/(?=(.)))|X(?=(..))|.#
(\$3.\$4?"X\$3\$4":\$1.\$2,"")[9<\$n++]#ge;
s#./|X#9#g+map{(3)x\$_}/./g
}

chomp( @ARGV=<DATA> ) if ! @ARGV;
for my \$line ( @ARGV ) {
print "\$line = ", bowl(\$line), "\n   ";
for(  0..9  ) {
print " ",bowl(\$line,9-\$_);
}
print \$/;
}
__END__
81633470434/72813/62
81633470434/72813/X18
X00X00X00X00X00
00X00X00X00X00X00
X11X11X11X11X11
11X11X11X11X11X11
5/63XX7043X4/813/6

The |. on the end of the first regex is required so that the regex matches the entire string. Take a 5-frame game as an example:

```6/ 45 X  7/ X3/
14  9 20 20 20
14 23 43 63 83
"6/45X7/X3/"
"6/" matches; \$1="6", \$2="/", \$3="4"; change to "X4"
"45" matches; \$1="4", \$2="5"; change to "45"
"X" matches; \$4="7/"; change to "X7/"
"7/" matches; \$1="7", \$2="/", \$3="X"; change to "XX"
"X" matches; \$4="3/"; change to "X3/"
"3" matches; change to "\$1\$2" eq ""
"/" matches; change to "\$1\$2" eq ""
(result: "X445X7/XXX3/")
Those last two substitutions wouldn't happen without the "|." on the end of the regex. The zero-width lookahead assertions, (?=...), aren't part of the "match" and so don't get "consumed" during replacement.

If we required that unused bonus frames be recorded as "-", for example, we could get even shorter. For example, this 86-stroke version:

```sub bowl {
\$_=pop;
s#(\d\d|.(/))(?=(.))|X(?=(..))|.#\$2.\$4?"X\$3\$4":\$1#ge;
s#./|X#9#g+map{(7)x\$_}/./g
}

chomp( @ARGV=<DATA> ) if ! @ARGV;
for my \$line ( @ARGV ) {
print "\$line = ", bowl(\$line), \$/;
}
__END__
81633470434/72813/62--
81633470434/72813/X18
X00X00X00X00X00--
00X00X00X00X00X00
X11X11X11X11X11--
11X11X11X11X11X11
5/63XX7043X4/813/6

- tye (but my friends call me "Tye")
Yes, but since you're now counting the frames (and replacing ./ and X later) you don't have to match the whole string!
Much simpler ( 84 chars):
```sub bowl {
(\$_,\$n)=@_;                                      # 11

s#./(?=(.))|X(?=(..))|..#\$&.(\$n++<9&&\$1.\$2)#ge;  # 47

s#./|X#9#g+map{(1)x\$_}/./g                       # 26
}
#                                                   ___
#                                                    84
And here's a little bit more complicated one which passes strict and -w (and yes, I do have other things I'm supposed to be doing with my time):
```sub bowl {
\$_=pop;                                          #  7

\$a=()=/\d\d\B/g;                                 # 16

s#(?=./(.)|X(..))#\$a++<9&&(\$2||\$1)#ge;           # 38

s#./|X#55#g;                                     # 12
s/\B/+/g;                                        #  9
eval                                             #  4
}
#                                                   ___
#                                                    86
update(5sep): Actually, here's a pretty straightforword one for perl 5.6.0 and higher that passes -w and use strict at 85 chars:
```sub bowl {
\$_=pop;                                          #  7

m#(./(?=(.)(?{\$_.=\$2}))|X(?=(..)(?{\$_.=\$3}))|..){9}#;
# 53
s#./|X#55#g;                                     # 12
s/\B/+/g;                                        #  9
eval                                             #  4
}
#                                                   ___
#                                                    85

p

Create A New User
Node Status?
node history
Node Type: note [id://104627]
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (7)
As of 2018-06-22 23:06 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
Should cpanminus be part of the standard Perl release?

Results (124 votes). Check out past polls.

Notices?