-
Notifications
You must be signed in to change notification settings - Fork 98
/
main.go
122 lines (97 loc) · 2.18 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package main
import (
"fmt"
"log"
"os"
"time"
"github.com/goccy/go-json"
"github.com/ugurcsen/gods-generic/trees/binaryheap"
)
type Post struct {
ID string `json:"_id"`
Title string `json:"title"`
Tags []string `json:"tags"`
}
type PostWithSharedTags struct {
Post int
SharedTags int
}
type RelatedPosts struct {
ID string `json:"_id"`
Tags []string `json:"tags"`
Related []*Post `json:"related"`
}
func main() {
file, err := os.Open("../posts.json")
if err != nil {
log.Panicln(err)
}
var posts []Post
err = json.NewDecoder(file).Decode(&posts)
if err != nil {
log.Panicln(err)
}
start := time.Now()
tagMap := make(map[string][]int, 100)
for i, post := range posts {
for _, tag := range post.Tags {
tagMap[tag] = append(tagMap[tag], i)
}
}
allRelatedPosts := make([]RelatedPosts, 0, len(posts))
taggedPostCount := make([]int, len(posts))
t5 := binaryheap.NewWith[PostWithSharedTags](PostComparator)
for i := range posts {
for j := range taggedPostCount {
taggedPostCount[j] = 0
}
for _, tag := range posts[i].Tags {
for _, otherPostIdx := range tagMap[tag] {
if otherPostIdx != i {
taggedPostCount[otherPostIdx]++
}
}
}
for v, count := range taggedPostCount {
if t5.Size() < 5 {
t5.Push(PostWithSharedTags{Post: v, SharedTags: count})
} else {
if t, _ := t5.Peek(); t.SharedTags < count {
t5.Pop()
t5.Push(PostWithSharedTags{Post: v, SharedTags: count})
}
}
}
num := min(5, t5.Size())
topPosts := make([]*Post, num)
for i := 0; i < num; i++ {
if t, ok := t5.Pop(); ok {
topPosts[i] = &posts[t.Post]
}
}
allRelatedPosts = append(allRelatedPosts, RelatedPosts{
ID: posts[i].ID,
Tags: posts[i].Tags,
Related: topPosts,
})
}
end := time.Now()
fmt.Println("Processing time (w/o IO)", end.Sub(start))
file, err = os.Create("../related_posts_go.json")
if err != nil {
log.Panicln(err)
}
err = json.NewEncoder(file).Encode(allRelatedPosts)
if err != nil {
log.Panicln(err)
}
}
func PostComparator(a, b PostWithSharedTags) int {
if a.SharedTags > b.SharedTags {
return 1
}
if a.SharedTags < b.SharedTags {
return -1
}
return 0
}