-
Notifications
You must be signed in to change notification settings - Fork 3
/
main.go
123 lines (106 loc) · 1.95 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
package main
func fs1(p1 int, p2 int) int {
score1 := 0
score2 := 0
dice := newDice()
for {
p1 = play(p1, dice)
score1 += p1 + 1
if score1 >= 1000 {
return score2 * dice.rolled
}
p2 = play(p2, dice)
score2 += p2 + 1
if score1 >= 1000 {
return score1 * dice.rolled
}
}
}
func play(p int, d *Dice) int {
v := d.roll() + d.roll() + d.roll()
return (p + v) % 10
}
type Dice struct {
i int
rolled int
}
func newDice() *Dice {
return &Dice{
i: 1,
}
}
func (d *Dice) roll() int {
d.rolled++
v := d.i
d.i++
if d.i > 100 {
d.i = 1
}
return v
}
func fs2(p1 int, p2 int) int {
a, b := dirac(true, 0, 0, p1, p2, make(map[Key]Value), 1)
if a > b {
return a
}
return b
}
type Key struct {
player1ToPlay bool
score1 int
score2 int
p1 int
p2 int
universe int
}
type Value struct {
p1 int
p2 int
}
func init() {
calcOptions(0, 3)
}
func calcOptions(sum, dice int) {
if dice == 0 {
options[sum]++
return
}
for i := 1; i <= 3; i++ {
calcOptions(sum+i, dice-1)
}
}
var options = make(map[int]int)
func dirac(player1ToPlay bool, score1, score2, p1, p2 int, visited map[Key]Value, universe int) (int, int) {
k := Key{player1ToPlay, score1, score2, p1, p2, universe}
if v, exists := visited[k]; exists {
return v.p1, v.p2
}
sumP1 := 0
sumP2 := 0
for dice := 3; dice <= 9; dice++ {
const win = 21
if player1ToPlay {
p := (p1 + dice) % 10
score := score1 + p + 1
if score >= win {
sumP1 += universe * options[dice]
continue
}
a, b := dirac(!player1ToPlay, score, score2, p, p2, visited, universe*options[dice])
sumP1 += a
sumP2 += b
} else {
p := (p2 + dice) % 10
score := score2 + p + 1
if score >= win {
sumP2 += universe * options[dice]
continue
}
a, b := dirac(!player1ToPlay, score1, score, p1, p, visited, universe*options[dice])
sumP1 += a
sumP2 += b
}
}
visited[k] = Value{sumP1, sumP2}
return sumP1, sumP2
}