Ruby odd behavior of Array.each - ruby

class Point
attr_accessor :x, :y
def initialize(x =0, y = 0)
#x = x
#y = y
end
def to_s
"x: #{#x}; y: #{#y}"
end
def move(x,y)
#x = #x + x
#y = #y + y
end
end
my_point= Point.new(4,6)
puts my_point
my_point.move(7,14)
puts my_point
puts
my_square = Array.new(4, Point.new)
a_square = []
my_square.each {|i| puts i}
puts
my_square.each do|i|
b = i
b.move(2,4)
a_square<< b
end
a_square.each {|i| puts i}
The result
x: 4; y: 6
x: 11; y: 20
x: 0; y: 0
x: 0; y: 0
x: 0; y: 0
x: 0; y: 0
x: 8; y: 16
x: 8; y: 16
x: 8; y: 16
x: 8; y: 16
when it should be
x: 4; y: 6
x: 11; y: 20
x: 0; y: 0
x: 0; y: 0
x: 0; y: 0
x: 0; y: 0
x:2; y: 4
x:2; y: 4
x:2; y: 4
x:2; y: 4

Array.new(4, Point.new) will create an array with the same object (in this case an instance of Point).
my_square = Array.new(4, Point.new)
p my_square.map(&:object_id).uniq.count
#=> 1
If you change to Array.new(4) { Point.new }, this will populate array with different objects.
my_square = Array.new(4) { Point.new }
p my_square.map(&:object_id).uniq.count
#=> 4
Check this for more info.

Related

How to flip the axis of a plot under ruby?

I wrote a ruby function to display the contents of a Daru dataframe df:
def plot_dataframe(df)
test = df.plot type: :line, x: :value, y: :depth
test.export_html(filename='test')
return
end
This outputs an html file named test.html.
How can I flip the y axis (ordinate) so that the depth starts at 0 and increases downwards?
I am looking for an equivalent to Python's invert_yaxis().
At #Serge de Gosson de Varennes' request, here is a MRE:
require 'json'
require 'daru'
require 'nyaplot'
df = Daru::DataFrame.new(
value: [1.2, 1.4, 1.1, 1.0, 1.0],
depth: [0, 1, 2, 3, 4]
)
test = df.plot type: :line, x: :value, y: :depth, y_reverse: true
test.export_html(filename='MRE')
This outputs:
You can do this in one of two ways:
def plot_dataframe(df)
test = df.plot type: :line, x: :value, y: :depth, y_reverse: true
test.export_html(filename='test')
return
end
or
def plot_dataframe(df)
test = df.plot type: :line, x: :value, y: :depth, y_axis_scale: :reverse
test.export_html(filename='test')
return
end

Error in my program!!!! There is no rendering queue for this operation

