如何解决有没有一种方法可以将数组的元素与Ruby中的哈希键匹配?
我目前是一名学生。这是作业的问题之一:
过敏测试产生一个单一的数字分数,其中包含有关该人所有(已对其进行测试的)过敏的信息。被测试的项目列表(及其值)是:
- 鸡蛋(1)
- 花生(2)
- 贝类(4)
- 草莓(8)
- 西红柿(16)
- 巧克力(32)
- 花粉(64)
- 猫(128)
因此,如果汤姆对花生和巧克力过敏,他的得分为34。
编写一个程序,给定一个人的分数可以告诉他们: a)他们是否对特定物品过敏 b)过敏的完整清单。
现在我的代码是:
#A single numeric score is given,which is the sum of the combination of any item above
#When there is only ONE item,the score can be: 1,2,4,8,16,32,64 or 128
#when TWO items,the score can be: (1 + 2 =) 3,(1+ 4 =) 5,(1 + 8 =) 9,17,33,65,129...,192
#When THREE items: 7,11,19,35,67,131 ....,224
#....
#When EIGHT items : 255
#Does order matter in this case? No. use combination
#Choose a do/while loop,given the numbers the user must be allergic to something no matter what
allergens = {
"cats" => 1,"pollen" => 2,"chocolate" => 4,"tomatoes" => 8,"strawberries" => 16,"shellfish" => 32,"peanuts" => 64,"eggs" => 128,}
score = [1,64,128]
num_of_allergens = 1
puts "Please enter your given score: "
total_score = gets.chomp.to_i
loop do
a1 = score.combination(num_of_allergens).to_a
a2 = a1.map{|i| i.inject(:+)}
if a2.include? total_score
puts "You are allergic to: "
a3 = a2.find_index(total_score)
a4 = a1[a3]
puts a4.map{|alrg| allergens.key(alrg)}
break
end
if num_of_allergens > 255 || num_of_allergens < 1
puts "Please enter a valid number."
break
end
num_of_allergens += 1
end
我要驱动的是我想将a4与过敏原哈希匹配,以便最终以哈希形式打印出键值对以指定过敏原(num_of_allergens和total_score是固定的,现在是输入)。这可能吗?
P.S。鉴于hash(2 ^ 0,2 ^ 1 ....,2 ^ 7)值的特殊性,我的一位同学提出了使用如下所示的循环的想法:
if hash.each do |k,v|
if score % value != score
some_arr << (k,v)
update score
end
end
这应该是解决问题的最直接,最简洁的方法,但是仍然需要一些时间来解决问题。任何人都可以给我一些指示吗?谢谢!!
我编辑了帖子,并设法获得了密钥,但是现在还可以
解决方法
请注意,每种过敏原的得分是2的幂。 您可以利用它来计算偏移量以查找翠绿色:
allergens = %w[eggs peanutes shellfish strawberries tomatoes chocolate pollen cats]
score = 34 # peanuts and chocolate
puts "Your score is: #{score}"
digits = score.digits(2)
digits.each_with_index do |digit,index|
next if digit == 0
puts "You are allergic to #{allergens[index]}"
end
所以逐步:
%w[]
是创建字符串数组的简写
数组中每个变应原的索引(从0开始)可用于计算其得分:
score_of_allergene = 2 ** index_of_allergene
此人的分数可以转换为二进制表示形式,作为数字数组:
score.digits(2) # 2 => base 2 (binary) => [0,1,1]
现在每个1
的位置都对应于该人发生反应的过敏原,0
对应于该人未发生反应的过敏原。
因此,当我们循环所有标志时,可以使用0
跳过next if flag == 0
并打印其他所有内容。
您可以检查:
(1..allergens.size).each { |n| p (allergens.values.sum - allergens.values.reverse.first(n).sum) }
# 127
# 63
# 31
# 15
# 7
# 3
# 1
# 0
并且发现只要结果为正,您就可以按相反的顺序从分数中减去值:
total_score = 191
res = allergens.to_a.reverse.each_with_object([]) do |(k,v),res|
tmp = total_score - v
if tmp >= 0
total_score = tmp
res << k
end
end
res #=> ["eggs","shellfish","strawberries","tomatoes","chocolate","pollen","cats"]
检查结果:
res.sum { |k| allergens[k] }
#=> 191
,
假设发现萝拉对花粉和贝类过敏。她对花粉的过敏对她的过敏评分有2
:
score = allergens["pollen"]
#=> 2
让我们看一下代表整数2
的位:
nbits = score.bit_length
#=> 2
nbits.times.map { |i| score[i] }
#=> [0,1]
这是
0*(2**0) + 1*(2**1) #=> 2
请参见Integer#bit_length和Integer#[]。
现在让我们看看她的贝类评分,忘记了她的花粉过敏。
score = allergens["shellfish"]
#=> 32
nbits = score.bit_length
#=> 6
nbits.times.map { |i| score[i] }
#=> [0,1]
我们看到了
0*(2**0) + 0*(2**1) + 0*(2**2) + 0*(2**3) + 0*(2**4) + 1*(2**5)
#=> 32
因为已为每个过敏原分配了一个得分,该得分是2
的幂,所以得分的一位等于1
,而其余位等于0。具体来说,如果分数等于2**n
,则第n+1
个有效位将等于1
。
现在让我们计算Lola的总得分:
score = allergens["pollen"] + allergens["shellfish"]
#=> 34
nbits = score.bit_length
#=> 6
nbits.times.map { |i| score[i] }
#=> [0,1]
请注意,我们可以改写
score = allergens["pollen"] | allergens["shellfish"]
#=> 34
请参见Integer#|。
我们首先需要编写一种方法,确定给定一个人的总得分是否对某种过敏原过敏。
第一步,创建一个由常量保存的新哈希,该哈希将每个过敏原映射为2的幂,对应于代表总分中过敏原的位。
ALLERGEN_TO_BIT = allergens.transform_values do |n|
n.bit_length-1
end
#=> {"cats"=>0,"pollen"=>1,"chocolate"=>2,"tomatoes"=>3,# "strawberries"=>4,"shellfish"=>5,"peanuts"=>6,"eggs"=>7}
我们现在可以编写该方法。
def allergic_to?(score,allergen)
score[ALLERGEN_TO_BIT[allergen]] == 1
end
score = 34
allergic_to?(score,"pollen")
#=> true
allergic_to?(score,"shellfish")
#=> true
allergic_to?(score,"cats")
#=> false
现在转到第二项任务:给定总分,返回该人对之过敏的一系列过敏原。
def allergic_to(score)
ALLERGEN_TO_BIT.keys.select do |allergen|
score[ALLERGEN_TO_BIT[allergen]] == 1
end
end
allergic_to(34)
#=> ["pollen","shellfish"]
allergic_to(38)
#=> ["pollen","shellfish"]
allergic_to(73)
#=> ["cats","peanuts"]
请注意
ALLERGEN_TO_BIT.keys
#=> ["cats",# "shellfish","peanuts","eggs"]
假设我们要计算
allergic_to(10_000)
#=> ["strawberries"]
但是,这有误导性,因为10000
不是有效分数。最小和最大有效分数被视为介于0
和1+2+4+...+128
之间。请注意,这些限制之间的任何整数都是有效分数,因为它等于该范围内某些不同整数集合中两个的幂之和。
1+2+4+...+128
等于一个几何序列的和,等于 1 2*(128)-1
。
因此,我们可以构建一种方法来检查声称的分数确实有效。
def valid_score?(score)
score.between?(0,2*(2**ALLERGEN_TO_BIT.values.max)-1)
end
valid_score?(-1)
#=> false
valid_score?(0)
#=> true
valid_score?(38)
#=> true
valid_score?(255)
#=> true
valid_score?(256)
#=> false
1。我总是忘记几何级数的公式,但是我记得它是如何得出的:t = 1+2+4+...+128; 2*t = 2+4+...+128+2*(128); t = 2*t-t = 2*(128)-1
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。