-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy path06_string_compression.go
145 lines (121 loc) · 2.89 KB
/
06_string_compression.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package ch01
import (
"strconv"
"strings"
)
// Compress returns "compressed" string - all duplicates chars relpaced with "xN",
// where x is original char and N is a number of chars
// If compressed string isn't smaller, than original, original string will be returned
func Compress(s string) string {
slen := len(s)
// if len is less than 3, the original string will be smaller
if slen < 3 {
return s
}
compressed := ""
count := 1
for i := 1; i < slen; i++ {
if s[i-1] != s[i] {
compressed += string(s[i-1]) + strconv.Itoa(count)
count = 1
} else {
count++
}
}
compressed += string(s[slen-1]) + strconv.Itoa(count)
if len(compressed) < slen {
return compressed
}
return s
}
// CompressBytes is the Compress implementation using byte slice
func CompressBytes(s string) string {
slen := len(s)
// if len is less than 3, the original string will be smaller
if slen < 3 {
return s
}
bytes := make([]byte, 0)
count := 1
for i := 1; i < slen; i++ {
if s[i-1] != s[i] {
bytes = append(bytes, s[i-1])
bytes = append(bytes, []byte(strconv.Itoa(count))...)
count = 1
} else {
count++
}
}
bytes = append(bytes, s[slen-1])
bytes = append(bytes, []byte(strconv.Itoa(count))...)
if len(bytes) < slen {
return string(bytes)
}
return s
}
// CompressBuilder is the Compress implementation based on strings.Builder
func CompressBuilder(s string) string {
slen := len(s)
// if len is less than 3, the original string will be smaller
if slen < 3 {
return s
}
var compressed strings.Builder
count := 1
for i := 1; i < slen; i++ {
if s[i-1] != s[i] {
compressed.WriteByte(s[i-1])
compressed.WriteString(strconv.Itoa(count))
count = 1
} else {
count++
}
}
compressed.WriteByte(s[slen-1])
compressed.WriteString(strconv.Itoa(count))
if compressed.Len() < slen {
return compressed.String()
}
return s
}
// CompressBuilderCap is the Compress implementation based on strings.Builder
// To optimize strings.Builder capacity, we're going to calculate the length
// pf compressed string ahead
func CompressBuilderCap(s string) string {
slen := len(s)
cmplen := compressedLength(s)
// if len is less than compressed length, the original string will be returned
if slen <= cmplen {
return s
}
var compressed strings.Builder
compressed.Grow(cmplen)
count := 1
for i := 1; i < slen; i++ {
if s[i-1] != s[i] {
compressed.WriteByte(s[i-1])
compressed.WriteString(strconv.Itoa(count))
count = 1
} else {
count++
}
}
compressed.WriteByte(s[slen-1])
compressed.WriteString(strconv.Itoa(count))
return compressed.String()
}
// compressedLength returns compressed length of string s
func compressedLength(s string) int {
slen := len(s)
cmlen := 0
count := 1
for i := 1; i < slen; i++ {
if s[i-1] != s[i] {
cmlen += 1 + len(strconv.Itoa(count))
count = 1
} else {
count++
}
}
return cmlen + 1 + len(strconv.Itoa(count))
}