Modernize Go: slices, range-over-int, min builtin
This commit is contained in:
58
main.go
58
main.go
@@ -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})
|
||||||
|
|||||||
Reference in New Issue
Block a user