diff --git a/src/main/scala/org/lemon/advent/lib/collections.scala b/src/main/scala/org/lemon/advent/lib/collections.scala index 5fcd983..66d88d0 100644 --- a/src/main/scala/org/lemon/advent/lib/collections.scala +++ b/src/main/scala/org/lemon/advent/lib/collections.scala @@ -1,5 +1,17 @@ package org.lemon.advent.lib extension [A](it: Iterator[A]) + /** Returns the nth element of the iterator. + * + * @param n the index of the element to return + * @throws NoSuchElementException if there is no nth element + * @return the nth element of the iterator + */ def nth(n: Int): A = it.drop(n).next + + /** Returns the nth element of the iterator, or None if there is no nth element. + * + * @param n the index of the element to return + * @return the nth element of the iterator, or None if there is no nth element + */ def nthOption(n: Int): Option[A] = it.drop(n).nextOption diff --git a/src/main/scala/org/lemon/advent/lib/combinations.scala b/src/main/scala/org/lemon/advent/lib/combinations.scala index d5b8b0c..e95942c 100644 --- a/src/main/scala/org/lemon/advent/lib/combinations.scala +++ b/src/main/scala/org/lemon/advent/lib/combinations.scala @@ -1,7 +1,11 @@ package org.lemon.advent.lib extension [T](xs: Iterable[T]) - + /** Returns an iterator of all unordered pairs of elements in the iterable. + * If the collection contains duplicates, the pairs will not be unique. + * + * @return iterator of all unordered pairs + */ def pairs: Iterator[(T, T)] = for (x, i) <- xs.iterator.zipWithIndex @@ -9,6 +13,11 @@ extension [T](xs: Iterable[T]) if i < j yield (x, y) + /** Returns an iterator of all unordered triples of elements in the iterable. + * If the collection contains duplicates, the triples will not be unique. + * + * @return iterator of all unordered triples + */ def triples: Iterator[(T, T, T)] = for (x, i) <- xs.iterator.zipWithIndex diff --git a/src/main/scala/org/lemon/advent/lib/math.scala b/src/main/scala/org/lemon/advent/lib/math.scala index c3731fe..1890a25 100644 --- a/src/main/scala/org/lemon/advent/lib/math.scala +++ b/src/main/scala/org/lemon/advent/lib/math.scala @@ -4,13 +4,29 @@ import scala.math.Integral.Implicits._ import scala.math.Ordering.Implicits._ extension [N: Integral](a: N) + /** Returns the positive modulo of this mod `n`. If the regular modulo is negative, this + * will shift it back into the positive ranges. + * + * @param n the modulus + * @return the positive modulo of this mod `n` + */ def +%(n: N): N = val mod = a % n if mod < Integral[N].zero then mod + n else mod + /** Returns the greatest common divisor of this and `b`. + * + * @param b the other number + * @return the greatest common divisor of this and `b` + */ def gcd(b: N): N = @annotation.tailrec def loop(a: N, b: N): N = if b == Integral[N].zero then a else loop(b, a % b) loop(a, b) + /** Returns the least common multiple of this and `b`. + * + * @param b the other number + * @return the least common multiple of this and `b` + */ def lcm(b: N): N = a * b / a.gcd(b) diff --git a/src/main/scala/org/lemon/advent/lib/memoize.scala b/src/main/scala/org/lemon/advent/lib/memoize.scala index e17b6d7..d88428f 100644 --- a/src/main/scala/org/lemon/advent/lib/memoize.scala +++ b/src/main/scala/org/lemon/advent/lib/memoize.scala @@ -2,6 +2,20 @@ package org.lemon.advent.lib import scala.collection.mutable +/** Memoizes a function, caching the results of previous calls. + * Use as: + * ```scala + * lazy val fib: BigInt => BigInt = memoize { + * case 0 => 0 + * case 1 => 1 + * case n => fib(n - 1) + fib(n - 2) + * } + * fib(100) shouldBe BigInt("354224848179261915075") + * ``` + * + * @param f the function to memoize + * @return a memoized version of the function + */ def memoize[T, R](f: T => R): T => R = val cache = mutable.Map.empty[T, R] (t: T) => cache.getOrElseUpdate(t, f(t))