Ruby将数字拆分为1或一半
我喜欢把分数分成n个位置的数组 假设我的分数是11,数组大小是12。 然后我想用一些数组来填充,例如11个1或10个1和2个半(0.5)。最后应该加起来是11 那么可能的分数是:Ruby将数字拆分为1或一半,ruby,Ruby,我喜欢把分数分成n个位置的数组 假设我的分数是11,数组大小是12。 然后我想用一些数组来填充,例如11个1或10个1和2个半(0.5)。最后应该加起来是11 那么可能的分数是: size=12 可能的分数=(0..size)。步骤(0.5)。到 我可以创建12个位置的数组: scores=Array.new(大小){0} 我可以从以下可能的值中选择一个随机值: [0,0.5,1]。示例 如果可能的话,我正在寻找一种有效的方法来检索随机数组,而不需要很多状态变量。我已经在while循环中尝
size=12
可能的分数=(0..size)。步骤(0.5)。到
我可以创建12个位置的数组:
scores=Array.new(大小){0}
我可以从以下可能的值中选择一个随机值:
[0,0.5,1]。示例
如果可能的话,我正在寻找一种有效的方法来检索随机数组,而不需要很多状态变量。我已经在while循环中尝试过这样做:
而分数<0
并使用随机值减少分数值,并跟踪设置的数组位置。但它变成了一段相当混乱的代码
有什么办法解决这个问题吗?谢谢
编辑:
对于这个例子,我想要一个总数为11的数组。那么你们中的任何一个
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.5, 0.5]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1]
或者不管是什么组合,总共11个。如果我明白了这一点,一个可能的选择是(暴力)
size=12
总和=11
tmp=Array.new(12){1}
环道
如果tmp.sum[0.5,0.5,1,1,1,1,1,1,1,1,1,1]
tmp.sum#=>11.0
Ruby提供了您所需的一切,无需编写任何算法代码。你的朋友在吗
[0, 0.5, 1].
repeated_combination(12). # 91 unique variant
to_a. # unfortunately it cannot be lazy
shuffle. # to randomize array outcome
detect { |a| a.sum == 11 }.
shuffle # to randomize numbers inside array
#⇒ [0.5, 0.5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
旁注:使用可以避免两次洗牌(生成的数组和生成的数组),但这会大大增加内存负载和执行时间。参数和变量 鉴于:
,所需总数,为tot
0.5的整数或奇数倍;及
,size
,0
和0.5
的总数是总的1
,要求tot
size>=tot
等于零的数目李>n0
等于n0pt5_对
的对数;及0.5
等于一个数n1
tot
是一个整数
我们要求:
0 <= n0pt5_pairs <= [tot, size-tot].min
因此,我们可以随机选择一个三元组[n0,2*n0pt5_对,n1]
,如下所示:
def random_combo(size, tot)
n0pt5_pairs = rand(1+[tot, size-tot].min)
[size-tot-n0pt5_pairs, 2*n0pt5_pairs, tot-n0pt5_pairs]
end
例如:
arr = random_combo(17, 11)
#=> [3, 6, 8]
这用于生成数组
arr1 = [*[0]*arr[0], *[0.5]*arr[1], *[1]*arr[2]]
#=> [0, 0, 0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1, 1, 1, 1, 1, 1, 1, 1]
我们洗牌:
arr1.shuffle
#=> [1, 0, 0.5, 1, 0.5, 0, 1, 1, 0, 1, 1, 1, 0.5, 0.5, 1, 0.5, 0.5]
注意arr1.size#=>17
和arr.sum#=>11
情况2:tot
是0.5的倍数
如果
如果n
是一个整数,则0
、0.5
和1
的每个组合将至少有一个0.5
。因此,我们可以计算0
和1
的数量,以及超过1的0.5
的数量。为此,我们只需将tot
减少0.5
(使其等于一个整数)并将size
减少1,使用generate\u for_integer
解决该问题,然后对于该方法返回的每个三元素数组,将0.5
的数量增加1
def generate(size, tot)
return nil if size.zero?
is_int = (tot == tot.floor)
tot = tot.floor
size -= 1 unless is_int
n0pt5_pairs = rand(1+[tot, size-tot].min)
[*[0]*(size-tot-n0pt5_pairs), *[0.5]*(2*n0pt5_pairs + (is_int ? 0 : 1)),
*[1]*(tot-n0pt5_pairs)].
shuffle
end
我喜欢Cary Swoveland的答案,但事实上,这可以在不产生一系列解决方案的情况下实现
让我们考虑几个例子。
给定size=6和score=3,在不进行混洗的情况下,这些是可能的输出(出于显而易见的原因,在左侧编号):i 1/2 0
0│ 1 1 1 0 0 0 3 0 3
1.│ 1 1 ½ ½ 0 0 2 2 2
2.│ 1 ½ ½ ½ ½ 0 1 4 1
3.│ ½ ½ ½ ½ ½ ½ 0 6 0
给定尺寸=6,分数=3.5:
i 1/2 0
0│ 1 1 1 ½ 0 0 3 1 2
1.│ 1 1 ½ ½ ½ 0 2 3 1
2.│ 1 ½ ½ ½ ½ ½ 1 5 0
给定尺寸=11,分数=4.5:
i 1/2 0
0│ 1 1 1 1 ½ 0 0 0 0 0 0 4 1 6
1.│ 1 1 1 ½ ½ ½ 0 0 0 0 0 3 3 5
2.│ 1 1 ½ ½ ½ ½ ½ 0 0 0 0 2 5 4
3.│ 1 ½ ½ ½ ½ ½ ½ ½ 0 0 0 1 7 3
4.│ ½ ½ ½ ½ ½ ½ ½ ½ ½ 0 0 0 9 2
给定尺寸=12,分数=11:
i 1/2 0
0│ 1 1 1 1 1 1 1 1 1 1 1 0 11 0 1
1.│ 1 1 1 1 1 1 1 1 1 1 ½ ½ 10 2 0
你能看到图案吗?在抓挠下巴之后,我们发现了以下事实:
[11,0,0,0]
)您是否试图使每个数字尽可能与其他数字相似?如果是这样的话,为什么不使用[11/4,11/4,11/4,11/4]
?我想要一个数组,它可以将这个[1,1,1,1,1,1,1,1,1,1,1]或[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.5]加起来。它只能有值0、0.5或1。我需要它来生成测试数据。如果我运行你的方法random_scores(12,11)
,它会抛出一个错误,并且它不会一直返回一个大小为12的数组,这与我想要的非常接近,但我有一些不会引发异常的东西。我想要一个生成随机数组的东西,我之前没有提到过。抱歉。也许在最后添加shuffle
。确实,shuffle可以做到这一点,谢谢。我有一个可行的解决方案,看看我的问题。我不知道它是否可以改进,但它确实有效。这正是我所追求的完美答案。两次洗牌都需要进行组合
arr1.shuffle
#=> [1, 0, 0.5, 1, 0.5, 0, 1, 1, 0, 1, 1, 1, 0.5, 0.5, 1, 0.5, 0.5]
tot = n + 0.5
def generate(size, tot)
return nil if size.zero?
is_int = (tot == tot.floor)
tot = tot.floor
size -= 1 unless is_int
n0pt5_pairs = rand(1+[tot, size-tot].min)
[*[0]*(size-tot-n0pt5_pairs), *[0.5]*(2*n0pt5_pairs + (is_int ? 0 : 1)),
*[1]*(tot-n0pt5_pairs)].
shuffle
end
ge = generate(17, 10)
#=> [0, 1, 0, 1, 0.5, 0.5, 0, 0.5, 0.5, 1, 1, 1, 1, 0.5, 0.5, 0.5, 0.5]
ge.size #=> 17
ge.sum #=> 10.0
go = generate(17, 10.5)
#=> [0.5, 0.5, 0.5, 1, 0, 0.5, 0.5, 1, 1, 0.5, 1, 1, 0.5, 1, 0.5, 0.5, 0]
go.size #=> 17
go.sum #=> 10.5