hackathon/question/q01.go

151 lines
2.8 KiB
Go

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
}
func init() {
const directions = "NSWE"
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
for i := 0; i < 100; i++ {
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))
}
n := rand.Intn(20) + 10
locX, locY := q1P1(res[:n])
dup := rand.Intn(20) + 35
lastX, lastY := q1P1(res[:dup])
fmt.Println(locX, locY)
fmt.Println(lastX, lastY)
fmt.Println(dup)
dX := math.Max(float64(locX), float64(lastX)) - math.Min(float64(locX), float64(lastX))
if locX > lastX {
res[dup] = fmt.Sprintf("E%d", int(dX))
dup++
} else if locX < lastX {
res[dup] = fmt.Sprintf("W%d", int(dX))
dup++
}
fmt.Println(res[dup-1])
fmt.Println("!!")
if locY > lastY {
res[dup] = fmt.Sprintf("N%d", int(math.Max(float64(locY), float64(lastY))-math.Min(float64(locY), float64(lastY))))
} else if locY < lastY {
res[dup] = fmt.Sprintf("S%d", int(math.Max(float64(locY), float64(lastY))-math.Min(float64(locY), float64(lastY))))
}
return strings.Join(res, "\n")
},
Validate: func(u *models.User, level Part, input string) bool {
inp := q.Generate(u)
lastX, lastY := q1P1(strings.Split(inp, "\n"))
if level == Part1 {
total := q1Total(lastX, lastY)
return strconv.Itoa(total) == input
}
lastX, lastY = q1P2(strings.Split(inp, "\n"))
if level == Part2 {
total := q1Total(lastX, lastY)
return strconv.Itoa(total) == input
}
return false
},
}
Register(q)
}
//go:embed prompts/q01.md
var q01Text string