-
Notifications
You must be signed in to change notification settings - Fork 0
/
morse.go
103 lines (89 loc) · 1.95 KB
/
morse.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
package morse
import (
"fmt"
"strings"
)
const (
// 2.1 A dash is equal to three dots
dashDotRatio = 3
// 2.2 The space between the signals forming the same letter is equal to
// one dot
symbolDotRatio = 1
// 2.3 The sapce between two letters is equal to three dots
letterDotRatio = 3
// 2.4 The space between two words is equal to seven dots
wordDotRatio = 7
)
type Mapper func(rune) string
// Code creates morse for a given string
func Code(s string) string {
// identity mapper
return encode(s, ' ', func(r rune) string {
return string(r)
})
}
// Signal creates a transmission enabled signal
func Signal(s string) string {
return encode(s, '0', DitDah)
}
const Dit = "1"
const Dah = "111" // strings.Repeat(Dit, dashDotRatio) is not a constant
// DitDah returns Dit for a '.', Dah for a '-', and panics otherwise.
func DitDah(r rune) string {
switch r {
case '.':
return Dit
case '-':
return Dah
default:
panic(fmt.Errorf("want '.' or '-' but got %c\n", r))
}
}
// ToBinary maps "0" to false and "1" to true.
// panics otherwise.
func ToBinary(r rune) bool {
switch r {
case '0':
return false
case '1':
return true
default:
panic(fmt.Errorf("want '0' or '1' but got %+v\n", r))
}
}
// WikipediaNotation uses = and _
func WikipediaNotation(r rune) rune {
if ToBinary(r) {
return '='
}
return '_'
}
func encode(s string, pause rune, mapper Mapper) string {
var sb strings.Builder
repeat := func(r rune, n int) {
for i := 0; i < n; i++ {
sb.WriteRune(r)
}
}
words := strings.Fields(strings.ToLower(s))
for i, word := range words {
for j, letter := range word {
t := icuTable[letter]
for k, symbol := range t {
mapped := mapper(symbol)
sb.WriteString(mapped)
// separator if more to come
if k+1 < len(t) {
repeat(pause, symbolDotRatio)
}
}
if j+1 < len(word) {
repeat(pause, letterDotRatio)
}
}
if i+1 < len(words) {
repeat(pause, wordDotRatio)
}
}
return sb.String()
}