-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
149 lines (120 loc) · 2.51 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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package main
import (
"encoding/csv"
"fmt"
"io"
"os"
"path"
"strconv"
)
func input() *os.File {
input, err := os.Open(path.Join("2019", "4", "input.txt"))
if err != nil {
panic(err)
}
return input
}
func parse(r io.Reader) (int, int) {
csvReader := csv.NewReader(r)
row, err := csvReader.Read()
if err != nil {
panic(err)
}
min, err := strconv.Atoi(row[0])
if err != nil {
panic(err)
}
max, err := strconv.Atoi(row[1])
if err != nil {
panic(err)
}
return min, max
}
// returns the digits that make up value
func digits(val int) []int {
ret := []int{0, 0, 0, 0, 0, 0}
for i := 5; i >= 0; i-- {
ret[i] = val % 10
val /= 10
}
return ret
}
// modifies digs to represent the next value after the one digs represents which still has all digits non-decreasing
// faster, but requires the input to already be non-decreasing
func incrementFast(digs []int) {
for i := len(digs) - 1; i > -1; i-- {
if digs[i] != 9 {
digs[i] += 1
for j := i + 1; j < len(digs); j++ {
digs[j] = digs[i]
}
return
}
}
panic("can't increment 999999")
}
// modifies digs to represent the next value after the one digs represents which still has all digits non-decreasing
// slower, but has no preconditions on the input
func incrementSlow(digs []int) {
// increase by 1
for i := 5; i >= 0; i-- {
digs[i] += 1
if digs[i] == 10 {
digs[i] = 0
} else {
break
}
}
// set to next non-decreasing number
for i := 1; i < 6; i++ {
if digs[i] < digs[i-1] {
for k := i; k < 6; k++ {
digs[k] = digs[i-1]
}
}
}
}
// returns whether the number a represents is less than the number b represents
func isLessThanOrEqual(a, b []int) bool {
for i := 0; i < 6; i++ {
if a[i] < b[i] {
return true
}
if a[i] > b[i] {
return false
}
}
return true
}
func solve(min, max int) int {
result := 0
maxDigs := digits(max)
// start with digits that meet the non-decreasing rule
digs := digits(min - 1)
incrementSlow(digs)
// check range rule
for isLessThanOrEqual(digs, maxDigs) {
// check double rule
double := false
for j := 1; j < 6; j++ {
if digs[j] == digs[j-1] {
double = true
break
}
}
// non-decreasing and range rules are already met
if double {
result += 1
}
// get next non-decreasing rule following number
incrementFast(digs)
}
return result
}
func main() {
fmt.Printf("%v\n", digits(123456))
fmt.Println(solve(111111, 111111))
fmt.Println(solve(223450, 223450))
fmt.Println(solve(123789, 123789))
fmt.Println(solve(parse(input())))
}