From d9b3635f794ec5d32c0d4d7c38e169c215afb146 Mon Sep 17 00:00:00 2001 From: Yan Date: Sat, 18 Apr 2020 00:42:11 +0000 Subject: [PATCH 1/2] initial commit --- src/diff.mo | 45 +++++++++++++++++++++++++++++++++++++++++++++ src/main.mo | 16 +++++++++++++--- 2 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 src/diff.mo diff --git a/src/diff.mo b/src/diff.mo new file mode 100644 index 0000000..5ccfef5 --- /dev/null +++ b/src/diff.mo @@ -0,0 +1,45 @@ +import Array "mo:stdlib/array"; +import Hash "mo:stdlib/hash"; +import HashMap "mo:stdlib/hashMap"; + +module { + public type Time = Nat; + public type Diff = Int; + public type ValueDiff = { + time: Time; + diff: Diff; + }; + public type Trace = HashMap.HashMap; + public type ExportTrace = [(Key, [ValueDiff])]; + + public class Collection( + keyEq: (K,K) -> Bool, + keyHash: K -> Hash.Hash) { + public let trace: Trace = HashMap.HashMap(0, keyEq, keyHash); + public func exportTrace(): ExportTrace { + var res: ExportTrace = []; + for ((k, diffs) in trace.iter()) { + res := Array.append<(K, [ValueDiff])>(res, [(k, diffs)]); + }; + return res; + }; + public func insert(k: K, t: Time) { + let diff = { time = t; diff = 1 }; + let diffs = switch (trace.get(k)) { + case null { [diff] }; + case (?diffs) { Array.append(diffs, [diff]) }; + }; + ignore trace.set(k, diffs); + }; + public func map(f:K -> K): Collection { + let res = Collection(keyEq, keyHash); + for ((k,diffs) in trace.iter()) { + let new_k = f(k); + for (diff in diffs.vals()) { + res.insert(new_k, diff.time); + } + }; + return res; + } + }; +} \ No newline at end of file diff --git a/src/main.mo b/src/main.mo index 014bf49..d58c2f8 100644 --- a/src/main.mo +++ b/src/main.mo @@ -1,9 +1,11 @@ import A "mo:stdlib/array"; -import P "mo:stdlib/prelude"; -import List "mo:stdlib/list"; +import B "mo:stdlib/buf"; +import Diff "diff"; import H "mo:stdlib/hashMap"; import Hash "mo:stdlib/hash"; -import B "mo:stdlib/buf"; +import List "mo:stdlib/list"; +import P "mo:stdlib/prelude"; +import a "mo:stdlib/trie"; let N = 600; @@ -137,4 +139,12 @@ actor { public query func output() : async ([Object], Int, Int, Int) { (E.objects.toArray(), E.pos.x, E.pos.y, E.pos.dir) }; + + public func testDiff(): async Diff.ExportTrace { + let a = Diff.Collection(varEq, Hash.hashOfText); + let b = a.map(func (x:Text): Text = x#"_" ); + a.insert("a",0); a.insert("b",0); + a.insert("a",1); a.insert("c",1); + return b.exportTrace(); + }; }; From 7344430e4cd8232e45c024adbfca8c82e7e2c993 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Fri, 24 Apr 2020 13:42:45 -0700 Subject: [PATCH 2/2] checkpoint --- src/diff.mo | 20 ++++++++++------- src/main.mo | 5 +++-- src/pq.mo | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 10 deletions(-) create mode 100644 src/pq.mo diff --git a/src/diff.mo b/src/diff.mo index 5ccfef5..6cf7009 100644 --- a/src/diff.mo +++ b/src/diff.mo @@ -1,6 +1,7 @@ import Array "mo:stdlib/array"; import Hash "mo:stdlib/hash"; import HashMap "mo:stdlib/hashMap"; +import PQ "pq"; module { public type Time = Nat; @@ -9,25 +10,28 @@ module { time: Time; diff: Diff; }; - public type Trace = HashMap.HashMap; + public type Trace = HashMap.HashMap>; public type ExportTrace = [(Key, [ValueDiff])]; + func ord(x: ValueDiff, y: ValueDiff): Bool { x.time < y.time }; + public class Collection( - keyEq: (K,K) -> Bool, - keyHash: K -> Hash.Hash) { + keyEq: (K,K) -> Bool, + keyHash: K -> Hash.Hash) { public let trace: Trace = HashMap.HashMap(0, keyEq, keyHash); public func exportTrace(): ExportTrace { var res: ExportTrace = []; for ((k, diffs) in trace.iter()) { - res := Array.append<(K, [ValueDiff])>(res, [(k, diffs)]); + let vec_diffs = diffs.heap.toArray(); + res := Array.append<(K, [ValueDiff])>(res, [(k, vec_diffs)]); }; return res; }; public func insert(k: K, t: Time) { let diff = { time = t; diff = 1 }; let diffs = switch (trace.get(k)) { - case null { [diff] }; - case (?diffs) { Array.append(diffs, [diff]) }; + case null { let pq = PQ.PQ(ord); pq.add(diff); pq }; + case (?diffs) { diffs.add(diff); diffs }; }; ignore trace.set(k, diffs); }; @@ -35,11 +39,11 @@ module { let res = Collection(keyEq, keyHash); for ((k,diffs) in trace.iter()) { let new_k = f(k); - for (diff in diffs.vals()) { + for (diff in diffs.heap.iter()) { res.insert(new_k, diff.time); } }; return res; } }; -} \ No newline at end of file +} diff --git a/src/main.mo b/src/main.mo index d58c2f8..693a6ca 100644 --- a/src/main.mo +++ b/src/main.mo @@ -5,7 +5,7 @@ import H "mo:stdlib/hashMap"; import Hash "mo:stdlib/hash"; import List "mo:stdlib/list"; import P "mo:stdlib/prelude"; -import a "mo:stdlib/trie"; +import D "mo:stdlib/debug"; let N = 600; @@ -142,9 +142,10 @@ actor { public func testDiff(): async Diff.ExportTrace { let a = Diff.Collection(varEq, Hash.hashOfText); - let b = a.map(func (x:Text): Text = x#"_" ); a.insert("a",0); a.insert("b",0); a.insert("a",1); a.insert("c",1); + D.print(debug_show(a.exportTrace())); + let b = a.map(func (x:Text): Text = x#"_" ); return b.exportTrace(); }; }; diff --git a/src/pq.mo b/src/pq.mo new file mode 100644 index 0000000..d20a37a --- /dev/null +++ b/src/pq.mo @@ -0,0 +1,65 @@ +import Buf "mo:stdlib/buf"; +import D "mo:stdlib/debug"; + +module { + public class PQ(ord: (T, T) -> Bool) { + public let heap = Buf.Buf(0); + public func add(x: T) { + let i = heap.len(); + heap.add(x); + up_heap(i); + }; + /* + public func pop(): ?T { + let n = heap.len(); + if (n == 0) { + return null; + }; + let x = h.get(0); + let y = h.get(n - 1); + h.set(0, y); + // h.remove_last(); + down_heap(pq, 0); + ?x + }; + func down_heap(pq: PQ, i: Nat) { + let h = pq.heap; + let ord = pq.order; + let n = h.len(); + let x = h.get(i); + func down_heap(j: Nat) { + if (2 * j + 1 < n) { + let l = 2 * j + 1; + let r = 2 * j + 2; + let k = if (r < n and not ord(h.get(l), h.get(r))) { r } else { l }; + let y = h.get(k); + if (ord(x, y)) { + h.set(j, x); + } else { + h.set(j, y); + down_heap(k); + } + } else if (j != i) { + h.set(j, x); + } + }; + down_heap(i) + };*/ + func up_heap(i: Nat) { + let x = heap.get(i); + func up_heap_(j: Nat) { + let k = (j - 1) / 2; + let y = heap.get(k); + if (j == 0 or ord(y,x)) { + heap.set(j, x); + } else { + heap.set(j, y); + up_heap_(k); + } + }; + if (i > 0) { + up_heap_(i); + }; + }; + }; +}