hackathon/question/q03/q03.go

120 lines
2.0 KiB
Go

2022-04-28 23:31:09 +07:00
package q03
import (
_ "embed"
"fmt"
"math/rand"
"strconv"
"strings"
"text/template"
"github.com/hhhapz/codequest/models"
"github.com/hhhapz/codequest/question"
)
type weightedChoice struct {
weight int
value int
}
func weightedRandom(choices []weightedChoice, r *rand.Rand) int {
var total int
for _, c := range choices {
total += c.weight
}
rnd := r.Intn(total)
for _, c := range choices {
if rnd < c.weight {
return c.value
}
rnd -= c.weight
}
panic("unreachable")
}
func init() {
t := template.New("dragon")
var err error
t, err = t.Parse(q03Text)
if err != nil {
panic(err)
}
question.Register(
&question.Question{
ID: "dragon",
Name: "The Dragon Festival",
Text: t,
Level: question.Level1,
Generate: func(u *models.User) string {
inp := generate(u)
res := make([]string, rows)
for i, row := range inp {
for _, n := range row {
res[i] += strconv.Itoa(n)
}
}
return strings.Join(res, "\n")
},
Validate: func(u *models.User, part question.Part, solution string) bool {
return Validate(u, part, solution)
},
})
}
const (
rows = 120
cols = 80
)
var numWeights = []weightedChoice{
{weight: 1, value: 0},
{weight: 4, value: 1},
{weight: 4, value: 2},
{weight: 4, value: 3},
{weight: 4, value: 4},
{weight: 4, value: 5},
{weight: 4, value: 6},
{weight: 2, value: 7},
{weight: 2, value: 8},
{weight: 1, value: 9},
}
func generate(u *models.User) [][]int {
res := make([][]int, rows)
r := question.UserRandom(u)
for i := 0; i < rows; i++ {
res[i] = make([]int, cols)
for j := 0; j < cols; j++ {
res[i][j] = weightedRandom(numWeights, r)
}
}
return res
}
func Validate(u *models.User, p question.Part, sol string) bool {
inp := generate(u)
var n int
switch p {
case question.Part1:
n = solveP1(inp)
case question.Part2:
n = solveP2(inp)
default:
return false
}
fmt.Println("submitted", sol)
fmt.Println("actual", n)
return strconv.Itoa(n) == sol
}
//go:embed q03.md
var q03Text string