From ab8903875c25562f98a78c385aba1b087cedb7a9 Mon Sep 17 00:00:00 2001 From: Alexey Filippov Date: Sun, 5 May 2019 17:29:26 +0100 Subject: [PATCH] #4 - Add finger tree concatenation --- src/main/scala/finger/FingerTreeDeque.scala | 6 +++-- src/main/scala/finger/Fingers.scala | 22 +++++++++++++++++++ .../scala/finger/FingerTreeDequeSpec.scala | 4 ++-- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/main/scala/finger/FingerTreeDeque.scala b/src/main/scala/finger/FingerTreeDeque.scala index d0dc4c2..495a0e8 100644 --- a/src/main/scala/finger/FingerTreeDeque.scala +++ b/src/main/scala/finger/FingerTreeDeque.scala @@ -1,9 +1,9 @@ package finger import finger.Fingers.{Empty, FingerTree} -import okasaki.Deque +import okasaki.CatenableDeque -class FingerTreeDeque[E] extends Deque[E, FingerTree[E]] { +class FingerTreeDeque[E] extends CatenableDeque[E, FingerTree[E]] { override def init(q: FingerTree[E]): FingerTree[E] = Fingers.init(q) override def last(q: FingerTree[E]): E = Fingers.last(q) @@ -19,4 +19,6 @@ class FingerTreeDeque[E] extends Deque[E, FingerTree[E]] { override def head(q: FingerTree[E]): E = Fingers.head(q) override def tail(q: FingerTree[E]): FingerTree[E] = Fingers.tail(q) + + override def ++(a: FingerTree[E], b: FingerTree[E]): FingerTree[E] = Fingers.concat(a, b) } diff --git a/src/main/scala/finger/Fingers.scala b/src/main/scala/finger/Fingers.scala index c8cbdf3..13138a5 100644 --- a/src/main/scala/finger/Fingers.scala +++ b/src/main/scala/finger/Fingers.scala @@ -222,4 +222,26 @@ object Fingers { case NilR => throw new IllegalStateException("init() of an empty tree") case SnocR(t, _) => t } + + // ========================================================================================== + def app3[A](fta: FingerTree[A], ts: List[A], ftb: FingerTree[A]): FingerTree[A] = + (fta, ftb) match { + case (Empty, xs) => cons1(ts, xs) + case (xs, Empty) => snoc1(xs, ts) + case (Single(x), xs) => cons(x, cons1(ts, xs)) + case (xs, Single(x)) => snoc(snoc1(xs, ts), x) + case (Deep(pr1, m1, sf1), Deep(pr2, m2, sf2)) => + Deep(pr1, app3(m1, nodes(toList(sf1) ++ ts ++ toList(pr2)), m2), sf2) + } + + def nodes[A](xs: List[A]): List[Node[A]] = xs match { + case List(a, b) => List(Node2(a, b)) + case List(a, b, c) => List(Node3(a, b, c)) + case List(a, b, c, d) => List(Node2(a, b), Node2(c, d)) + case a :: b :: c :: rest => Node3(a, b, c) :: nodes(rest) + } + + def concat[A](xs: FingerTree[A], ys: FingerTree[A]): FingerTree[A] = + app3(xs, Nil, ys) + } diff --git a/src/test/scala/finger/FingerTreeDequeSpec.scala b/src/test/scala/finger/FingerTreeDequeSpec.scala index 27e458e..7c5bacb 100644 --- a/src/test/scala/finger/FingerTreeDequeSpec.scala +++ b/src/test/scala/finger/FingerTreeDequeSpec.scala @@ -1,6 +1,6 @@ package finger -import okasaki.{DequeSpec, IntElements} +import okasaki.{CatenableDequeSpec, IntElements} -class FingerTreeDequeSpec extends DequeSpec(new FingerTreeDeque[Int]) +class FingerTreeDequeSpec extends CatenableDequeSpec(new FingerTreeDeque[Int]) with IntElements \ No newline at end of file