-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
109 lines (87 loc) · 2.29 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
package main
import (
"io/ioutil"
"log"
"strings"
)
func main() {
input, err := ioutil.ReadFile("input.txt")
if err != nil {
log.Fatalf("unable to read file: %v", err)
}
lines := strings.Split(string(input), "\n")
log.Printf("checksum: %d\n", Checksum(lines))
match, ok := MatchBoxIDs(lines)
if ok {
log.Printf("match: %s\n", match)
} else {
log.Println("no match")
}
}
// checksum calculates the checksum over the given list of `boxIds`.
func Checksum(boxIds []string) int {
var x, y int
for _, id := range boxIds {
if hasNOfAnyLetter(id, 2) {
x++
}
if hasNOfAnyLetter(id, 3) {
y++
}
}
return x * y
}
// hasNOfAnyLetter checks the given `boxId` for a character that occurs exactly `n` times.
func hasNOfAnyLetter(boxId string, n int) bool {
var occurrences = make(map[rune]int)
// Count occurrences of each character in the boxId
for _, c := range boxId {
occurrences[c]++
}
// Check the occurrences for a value that matches n
for _, i := range occurrences {
if i == n {
return true
}
}
return false
}
// MatchBoxIDs looks for a pair of box IDs in the given list that differ by exactly one character at the same position. It returns the boxID with that one character removed, if found.
func MatchBoxIDs(boxIDs []string) (string, bool) {
if len(boxIDs) == 0 {
return "", false
}
length := len(boxIDs[0])
for pos := 0; pos < length; pos++ {
altered := make([]string, len(boxIDs))
for i, boxID := range boxIDs {
altered[i] = removeCharacterAt(boxID, pos)
}
if found, ok := findDuplicate(altered); ok {
return found, true
}
}
return "", false
}
// findDuplicate looks for a pair of strings in the given list that are equal. It returns the duplicate string if found.
func findDuplicate(input []string) (string, bool) {
var visited = make(map[string]bool)
for _, item := range input {
if visited[item] {
return item, true
}
visited[item] = true
}
return "", false
}
// removeCharacterAt takes an input string and removes the character at the given position. The result of the operation is returned
func removeCharacterAt(input string, position int) string {
length := len(input)
if position == 0 {
return input[1:]
}
if position == len(input)-1 {
return input[0 : length-1]
}
return input[0:position] + input[position+1:]
}