You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

main.go 1.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. package main
  2. import (
  3. "github.com/csmith/aoc-2019/common"
  4. "math"
  5. "strings"
  6. )
  7. type chemical string
  8. type recipeBook map[chemical]*recipe
  9. type amount struct {
  10. chemical chemical
  11. quantity int
  12. }
  13. type recipe struct {
  14. produces *amount
  15. requires []*amount
  16. }
  17. func parseAmount(text string) *amount {
  18. parts := strings.Split(text, " ")
  19. return &amount{
  20. quantity: common.MustAtoi(parts[0]),
  21. chemical: chemical(parts[1]),
  22. }
  23. }
  24. func parseInput(file string) recipeBook {
  25. recipes := make(map[chemical]*recipe)
  26. for _, line := range common.ReadFileAsStrings(file) {
  27. parts := strings.Split(line, " => ")
  28. ingredients := strings.Split(parts[0], ", ")
  29. r := &recipe{
  30. produces: parseAmount(parts[1]),
  31. requires: make([]*amount, 0, len(ingredients)),
  32. }
  33. for _, in := range ingredients {
  34. r.requires = append(r.requires, parseAmount(in))
  35. }
  36. recipes[r.produces.chemical] = r
  37. }
  38. return recipes
  39. }
  40. func (rb recipeBook) produce(target chemical, quantity int, used map[chemical]int, spare map[chemical]int) {
  41. recipe := rb[target]
  42. needed := quantity
  43. if recipe == nil {
  44. used[target] += needed
  45. return
  46. }
  47. free := spare[target]
  48. if free >= needed {
  49. used[target] += needed
  50. spare[target] -= needed
  51. return
  52. } else {
  53. used[target] += free
  54. spare[target] = 0
  55. needed -= free
  56. }
  57. runs := int(math.Ceil(float64(needed) / float64(recipe.produces.quantity)))
  58. for _, i := range recipe.requires {
  59. rb.produce(i.chemical, i.quantity*runs, used, spare)
  60. }
  61. used[target] += needed
  62. spare[target] += (recipe.produces.quantity * runs) - needed
  63. }
  64. func main() {
  65. recipes := parseInput("14/input.txt")
  66. used := make(map[chemical]int, len(recipes))
  67. spare := make(map[chemical]int, len(recipes))
  68. recipes.produce("FUEL", 1, used, spare)
  69. orePerFuel := used["ORE"]
  70. println(used["ORE"])
  71. last := 0
  72. for used["ORE"] < 1000000000000 {
  73. last = used["FUEL"]
  74. recipes.produce("FUEL", common.Max(1, (1000000000000-used["ORE"])/orePerFuel), used, spare)
  75. }
  76. println(last)
  77. }