-
Notifications
You must be signed in to change notification settings - Fork 5
/
generator.go
87 lines (66 loc) · 1.7 KB
/
generator.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
package memory
import (
"math/rand"
"strings"
)
func generator(w, h, pairSize int, showPositions bool) ([][]string, []PairPositions, error) {
if w < 0 || h < 0 {
return nil, nil, errNegativeNumbers
}
pool, usedLetters, err := lettersPool(w*h, pairSize)
if err != nil {
return nil, nil, err
}
grid := make([][]string, h)
for i := range grid {
grid[i] = pool[i*w : w*(i+1)]
}
if showPositions {
pp := definePositions(grid, usedLetters, pairSize)
return grid, pp, nil
}
return grid, nil, nil
}
func lettersPool(totalLetters, pairSize int) ([]string, string, error) {
_, ok := _pairSizes[pairSize]
if !ok {
return nil, "", errPairSizeNotAllowed
}
if totalLetters > len(_lowerCaseLetters)*2*pairSize {
return nil, "", errTooBigGrid
}
if totalLetters%pairSize != 0 {
return nil, "", errIncorrectGridSize
}
totalPairs := totalLetters / pairSize
allLetters := _lowerCaseLetters
if totalPairs > len(_lowerCaseLetters) {
allLetters += _upperCaseLetters
}
usedLetters := allLetters[:totalPairs]
pool := strings.Split(strings.Repeat(usedLetters, pairSize), "")
rand.Shuffle(len(pool), func(i, j int) {
pool[i], pool[j] = pool[j], pool[i]
})
return pool, usedLetters, nil
}
func definePositions(grid [][]string, letters string, ps int) []PairPositions {
values := make(map[string][][]int)
for i, row := range grid {
for j, val := range row {
_, ok := values[val]
if !ok {
values[val] = make([][]int, 0, ps)
}
values[val] = append(values[val], []int{i + 1, j + 1})
}
}
pp := make([]PairPositions, len(letters))
for i, letter := range letters {
pp[i] = PairPositions{
Value: string(letter),
Positions: values[string(letter)],
}
}
return pp
}