hackathon/question/q01.go

151 lines
2.6 KiB
Go

2021-12-20 13:00:56 +07:00
package question
import (
_ "embed"
"fmt"
"math"
"math/rand"
"strconv"
"strings"
"github.com/hhhapz/codequest/models"
)
func move(x, y int, dir byte, step int) (int, int) {
switch dir {
case 'N':
return x, y + step
case 'S':
return x, y - step
case 'E':
return x + step, y
case 'W':
return x - step, y
}
return x, y
}
func q1P1(steps []string) (x int, y int) {
for _, step := range steps {
dir := step[0]
amt, _ := strconv.Atoi(step[1:])
x, y = move(x, y, dir, amt)
}
return
}
func q1P2(steps []string) (x int, y int) {
known := make(map[int]map[int]bool)
for _, step := range steps {
dir := step[0]
amt, _ := strconv.Atoi(step[1:])
x, y = move(x, y, dir, amt)
if known[x] == nil {
known[x] = make(map[int]bool)
}
if known[x][y] {
return
}
known[x][y] = true
}
return
}
func q1Total(a, b int) int {
if a < 0 {
a = -a
}
if b < 0 {
b = -b
}
return a + b
}
2021-12-20 15:42:41 +07:00
const (
q1Entries = 100
q1Range = 20
directions = "NSWE"
)
2021-12-20 13:00:56 +07:00
func init() {
var q *Question
q = &Question{
ID: "directions",
Text: q01Text,
Level: Level1,
Generate: func(u *models.User) string {
res := make([]string, 0, 100)
r := userRandom(u)
known := make(map[int]map[int]bool)
var x, y int
2021-12-20 15:42:41 +07:00
for i := 0; i < q1Entries; i++ {
2021-12-20 13:00:56 +07:00
dir := directions[r.Intn(4)]
steps := r.Intn(30) + 1
newX, newY := move(x, y, dir, steps)
if known[newX] == nil {
known[newX] = make(map[int]bool)
}
if known[newX][newY] {
i--
continue
}
known[newX][newY] = true
x, y = newX, newY
res = append(res, fmt.Sprintf("%c%d", dir, steps))
}
2021-12-20 15:42:41 +07:00
n := rand.Intn(q1Range) + 10
2021-12-20 13:00:56 +07:00
locX, locY := q1P1(res[:n])
2021-12-20 15:42:41 +07:00
n = rand.Intn(q1Range) + 35
lastX, lastY := q1P1(res[:n])
2021-12-20 13:00:56 +07:00
dX := math.Max(float64(locX), float64(lastX)) - math.Min(float64(locX), float64(lastX))
2021-12-20 15:42:41 +07:00
dY := math.Max(float64(locY), float64(lastY)) - math.Min(float64(locY), float64(lastY))
2021-12-20 13:00:56 +07:00
if locX > lastX {
2021-12-20 15:42:41 +07:00
res[n] = fmt.Sprintf("E%d", int(dX))
n++
2021-12-20 13:00:56 +07:00
} else if locX < lastX {
2021-12-20 15:42:41 +07:00
res[n] = fmt.Sprintf("W%d", int(dX))
n++
2021-12-20 13:00:56 +07:00
}
if locY > lastY {
2021-12-20 15:42:41 +07:00
res[n] = fmt.Sprintf("N%d", int(dY))
2021-12-20 13:00:56 +07:00
} else if locY < lastY {
2021-12-20 15:42:41 +07:00
res[n] = fmt.Sprintf("S%d", int(dY))
2021-12-20 13:00:56 +07:00
}
return strings.Join(res, "\n")
},
2021-12-20 15:42:41 +07:00
Validate: func(u *models.User, level Part, input string) bool {
raw := q.Generate(u)
inp := strings.Split(raw, "\n")
switch level {
case Part1:
x, y := q1P1(inp)
return q1Total(x, y) == 0
case Part2:
x, y := q1P2(inp)
return q1Total(x, y) == 0
2021-12-20 13:00:56 +07:00
}
return false
},
}
Register(q)
}
//go:embed prompts/q01.md
var q01Text string