背景 (Background)
When I learned to code, I hadn’t slept in a math classroom in 14 years.
当我学会编码的时候,我已经有14年没睡在数学教室了。
I studied philosophy and taught courses on Symbolic Logic. I can talk about deductive proofs for days, but when people pull out a f of n’s… x²… [insert Greek letter] — I nod along, but trust me, I have no idea what’s happening.
我学习了哲学,并教授了符号逻辑课程。 我可以谈论几天的演绎证明,但是当人们拿出n的 f … x²… [插入希腊字母]时—我一直点头,但请相信我,我不知道发生了什么事。
For this reason, I got a huge boost of empowerment when I figured out an algorithm question asking, “How can you determine the mathematical combination (nCr) of two numbers?”
出于这个原因,当我想到一个算法问题:“如何确定两个数字的数学组合(nCr)?”时,我的能力得到了极大的提升。
If you’re like ‘what the…?’, then hell yeah, you are me a day ago. Let’s go!
如果您想说“什么……?”,那么,是的,您是我前一天。 我们走吧!
这肉 (The Meat)
Defining the Problem
定义问题
I’ll try my best to explain a combination:
我会尽力解释一个组合 :
Imagine you’re losing a high stakes poker game. You have sweat on your neck as a couple Mafia grunts stare daggers at you. As the big one cracks his knuckles, you think “It’s a shame I never learned to count cards. But maybe start now?”
想象一下,您正在输掉高额桌扑克游戏。 一对黑手党的咕star声凝视着匕首,您的脖子上流汗了。 当大个子打断他的指关节时,您会认为“这是我从未学过数数卡的可耻之处。 但是也许现在开始?”
Your mind is racing. You start thinking, how do I start? How many possible hands are there in the deck? Well, there are 52 cards. You get 5 distinct cards in each hand, and they can come in any order. Let’s see, some quick math in your head and…
你的想法在加速。 您开始思考,我该如何开始? 甲板上有几只手? 好,有52张卡片。 您每手有5张不同的卡,它们可以按任何顺序排列。 让我们来看看,您的脑子里有了一些快速数学运算……
Yeah, the answer is not obvious. But, you’re attempting a combination. A combination is when you have a collection of items and you want to find all the possible selections from that collection — for example, every possible hand from a deck of cards.
是的,答案并不明显。 但是,您正在尝试组合。 组合是指您拥有一个项目集合,并且想要从该集合中找到所有可能的选择-例如,一副纸牌中的每只可能的手。
By the way, the answer is 2,598,960. Each hand has a 1/2,598,960th chance of being drawn. With numbers that big, it’s good we can train a computer to solve the problem.
顺便说一句,答案是2,598,960。 每只手都有1 / 2,598,960的被抽中机会。 有了这么大的数字,我们可以训练一台计算机来解决问题,这是很好的。
Solution
解
The mathematical formula for finding a combination between two terms looks like this:
查找两个术语之间的组合的数学公式如下所示:
The Ruby version looks like this:
Ruby版本如下所示:
Explanation
说明
Okay, let’s break this down. The math works like this:
好吧,让我们分解一下。 数学原理如下:
On top, we have
n!
. First, we find the factorial of our collection.最重要的是,我们有
n!
。 首先,我们找到集合的阶乘。Next, we subtract our selection from the collection and find the factorial of that or
(n — r)!
.接下来,我们从集合中减去我们的选择,然后找到那个或
(n — r)!
的阶乘(n — r)!
。Find the factorial of our selection
r!
and multiply by the result of step 2.找到我们选择的阶乘
r!
并乘以步骤2的结果。Finally, divide step 1 —
n!
— by the result of step 3 —r!(n-r)!
.最后,划分步骤1-
n!
-通过第3步的结果r!(nr)!
。
Let’s translate this to Ruby
让我们将其翻译成Ruby
Ruby does not have a method for finding a factorial so we have to write one. I found a couple of nice one-liners here and here.
def factorial(num)
(1..num).inject(1) { |prod, i| prod * i }
end
A factorial is the product of an integer and all the integers below it. So, if we wanted to know the factorial of 3 or3!
, we calculate 1 * 2 * 3
and get 6
.
阶乘是整数和其下所有整数的乘积。 因此,如果我们想知道3或3!
的阶乘3!
,我们计算出1 * 2 * 3
并得到6
。
Abstracting this with Ruby, inject
will be a useful method. inject
among other things, can take an array of numbers and apply a block reducing them to a single number. (That’s why inject
is aliased as reduce
).
使用Ruby对此进行抽象, inject
将是一种有用的方法。 除其他外, inject
可以采用数字数组并应用一个将其减少为单个数字的块。 (这就是为什么inject
被别名为reduce
的原因)。
In this case, our array is the range of numbers from 1 to our target. We iterate through the array multiplying each number to a parameter initially set to 1, and return the result.
在这种情况下,我们的数组是从1到目标的数字范围。 我们遍历数组,将每个数字乘以一个初始设置为1的参数,然后返回结果。
2. With our factorial method written, we can find the combination in one line.
2.通过编写阶乘方法,我们可以在一行中找到组合。
def get_combination(num1, num2)
factorial(num1) / (factorial(num2) * factorial(num1 - num2))
end
Here we are simply following the mathematical steps outlined earlier. We find the factorial of our collection, and divide it by the factorial of our set multiplied by the result of a factorial of the result of our collection minus our set. Got it?
在这里,我们仅遵循前面概述的数学步骤。 我们找到集合的阶乘,然后将其除以集合的阶乘乘以集合结果减去我们的集合的阶乘的结果。 得到它了?
Thanks for reading. Hope this helps someone!
谢谢阅读。 希望这对某人有帮助!
翻译自: https://medium.com/weekly-webtips/algorithms-calculating-combination-with-ruby-2784f6ddce4