[QUIZ] Bowling Scores (#181)

M

Matthew Moss

Apologies for not having the Long Division quiz summary done yet. It
will come sometime today or tomorrow. Meanwhile, I have the next quiz
ready...

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

The three rules of Ruby Quiz 2:

1. Please do not post any solutions or spoiler discussion for this
quiz until 48 hours have passed from the time on this message.

2. Support Ruby Quiz 2 by submitting ideas as often as you can! (A
permanent, new website is in the works for Ruby Quiz 2. Until then,
please visit the temporary website at

<http://splatbang.com/rubyquiz/>.

3. Enjoy!

Suggestion: A [QUIZ] in the subject of emails about the problem
helps everyone on Ruby Talk follow the discussion. Please reply to
the original quiz message, if you can.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

## Bowling Scores (#181)


Whether it is real or on the Wii, bowling is a fun game. (Okay, for
the sake of the quiz, let's assume it's a fun game.) But I've known
folks who just don't understand [how to score properly][1]. They can
count pins knocked down, and know that getting all ten pins in one
roll is good, but they still can't keep score.

Your task this week is to tally scores for these people. The input
will be the player's name and the number of pins felled from each
roll. For example:

ruby bowling_scores.rb John 6 2 7 1 10 9 0 8 2 10 10 3 5 7 2 5 5 8

Your should tally the per-frame scores and generate output in table
form, such as:

John's final score: 140

Frame Roll Roll Score
1 6 2 8
2 7 1 16
3 X 35
4 9 - 44
5 8 / 64
6 X 87
7 X 105
8 3 5 113
9 7 2 122
10 5 / 140
* 8


Note that you should make use of typical bowling symbols: `X` for a
strike, `/` for a spare, and `-` for zero. Also, if extra balls were
thrown at the end (to supplement a strike or spare in the final
frame), list those as frame `*` like the above, but without a score.

Extra credit: Generate ascii or graphical output that looks more like
the traditional bowling score form, which can be seen on [this page][1].


[1]: http://www.bowling2u.com/trivia/game/scoring.asp
 
K

Kristian Elof Sørensen

fre, 24 10 2008 kl. 23:25 +0900, skrev Matthew Moss:
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

## Bowling Scores (#181)

# a simple no-frills tail-recursive implementation
class Bowling
def initialize
playBowling(ARGV[0], ARGV[1..ARGV.length].collect { |n| n.to_i })
end
def playBowling(player, pins)
printf("\nFrame Roll Roll Score\n")
printf("\n%s's final score: %d\n\n", player, doFrame(pins))
end
def doFrame(pins, frame = 1, subtotal = 0)
dSubtotal = 0
if pins.length > 0
if frame > 10
printFrame("*", pins[0], pins[1], "")
pins = []
elsif pins[0] == 10
dSubtotal = + pins[0] + pins[1] + pins[2]
printFrame(frame, "X", " ", subtotal + dSubtotal)
pins = pins[1..pins.length]
elsif pins[0] + pins[1] == 10
dSubtotal = pins[0] + pins[1] + pins[2]
printFrame(frame, pins[0], "/", subtotal + dSubtotal)
pins = pins[2..pins.length]
else
dSubtotal = pins[0] + pins[1]
printFrame(frame, pins[0], pins[1], subtotal + dSubtotal)
pins = pins[2..pins.length]
end
doFrame(pins, frame + 1, subtotal + dSubtotal)
else
subtotal
end
end
def printFrame(frameNr, ball0, ball1, subtotal)
printf(" %2s %s %s %3s\n", frameNr, ball0, ball1, subtotal)
end
end

Bowling.new() if $0 == __FILE__
 
K

Ken Bloom

Apologies for not having the Long Division quiz summary done yet. It
will come sometime today or tomorrow. Meanwhile, I have the next quiz
ready...

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

The three rules of Ruby Quiz 2:

1. Please do not post any solutions or spoiler discussion for this quiz
until 48 hours have passed from the time on this message.

2. Support Ruby Quiz 2 by submitting ideas as often as you can! (A
permanent, new website is in the works for Ruby Quiz 2. Until then,
please visit the temporary website at

<http://splatbang.com/rubyquiz/>.

3. Enjoy!

Suggestion: A [QUIZ] in the subject of emails about the problem helps
everyone on Ruby Talk follow the discussion. Please reply to the
original quiz message, if you can.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

## Bowling Scores (#181)


Whether it is real or on the Wii, bowling is a fun game. (Okay, for the
sake of the quiz, let's assume it's a fun game.) But I've known folks
who just don't understand [how to score properly][1]. They can count
pins knocked down, and know that getting all ten pins in one roll is
good, but they still can't keep score.

Your task this week is to tally scores for these people. The input will
be the player's name and the number of pins felled from each roll. For
example:

ruby bowling_scores.rb John 6 2 7 1 10 9 0 8 2 10 10 3 5 7 2 5 5 8

Your should tally the per-frame scores and generate output in table
form, such as:

John's final score: 140

Frame Roll Roll Score
1 6 2 8
2 7 1 16
3 X 35
4 9 - 44
5 8 / 64
6 X 87
7 X 105
8 3 5 113
9 7 2 122
10 5 / 140
* 8


Note that you should make use of typical bowling symbols: `X` for a
strike, `/` for a spare, and `-` for zero. Also, if extra balls were
thrown at the end (to supplement a strike or spare in the final frame),
list those as frame `*` like the above, but without a score.

Extra credit: Generate ascii or graphical output that looks more like
the traditional bowling score form, which can be seen on [this page][1].


[1]: http://www.bowling2u.com/trivia/game/scoring.asp

#!/usr/bin/env ruby
#Requires Ruby 1.8.7

class Fixnum
def to_bowl
return '-' if self==0
return 'X' if self==10
return self.to_s
end
end

class Array
def strike?
self[0]==10
end
def spare?
self[0]+self[1]==10
end
end

module Enumerable
#each cons is almost what I want, but it won't generate partial cons at the end
def mycons n
result=[]
each_with_index do |f,i|
result << self[i,n]
end
result
end
end

ARGV.map!(&:to_i)
fail if ARGV.any?{|x| x>10}
frames=ARGV.mycons(3)
frames.delete_at(-1)

frames.each_with_index do |f,i|
frames[i+1]=nil if f and not f.strike?
end
frames.compact!
totals=frames.inject([]) do |h,frame|
last = h[-1] || 0
frame.delete_at(2) unless frame.spare? or frame.strike?
h+[last+frame.inject(&:+)]
end
printf "%8s%8s%8s%8s\n", "Frame", "Roll", "Roll", "Score"
frames.each_with_index do |f,i|
spare='/' if f[0]+f[1]==10
printf "%8s%8s%8s%8s\n", i+1, f[0].to_bowl, (spare or f[1].to_bowl unless f.strike?), totals
if i==9 and f.spare?
printf "%8s%8s\n", '*', f[2].to_bowl
elsif i==9 and f.strike?
printf "%8s%8s%8s\n", '*', f[1].to_bowl, f[2].to_bowl
end
end
 
S

Sandro Paganotti

[Note: parts of this message were removed to make it a legal post.]

Here there's my attempt:


=== CODE START ===

class Array
def sum; self.inject{|a,b| a+b}; end
end

def get_points (shot,next_shots)
return shot.sum + (
# strike
if shot.first == 10
next_shots.flatten[0..1].sum
# spare
elsif shot.sum == 10
next_shots.first.first
# normal
else
0
end
)
end

def symbols(score,sep)
return "X#{sep}" if score.first == 10
return "#{score[0]}#{sep}/" if score.sum == 10
return "#{score[0]}#{sep}#{score[1]}"
end

name, score, points = ARGV.first, ARGV[1..-1].join(" "), []
raise "Usage: 'ruby 181_bowling_score.rb [name] [scores]'" if name.nil? or
score.to_a.empty?

score = score.scan(/10|\d+\s*\d*/).collect{|e| e.split(" ").map!{|e|
e.to_i}}
score.each_with_index { |s,i| points = get_points(s,score[i+1..-1]) }

puts "#{name}'s final score: #{points[0..9].sum}";
puts "Frame\tRoll\tRoll\tScore\t"
score.each_with_index do |s,i|
puts "#{i+1}\t#{symbols(s,"\t")}\t#{(i<10) ? points[0..i].sum : ''}"
end


=== CODE END ===




Apologies for not having the Long Division quiz summary done yet. It
will come sometime today or tomorrow. Meanwhile, I have the next quiz
ready...

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

The three rules of Ruby Quiz 2:

1. Please do not post any solutions or spoiler discussion for this quiz
until 48 hours have passed from the time on this message.

2. Support Ruby Quiz 2 by submitting ideas as often as you can! (A
permanent, new website is in the works for Ruby Quiz 2. Until then,
please visit the temporary website at

<http://splatbang.com/rubyquiz/>.

3. Enjoy!

Suggestion: A [QUIZ] in the subject of emails about the problem helps
everyone on Ruby Talk follow the discussion. Please reply to the
original quiz message, if you can.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

## Bowling Scores (#181)


Whether it is real or on the Wii, bowling is a fun game. (Okay, for the
sake of the quiz, let's assume it's a fun game.) But I've known folks
who just don't understand [how to score properly][1]. They can count
pins knocked down, and know that getting all ten pins in one roll is
good, but they still can't keep score.

Your task this week is to tally scores for these people. The input will
be the player's name and the number of pins felled from each roll. For
example:

ruby bowling_scores.rb John 6 2 7 1 10 9 0 8 2 10 10 3 5 7 2 5 5 8

Your should tally the per-frame scores and generate output in table
form, such as:

John's final score: 140

Frame Roll Roll Score
1 6 2 8
2 7 1 16
3 X 35
4 9 - 44
5 8 / 64
6 X 87
7 X 105
8 3 5 113
9 7 2 122
10 5 / 140
* 8


Note that you should make use of typical bowling symbols: `X` for a
strike, `/` for a spare, and `-` for zero. Also, if extra balls were
thrown at the end (to supplement a strike or spare in the final frame),
list those as frame `*` like the above, but without a score.

Extra credit: Generate ascii or graphical output that looks more like
the traditional bowling score form, which can be seen on [this page][1].


[1]: http://www.bowling2u.com/trivia/game/scoring.asp

#!/usr/bin/env ruby
#Requires Ruby 1.8.7

class Fixnum
def to_bowl
return '-' if self==0
return 'X' if self==10
return self.to_s
end
end

class Array
def strike?
self[0]==10
end
def spare?
self[0]+self[1]==10
end
end

module Enumerable
#each cons is almost what I want, but it won't generate partial cons at
the end
def mycons n
result=[]
each_with_index do |f,i|
result << self[i,n]
end
result
end
end

ARGV.map!(&:to_i)
fail if ARGV.any?{|x| x>10}
frames=ARGV.mycons(3)
frames.delete_at(-1)

frames.each_with_index do |f,i|
frames[i+1]=nil if f and not f.strike?
end
frames.compact!
totals=frames.inject([]) do |h,frame|
last = h[-1] || 0
frame.delete_at(2) unless frame.spare? or frame.strike?
h+[last+frame.inject(&:+)]
end
printf "%8s%8s%8s%8s\n", "Frame", "Roll", "Roll", "Score"
frames.each_with_index do |f,i|
spare='/' if f[0]+f[1]==10
printf "%8s%8s%8s%8s\n", i+1, f[0].to_bowl, (spare or f[1].to_bowl unless
f.strike?), totals
if i==9 and f.spare?
printf "%8s%8s\n", '*', f[2].to_bowl
elsif i==9 and f.strike?
printf "%8s%8s%8s\n", '*', f[1].to_bowl, f[2].to_bowl
end
end
 
S

Sandro Paganotti

[Note: parts of this message were removed to make it a legal post.]

Sorry, I forgot to translate zeros into -, here's the fixxed version:



=== CODE START (FIX) ===


=begin


## Bowling Scores (#181)


Whether it is real or on the Wii, bowling is a fun game. (Okay, for the sake
of the quiz, let's assume it's a fun game.) But I've known folks who just
don't understand [how to score properly][1]. They can count pins knocked
down, and know that getting all ten pins in one roll is good, but they still
can't keep score.

Your task this week is to tally scores for these people. The input will be
the player's name and the number of pins felled from each roll. For example:

ruby bowling_scores.rb John 6 2 7 1 10 9 0 8 2 10 10 3 5 7 2 5 5 8

Your should tally the per-frame scores and generate output in table form,
such as:

John's final score: 140

Frame Roll Roll Score
1 6 2 8
2 7 1 16
3 X 35
4 9 - 44
5 8 / 64
6 X 87
7 X 105
8 3 5 113
9 7 2 122
10 5 / 140
* 8


Note that you should make use of typical bowling symbols: `X` for a strike,
`/` for a spare, and `-` for zero. Also, if extra balls were thrown at the
end (to supplement a strike or spare in the final frame), list those as
frame `*` like the above, but without a score.

Extra credit: Generate ascii or graphical output that looks more like the
traditional bowling score form, which can be seen on [this page][1].


[1]: http://www.bowling2u.com/trivia/game/scoring.asp



=end

class Array
def sum; self.inject{|a,b| a+b}; end
end

def get_points (shot,next_shots)
return shot.sum + (
# strike
if shot.first == 10
next_shots.flatten[0..1].sum
# spare
elsif shot.sum == 10
next_shots.first.first
# normal
else
0
end
)
end

def symbols(score,sep)
return "X#{sep}" if score.first == 10
return (score.sum == 10 ? "#{score[0]}#{sep}/" :
"#{score[0]}#{sep}#{score[1]}").gsub("0","-")
end

name, score, points = ARGV.first, ARGV[1..-1].join(" "), []
raise "Usage: 'ruby 181_bowling_score.rb [name] [scores]'" if name.nil? or
score.to_a.empty?

score = score.scan(/10|\d+\s*\d*/).collect{|e| e.split(" ").map!{|e|
e.to_i}}
score.each_with_index { |s,i| points = get_points(s,score[i+1..-1]) }

puts "#{name}'s final score: #{points[0..9].sum}";
puts "Frame\tRoll\tRoll\tScore\t"
score.each_with_index do |s,i|
puts "#{i+1}\t#{symbols(s,"\t")}\t#{(i<10) ? points[0..i].sum : ''}"
end




=== CODE END (FIX) ===








On Sun, Oct 26, 2008 at 11:25 PM, Sandro Paganotti <
Here there's my attempt:


=== CODE START ===

class Array
def sum; self.inject{|a,b| a+b}; end
end

def get_points (shot,next_shots)
return shot.sum + (
# strike
if shot.first == 10
next_shots.flatten[0..1].sum
# spare
elsif shot.sum == 10
next_shots.first.first
# normal
else
0
end
)
end

def symbols(score,sep)
return "X#{sep}" if score.first == 10
return "#{score[0]}#{sep}/" if score.sum == 10
return "#{score[0]}#{sep}#{score[1]}"
end

name, score, points = ARGV.first, ARGV[1..-1].join(" "), []
raise "Usage: 'ruby 181_bowling_score.rb [name] [scores]'" if name.nil? or
score.to_a.empty?

score = score.scan(/10|\d+\s*\d*/).collect{|e| e.split(" ").map!{|e|
e.to_i}}
score.each_with_index { |s,i| points = get_points(s,score[i+1..-1]) }

puts "#{name}'s final score: #{points[0..9].sum}";
puts "Frame\tRoll\tRoll\tScore\t"
score.each_with_index do |s,i|
puts "#{i+1}\t#{symbols(s,"\t")}\t#{(i<10) ? points[0..i].sum : ''}"
end


=== CODE END ===





Apologies for not having the Long Division quiz summary done yet. It
will come sometime today or tomorrow. Meanwhile, I have the next quiz
ready...

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

The three rules of Ruby Quiz 2:

1. Please do not post any solutions or spoiler discussion for this quiz
until 48 hours have passed from the time on this message.

2. Support Ruby Quiz 2 by submitting ideas as often as you can! (A
permanent, new website is in the works for Ruby Quiz 2. Until then,
please visit the temporary website at

<http://splatbang.com/rubyquiz/>.

3. Enjoy!

Suggestion: A [QUIZ] in the subject of emails about the problem helps
everyone on Ruby Talk follow the discussion. Please reply to the
original quiz message, if you can.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

## Bowling Scores (#181)


Whether it is real or on the Wii, bowling is a fun game. (Okay, for the
sake of the quiz, let's assume it's a fun game.) But I've known folks
who just don't understand [how to score properly][1]. They can count
pins knocked down, and know that getting all ten pins in one roll is
good, but they still can't keep score.

Your task this week is to tally scores for these people. The input will
be the player's name and the number of pins felled from each roll. For
example:

ruby bowling_scores.rb John 6 2 7 1 10 9 0 8 2 10 10 3 5 7 2 5 5 8

Your should tally the per-frame scores and generate output in table
form, such as:

John's final score: 140

Frame Roll Roll Score
1 6 2 8
2 7 1 16
3 X 35
4 9 - 44
5 8 / 64
6 X 87
7 X 105
8 3 5 113
9 7 2 122
10 5 / 140
* 8


Note that you should make use of typical bowling symbols: `X` for a
strike, `/` for a spare, and `-` for zero. Also, if extra balls were
thrown at the end (to supplement a strike or spare in the final frame),
list those as frame `*` like the above, but without a score.

Extra credit: Generate ascii or graphical output that looks more like
the traditional bowling score form, which can be seen on [this page][1].


[1]: http://www.bowling2u.com/trivia/game/scoring.asp

#!/usr/bin/env ruby
#Requires Ruby 1.8.7

class Fixnum
def to_bowl
return '-' if self==0
return 'X' if self==10
return self.to_s
end
end

class Array
def strike?
self[0]==10
end
def spare?
self[0]+self[1]==10
end
end

module Enumerable
#each cons is almost what I want, but it won't generate partial cons at
the end
def mycons n
result=[]
each_with_index do |f,i|
result << self[i,n]
end
result
end
end

ARGV.map!(&:to_i)
fail if ARGV.any?{|x| x>10}
frames=ARGV.mycons(3)
frames.delete_at(-1)

frames.each_with_index do |f,i|
frames[i+1]=nil if f and not f.strike?
end
frames.compact!
totals=frames.inject([]) do |h,frame|
last = h[-1] || 0
frame.delete_at(2) unless frame.spare? or frame.strike?
h+[last+frame.inject(&:+)]
end
printf "%8s%8s%8s%8s\n", "Frame", "Roll", "Roll", "Score"
frames.each_with_index do |f,i|
spare='/' if f[0]+f[1]==10
printf "%8s%8s%8s%8s\n", i+1, f[0].to_bowl, (spare or f[1].to_bowl unless
f.strike?), totals
if i==9 and f.spare?
printf "%8s%8s\n", '*', f[2].to_bowl
elsif i==9 and f.strike?
printf "%8s%8s%8s\n", '*', f[1].to_bowl, f[2].to_bowl
end
end

 
J

James Coglan

[Note: parts of this message were removed to make it a legal post.]
John's final score: 140

Frame Roll Roll Score
1 6 2 8
2 7 1 16
3 X 35
4 9 - 44
5 8 / 64
6 X 87
7 X 105
8 3 5 113
9 7 2 122
10 5 / 140
* 8


Quick and dirty solution. Should really be able to factor this into a single
loop but parts of it might end up getting messy.

http://gist.github.com/20087
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,023
Latest member
websitedesig25

Latest Threads

Top