I'm creating a game with ruby and gosu, and I get an error:
C:/Ruby26-x64/destroy!/bullet.rb:14:in draw_rot': There is no rendering queue for this operation (RuntimeError)
from C:/Ruby26-x64/destroy!/bullet.rb:14:indraw'
from C:/Ruby26-x64/destroy!/player.rb:45:in fire'
from C:/Ruby26-x64/destroy!/destroy.rb:36:inupdate'
from C:/Ruby26-x64/lib/ruby/gems/2.6.0/gems/gosu-0.14.5-x64-mingw32/lib/gosu/patches.rb:72:in tick'
from C:/Ruby26-x64/lib/ruby/gems/2.6.0/gems/gosu-0.14.5-x64-mingw32/lib/gosu/patches.rb:72:intick'
from C:/Ruby26-x64/destroy!/destroy.rb:40:in `'
[Finished in 0.517s]
I've tried to change draw in the bullet class to draw_rot, but no avail.
My Classes
Destroy
require 'gosu'
require 'cmath'
require_relative 'player.rb'
require_relative 'enemy.rb'
require_relative 'bullet.rb'
class Destroy < Gosu::Window
def initialize
super(800, 600)
self.caption = 'Destroy!'
#player = Player.new(self)
#enemies = []
#enemies.push(Enemy.new(self))
end
def draw
#player.draw
#enemies.each do |enemy|
enemy.draw
end
end
def update
#player.righturn if button_down?(Gosu::KbRight)
#player.lefturn if button_down?(Gosu::KbLeft)
#player.startmove
#player.move if button_down?(Gosu::KbUp)
#freq = 0.0025
if rand < #freq
#enemies.push(Enemy.new(self))
end
#enemies.each do |enemy|
enemy.move
enemy.update(#player.x, #player.y)
end
if #freq < 0.5
#freq += 0.0002
end
#player.fire(self)
end
end
window = Destroy.new
window.show
Bullet
class Bullet
attr_accessor :x
attr_accessor :y
attr_accessor :fired
def initialize(window)
#image = Gosu::Image.new('C:\Ruby26-x64\destroy!\images\bullet.png')
#fired = 0
#x = 0
#y = 0
end
def draw(x, y)
#x = x
#y = y
#image.draw_rot(x, y, 1, 0)
#fired = 1
end
def update(angle)
#xspeed = Gosu.offset_x(angle, 2)
#yspeed = Gosu.offset_y(angle, 2)
if (#x > 800 || #x < 0 || #y > 600 || #y < 0)
#fired = 0
end
end
end
Player
require_relative 'bullet.rb'
require 'gosu'
class Player
attr_accessor :x
attr_accessor :y
def initialize(window)
#x = 200
#y = 200
#xspeed = 0
#yspeed = 0
#angle = 0
#image = Gosu::Image.new('C:/Ruby26-x64/destroy!/images/man.png')
end
def draw
#image.draw_rot(#x, #y, 1, #angle)
end
def righturn
#angle += 3
end
def lefturn
#angle -= 3
end
def startmove
#xspeed = Gosu.offset_x(#angle, 2)
#yspeed = Gosu.offset_y(#angle, 2)
end
def move
if #x > 767
#xpeed = 0
#x = 767
end
if #x < 33
#xpeed = 0
#x = 33
end
if #y > 567
#yspeed = 0
#y = 567
end
#x += #xspeed
#y += #yspeed
end
def fire(window)
#bullet = Bullet.new(window)
#bullet.draw(#x, #y)
while #bullet.fired = 1
#bullet.update(#angle)
end
end
end
Enemy
require 'cmath'
class Enemy
def initialize(window)
#flipped = 0
#x = rand(800 - 2 * 30) + 30
#y = rand(600 - 2 * 30) + 30
#firefreq = 1 / 60
#health = 5
#numkilled = 0
#dead = 0
#xspeed = 0
#yspeed = 0
#angle = 0
#image = Gosu::Image.new('C:/Ruby26-x64/destroy!/images/enemy.png')
#imageflipped = Gosu::Image.new('C:/Ruby26-x64/destroy!/images/enemyflip.png')
end
def gethit
#health -= 1
end
def die
#numkilled += 1
#dead = 1
end
def move
if rand < 0.1
#xspeed = rand(-3..3)
#yspeed = rand(-3..3)
end
if #x + #xspeed > 800
#x = 800
end
if #x + #xspeed < 0
#x = 0
end
if #y + #yspeed > 600
#y = 600
end
if #y + #yspeed < 0
#y = 0
end
if !(#y + #yspeed < 0 && #y + #yspeed > 600 && #x + #xspeed < 0 && #x + #xspeed > 800)
#y += #yspeed
#x += #xspeed
end
end
def draw
if #dead == 0
if #flipped == 1
#imageflipped.draw_rot(#x, #y, 1, #angle)
end
if #flipped == 0
#image.draw_rot(#x, #y, 1, #angle)
end
end
end
def update(xdist, ydist)
if #x < xdist
(#angle = CMath.atan((ydist - #y) / (xdist - #x)) * 180 / 3.14159265358979323846264338327950289)
#flipped = 0
end
if #x > xdist
(#angle = CMath.atan(-(ydist - #y) / (#x - xdist)) * 180 / 3.14159265358979323846264338327950289)
#flipped = 1
end
end
end
I do not get this at all.
Your Destroy#update method calls Player#fire which calls Bullet#draw which calls Gosu::Image#draw_rot. You can't call draw methods from within the main update method.
You will have to move your #bullet.draw method call out from Player#fire (which gets called during main update) and into Player#draw (which gets called during main draw)

having problems with Gosu tutorial, possibly not just a syntax error

I've been trying out the Gosu tutorial so I can learn to make games. I'm getting errors with my code. Could someone point out to me what I'm doing wrong? Here's the tutorial link:
https://github.com/jlnr/gosu/wiki/Ruby-Tutorial
here's my code:
require 'Gosu'
class GameWindow < Gosu::Window
def initialize
super 640, 480, false
self.caption = "Gosu Tutorial Game"
#background_image = Gosu::Image.new(self, "Usable Images/final_fantasy_background.png", true)
#player = Player.new(self)
#player.warp(320, 240)
#Star_anim = Gosu::Image::load_tiles(self, "Usable Images/donut.png", 25, 25, false)
#Star = Array.new
end
def update
if button_down? Gosu::KbLeft or button_down? Gosu::GpLeft then
#player.turn_left
end
if button_down? Gosu::KbRight or button_down? Gosu::GpRight then
#player.turn_left
end
if button_down? Gosu::KbUp or button_down? Gosu::GpButton0 then
#player.accelerate
end
#player.move
#player.collect_stars(#stars)
if rand(100) < 4 and #Star.size < 25 then
#Star.push(Star.new(#Star_anim))
end
end
def draw
#background_image.draw(0,0,ZOrder::Background)
#player.draw
stars = Star.new()
#stars.each{ |star| star.draw}
end
def button_down(id)
if id == Gosu::KbEscape
close
end
end
end
class Player
def initialize(window)
#image = Gosu::Image.new(window, "Usable Images/eric_cartman.png", false)
#x = #y = #vel_x = #vel_y = #angle = 0.0
#score = 0
end
def warp(x, y)
#x, #y = x, y
end
def turn_left
#angle -= 4.5
end
def turn_right
#angle += 4.5
end
def accelerate
#vel_x += Gosu::offset_x(#angle, 0.5)
#vel_y += Gosu::offset_x(#angle, 0.5)
end
def move
#x += #vel_x
#y += #vel_y
#x %= 640
#y %= 480
#vel_x *= 0.95
#vel_y *= 0.95
end
def draw
#image.draw_rot(#x, #y, 1, #angle)
end
def score
#score
end
def collect_Star(star)
if Star.reject! {|star| Gosu::distance(#x, #y, Star.x, star.y) < 35} then
#score += 1
end
end
end
module ZOrder
Background, Star, Player, UI = *0..3
end
class Star
attr_reader :x, :y
def initialize(animation)
#animation = animation
#color = Gosu::Color.new(0xff000000)
#color.red = rand(256 - 40) + 40
#color.green = rand(256 - 40) + 40
#color.blue = rand(256 - 40) + 40
#x = rand * 640
#y = rand * 480
end
def draw
img = #animation[Gosu::milliseconds / 100 % #animation.size];
img.draw(#x - image.width / 2.0, #y - img.height / 2.0, ZOrder::Star, 1, 1, #color, :add)
end
end
window = GameWindow.new
window.show
You have Star.new(), but you define it as initialize(animation) (with one mandatory argument).

I need advice on how to do collision in a clone of Pong

Hi I am building a clone pong program with ruby and rubygame. My ain problem at the moment is the collision of the leftside. The collision happends backwards. The right works perfectly fine. I need help. Can anyone fix this?
Heres my code
require 'rubygems'
require 'rubygame'
Rubygame::TTF.setup
class Game
def initialize
#screen = Rubygame::Screen.new [640,480], 0,
[Rubygame::HWSURFACE, Rubygame::DOUBLEBUF]
#screen.title = "Pong"
#queue = Rubygame::EventQueue.new
#clock = Rubygame::Clock.new
#clock.target_framerate = 60
limit = #screen.height - 10
#player = Paddle.new 50, 10, Rubygame::K_W, Rubygame::K_S, 10, limit
#enemy = Paddle.new #screen.width-50-#player.width, 10,
Rubygame::K_UP, Rubygame::K_DOWN, 10, limit
#player.center_y #screen.height
#enemy.center_y #screen.height
#ball = Ball.new #screen.width/2, #screen.height/2
#background = Background.new #screen.width, #screen.height
end
def run!
loop do
update
draw
#clock.tick
end
end
def update
#player.update
#enemy.update
#ball.update #screen
#queue.each do |ev|
#player.handle_event ev
#enemy.handle_event ev
case ev
when Rubygame::QuitEvent
Rubygame.quit
exit
when Rubygame::KeyDownEvent
if ev.key==Rubygame::K_ESCAPE
#queue.push Rubygame::QuitEvent.new
end
end
end
if collision? #ball, #player
#ball.collision #player, #ball
elsif collision? #ball, #enemy
#ball.collision #enemy, #ball
end
end
def draw
#screen.fill [0,0,0]
#background.draw #screen
#player.draw #screen
#enemy.draw #screen
#ball.draw #screen
#screen.flip
end
def collision? obj1, obj2
if obj1.y + obj1.height < obj2.y ; return false ; end
if obj1.y > obj2.y + obj2.height ; return false ; end
if obj1.x + obj1.width < obj2.x ; return false ; end
if obj1.x > obj2.x + obj2.width ; return false ; end
return true
end
end
class GameObject
attr_accessor :x, :y, :width, :height, :surface
def initialize x, y, surface
#x = x
#y = y
#surface = surface
#width = surface.width
#height = surface.height
end
def update
end
def draw screen
#surface.blit screen, [#x, #y]
end
def handle_event event
end
end
class Paddle < GameObject
def initialize x,y,up_key,down_key,top_limit,bottom_limit
surface = Rubygame::Surface.new [20, 100]
surface.fill [255, 255, 255]
#up_key = up_key
#down_key = down_key
#moving_up = false
#moving_down = false
#top_limit = top_limit
#bottom_limit = bottom_limit
super x, y, surface
end
def center_y h
#y = h/2-#height/2
end
def handle_event event
case event
when Rubygame::KeyDownEvent
if event.key==#up_key
#moving_up = true
elsif event.key==#down_key
#moving_down = true
end
when Rubygame::KeyUpEvent
if event.key==#up_key
#moving_up = false
elsif event.key==#down_key
#moving_down = false
end
end
end
def update
if #moving_up and #y > #top_limit
#y -= 5
end
if #moving_down and #y+#height < #bottom_limit
#y += 5
end
end
end
class Background < GameObject
def initialize width, height
surface = Rubygame::Surface.new [width, height]
# Draw Background
white = [255, 255, 255]
#Top
surface.draw_box_s [0, 0], [surface.width, 10], white
#Left
surface.draw_box_s [0, 0], [10, surface.height], white
#Bottom
surface.draw_box_s [0, surface.height-10, 10],
[surface.width, surface.height], white
#Right
surface.draw_box_s [surface.width-10, 0],
[surface.width, surface.height], white
#Middle Divide
surface.draw_box_s [surface.width/2-5, 0],
[surface.width/2+5, surface.height], white
super 0, 0, surface
end
end
class Ball < GameObject
def initialize x, y
surface = Rubygame::Surface.load('Ball.png')
#vx = #vy = 5
super x, y, surface
end
def update screen
#x += #vx
#y += #vy
if #x <= 10 or #x+#width >= screen.width-10
#vx *= -1
end
if #y <= 10 or #y+#height >= screen.height-10
#vy *= -1
end
end
def collision paddle, screen
if paddle.x < screen.width/2
unless #x < paddle.x-5
#x = paddle.x+paddle.width+1
#vx *= -1
end
else
unless #x > paddle.x+5
#x = paddle.x-#width-1
#vx *= -1
end
end
end
end
class Text < GameObject
def initialize x=0, y=0, text="Hello, World!", size=40
#font = Rubygame::TTF.new "font.ttf", size
#text = textssssw
super x, y, #font.render(#text, true, [255,255,255])
end
end
g = Game.new
g.run! `

