Skip to content

Commit 58f44e7

Browse files
committed
Refactor
1 parent 65b0517 commit 58f44e7

6 files changed

Lines changed: 171 additions & 3 deletions

File tree

Readme.md

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,38 @@
3535

3636
## CRDT
3737

38+
39+
40+
41+
https://github.com/nictuku/dht
42+
https://github.com/shiyanhui/dht
43+
44+
45+
46+
47+
* [Collaborative Text Editing Paper](https://arxiv.org/pdf/2305.00583)
48+
49+
* https://github.com/josephg/crdt-from-scratch
50+
* https://github.com/josephg/egwalker-from-scratch
51+
3852
* [Collaborative Text Editing with Eg-Walker](https://www.youtube.com/watch?v=rjbEG7COj7o)
3953
* [Text CRDTs from scratch, in code!](https://www.youtube.com/watch?v=_lQ2Q4Kzi1I)
4054
* [Lets write Eg-walker from scratch! Part 1](https://www.youtube.com/watch?v=ggXka5TTsOs)
4155

56+
* [Conflict-Free Replicated Data Types (CRDT) for Distributed JavaScript Apps](https://www.youtube.com/watch?v=M8-WFTjZoA0)
4257
* [CRDTs: The Hard Parts](https://www.youtube.com/watch?v=x7drE24geUw)
4358
* [CRDTs and the Quest for Distributed Consistency](https://www.youtube.com/watch?v=B5NULPSiOGw)
4459
* [A CRDT Primer: Defanging Order Theory](https://www.youtube.com/watch?v=OOlnp2bZVRs)
45-
* [Conflict-Free Replicated Data Types (CRDT) for Distributed JavaScript Apps.](https://www.youtube.com/watch?v=M8-WFTjZoA0)
4660

4761
* [Loro Is Local-First State With CRDT](https://www.youtube.com/watch?v=NB7HRfyufLk)
4862
* [How Yjs works from the inside out](https://www.youtube.com/watch?v=0l5XgnQ6rB4)
4963

64+
* [CRDTs for Non Academics](https://www.youtube.com/watch?v=vBU70EjwGfw)
5065
* [An introduction to Conflict-Free Replicated Data Types (CRDTs)](https://www.youtube.com/watch?v=gZP2VUmH05A)
5166

67+
* [CRDT Survey](https://mattweidner.com/2023/09/26/crdt-survey-1.html)
68+
* [An introduction to state-based CRDTs](https://www.bartoszsypytkowski.com/the-state-of-a-state-based-crdts/)
69+
5270
## Data Structure
5371

5472
* [Heaps, heapsort, and priority queues - Inside code](https://www.youtube.com/watch?v=pLIajuc31qk)
@@ -81,12 +99,15 @@ Content delivery networks deploy web caches around the world to cache and serve
8199

82100
### HyperLogLog
83101

102+
* [Wikipedia](https://en.wikipedia.org/wiki/HyperLogLog)
84103
* [PapersWeLove : HyperLogLog](https://www.youtube.com/watch?v=y3fTaxA8PkU)
85104
* [The Algorithm with the Best Name - HyperLogLog Explained](https://www.youtube.com/watch?v=2PlrMCiUN_s)
86105
* [A problem so hard even Google relies on Random Chance](https://www.youtube.com/watch?v=lJYufx0bfpw)
87106
* [Counting BILLIONS with Just Kilobytes](https://www.youtube.com/watch?v=f69hh3KgFEk)
88107
* https://github.com/tylertreat/BoomFilters/blob/master/hyperloglog.go
89108

109+
HyperLogLog is an algorithm for the count-distinct problem, Probabilistic cardinality estimators.
110+
90111
### Count–min sketch
91112

92113
* [Wikepedia](https://en.wikipedia.org/wiki/Count%E2%80%93min_sketch)
@@ -99,7 +120,7 @@ The goal of the basic version of the count–min sketch is to consume a stream o
99120

100121
* [Understanding Probabilistic Data Structures](https://www.youtube.com/watch?v=2Dzc7fxA0us)
101122

102-
### T Digest
123+
### TDigest
103124

104125
* [Sketching Data with T Digest](https://www.youtube.com/watch?v=ETUYhEZRtWE)
105126

datastructure/hyperloglog.go

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package datastructure
22

3-
import "github.com/zeebo/xxh3"
3+
import (
4+
"math"
5+
6+
"github.com/zeebo/xxh3"
7+
)
48

59
type HyperLogLog struct {
610
registers []uint8 // Buckets: each register holds the max number of leading zeros
@@ -34,3 +38,41 @@ func (hll *HyperLogLog) Add(data []byte) {
3438
hll.registers[idx] = rank
3539
}
3640
}
41+
42+
func alpha(m int) float64 {
43+
switch m {
44+
case 16:
45+
return 0.673
46+
case 32:
47+
return 0.697
48+
case 64:
49+
return 0.709
50+
default:
51+
return 0.7213 / (1 + 1.079/float64(m))
52+
}
53+
}
54+
55+
func (hll *HyperLogLog) Estimate() float64 {
56+
m := float64(len(hll.registers))
57+
sum := 0.0
58+
zeros := 0
59+
60+
for _, reg := range hll.registers {
61+
sum += 1.0 / float64(uint64(1)<<reg) // 2^-reg
62+
if reg == 0 {
63+
zeros++
64+
}
65+
}
66+
67+
alphaM := alpha(int(m))
68+
est := alphaM * m * m / sum
69+
70+
// 🔥 Small range correction
71+
if est <= 5.0*m {
72+
if zeros != 0 {
73+
est = m * math.Log(m/float64(zeros))
74+
}
75+
}
76+
77+
return est
78+
}

eggwalker/eggwalker.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package eggwalker
2+
3+
import "errors"
4+
5+
type Id struct {
6+
agent string
7+
seq int32
8+
}
9+
10+
func (b *Id) equals(a *Id) bool {
11+
return a != nil && b != nil && a.agent == b.agent && a.seq == b.seq
12+
}
13+
14+
type Item struct {
15+
content byte
16+
17+
id *Id
18+
originLeft *Id
19+
originRight *Id
20+
21+
deleted bool
22+
}
23+
24+
type Doc struct {
25+
content []Item
26+
}
27+
28+
func createDoc() Doc {
29+
return Doc{
30+
content: []Item{},
31+
}
32+
}
33+
34+
func getContent(doc Doc) string {
35+
notDeleted := make([]byte, len(doc.content))
36+
i := 0
37+
for _, item := range doc.content {
38+
if !item.deleted {
39+
notDeleted[i] = item.content
40+
i++
41+
}
42+
}
43+
return string(notDeleted[:i])
44+
}
45+
46+
func (doc Doc) localInsertOne(
47+
agent string,
48+
seq int32,
49+
pos int32,
50+
text byte,
51+
) {
52+
var originLeft *Id
53+
if ((pos - 1) > 0) && ((pos - 1) < int32(len(doc.content))) {
54+
originLeft = doc.content[pos-1].id
55+
}
56+
var originRight *Id
57+
if (pos > 0) && (pos < int32(len(doc.content))) {
58+
originRight = doc.content[pos].id
59+
}
60+
doc.intergrate(Item{
61+
content: text,
62+
id: &Id{
63+
agent: agent,
64+
seq: seq,
65+
},
66+
deleted: false,
67+
originLeft: originLeft,
68+
originRight: originRight,
69+
})
70+
}
71+
72+
func findItemIdxAtId(doc Doc, id *Id) (int32, error) {
73+
if id == nil {
74+
return -1, errors.New("Invalid id")
75+
}
76+
77+
for i := int32(0); int(i) < len(doc.content); i++ {
78+
if id.equals(doc.content[i].id) {
79+
return i, nil
80+
}
81+
}
82+
83+
return -1, errors.New("Item not found")
84+
}
85+
86+
func (doc Doc) intergrate(newItem Item) {
87+
// Add newItem into doc at right location
88+
}

eggwalker/eggwalker_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package eggwalker
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestGetContent(t *testing.T) {
8+
doc := createDoc()
9+
docGetcontent := getContent(doc)
10+
if docGetcontent != "" {
11+
t.Fatal("It should be empty, got", docGetcontent)
12+
}
13+
}

eggwalker/go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module github.com/codeharik/eggwalker
2+
3+
go 1.24.0

go.work

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ go 1.24.0
22

33
use (
44
./datastructure
5+
./eggwalker
56
./lockfree
67
./secretary
78
)

0 commit comments

Comments
 (0)