DEV Community

Daily Challenge #153 - Horse Race Gamble

dev.to staff on January 03, 2020

Setup Your friend likes to go to the horse races and gamble on which horses will finish first, second, and third place. Unfortunately, h...
Collapse
 
nickholmesde profile image
Nick Holmes

The code (F#)

let WinnerCombinations n =
    if (n <= 3) then None
    else Some (n * (n-1) * (n-2))

As F# is a strongly typed language, no need to check n is an integer - it is. Idiomatically, "undefined" in F# is handled with the Option monad, so we return either None or Some result.

The actual calculation is trivial; n * (n-1) * (n-2)

Collapse
 
centanomics profile image
Cent • Edited

Good old factorials. I had fun with this one. Feel free to give advice if I can make my code better!

JS

CodePen

Edit: forgot to convert the input to a number making all of the numbers that go through the function a string


// grabs the input, the number of horses, from the input tag
const calculate = (horses = Number(document.querySelector("#horses").value)) => {

  //puts the answer into an empty div
  document.querySelector("#answer").innerHTML = 
    horses !== parseInt(horses) ? undefined :
    horses < 4 ? horses :
    factorial(horses)/factorial(horses - 3);
}

const factorial = (n) => {
  return n ? n * factorial(n - 1) : 1;
}

Collapse
 
robertobutti profile image
Roberto B.
function horse(n: any): number|void {
    if (n === parseInt(n, 10)) {
        if (n > 3) {
            return n * (n - 1) * (n - 2)
        } else {
            return n
        }

    } else {
        return undefined
    }
}

console.log(horse(15))
console.log(horse(12))
console.log(horse(2))
console.log(horse(11))
console.log(horse("a"))
Collapse
 
dangerontheranger profile image
Kermit Alexander II • Edited

The word "combinations" being used here provides us with a good jumping-off point to figure out the solution - combinatorics! We can calculate the n choose k/binomial coefficient for the horses, where n is the total number of horses, and k is equal to 3, since we're looking for 3 horses (gold, silver, and bronze winners). From there, we need to take into account that ordering - which horse won which position - matters to us; mathematical combinations are sets in which order doesn't normally matter. We'll need permutations for that part.

So, knowing that the number of permutations for a set of n elements is equal to n!, we can multiply the result of our n choose k by 6 (which is just a shorthand for multiplying by 3!, as 3! = 6). Putting that all together with a little bit of error checking, we have the following short Python solution:

#!/usr/bin/env python3
import math


def nchoosek(n, k):
    n_fac = math.factorial(n)
    denominator = math.factorial(k) * math.factorial(n - k)
    return n_fac / denominator


def horses(num_horses):
    try:
        # check for non-integer but still numerical input
        if int(num_horses) != num_horses:
            return None
    except ValueError:
        # check for non-numerical input
        return None
    if num_horses <= 3:
        return num_horses
    return int(nchoosek(num_horses, 3) * 6)


if __name__ == "__main__":
    print(horses(15))
    print(horses(4))
    print(horses(1))
    print(horses("whoops"))
    print(horses(4.5))

edit: forgot to add code to check for floating-point numbers as input, whoops

Collapse
 
rafaacioly profile image
Rafael Acioly

Nice solution, you could also use the itertools package:

docs.python.org/3/library/itertool...

dev.to/rafaacioly/comment/jkno

Collapse
 
strickolas profile image
Nicholas Saccente

Here's my submission while I'm learning Nim.

proc fac(n: int): int =
  if n <= 1: return 1
  result = n * fac(n - 1)

proc nPr(n: int, r: int): int =
  result = fac(n) div fac(n-r)

proc `%`(n: int, r: int): int =
  result = nPr(n, r)

proc horses(n: int): int =
  if n <= 3: return n
  result = n % 3

when isMainModule:
  echo horses(15)    #=> 2730
  echo horses(12)    #=> 1320
  echo horses(2)     #=> 2
  echo horses(11)    #=> 990
  # echo horses(a)   #=> compiler error

Collapse
 
bamartindev profile image
Brett Martin • Edited

Shortest answer I could think of:

const horses = n => { 
    if(Number.isInteger(n)) return n < 3 ? n : n * (n-1) * (n-2)
};

And in Standard ML, since it has type checking I can skip the int check:

fun horses(n: int) : int = if n < 3 then n else n * (n - 1) * (n - 2)
Collapse
 
rafaacioly profile image
Rafael Acioly

Python solution 🐍

from intertools import permutations

WINNERS_QUANTITY = 3


def winner_combination(horses_amount: int) -> int:
    if horses_amount <= WINNERS_QUANTITY:
        return horses_amount

    possibilities = list(permutations(
        range(horses_amount), WINNERS_QUANTITY
    ))
    return len(possibilities)

Collapse
 
savagepixie profile image
SavagePixie • Edited

My JavaScript solution:

const winCombos = n => !Number.isInteger(n)
    ? undefined
    : n < 4
    ? n
    : n * (n - 1) * (n - 2)
Collapse
 
rdandekarslb profile image
Rashmin Dandekar

Ruby

def horses(num)
  if !(num % 1 == 0) || !(num.is_a? Numeric)
    return "undefined"
  elsif num < 3
    return num
  else
    return num*(num-1)*(num-2)
  end
end

puts horses(12)
puts horses(2)
puts horses(11)
puts horses(2.5)
puts horses("a")


Collapse
 
nickholmesde profile image
Nick Holmes

Yes, I said that in my post.

However, I misread the challenge, and thought that "undefined" should be returned when n <= 3, although it should actually return the input.

Collapse
 
idanarye profile image
Idan Arye

If the number of horses is 3 or less, return the input value.

Shouldn't that be "less than 3"? Shouldn't horses(3) return 6?

Collapse
 
vaibhavyadav1998 profile image
Vaibhav Yadav • Edited

In Go.

func horses(num uint64) uint64 {
    if num <= 3 {
        return num
    }
    return num * (num - 1) * (num - 2)
}