Skip to content

Commit

Permalink
🎨 doc some utilities
Browse files Browse the repository at this point in the history
  • Loading branch information
twentylemon committed Dec 23, 2024
1 parent a934e00 commit 9c43cf8
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 1 deletion.
12 changes: 12 additions & 0 deletions src/main/scala/org/lemon/advent/lib/collections.scala
Original file line number Diff line number Diff line change
@@ -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
11 changes: 10 additions & 1 deletion src/main/scala/org/lemon/advent/lib/combinations.scala
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
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
(y, j) <- xs.iterator.zipWithIndex
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
Expand Down
16 changes: 16 additions & 0 deletions src/main/scala/org/lemon/advent/lib/math.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
14 changes: 14 additions & 0 deletions src/main/scala/org/lemon/advent/lib/memoize.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down

0 comments on commit 9c43cf8

Please sign in to comment.