aboutsummaryrefslogtreecommitdiff
path: root/2021/08/second.go
blob: e71c23b22d1881eca1398947001e209fa19e3f4b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"sort"
	"strconv"
	"strings"
)

func sortStrings(strs []string) {
	for i, v := range strs {
		s := strings.Split(v, "")
		sort.Strings(s)
		strs[i] = strings.Join(s, "")
	}
}

func deduceSix(one string, zns []string) string { // zns == zero, nine and six
	for _, v := range zns {
		for _, c := range one {
			if !strings.Contains(v, string(c)) {
				return v
			}
		}
	}
	log.Fatalf("deduce(%+v, %+v) failed!", one, zns)
	return ""
}

func deduceTwoThreeFive(ttf []string, topRight, bottomRight byte) (two string, three string, five string) {
	for _, s := range ttf {
		if !strings.Contains(s, string(topRight)) {
			five = s
		} else if !strings.Contains(s, string(bottomRight)) {
			two = s
		} else {
			three = s
		}
	}
	return
}

func deduceRight(one, six string) (byte, byte) {
	if strings.Contains(six, string(one[0])) {
		return one[1], one[0]
	} else {
		return one[0], one[1]
	}
}

func deduceBottomLeft(one, two, five string) byte {
	for _, ch := range two {
		s := string(ch)
		if strings.Contains(one, s) || strings.Contains(five, s) {
			continue
		}
		return s[0]
	}
	log.Fatalf("deduceBottomLeft(%+v, %+v, %+v) failed!", one, two, five)
	return 0 // cannot happen
}

func deduceZeroNine(zsn []string, six string, bottomLeft byte) (zero string, nine string) {
	for _, s := range zsn {
		if s == six {
			continue
		}
		if strings.Contains(s, string(bottomLeft)) {
			zero = s
		} else {
			nine = s
		}
	}
	return
}

func main() {
	score := 0

	s := bufio.NewScanner(os.Stdin)
	for s.Scan() {
		inputs := strings.Split(s.Text(), " | ")
		hints := strings.Split(inputs[0], " ")
		outputs := strings.Split(inputs[1], " ")
		sort.Slice(hints, func(i, j int) bool {
			return len(hints[i]) < len(hints[j])
		})
		sortStrings(hints)
		sortStrings(outputs)

		// some digits are straightforward :
		one := hints[0]
		seven := hints[1]
		four := hints[2]
		eight := hints[9]

		// We can deduce number 6 by being in len 6 and missing a component from 1
		six := deduceSix(one, hints[6:9])
		// the right segments can be deduced from the one in 1 that is in the 6
		topRight, bottomRight := deduceRight(one, six)
		// We can deduce numbers two, three and five from the right segments
		two, three, five := deduceTwoThreeFive(hints[3:6], topRight, bottomRight)
		// We can deduce the bottom left segment from 1 2 and 5
		bottomLeft := deduceBottomLeft(one, two, five)
		// We can deduce numbers 0 and 9 from the bottom left segment and the fact we already know 6
		zero, nine := deduceZeroNine(hints[6:9], six, bottomLeft)

		key := make([]byte, 4)
		for i, s := range outputs {
			switch s {
			case zero:
				key[i] = '0'
			case one:
				key[i] = '1'
			case two:
				key[i] = '2'
			case three:
				key[i] = '3'
			case four:
				key[i] = '4'
			case five:
				key[i] = '5'
			case six:
				key[i] = '6'
			case seven:
				key[i] = '7'
			case eight:
				key[i] = '8'
			case nine:
				key[i] = '9'
			default:
				fmt.Println(zero, one, two, three, four, five, six, seven, eight, nine)
				log.Fatalf("Did not find %+v", s)
			}
		}
		v, _ := strconv.Atoi(string(key))
		score += v
	}
	fmt.Println(score)
}