|I'm not sure when it's appropriate to comment the code.|
Put a brief comment before each function saying what it does, what it's parameters are, and what the return value is. This doesn't have to be long. For example, for choose, you might say:
// Returns the number of ways to choose "column" items from "row" possibilities
Regarding the indentation style, if you ask 10 programmers how they indent their code, you'll get 15 answers. But consider this: the purpose of the braces is to guide the compiler, not the human. Humans read the indentation from the block structure and add whitespace where they think it's appropriate. I base my indentation style on this observation, modified slightly to take advantage of my editor's abilities to auto-indent.
|I was wondering where I can make improvements.|
The biggest improvement isn't in the style, but the functionality. At line 24, the intermediate results of factorial(row) / (factorial(column) * factorial(row-column)) will quickly overflow a computer's representation of integers. A calculation as simple as choose(15,3) will fail, even though the final result is just 455.
For unsigned values, it's best to compute choose(n,k) by alternating multiplication and division:
n * (n-1) / 2 * (n-2) / 3 * (n-3) / 4 ... * (n-k+1) / k
In addition to avoiding overflow, if you do it in this order, the divisions will always give an integer result, as long as the multiplications don't overflow. To see this, notice that in
n * (n-1)
, you multiply 2 consecutive numbers, which means that one of them must be even. So dividing by 2 in the next step results in an integer. Now when you multiple by n-2, you have 3 consecutive numbers in the numerator, so one must be divisible by 3. So the division by 3 in the next step also results in an integer.