mirror of
https://github.com/RussellChamp/advent-of-code-2021.git
synced 2026-10-27 21:52:32 +00:00
day 8 work and jumbled together
This commit is contained in:
1 parent
e76cb1a355
commit
c7ea0afedc
18 files changed
+457
-21
No files matched your search
+2
-2
@@ -37,8 +37,8 @@ func part1() {
|
|||||||
fmt.Println(" Answer: How many measurements are larger than the previous measurement?")
|
fmt.Println(" Answer: How many measurements are larger than the previous measurement?")
|
||||||
|
|
||||||
input, err := os.Open("./input.txt")
|
input, err := os.Open("./input.txt")
|
||||||
defer input.Close()
|
|
||||||
check(err)
|
check(err)
|
||||||
|
defer input.Close()
|
||||||
|
|
||||||
scanner := bufio.NewScanner(input)
|
scanner := bufio.NewScanner(input)
|
||||||
|
|
||||||
@@ -67,8 +67,8 @@ func part2() {
|
|||||||
fmt.Println(" Answer: How many sums are larger than the previous sum?")
|
fmt.Println(" Answer: How many sums are larger than the previous sum?")
|
||||||
|
|
||||||
input, err := os.Open("./input.txt")
|
input, err := os.Open("./input.txt")
|
||||||
defer input.Close()
|
|
||||||
check(err)
|
check(err)
|
||||||
|
defer input.Close()
|
||||||
|
|
||||||
scanner := bufio.NewScanner(input)
|
scanner := bufio.NewScanner(input)
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -1,14 +1,14 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
assert "AoC2021/utils/testing"
|
"AoC2021/utils/assert"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPrintPip(t *testing.T) {
|
func TestPrintPip(t *testing.T) {
|
||||||
DEBUG = false
|
DEBUG = false
|
||||||
str := GetPip(1, 1, 1, 100)
|
str := GetPip(1, 1, 1, 100)
|
||||||
assert.StrEquals(t, str, "", "Should return an empty string")
|
assert.EqualsStr(t, str, "", "Should return an empty string")
|
||||||
|
|
||||||
DEBUG = true
|
DEBUG = true
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
@@ -24,7 +24,7 @@ func TestPrintPip(t *testing.T) {
|
|||||||
|
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
str := GetPip(c.first, c.previous, c.current, c.total)
|
str := GetPip(c.first, c.previous, c.current, c.total)
|
||||||
assert.StrEquals(t, str, c.expected, c.msg)
|
assert.EqualsStr(t, str, c.expected, c.msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+2
-2
@@ -1,11 +1,11 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
assert "AoC2021/utils/testing"
|
"AoC2021/utils/assert"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDay2(t *testing.T) {
|
func TestDay2(t *testing.T) {
|
||||||
assert.IsTrue(t, true, "cool")
|
assert.IsTrue(t, true, "cool")
|
||||||
assert.StrEquals(t, "foo", "bar", "baz")
|
assert.EqualsStr(t, "foo", "bar", "baz")
|
||||||
}
|
}
|
||||||
+2
-2
@@ -1,11 +1,11 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
assert "AoC2021/utils/testing"
|
"AoC2021/utils/assert"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDay3(t *testing.T) {
|
func TestDay3(t *testing.T) {
|
||||||
assert.IsTrue(t, true, "cool")
|
assert.IsTrue(t, true, "cool")
|
||||||
assert.StrEquals(t, "foo", "bar", "baz")
|
assert.EqualsStr(t, "foo", "bar", "baz")
|
||||||
}
|
}
|
||||||
+2
-2
@@ -1,11 +1,11 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
assert "AoC2021/utils/testing"
|
"AoC2021/utils/assert"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDay4(t *testing.T) {
|
func TestDay4(t *testing.T) {
|
||||||
assert.IsTrue(t, true, "cool")
|
assert.IsTrue(t, true, "cool")
|
||||||
assert.StrEquals(t, "foo", "bar", "baz")
|
assert.EqualsStr(t, "foo", "bar", "baz")
|
||||||
}
|
}
|
||||||
+2
-2
@@ -1,11 +1,11 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
assert "AoC2021/utils/testing"
|
"AoC2021/utils/assert"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDay6(t *testing.T) {
|
func TestDay6(t *testing.T) {
|
||||||
assert.IsTrue(t, true, "cool")
|
assert.IsTrue(t, true, "cool")
|
||||||
assert.StrEquals(t, "foo", "bar", "baz")
|
assert.EqualsStr(t, "foo", "bar", "baz")
|
||||||
}
|
}
|
||||||
+2
-2
@@ -1,11 +1,11 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
assert "AoC2021/utils/testing"
|
"AoC2021/utils/assert"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDay7(t *testing.T) {
|
func TestDay7(t *testing.T) {
|
||||||
assert.IsTrue(t, true, "cool")
|
assert.IsTrue(t, true, "cool")
|
||||||
assert.StrEquals(t, "foo", "bar", "baz")
|
assert.EqualsStr(t, "foo", "bar", "baz")
|
||||||
}
|
}
|
||||||
+232
@@ -0,0 +1,232 @@
|
|||||||
|
/* Day 8: Seven Segment Search */
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"AoC2021/utils/arrays"
|
||||||
|
"AoC2021/utils/bits"
|
||||||
|
"AoC2021/utils/log"
|
||||||
|
"AoC2021/utils/timer"
|
||||||
|
"bufio"
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func check(e error) {
|
||||||
|
if e != nil {
|
||||||
|
log.Println(log.DEBUG, "Oh snap!")
|
||||||
|
panic(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
log.Println(log.NORMAL, "--- Day 8: Seven Segment Search ---")
|
||||||
|
timer.Start()
|
||||||
|
part1()
|
||||||
|
timer.Tick()
|
||||||
|
log.Println(log.NORMAL)
|
||||||
|
|
||||||
|
part2()
|
||||||
|
timer.Tick()
|
||||||
|
log.Println(log.NORMAL)
|
||||||
|
}
|
||||||
|
|
||||||
|
func part1() {
|
||||||
|
log.Println(log.NORMAL, "* Part 1 *")
|
||||||
|
log.Println(log.NORMAL, " Goal: For now, focus on the easy digits.")
|
||||||
|
log.Println(log.NORMAL, " Answer: In the output values, how many times do digits 1, 4, 7, or 8 appear?")
|
||||||
|
|
||||||
|
input, err := os.Open("./input.txt")
|
||||||
|
check(err)
|
||||||
|
defer input.Close()
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(input)
|
||||||
|
lines := 0
|
||||||
|
ones := 0
|
||||||
|
fours := 0
|
||||||
|
sevens := 0
|
||||||
|
eights := 0
|
||||||
|
|
||||||
|
for scanner.Scan() {
|
||||||
|
fields := strings.Split(scanner.Text(), " | ")
|
||||||
|
if len(fields) != 2 {
|
||||||
|
panic("Read invalid input line")
|
||||||
|
}
|
||||||
|
_ = strings.Fields(fields[0])
|
||||||
|
// count all the ones, fours, sevens, and eights in the output strings based on how many segments are lit up
|
||||||
|
outputDigits := strings.Fields(fields[1])
|
||||||
|
for _, d := range outputDigits {
|
||||||
|
switch len(d) {
|
||||||
|
case 2:
|
||||||
|
ones += 1
|
||||||
|
case 3:
|
||||||
|
sevens += 1
|
||||||
|
case 4:
|
||||||
|
fours += 1
|
||||||
|
case 7:
|
||||||
|
eights += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lines++
|
||||||
|
}
|
||||||
|
|
||||||
|
total := ones + fours + sevens + eights
|
||||||
|
log.Printf(log.NORMAL, "Read %d lines from input\n", lines)
|
||||||
|
log.Printf(log.NORMAL, "We counted %d ones, %d fours, %d sevens, and %d eights for a total of %d\n", ones, fours, sevens, eights, total)
|
||||||
|
}
|
||||||
|
|
||||||
|
func part2() {
|
||||||
|
log.Println(log.NORMAL, "* Part 2 *")
|
||||||
|
log.Println(log.NORMAL, " Goal: For each entry, determine all of the wire/segment connections and decode the four-digit output values")
|
||||||
|
log.Println(log.NORMAL, " Answer: What do you get if you add up all of the output values?")
|
||||||
|
|
||||||
|
input, err := os.Open("./input.txt")
|
||||||
|
check(err)
|
||||||
|
defer input.Close()
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(input)
|
||||||
|
lines := 0
|
||||||
|
total := 0
|
||||||
|
|
||||||
|
for scanner.Scan() {
|
||||||
|
fields := strings.Split(scanner.Text(), " | ")
|
||||||
|
if len(fields) != 2 {
|
||||||
|
panic("Read invalid input line")
|
||||||
|
}
|
||||||
|
inputFields := strings.Fields(fields[0])
|
||||||
|
segMap := createPatternMap(arrays.MapStrToInt(inputFields, ParseField))
|
||||||
|
log.Println(log.DEBUG, "Created pattern", segMap)
|
||||||
|
|
||||||
|
outputFields := strings.Fields(fields[1])
|
||||||
|
|
||||||
|
fieldValue := 0
|
||||||
|
fieldsCount := len(outputFields)
|
||||||
|
for idx, field := range outputFields {
|
||||||
|
fValue := segMap[ParseField(field)]
|
||||||
|
log.Printf(log.DIAGNOSTIC, "field %s => %d; ", field, fValue)
|
||||||
|
fieldValue += fValue * int(math.Pow10(fieldsCount-idx-1))
|
||||||
|
}
|
||||||
|
total += fieldValue
|
||||||
|
|
||||||
|
log.Println(log.DIAGNOSTIC)
|
||||||
|
log.Printf(log.DIAGNOSTIC, "Unscrambled %s => %d\n", outputFields, fieldValue)
|
||||||
|
lines++
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf(log.NORMAL, "Read %d lines from input\n", lines)
|
||||||
|
log.Printf(log.NORMAL, "Calculated total is %d\n", total)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Represent a segment as a 7-bit value
|
||||||
|
/* Segment values are aligned as below
|
||||||
|
* aaaa
|
||||||
|
* b c
|
||||||
|
* b c
|
||||||
|
* dddd
|
||||||
|
* e f
|
||||||
|
* e f
|
||||||
|
* gggg
|
||||||
|
|
||||||
|
* segment 'a' is found in [0, 2, 3, 5, 6, 7, 8, 9] but not [1, 4]
|
||||||
|
* segment 'b' is found in [0, 4, 5, 6, 8, 9] but not [1, 2, 3, 7]
|
||||||
|
* segment 'c' is found in [0, 1, 2, 3, 4, 7, 8, 9] but not [5, 6]
|
||||||
|
* segment 'd' is found in [2, 3, 4, 5, 6, 8, 9] but not [0, 1, 7]
|
||||||
|
* segment 'e' is found in [0, 2, 6, 8] but not [1, 3, 4, 5, 7, 9]
|
||||||
|
* segment 'f' is found in [0, 1, 3, 4, 5, 6, 7, 8, 9] but not [2]
|
||||||
|
* segment 'g' is found in [0, 2, 3, 5, 6, 8, 9] but not [1, 4, 7]
|
||||||
|
*/
|
||||||
|
|
||||||
|
// parse a field from a string value to a bit-map int value (eg 'cda' to b1101 => 13)
|
||||||
|
func ParseField(field string) int {
|
||||||
|
value := 0
|
||||||
|
for _, c := range field {
|
||||||
|
value += 1 << int(rune(c)-rune('a'))
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
// func getDefaultMap() map[int]int {
|
||||||
|
// return map[int]int{
|
||||||
|
// ParseField("abcefg"): 0,
|
||||||
|
// ParseField("cf"): 1,
|
||||||
|
// ParseField("acdeg"): 2,
|
||||||
|
// ParseField("acdfg"): 3,
|
||||||
|
// ParseField("bcdf"): 4,
|
||||||
|
// ParseField("abdfg"): 5,
|
||||||
|
// ParseField("abdefg"): 6,
|
||||||
|
// ParseField("acf"): 7,
|
||||||
|
// ParseField("abcdefg"): 8,
|
||||||
|
// ParseField("abcdfg"): 9}
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Given a list of a all 10 possible 7-segment displays create a map that can be used to unscramble values
|
||||||
|
func createPatternMap(input []int) map[int]int {
|
||||||
|
// initialize our translation map that will convert from character to character (eg wire 'a' actually goes to segment 'c')
|
||||||
|
segMap := make(map[int]int)
|
||||||
|
|
||||||
|
// first find and map all the values that can be known by counting segments
|
||||||
|
// find the only pattern that matches '1'
|
||||||
|
one := arrays.FindFirstInt(input, bits.ByBitCount(2))
|
||||||
|
|
||||||
|
// next find the one that matches '7'
|
||||||
|
seven := arrays.FindFirstInt(input, bits.ByBitCount(3))
|
||||||
|
|
||||||
|
// next find the one that matches '4'
|
||||||
|
four := arrays.FindFirstInt(input, bits.ByBitCount(4))
|
||||||
|
|
||||||
|
// the one that matches '8' will be the only one with 7 segments but tells us nothing about what those segments map to
|
||||||
|
eight := arrays.FindFirstInt(input, bits.ByBitCount(7))
|
||||||
|
|
||||||
|
// the two segments in '1' will match 'c' or 'f' but we don't know yet
|
||||||
|
// the additional segment in '7' will map to segment 'a'
|
||||||
|
segMap['a'] = seven - one
|
||||||
|
// the two additional segments in '4' will match 'b' or 'd' but we're not sure which ones yet
|
||||||
|
|
||||||
|
// all of '0', '6' and '9' have 6 segments
|
||||||
|
// the six-segment field that shares only 1 side with '1' is '6'
|
||||||
|
six := arrays.FindFirstInt(input, func(v int) bool { return bits.ByBitCount(6)(v) && bits.MatchingOnBits(one, v) == 1 })
|
||||||
|
|
||||||
|
// and we know that the segment not in six is 'c'
|
||||||
|
segMap['c'] = eight - six
|
||||||
|
// and the other value 'f' will be the other segment in '1'
|
||||||
|
segMap['f'] = one - segMap['c']
|
||||||
|
// but we can't yet place '0' or '9' with what we know
|
||||||
|
|
||||||
|
// all of '2', '3', and '5' have 5 segments
|
||||||
|
// three is the only 5 segment field that matches 3 bits in '7'
|
||||||
|
three := arrays.FindFirstInt(input, func(v int) bool { return bits.ByBitCount(5)(v) && bits.MatchingOnBits(seven, v) == 3 })
|
||||||
|
// the additional two segments are 'd' ang 'g' but we can't place them yet
|
||||||
|
// five is the other 5 segment field that matches 3 bits in '4'
|
||||||
|
five := arrays.FindFirstInt(input, func(v int) bool { return bits.ByBitCount(5)(v) && v != three && bits.MatchingOnBits(four, v) == 3 })
|
||||||
|
// segments 'b', 'd', and 'g' can't yet be placed
|
||||||
|
// but segment 'e' is what we get by subtracting five from six
|
||||||
|
segMap['e'] = six - five
|
||||||
|
|
||||||
|
// the last five segment number must be 2
|
||||||
|
two := arrays.FindFirstInt(input, func(v int) bool { return bits.ByBitCount(5)(v) && v != three && v != five })
|
||||||
|
|
||||||
|
// segment 'g' is the only one that doesn't appear in '1', '4', or '7' and is not 'e'
|
||||||
|
segMap['g'] = eight - bits.BitwiseAndA(one, four, seven, segMap['e'])
|
||||||
|
// segment 'd' is '3' minus 'a', 'c', 'f', and 'g'
|
||||||
|
segMap['d'] = three - segMap['a'] - segMap['c'] - segMap['f'] - segMap['g']
|
||||||
|
|
||||||
|
// then we know that zero is eight minus 'd'
|
||||||
|
zero := eight - segMap['d']
|
||||||
|
// and nine will be eight minus 'e'
|
||||||
|
nine := eight - segMap['e']
|
||||||
|
|
||||||
|
log.Println(log.DIAGNOSTIC, "segMap", segMap)
|
||||||
|
|
||||||
|
return map[int]int{
|
||||||
|
zero: 0,
|
||||||
|
one: 1,
|
||||||
|
two: 2,
|
||||||
|
three: 3,
|
||||||
|
four: 4,
|
||||||
|
five: 5,
|
||||||
|
six: 6,
|
||||||
|
seven: 7,
|
||||||
|
eight: 8,
|
||||||
|
nine: 9,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"AoC2021/utils/assert"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDay8ParseField(t *testing.T) {
|
||||||
|
assert.EqualsInt(t, ParseField("abc"), 7, "should parse fields correctly")
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
assert "AoC2021/utils/testing"
|
"AoC2021/utils/assert"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -11,4 +11,7 @@ build:
|
|||||||
cd day-$(day); go run .
|
cd day-$(day); go run .
|
||||||
|
|
||||||
test:
|
test:
|
||||||
cd day-$(day); go test
|
cd day-$(day); go test
|
||||||
|
|
||||||
|
test-utils:
|
||||||
|
go test ./utils/*
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package arrays
|
||||||
|
|
||||||
|
func FindFirst(list []string, filter func(string) bool) string {
|
||||||
|
for _, item := range list {
|
||||||
|
if filter(item) {
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic("No item found that matches criteria")
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindFirstInt(list []int, filter func(int) bool) int {
|
||||||
|
for _, item := range list {
|
||||||
|
if filter(item) {
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic("No item found that matches criteria")
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindAll(list []string, filter func(string) bool) []string {
|
||||||
|
var filteredList []string
|
||||||
|
for _, item := range list {
|
||||||
|
if filter(item) {
|
||||||
|
filteredList = append(filteredList, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filteredList
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindAllInt(list []int, filter func(int) bool) []int {
|
||||||
|
var filteredList []int
|
||||||
|
for _, item := range list {
|
||||||
|
if filter(item) {
|
||||||
|
filteredList = append(filteredList, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filteredList
|
||||||
|
}
|
||||||
|
|
||||||
|
func MapStrToInt(input []string, fn func(string) int) []int {
|
||||||
|
var retVals []int
|
||||||
|
for _, s := range input {
|
||||||
|
retVals = append(retVals, fn(s))
|
||||||
|
}
|
||||||
|
return retVals
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package arrays
|
||||||
|
|
||||||
|
import (
|
||||||
|
"AoC2021/utils/assert"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFindFirst(t *testing.T) {
|
||||||
|
list := []string{"foo", "bar", "baz"}
|
||||||
|
filter := func(s string) bool { return s == "baz" }
|
||||||
|
item := FindFirst(list, filter)
|
||||||
|
|
||||||
|
assert.EqualsStr(t, item, "baz", "should find item baz")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindFirstInt(t *testing.T) {
|
||||||
|
list := []int{1, 3, 4, 5}
|
||||||
|
filter := func(i int) bool { return i%2 == 0 }
|
||||||
|
item := FindFirstInt(list, filter)
|
||||||
|
|
||||||
|
assert.EqualsInt(t, item, 4, "should find even number")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindAll(t *testing.T) {
|
||||||
|
list := []string{"hello", "world", "foo"}
|
||||||
|
filter := func(s string) bool { return len(s) > 3 }
|
||||||
|
items := FindAll(list, filter)
|
||||||
|
|
||||||
|
assert.EqualsInt(t, len(items), 2, "should filter lists of strings")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindAllInt(t *testing.T) {
|
||||||
|
list := []int{1, 3, 99, 200, 9000}
|
||||||
|
filter := func(i int) bool { return i > 50 }
|
||||||
|
items := FindAllInt(list, filter)
|
||||||
|
|
||||||
|
assert.EqualsInt(t, len(items), 3, "should filter lists of ints")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapStrToInt(t *testing.T) {
|
||||||
|
list := []string{"alice", "bob", "carol"}
|
||||||
|
mapFn := func(s string) int { return int(s[0]) }
|
||||||
|
|
||||||
|
items := MapStrToInt(list, mapFn)
|
||||||
|
|
||||||
|
assert.EqualsInt(t, items[0], int('a'), "should run map function across all strings")
|
||||||
|
}
|
||||||
@@ -9,9 +9,16 @@ func IsTrue(t *testing.T, expr bool, message string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func StrEquals(t *testing.T, actual, expected, message string) {
|
func EqualsStr(t *testing.T, actual, expected, message string) {
|
||||||
if actual != expected {
|
if actual != expected {
|
||||||
t.Logf("Expected value '%s' but got '%s': %s", expected, actual, message)
|
t.Logf("Expected value '%s' but got '%s': %s", expected, actual, message)
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func EqualsInt(t *testing.T, actual, expected int, message string) {
|
||||||
|
if actual != expected {
|
||||||
|
t.Logf("Expected value '%d' but got '%d': %s", expected, actual, message)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package bits
|
||||||
|
|
||||||
|
func GetBitCount(val int) int {
|
||||||
|
count := 0
|
||||||
|
for val != 0 {
|
||||||
|
count += val & 1
|
||||||
|
val >>= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the number of matching bits in the two value's binary expression
|
||||||
|
func MatchingOnBits(v1 int, v2 int) int {
|
||||||
|
count := 0
|
||||||
|
for v1 != 0 && v2 != 0 {
|
||||||
|
if v1&1 == 1 && v2&1 == 1 {
|
||||||
|
count += 1
|
||||||
|
}
|
||||||
|
v1 >>= 1
|
||||||
|
v2 >>= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
func BitwiseAnd(v1 int, v2 int) int {
|
||||||
|
val := 0
|
||||||
|
for block := 1; v1 != 0 || v2 != 0; block <<= 1 {
|
||||||
|
if v1&1 == 1 || v2&1 == 1 {
|
||||||
|
val += block
|
||||||
|
}
|
||||||
|
if v1 > 0 {
|
||||||
|
v1 >>= 1
|
||||||
|
}
|
||||||
|
if v2 > 0 {
|
||||||
|
v2 >>= 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
func BitwiseAndA(a ...int) int {
|
||||||
|
total := 0
|
||||||
|
for _, i := range a {
|
||||||
|
total = BitwiseAnd(total, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
return total
|
||||||
|
}
|
||||||
|
|
||||||
|
func ByBitCount(size int) func(int) bool {
|
||||||
|
return func(val int) bool { return GetBitCount(val) == size }
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package bits
|
||||||
|
|
||||||
|
import (
|
||||||
|
"AoC2021/utils/assert"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetBitCount(t *testing.T) {
|
||||||
|
assert.EqualsInt(t, GetBitCount(0), 0, "should count zero bits")
|
||||||
|
assert.EqualsInt(t, GetBitCount(15), 4, "should count bits")
|
||||||
|
assert.EqualsInt(t, GetBitCount(16), 1, "should not count empty bits")
|
||||||
|
}
|
||||||
|
func TestMatchingOnBits(t *testing.T) {
|
||||||
|
assert.EqualsInt(t, MatchingOnBits(5 /*101*/, 13 /*1101*/), 2, "should match 2 bits")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBitwiseAnd(t *testing.T) {
|
||||||
|
assert.EqualsInt(t, BitwiseAnd(7 /*111*/, 18 /*10010*/), 23 /*10111*/, "should bitwise add")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBitwiseAndA(t *testing.T) {
|
||||||
|
assert.EqualsInt(t, BitwiseAndA(1, 4, 8, 12), 13 /*1101*/, "should bitwise add lists")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestByBitCount(t *testing.T) {
|
||||||
|
twoBitFilter := ByBitCount(2)
|
||||||
|
assert.IsTrue(t, twoBitFilter(17 /*10001*/), "should count bits")
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package filters
|
||||||
|
|
||||||
|
func ByLength(size int) func(string) bool {
|
||||||
|
return func(val string) bool { return len(val) == size }
|
||||||
|
}
|
||||||
+4
-3
@@ -3,9 +3,10 @@ package log
|
|||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
NONE = 0
|
NONE = 0
|
||||||
NORMAL = 1
|
NORMAL = 1
|
||||||
DEBUG = 2
|
DEBUG = 2
|
||||||
|
DIAGNOSTIC = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
var LOG_LEVEL = NORMAL
|
var LOG_LEVEL = NORMAL
|
||||||
|
|||||||
Reference in new issue
Block a user