code.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "log"
  6. "os"
  7. "strconv"
  8. "strings"
  9. )
  10. func readInput(file string) []string {
  11. content, err := ioutil.ReadFile(file)
  12. if err != nil {
  13. log.Fatal(err)
  14. }
  15. lines := strings.Split(string(content), "\n")
  16. return lines
  17. }
  18. func part1(lines []string) int64 {
  19. var gamma []string
  20. var epsilon []string
  21. for i := 0; i < len(lines[0]); i++ {
  22. counts := []int{0, 0}
  23. for _, line := range lines {
  24. if line[i] == '0' {
  25. counts[0]++
  26. } else {
  27. counts[1]++
  28. }
  29. }
  30. if counts[0] > counts[1] {
  31. gamma = append(gamma, "0")
  32. epsilon = append(epsilon, "1")
  33. } else {
  34. gamma = append(gamma, "1")
  35. epsilon = append(epsilon, "0")
  36. }
  37. }
  38. gammaNumber, err := strconv.ParseInt(strings.Join(gamma, ""), 2, 64)
  39. if err != nil {
  40. log.Fatal(err)
  41. }
  42. epsilonNumber, err := strconv.ParseInt(strings.Join(epsilon, ""), 2, 64)
  43. if err != nil {
  44. log.Fatal(err)
  45. }
  46. return gammaNumber * epsilonNumber
  47. }
  48. func keepWith(slice []string, index int, char byte) []string {
  49. var newSlice []string
  50. for _, line := range slice {
  51. if line[index] == char {
  52. newSlice = append(newSlice, line)
  53. }
  54. }
  55. return newSlice
  56. }
  57. func most(lines []string, values []byte, counts []int, index int) []string {
  58. if counts[0] > counts[1] {
  59. return keepWith(lines, index, values[0])
  60. }
  61. return keepWith(lines, index, values[1])
  62. }
  63. func least(lines []string, values []byte, counts []int, index int) []string {
  64. if counts[0] < counts[1] {
  65. return keepWith(lines, index, values[0])
  66. }
  67. return keepWith(lines, index, values[1])
  68. }
  69. func filter(lines []string, values []byte, decision func([]string, []byte, []int, int) []string) string {
  70. for i := 0; i < len(lines[0]); i++ {
  71. if len(lines) == 1 {
  72. break
  73. }
  74. counts := []int{0, 0}
  75. for _, line := range lines {
  76. if line[i] == values[0] {
  77. counts[0]++
  78. } else {
  79. counts[1]++
  80. }
  81. }
  82. lines = decision(lines, values, counts, i)
  83. }
  84. if len(lines) == 1 {
  85. return lines[0]
  86. }
  87. return ""
  88. }
  89. func part2(lines []string) int64 {
  90. generator := make([]string, len(lines))
  91. copy(generator, lines)
  92. scrubber := make([]string, len(lines))
  93. copy(scrubber, lines)
  94. generatorNumber, err := strconv.ParseInt(filter(generator, []byte{'0', '1'}, most), 2, 64)
  95. if err != nil {
  96. log.Fatal(err)
  97. }
  98. scrubberNumber, err := strconv.ParseInt(filter(scrubber, []byte{'1', '0'}, least), 2, 64)
  99. if err != nil {
  100. log.Fatal(err)
  101. }
  102. return generatorNumber * scrubberNumber
  103. }
  104. func main() {
  105. if len(os.Args) < 2 {
  106. log.Fatal("You need to provide path to input file!")
  107. }
  108. lines := readInput(os.Args[1])
  109. fmt.Println("Part1: ", part1(lines))
  110. fmt.Println("Part2: ", part2(lines))
  111. }