All Downloads are FREE. Search and download functionalities are using the official Maven repository.

hael.jjm-core_2.13.0.2.3.source-code.SetUnionFind.scala Maven / Gradle / Ivy

The newest version!
package jjm

import cats.Order

import scala.collection.immutable.Set

import io.circe.generic.JsonCodec

/** Basic, inefficient immutable union-find based on sets.
  * Invariant: all sets are disjoint.
  * TODO: write a custom json codec that enforces this?
  */
@JsonCodec case class SetUnionFind[A](
  val sets: Set[Set[A]]
) {

  def remove(a: A): SetUnionFind[A] = {
    SetUnionFind(sets.map(_.filter(_ != a)).filter(_.nonEmpty))
  }

  def add(a: A): SetUnionFind[A] =
    if(sets.forall(!_.contains(a))) SetUnionFind(sets + Set[A](a))
    else this

  def find(a: A) = for {
    subset <- sets.find(_.contains(a))
  } yield subset.head

  /** Unions a and b, adding them in if they're not already present */
  def union(a: A, b: A): SetUnionFind[A] = {
    val aSet = sets.find(_.contains(a)).getOrElse(Set(a))
    val bSet = sets.find(_.contains(b)).getOrElse(Set(b))
    SetUnionFind(sets - aSet - bSet + (aSet ++ bSet))
  }

  /** Unions a and b only if they're already present */
  def unionStrict(a: A, b: A): Option[SetUnionFind[A]] = for {
    aSet <- sets.find(_.contains(a))
    bSet <- sets.find(_.contains(b))
  } yield if(aSet != bSet) {
    SetUnionFind(sets - aSet - bSet + (aSet ++ bSet))
  } else this

  def representatives: Set[A] = sets.map(_.head)
}
object SetUnionFind {
  def empty[A]: SetUnionFind[A] = SetUnionFind(Set[Set[A]]())
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy