Skip to content

Commit

Permalink
Add intersection for treeset and treemap, incl. tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jiribenes committed Nov 25, 2024
1 parent f1ccf8c commit 2d23750
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 18 deletions.
12 changes: 8 additions & 4 deletions examples/stdlib/set/unique.check
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,19 @@ you: true
see: false
do: true
Effekt: true

Cons(Effekt, Cons(and, Cons(ask, Cons(but, Cons(can, Cons(do, Cons(fellow, Cons(for, Cons(language, Cons(man, Cons(my, Cons(not, Cons(of, Cons(programmers, Cons(programs, Cons(so, Cons(the, Cons(together, Cons(we, Cons(what, Cons(will, Cons(world, Cons(you, Cons(your, Nil()))))))))))))))))))))))))
true
sorted
Cons(Effekt, Cons(and, Cons(ask, Cons(but, Cons(can, Cons(do, Cons(fellow, Cons(for, Cons(language, Cons(man, Cons(my, Cons(not, Cons(of, Cons(programmers, Cons(programs, Cons(so, Cons(the, Cons(together, Cons(we, Cons(what, Cons(will, Cons(world, Cons(you, Cons(your, Nil()))))))))))))))))))))))))
true
sorted

Cons(after, Cons(around, Cons(better, Cons(do, Cons(ever, Cons(faster, Cons(harder, Cons(hour, Cons(is, Cons(it, Cons(make, Cons(makes, Cons(more, Cons(never, Cons(over, Cons(stronger, Cons(than, Cons(the, Cons(us, Cons(work, Cons(world, Nil())))))))))))))))))))))
true
sorted
lyrics / speech:
Cons(after, Cons(around, Cons(better, Cons(ever, Cons(faster, Cons(harder, Cons(hour, Cons(is, Cons(it, Cons(make, Cons(makes, Cons(more, Cons(never, Cons(over, Cons(stronger, Cons(than, Cons(us, Cons(work, Nil()))))))))))))))))))
speech / lyrics:
Cons(after, Cons(around, Cons(better, Cons(ever, Cons(faster, Cons(harder, Cons(hour, Cons(is, Cons(it, Cons(make, Cons(makes, Cons(more, Cons(never, Cons(over, Cons(stronger, Cons(than, Cons(us, Cons(work, Nil()))))))))))))))))))
Cons(Effekt, Cons(and, Cons(ask, Cons(but, Cons(can, Cons(fellow, Cons(for, Cons(language, Cons(man, Cons(my, Cons(not, Cons(of, Cons(programmers, Cons(programs, Cons(so, Cons(together, Cons(we, Cons(what, Cons(will, Cons(you, Cons(your, Nil())))))))))))))))))))))
speech n lyrics:
Cons(do, Cons(the, Cons(world, Nil())))
speech u lyrics:
Cons(Effekt, Cons(after, Cons(and, Cons(around, Cons(ask, Cons(better, Cons(but, Cons(can, Cons(do, Cons(ever, Cons(faster, Cons(fellow, Cons(for, Cons(harder, Cons(hour, Cons(is, Cons(it, Cons(language, Cons(make, Cons(makes, Cons(man, Cons(more, Cons(my, Cons(never, Cons(not, Cons(of, Cons(over, Cons(programmers, Cons(programs, Cons(so, Cons(stronger, Cons(than, Cons(the, Cons(together, Cons(us, Cons(we, Cons(what, Cons(will, Cons(work, Cons(world, Cons(you, Cons(your, Nil()))))))))))))))))))))))))))))))))))))))))))
40 changes: 29 additions & 11 deletions examples/stdlib/set/unique.effekt
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,28 @@ def main() = {
test("Effekt")

// ---
println("")

def testSorted(s: Set[String]) = {
val sorted = s.toList.isSortedBy { (x, y) => x <= y }
if (sorted) {
println("sorted")
} else {
println("unsorted")
}
}

println(uniqueWords.toList)
println(uniqueWords.toList.isSortedBy { (x, y) => x <= y })
println(uniqueSpeech.toList)
testSorted(uniqueSpeech)

println(set::fromList(words).toList)
println(set::fromList(words).toList.isSortedBy { (x, y) => x <= y })
println(set::fromList(speech).toList)
testSorted(set::fromList(speech))

// ---
println("")

// around the World / Harder, Better, Faster, Stronger by Daft Punk from Alive 2007
val alive2007: List[String] = [
// Around the World / Harder, Better, Faster, Stronger by Daft Punk (Alive 2007)
val lyrics: List[String] = [
"around", "the", "world", "around", "the", "world",
"around", "the", "world", "around", "the", "world",
"around", "the", "world", "around", "the", "world",
Expand All @@ -70,16 +81,23 @@ def main() = {
"around", "the", "world", "around", "the", "world"
]

val uniqueLyrics = unique(alive2007)
val uniqueLyrics = unique(lyrics)

println(uniqueLyrics.toList)
println(uniqueLyrics.toList.isSortedBy { (a, b) => a <= b })
testSorted(uniqueLyrics)

// ---
println("")

println("lyrics / speech:")
println(uniqueLyrics.difference(uniqueWords).toList)
println(uniqueLyrics.difference(uniqueSpeech).toList)

println("speech / lyrics:")
println(uniqueLyrics.difference(uniqueWords).toList)
println(uniqueSpeech.difference(uniqueLyrics).toList)

println("speech n lyrics:")
println(uniqueLyrics.intersection(uniqueSpeech).toList)

println("speech u lyrics:")
println(uniqueLyrics.union(uniqueWords).toList)
println(uniqueLyrics.union(uniqueSpeech).toList)
}
35 changes: 32 additions & 3 deletions libraries/common/map.effekt
Original file line number Diff line number Diff line change
Expand Up @@ -460,9 +460,38 @@ def union[K, V](m1: Map[K, V], m2: Map[K, V]) { combine : (V, V) => V }: Map[K,
/// Left-biased: Uses values from `m1` if there are duplicate keys.
///
/// O(???)
def union[K, V](m1: Map[K, V], m2: Map[K, V]): Map[K, V] = {
union(m1, m2) { (k, v1, v2) => v1 }
}
def union[K, V](m1: Map[K, V], m2: Map[K, V]): Map[K, V] =
union[K, V](m1, m2) { (k, v1, v2) => v1 }

/// Construct a new map which combines all elements that are in both `m1` and `m2` using the `combine` function.
///
/// O(???)
def intersection[K, A, B, C](m1: Map[K, A], m2: Map[K, B]) { combine: (K, A, B) => C }: Map[K, C] =
(m1, m2) match {
case (Tip(), _) => Tip()
case (_, Tip()) => Tip()
case (Bin(_, k, v1, l1, r1), _) =>
val (l2, mid, r2) = m2.splitLookup(k)
val left = l1.intersection(l2) { combine }
val right = r1.intersection(r2) { combine }
mid match {
case Some(v2) => link(k, combine(k, v1, v2), left, right)
case None() => link2(left, right)
}
}

/// Construct a new map which combines all elements that are in both `m1` and `m2` using the `combine` function.
///
/// O(???)
def intersection[K, A, B, C](m1: Map[K, A], m2: Map[K, B]) { combine: (A, B) => C }: Map[K, C] =
m1.intersection[K, A, B, C](m2) { (k, v1, v2) => combine(v1, v2) }

/// Construct a new map which combines all elements that are in both `m1` and `m2`.
/// Left-biased: Always uses values from `m1`.
///
/// O(???)
def intersection[K, A, B](m1: Map[K, A], m2: Map[K, B]): Map[K, A] =
m1.intersection[K, A, B, A](m2) { (k, v1, v2) => v1 }

// -------------
// Internal
Expand Down
11 changes: 11 additions & 0 deletions libraries/common/set.effekt
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,17 @@ def union[A](s1: Set[A], s2: Set[A]): Set[A] = {
}
}

/// Construct a new set which contains only elements which are in both of `s1` and `s2`.
///
/// O(???)
def intersection[A](s1: Set[A], s2: Set[A]): Set[A] = {
s1.internal::viaInplace { m1 =>
s2.internal::via { m2 =>
m1.intersection(m2)
}
}
}

// -------------
// Internal

Expand Down

0 comments on commit 2d23750

Please sign in to comment.