152 lines
2.8 KiB
Go
152 lines
2.8 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type container struct {
|
|
value int
|
|
name string
|
|
}
|
|
|
|
func main() {
|
|
if len(os.Args) < 2 {
|
|
fmt.Println("Usage: day17 <liters>")
|
|
os.Exit(1)
|
|
}
|
|
total := mustAtoi(os.Args[1])
|
|
|
|
var input []string
|
|
scanner := bufio.NewScanner(os.Stdin)
|
|
for scanner.Scan() {
|
|
input = append(input, scanner.Text())
|
|
}
|
|
|
|
var containers []container
|
|
for i := range input {
|
|
val := mustAtoi(input[i])
|
|
// Generate a name for this container
|
|
var u int
|
|
for j := range containers {
|
|
if containers[j].value == val {
|
|
u++
|
|
}
|
|
}
|
|
n := strconv.Itoa(val) + "-" + strconv.Itoa(u)
|
|
containers = append(containers, container{value: val, name: n})
|
|
}
|
|
fmt.Println("All Containers: ")
|
|
fmt.Println(containers)
|
|
fmt.Println()
|
|
|
|
fmt.Println("Finding Combinations...")
|
|
res := findCombis(total, containers)
|
|
var final [][]container
|
|
fmt.Println()
|
|
fmt.Println("Sorting Results...")
|
|
for i := 0; i < len(res); i++ {
|
|
tst := sortContainers(res[i])
|
|
var dup bool
|
|
for j := 0; j < len(final); j++ {
|
|
if isEqual(tst, final[j]) {
|
|
dup = true
|
|
}
|
|
}
|
|
if !dup {
|
|
final = append(final, tst)
|
|
}
|
|
}
|
|
minNum := len(final[0])
|
|
var minConfig [][]container
|
|
for i := 0; i < len(final); i++ {
|
|
if len(final[i]) < minNum {
|
|
minNum = len(final[i])
|
|
}
|
|
}
|
|
for i := 0; i < len(final); i++ {
|
|
if len(final[i]) == minNum {
|
|
minConfig = append(minConfig, final[i])
|
|
}
|
|
}
|
|
|
|
fmt.Print("Total Combinations: ")
|
|
fmt.Println(strconv.Itoa(len(final)))
|
|
|
|
fmt.Println("Minimum Containers: " + strconv.Itoa(minNum))
|
|
fmt.Println("Num Configurations: " + strconv.Itoa(len(minConfig)))
|
|
}
|
|
|
|
func findCombis(total int, containers []container) [][]container {
|
|
var ret [][]container
|
|
|
|
for i := range containers {
|
|
if total == containers[i].value {
|
|
fmt.Print("O")
|
|
ret = append(ret, []container{containers[i]})
|
|
}
|
|
if containers[i].value < total {
|
|
fmt.Print(".")
|
|
bld := []container{containers[i]}
|
|
|
|
var pass []container
|
|
for j := range containers {
|
|
if i != j {
|
|
pass = append(pass, containers[j])
|
|
}
|
|
}
|
|
|
|
tmp := findCombis((total - containers[i].value), pass)
|
|
|
|
for idx := 0; idx < len(tmp); idx++ {
|
|
tmp[idx] = append(bld, tmp[idx]...)
|
|
}
|
|
ret = append(ret, tmp...)
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func sortContainers(c []container) []container {
|
|
n := len(c)
|
|
swapped := true
|
|
for swapped {
|
|
swapped = false
|
|
for i := 1; i <= n-1; i++ {
|
|
if strings.Compare(c[i-1].name, c[i].name) > 0 {
|
|
tmp := c[i-1]
|
|
c[i-1] = c[i]
|
|
c[i] = tmp
|
|
swapped = true
|
|
}
|
|
}
|
|
n = n - 1
|
|
}
|
|
return c
|
|
}
|
|
|
|
func isEqual(a, b []container) bool {
|
|
if len(a) != len(b) {
|
|
return false
|
|
}
|
|
for i := 0; i < len(a); i++ {
|
|
if a[i].name != b[i].name {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func mustAtoi(s string) int {
|
|
var i int
|
|
var err error
|
|
if i, err = strconv.Atoi(s); err != nil {
|
|
fmt.Println("Tried to atoi " + s)
|
|
os.Exit(1)
|
|
}
|
|
return i
|
|
}
|