package main import ( "encoding/json" "math" "net/http" ) type Container struct { Length float64 `json:"length"` Width float64 `json:"width"` Height float64 `json:"height"` } type Box struct { Length float64 `json:"length"` Width float64 `json:"width"` Height float64 `json:"height"` } type Placement struct { X, Y, Z float64 `json:"x"` } func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "index.html") }) http.HandleFunc("/calculate", func(w http.ResponseWriter, r *http.Request) { var data struct { Container Container `json:"container"` Box Box `json:"box"` } json.NewDecoder(r.Body).Decode(&data) layout := optimizePacking(data.Container, data.Box) count := len(layout) response := struct { Count int `json:"count"` Layout []Placement `json:"layout"` }{ Count: count, Layout: layout, } json.NewEncoder(w).Encode(response) }) http.ListenAndServe(":8080", nil) } func optimizePacking(con Container, box Box) []Placement { var bestLayout []Placement maxCount := 0 rotations := generateRotations(box) for _, r := range rotations { for _, strategy := range []string{"XY", "XZ", "YX", "YZ", "ZX", "ZY"} { var xCount, yCount, zCount float64 switch strategy { case "XY": xCount = math.Floor(con.Length / r.Length) yCount = math.Floor(con.Width / r.Width) zCount = math.Floor(con.Height / r.Height) case "XZ": xCount = math.Floor(con.Length / r.Length) zCount = math.Floor(con.Height / r.Height) yCount = math.Floor(con.Width / r.Width) case "YX": yCount = math.Floor(con.Width / r.Length) xCount = math.Floor(con.Length / r.Width) zCount = math.Floor(con.Height / r.Height) case "YZ": yCount = math.Floor(con.Width / r.Length) zCount = math.Floor(con.Height / r.Height) xCount = math.Floor(con.Length / r.Width) case "ZX": zCount = math.Floor(con.Height / r.Length) xCount = math.Floor(con.Length / r.Width) yCount = math.Floor(con.Width / r.Height) case "ZY": zCount = math.Floor(con.Height / r.Length) yCount = math.Floor(con.Width / r.Height) xCount = math.Floor(con.Length / r.Width) } total := int(xCount * yCount * zCount) if total > maxCount && total > 0 { maxCount = total layout := generateLayout(r, xCount, yCount, zCount, strategy) bestLayout = layout } } } return bestLayout } func generateRotations(box Box) []Box { return []Box{ {box.Length, box.Width, box.Height}, {box.Length, box.Height, box.Width}, {box.Width, box.Length, box.Height}, {box.Width, box.Height, box.Length}, {box.Height, box.Length, box.Width}, {box.Height, box.Width, box.Length}, } } func generateLayout(r Box, xCount, yCount, zCount float64, strategy string) []Placement { var layout []Placement switch strategy { case "XY": for x := 0.0; x < xCount; x++ { for y := 0.0; y < yCount; y++ { for z := 0.0; z < zCount; z++ { layout = append(layout, Placement{ X: x * r.Length, Y: z * r.Height, Z: y * r.Width, }) } } } case "XZ": for x := 0.0; x < xCount; x++ { for z := 0.0; z < zCount; z++ { for y := 0.0; y < yCount; y++ { layout = append(layout, Placement{ X: x * r.Length, Y: z * r.Height, Z: y * r.Width, }) } } } case "YX": for y := 0.0; y < yCount; y++ { for x := 0.0; x < xCount; x++ { for z := 0.0; z < zCount; z++ { layout = append(layout, Placement{ X: x * r.Width, Y: z * r.Height, Z: y * r.Length, }) } } } case "YZ": for y := 0.0; y < yCount; y++ { for z := 0.0; z < zCount; z++ { for x := 0.0; x < xCount; x++ { layout = append(layout, Placement{ X: x * r.Width, Y: z * r.Height, Z: y * r.Length, }) } } } case "ZX": for z := 0.0; z < zCount; z++ { for x := 0.0; x < xCount; x++ { for y := 0.0; y < yCount; y++ { layout = append(layout, Placement{ X: x * r.Width, Y: z * r.Length, Z: y * r.Height, }) } } } case "ZY": for z := 0.0; z < zCount; z++ { for y := 0.0; y < yCount; y++ { for x := 0.0; x < xCount; x++ { layout = append(layout, Placement{ X: x * r.Width, Y: z * r.Length, Z: y * r.Height, }) } } } } return layout }