Skip to content

Commit

Permalink
Add Fabergé Easter Eggs crush test
Browse files Browse the repository at this point in the history
Kata: 54cb771c9b30e8b5250011d4
  • Loading branch information
sierikov committed Feb 12, 2024
1 parent 8423b42 commit 9bfcdd5
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 5 deletions.
1 change: 1 addition & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Stores my solutions to kata problems listed on [Codewars](https://www.codewars.c
[Texas Hold'em Hands](https://www.codewars.com/kata/524c74f855025e2495000262),
[Millionth Fibonacci Kata](https://www.codewars.com/kata/53d40c1e2f13e331fc000c26),
[Alphabetic Anagrams](https://www.codewars.com/kata/53e57dada0cb0400ba000688),
[Fabergé Easter Eggs crush test](https://www.codewars.com/kata/54cb771c9b30e8b5250011d4),

### 4 kuy

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ object SymbolicDifferentiationPrefixExpressions {
case (_, Value(1)) => l.simplify
case _ => Pow(l.simplify, r.simplify)
}

override def diff: Expr = (l, r) match {
// (^ (sin x) 3) -> (* 3 (^ (sin x) 2) (cos x))
case (l, Value(rv)) => Mul(Mul(Value(rv), Pow(l.simplify, Value(rv - 1))), l.simplify.diff)
Expand Down
41 changes: 41 additions & 0 deletions src/main/scala/sierikov/codewars/kyu3/FabergeEasterEgg.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package sierikov.codewars.kyu3

import java.math.BigInteger
import java.math.BigInteger.{ONE, ZERO}

object FabergeEasterEgg {

/**
* Use binomial coefficient to calculate the number of ways to distribute the tries among the eggs.
* The number of ways to distribute the tries among the eggs is the sum of the binomial coefficients.
* Applied dynamic programming to pass the performance tests.
* @note Using BigIntegers due kata requirements.
* @note Using cumulative sum of coefficient to avoid recalculating the same values.
* @see [[https://en.wikipedia.org/wiki/Binomial_coefficient]]
*/
def height(eggs: BigInteger, tries: BigInteger): BigInteger = {
if (eggs == ZERO || tries == ZERO) return ZERO

/**
* Having more eggs than tries doesn't provide any additional advantage.
* The limiting factor in determining the maximum height is the number of tries, not the number of eggs.
*/
val numberOfEggs = if (eggs.compareTo(tries) > 0) BigInt(tries) else BigInt(eggs)

var currentEgg = ONE
var remainingFloors = ONE
var result = ZERO

while (currentEgg.compareTo(numberOfEggs) <= 0) {
val remainTries = tries.add(ONE).subtract(currentEgg)
val newFloors =
remainingFloors.multiply(remainTries).divide(currentEgg) // evenly distribute the tries among the eggs

remainingFloors = newFloors
currentEgg = currentEgg.add(ONE)
result = result.add(newFloors)
}

result
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ class SymbolicDifferentiationPrefixExpressionSpec extends AnyFlatSpec {

import SymbolicDifferentiationPrefixExpressions._


private val parseCases = List(
"5" -> Value(5),
"x" -> Variable,
Expand All @@ -29,15 +28,13 @@ class SymbolicDifferentiationPrefixExpressionSpec extends AnyFlatSpec {
"(^ (sin x) 3)" -> Pow(Sin(Variable), Value(3))
)

behavior of "Parser"
behavior.of("Parser")
parseCases.foreach { case (expr, expected) =>
it should s"return $expected for $expr" in {
Expr.parse(expr) shouldEqual expected
}
}



private val simpleCases = List(
"5" -> List("0"),
"x" -> List("1"),
Expand Down
32 changes: 32 additions & 0 deletions src/test/scala/sierikov/codewars/kyu3/FabergeEasterEggSpec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package sierikov.codewars.kyu3

import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers.shouldBe

import java.math.BigInteger

class FabergeEasterEggSpec extends AnyFlatSpec {

import FabergeEasterEgg._

private val testCases = List(
(0, 0, "0"),
(1, 51, "51"),
(2, 1, "1"),
(4, 17, "3213"),
(16, 19, "524096"),
(6015, 5, "31"),
(23, 19, "524287"),
// stress test
(13, 550, "60113767426276772744951355")
).map { case (n, m, expected) =>
(BigInteger.valueOf(n), BigInteger.valueOf(m), BigInteger(expected))
}

testCases.foreach { case (n, m, expected) =>
it should s"return $expected for n = $n, m = $m" in {
height(n, m) shouldBe expected
}
}

}

0 comments on commit 9bfcdd5

Please sign in to comment.