卖酒的算法题解

栏目: Ruby · 发布时间: 5年前

内容简介:基友发来一道算法题:大概的意思就是:一共有六桶酒,白酒数量为5,上午卖了2,下午还剩3。因此下午三桶的升数之和应该是上午的两倍:

基友发来一道算法题:

卖酒的算法题解

大概的意思就是:一共有六桶酒,白酒数量为5,上午卖了2,下午还剩3。因此下午三桶的升数之和应该是上午的两倍:

  • afternoon = morning * 2

找到这样的关系以后,那么最后剩下那桶就是红酒了。大概想了下,一个比较直接的思路就是,可以把它当成是一个排列组合的任务:上午卖两桶,就是从5个元素里面任意取两个元素;下午卖三桶,就是在剩下的四桶里面任意取3。然后在这样的排列组合当中,找到下午的数字之和是上午的二分之一的组合,然后最后剩下的那个元素就是红酒了。这个任务可以用 ruby 代码来做做看。 rubyarraypermutation 的能力,我们可以用用看:

卖酒的算法题解

可以看到 permutation 把数组里元素所有可能的顺序组合都列出来了。这个 permutation 方法还支持定制选取元素的数量进行排列:

irb(main):005:0> arr.permutation(2).to_a
=> [[1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2]]

有了这个方法,我们就可以列出所有酒桶的排列方式了。首先是定义酒桶的数组:

irb(main):006:0> buckets = [30, 32, 36, 38, 40, 62]
=> [30, 32, 36, 38, 40, 62]

然后是取其中两个元素,列出所有的可能性,相当于上午取两桶酒的所有可能:

卖酒的算法题解

上面这个排列组合里面,数组的元素是有顺序的,因为是 permutation ,而不是 combinationruby 除了『排列』,也提供了『组合』的功能。下面是 combination(...) 方法:

irb(main):012:0> buckets.combination(2).to_a
=> [[30, 32], [30, 36], [30, 38], [30, 40], [30, 62], [32, 36], [32, 38], [32, 40], [32, 62], [36, 38], [36, 40], [36, 62], [38, 40], [38, 62], [40, 62]]

从上面的结果可以看到顺序不同,元素一样的数组不存在了,只剩下元素不同的数组。上面这个数组代表了『上午卖出的两桶酒』的所有可能。因此,我们针对每一个可能,刨去上面的元素,再从剩下的4个元素里面取3,并列出所有的组合。从一个数组中刨去某些元素的代码如下:

卖酒的算法题解

可以看到,使用减号就可以了,剩下的元素是刨去了上午售出的酒。此时在这个数组当中再用 combination(...) 方法,取出三个元素,列出所有组合。然后把三个元素的值相加,如果是上午的两个元素相加的值的两倍,那么剩下的那个元素就是最后剩下的红酒了。因此,两个 for 循环就可以完成上面所讲的逻辑了。完整的代码如下:

buckets = [30, 32, 36, 38, 40, 62]
sold_at_morning = buckets.combination(2).to_a

arr = []
for x in sold_at_morning
  left = buckets - x
  sold_at_afternoon = left.combination(3).to_a
  sum_morning = x.inject(0) { |sum, _x| sum + _x }
  for y in sold_at_afternoon
    sum_afternoon = y.inject(0) { |sum, _y| sum + _y }
    if sum_afternoon.to_f / sum_morning == 2
      puts "morning: #{x} / afternoon: #{y} / red wine: #{buckets - x - y}"
      exit
    end
  end
end

上面的代码就是前面讲的思路的实现,具体用到的一些之前没讲到的技巧包括:

sum_morning = x.inject(0) { |sum, _x| sum + _x }

上面这个block会计算数组的元素之和。

sum_afternoon.to_f / sum_morning == 2

上面的 to_f ,把 sum_afternoon 的数值类型从 int 转化成 float ,这样保证我们计算所得是被整除的。因为两个 int 型数据相除是会取整的,这样结果为 2 的时候不一定是被整除为 2 。运行上面的代码,结果如下:

morning: [30, 36] / afternoon: [32, 38, 62] / red wine: [40]

得到结果是红酒为 40 升的这桶,并给出了上午和下午卖出酒桶的升数。以上是对解题思路的一个记录。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

司法的过程

司法的过程

(美)亨利·J.亚伯拉罕 / 泮伟江 宦盛奎 韩阳 / 北京大学出版社 / 2009-07-28 / 58.00元

本书是以比较研究的方法来分析司法哲学的经典文本之一。作者以敏锐的眼光透视了司法过程背后的理论、实践和参与其中的人。比较了美国、英国、法国的具体法院运作,审视了“司法能动主义”和“司法克制主义”之间的争辩。本书第七版的介绍吸收了美国、英国、法国和欧洲法院体系运作中的最新和重要的发展。 目前国内非常关注司法的运作过程、法官的裁判过程,此书的翻译对于这方面的研究很有助益,对于英国和法国法院的介绍填补了国......一起来看看 《司法的过程》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器