Ruby Koans Scoring Project

I'm working through the Ruby Koans, and I'm having a bit of trouble figuring out what is going wrong with a method I've written. I'm in about_scoring_project.rb, and I've written the score method for the dice game:
def score(dice)
return 0 if dice == []
sum = 0
rolls = dice.inject(Hash.new(0)) { |result, element| result[element] += 1; result; }
rolls.each { |key, value|
# special condition for rolls of 1
if key == 1
sum += 1000 | value -= 3 if value >= 3
sum += 100*value
next
end
sum += 100*key | value -= 3 if value >= 3
sum += 50*value if key == 5 && value > 0
}
return sum
end
For those unfamiliar with the exercise:
Greed is a dice game where you roll up to five dice to accumulate
points. The following "score" function will be used to calculate the
score of a single roll of the dice.
A greed roll is scored as follows:
A set of three ones is 1000 points
A set of three numbers (other than ones) is worth 100 times the number. (e.g. three fives is 500 points).
A one (that is not part of a set of three) is worth 100 points.
A five (that is not part of a set of three) is worth 50 points.
Everything else is worth 0 points.
Examples:
score([1,1,1,5,1]) => 1150 points score([2,3,4,6,2]) => 0 points
score([3,4,5,3,3]) => 350 points score([1,5,1,2,4]) => 250 points
More scoring examples are given in the tests below:
Your goal is to write the score method.
I run into trouble when I try to run the last test in the file: assert_equal 550, score([5,5,5,5])
For some reason I am returning 551 instead of 550. Thanks for your help!
Here is my approach:
def score(dice)
# Count how many what
clusters = dice.reduce(Hash.new(0)) {|hash, num| hash[num] += 1; hash }
# Since 1's are special, handle them first
ones = clusters.delete(1) || 0
score = ones % 3 * 100 + ones / 3 * 1000
# Then singular 5's
score += clusters[5] % 3 * 50
# Then the triples other than triple-one
clusters.reduce(score) {|s, (num, count)| s + count / 3 * num * 100 }
end
My approach uses two lookup tables - one containing the scores for triples, the other for singles. I work out the score for each number using the tables, and accumulate the total using inject:
def score(dice)
triple_scores = [1000, 200, 300, 400, 500, 600]
single_scores = [100, 0, 0, 0, 50, 0]
(1..6).inject(0) do |score, number|
count = dice.count(number)
score += triple_scores[number - 1] * (count / 3)
score += single_scores[number - 1] * (count % 3)
end
end
I went with
def score(dice)
dice.uniq.map do |die|
count = dice.count die
if count > 2
count -= 3
die == 1 ? 1000 : 100 * die
else 0
end + case die
when 1 then count * 100
when 5 then count * 50
else 0
end
end.inject(:+) || 0
end
This is because you're really adding the result of a | operator (Bitwise OR) to the total score:
sum += 100*key | value -= 3 if value >= 3 # This is 501 in your case
Proof:
irb(main):004:0> value = 4
=> 4
irb(main):005:0> 100 * 5 | value -= 3 # This should be read as (500) | 1 which is 501
=> 501
So rewrite it like this:
if value >= 3
sum += 100 * key
value -= 3
end
My approach was:
def score(dice)
calculator = ->(no, group_multipler, individual_multipler) { (no / 3 * group_multipler) + (no % 3 * individual_multipler) }
dice.group_by {|i| i % 7 }.inject(0) do |total, (value, scores)|
group_multipler, individual_multipler = case value
when 1
[1000, 100]
when 5
[500, 50]
else
[value * 100, 0]
end
total += calculator.call(scores.size, group_multipler, individual_multipler)
end
end
My approach:
def score(dice)
score = 0
score += dice.count(1) >= 3? (1000+ (dice.count(1) -3)*100): dice.count(1) * 100
score += dice.count(5) >= 3 ? (500 + (dice.count(5) -3)*50): dice.count(5) * 50
[2,3,4,6].each {|x| dice.count(x) >=3? score+= x*100:0}
return score
end
Here's my answer:
def score(dice)
frequency = dice.inject(Hash.new(0)) do |h, el|
h[el] += 1
h
end
score_triples = { 1 => 1000 }
score_singles = { 1 => 100, 5 => 50 }
score = 0
frequency.each do |k, v|
score += v / 3 * score_triples.fetch(k, 100 * k)
score += v % 3 * score_singles.fetch(k, 0)
end
score
end
My approach used integer division and modulus division:
def score(dice)
points = 1000 * (dice.count(1) / 3)
points += 100 * (dice.count(1) % 3)
points += 50 * (dice.count(5) % 3)
(2..6).each do |i|
points += (100 * i) * (dice.count(i) / 3)
end
points
end
This was the first piece of code I ever wrote by myself (With a ton of help of stackoverflow, of course.) After watching all other answers I realize it is way overkill specially because it works for a 9 numbers dice (does that exist?)
def score(dice)
if dice.empty?
return 0
end
var_score = 0
conteo = (0..9).to_a.each.map { |x| dice.count(x)}
#Evaluating 1
if ( conteo[1] / 3 ) >= 0
multiplier1 = conteo[1]/3
var_score += multiplier1 * 1000
end
if ( conteo[1] % 3 ) != 0
var_score += (conteo[1] % 3)*100
end
#Evaluating 5
if ( conteo[5] % 3 ) != 0
var_score += (conteo[5] % 3)* 50
end
#Evaluating numbers x 3
if (conteo[2..9].count { |x| x >= 3 }) > 0
triplets = conteo[2..9].map {|x| x / 3}
array_multiplicator = triplets.each_with_index.select {|num,index| (num > 0)}.map {|x| x[0]}
product_triplets = triplets.each_with_index.select {|num,index| (num > 0)}.map {|x| x[1]}.map {|x| (x+2)*100}
var_score += array_multiplicator.zip(product_triplets).map{|x| x.inject(&:*)}.sum
end
var_score
end
It took 29 lines, but this is my first Ruby
def score(dice)
return 0 if dice == []
sums = Array.new # To hold number of occurrences 1 - 6
for i in 0..6 # Initialize to 0... note [0] is not used
sums[i] = 0
end
total = 0 # To hold total
dice.each do |dots| # Number of dots showing on dice
sums[dots] += 1 # Increment the array members 1 - 6
end
if sums[1] > 2 then # If 3 1's
total += 1000
sums[1] -= 3 # Remove the 3 you took, in case there's more
end
if sums[2] > 2 then total += 200 # If 3 2's
end
if sums[3] > 2 then total += 300 #If 3 3's
end
if sums[4] > 2 then total += 400 #If 3 4's
end
if sums[5] > 2 then total += 500 #If 3 5's
sums[5] -= 3 #Remove the 5's you took
end
if sums[6] > 2 then total += 600 #If 3 6's
end
total += (sums[1] * 100) # If any ones are left
total += (sums[5] * 50) # Same for fives
return total
end
This is my solutions.
def score(dice)
score = 0
# grab all the numbers and their amounts
number_amounts = dice.reduce(Hash.new(0)) { |hash, numb| hash[numb] += 1; hash }
# iterate through each pair
number_amounts.each do |key, value|
# case with number 1
score += (value % 3) * 100 + value / 3 * 1000 if (key == 1)
# case with number 5
score += (value % 3) * 50 + value / 3 * key * 100 if (key == 5)
# all numbers except 1 and 5
score += (value / 3) * key * 100 if (key != 1 && key != 5)
end
score
end
def score(dice)
# Set up rules Hash
rules = { 1 => {:triples => 1000, :singles => 100}, 5 => {:triples => 100, :singles => 50} }
[2,3,4,6].each {|i| rules[i] = {:triples => 100, :singles => 0} }
# Count all ocourencies
counts = dice.each_with_object(Hash.new(0)) {|e, h| h[e] += 1}
#calculate total
total = 0
counts.each_pair{ | key, value |
total += value >= 3? (rules[key][:triples]*key + (value -3)*rules[key][:singles]): value * rules[key][:singles]
}
return total
end
I used the new ruby enumerable method tally
def score(dice)
return 0 if dice.empty?
ans = dice.tally.map do |k,v|
case k
when 1
three = (k * 1000) * (v/3)
val = (v%3) * 100
val + three
when 5
three = (k * 100) * (v/3)
val = (v%3) * 50
val + three
else
(k * 100) * (v/3)
end
end
ans.reduce(0, :+)
end
My attempt, feedback and refactoring suggestions most welcome:
def score(dice)
score = 0
score_array = [[0, 100, 200, 1000, 1100, 1200], [0, 0, 0, 200, 200, 200], [0, 0, 0, 300, 300, 300], [0, 0, 0, 400, 400, 400], [0, 50, 100, 500, 550, 600], [0, 0, 0, 600, 600, 600]]
tally_hash = {1=>0, 2=>0, 3=>0, 4=>0, 5=>0, 6=>0}
dice.sort.tally.each do |key, value|
tally_hash[key] += value
end
tally_hash.each do |key, value|
score += score_array[key -1][value]
end
return score
end
I used hash for score
def score(dice)
score_map = {
1 => 100,
5 => 50
}
cluster = dice.inject(Hash.new(0)) {|hash, num| hash[num] += 1; hash}
cluster.inject(0) do |sum, (num, count)|
set_count = count / 3
sum += num == 1 ? 1000 * set_count : num * 100 * set_count
sum + (score_map[num] || 0) * (count % 3)
end
end
def score(dice)
score = 0
dice.uniq.each do |number|
count = dice.count number
weight = if number == 1 then 10 else number end
if count >= 3
score += weight * 100
count -= 3
end
if count > 0 and number == 1 or number == 5
score += count * weight * 10
end
end
score
end
def score(dice)
ones = fives = rest = 0
one_count = dice.count(1)
if one_count > 2
ones = 1000
one_count -= 3
end
ones += one_count * 100
five_count = dice.count(5)
if five_count > 2
fives = 500
five_count -= 3
end
fives += five_count * 50
[2,3,4,6].each do |num|
if dice.count(num) > 2
rest += num * 100
end
end
return ones + fives + rest
end

Resources