Modernize Go: slices, range-over-int, min builtin

This commit is contained in:
Ian Gulliver
2026-02-16 09:55:42 -08:00
parent 8ec03f1d96
commit b08584f1d6

58
main.go
View File

@@ -10,11 +10,11 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"html/template" "html/template"
"math/rand"
"log" "log"
"math/rand"
"net/http" "net/http"
"os" "os"
"sort" "slices"
"strconv" "strconv"
"strings" "strings"
texttemplate "text/template" texttemplate "text/template"
@@ -179,12 +179,9 @@ func authorize(r *http.Request) (string, bool) {
} }
func isAdmin(email string) bool { func isAdmin(email string) bool {
for _, a := range strings.Split(os.Getenv("ADMINS"), ",") { return slices.ContainsFunc(strings.Split(os.Getenv("ADMINS"), ","), func(a string) bool {
if strings.TrimSpace(a) == email { return strings.TrimSpace(a) == email
return true })
}
}
return false
} }
func requireAdmin(w http.ResponseWriter, r *http.Request) (string, bool) { func requireAdmin(w http.ResponseWriter, r *http.Request) (string, bool) {
@@ -825,14 +822,7 @@ func handleCreateConstraint(db *sql.DB) http.HandlerFunc {
http.Error(w, "forbidden", http.StatusForbidden) http.Error(w, "forbidden", http.StatusForbidden)
return return
} }
owns := false if !slices.Contains(myStudentIDs, body.StudentAID) {
for _, sid := range myStudentIDs {
if sid == body.StudentAID {
owns = true
break
}
}
if !owns {
http.Error(w, "forbidden", http.StatusForbidden) http.Error(w, "forbidden", http.StatusForbidden)
return return
} }
@@ -1026,7 +1016,7 @@ func handleSolve(db *sql.DB) http.HandlerFunc {
} }
groups := map[int][]int{} groups := map[int][]int{}
for i := 0; i < n; i++ { for i := range n {
root := ufFind(i) root := ufFind(i)
groups[root] = append(groups[root], i) groups[root] = append(groups[root], i)
} }
@@ -1054,7 +1044,7 @@ func handleSolve(db *sql.DB) http.HandlerFunc {
if sameRoom { s -= pnMultiple } if sameRoom { s -= pnMultiple }
} }
} }
for i := 0; i < n; i++ { for i := range n {
if hasPrefer[i] && !gotPrefer[i] { if hasPrefer[i] && !gotPrefer[i] {
s -= npCost s -= npCost
} }
@@ -1083,9 +1073,7 @@ func handleSolve(db *sql.DB) http.HandlerFunc {
for _, members := range groups { for _, members := range groups {
groupList = append(groupList, members) groupList = append(groupList, members)
} }
sort.Slice(groupList, func(i, j int) bool { slices.SortFunc(groupList, func(a, b []int) int { return len(b) - len(a) })
return len(groupList[i]) > len(groupList[j])
})
roomCap := make([]int, numRooms) roomCap := make([]int, numRooms)
for i := range roomCap { roomCap[i] = roomSize } for i := range roomCap { roomCap[i] = roomSize }
@@ -1095,7 +1083,7 @@ func handleSolve(db *sql.DB) http.HandlerFunc {
placeGroups = func(gi int) bool { placeGroups = func(gi int) bool {
if gi >= len(groupList) { return true } if gi >= len(groupList) { return true }
grp := groupList[gi] grp := groupList[gi]
for room := 0; room < numRooms; room++ { for room := range numRooms {
if roomCap[room] < len(grp) { continue } if roomCap[room] < len(grp) { continue }
ok := true ok := true
for _, member := range grp { for _, member := range grp {
@@ -1105,11 +1093,11 @@ func handleSolve(db *sql.DB) http.HandlerFunc {
if p[1] == member { partner = p[0] } if p[1] == member { partner = p[0] }
if partner >= 0 && assignment[partner] == room { if partner >= 0 && assignment[partner] == room {
alreadyPlaced := false alreadyPlaced := false
for gj := 0; gj < gi; gj++ { for gj := range gi {
for _, m := range groupList[gj] { if slices.Contains(groupList[gj], partner) {
if m == partner { alreadyPlaced = true; break } alreadyPlaced = true
break
} }
if alreadyPlaced { break }
} }
if alreadyPlaced { ok = false; break } if alreadyPlaced { ok = false; break }
} }
@@ -1127,7 +1115,7 @@ func handleSolve(db *sql.DB) http.HandlerFunc {
placed = placeGroups(0) placed = placeGroups(0)
if !placed { if !placed {
for i := 0; i < n; i++ { for i := range n {
assignment[i] = i % numRooms assignment[i] = i % numRooms
} }
} }
@@ -1151,7 +1139,7 @@ func handleSolve(db *sql.DB) http.HandlerFunc {
for root := range groups { for root := range groups {
uniqueGroups = append(uniqueGroups, root) uniqueGroups = append(uniqueGroups, root)
} }
sort.Ints(uniqueGroups) slices.Sort(uniqueGroups)
hillClimb := func(assignment []int) int { hillClimb := func(assignment []int) int {
currentScore := score(assignment) currentScore := score(assignment)
@@ -1165,7 +1153,7 @@ func handleSolve(db *sql.DB) http.HandlerFunc {
grp := groups[gRoot] grp := groups[gRoot]
gRoom := assignment[grp[0]] gRoom := assignment[grp[0]]
for room := 0; room < numRooms; room++ { for room := range numRooms {
if room == gRoom { continue } if room == gRoom { continue }
if roomCount(assignment, room)+len(grp) > roomSize { continue } if roomCount(assignment, room)+len(grp) > roomSize { continue }
for _, m := range grp { assignment[m] = room } for _, m := range grp { assignment[m] = room }
@@ -1257,7 +1245,7 @@ func handleSolve(db *sql.DB) http.HandlerFunc {
perturb := func(src []int, count int) { perturb := func(src []int, count int) {
copy(assignment, src) copy(assignment, src)
indices := rand.Perm(len(uniqueGroups)) indices := rand.Perm(len(uniqueGroups))
if count > len(indices) { count = len(indices) } count = min(count, len(indices))
for _, gi := range indices[:count] { for _, gi := range indices[:count] {
grp := groups[uniqueGroups[gi]] grp := groups[uniqueGroups[gi]]
oldRoom := assignment[grp[0]] oldRoom := assignment[grp[0]]
@@ -1279,7 +1267,7 @@ func handleSolve(db *sql.DB) http.HandlerFunc {
copy(bestAssignment, assignment) copy(bestAssignment, assignment)
} }
for restart := 0; restart < 30; restart++ { for range 30 {
if randomPlacement() { if randomPlacement() {
s := hillClimb(assignment) s := hillClimb(assignment)
if s > bestScore { if s > bestScore {
@@ -1289,7 +1277,7 @@ func handleSolve(db *sql.DB) http.HandlerFunc {
} }
} }
for ils := 0; ils < 200; ils++ { for range 200 {
perturb(bestAssignment, 2+rand.Intn(3)) perturb(bestAssignment, 2+rand.Intn(3))
s := hillClimb(assignment) s := hillClimb(assignment)
if s > bestScore { if s > bestScore {
@@ -1308,13 +1296,13 @@ func handleSolve(db *sql.DB) http.HandlerFunc {
roomMap[room] = append(roomMap[room], roomMember{ID: sid, Name: studentName[sid]}) roomMap[room] = append(roomMap[room], roomMember{ID: sid, Name: studentName[sid]})
} }
var rooms [][]roomMember var rooms [][]roomMember
for room := 0; room < numRooms; room++ { for room := range numRooms {
if members, ok := roomMap[room]; ok { if members, ok := roomMap[room]; ok {
sort.Slice(members, func(i, j int) bool { return members[i].Name < members[j].Name }) slices.SortFunc(members, func(a, b roomMember) int { return strings.Compare(a.Name, b.Name) })
rooms = append(rooms, members) rooms = append(rooms, members)
} }
} }
sort.Slice(rooms, func(i, j int) bool { return rooms[i][0].Name < rooms[j][0].Name }) slices.SortFunc(rooms, func(a, b []roomMember) int { return strings.Compare(a[0].Name, b[0].Name) })
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]any{"rooms": rooms, "score": bestScore}) json.NewEncoder(w).Encode(map[string]any{"rooms": rooms, "score": bestScore})