mirror of
				https://github.com/onyx-and-iris/aoc2023.git
				synced 2025-10-31 12:51:49 +00:00 
			
		
		
		
	day-4
This commit is contained in:
		
							parent
							
								
									714558f3c1
								
							
						
					
					
						commit
						8aa073b5ad
					
				
							
								
								
									
										5
									
								
								day-4/go.mod
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								day-4/go.mod
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | |||||||
|  | module github.com/onyx-and-iris/aoc2023/day-4 | ||||||
|  | 
 | ||||||
|  | go 1.20 | ||||||
|  | 
 | ||||||
|  | require github.com/go-playground/assert v1.2.1 | ||||||
							
								
								
									
										2
									
								
								day-4/go.sum
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								day-4/go.sum
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | |||||||
|  | github.com/go-playground/assert v1.2.1 h1:ad06XqC+TOv0nJWnbULSlh3ehp5uLuQEojZY5Tq8RgI= | ||||||
|  | github.com/go-playground/assert v1.2.1/go.mod h1:Lgy+k19nOB/wQG/fVSQ7rra5qYugmytMQqvQ2dgjWn8= | ||||||
							
								
								
									
										61
									
								
								day-4/one.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								day-4/one.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,61 @@ | |||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"regexp" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type M map[string]interface{} | ||||||
|  | 
 | ||||||
|  | var allCards []M | ||||||
|  | 
 | ||||||
|  | var _regex_winning_numbers = regexp.MustCompile( | ||||||
|  | 	`^Card (?P<card>[\s\d]+):\s` + | ||||||
|  | 		`(?P<winning>[0-9\s]+)\s` + | ||||||
|  | 		`\|\s` + | ||||||
|  | 		`(?P<mynums>[0-9\s]+)$`) | ||||||
|  | 
 | ||||||
|  | var _regex_nums = regexp.MustCompile("[0-9]+") | ||||||
|  | 
 | ||||||
|  | // compareLists returns the number of matching elements between winning and mynums | ||||||
|  | func compareLists(winningStr string, mynumsStr string) (int, error) { | ||||||
|  | 	x, err := numStrToArr(winningStr, []int{}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return 0, err | ||||||
|  | 	} | ||||||
|  | 	winning := x | ||||||
|  | 	x, err = numStrToArr(mynumsStr, []int{}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return 0, err | ||||||
|  | 	} | ||||||
|  | 	mynums := x | ||||||
|  | 
 | ||||||
|  | 	n := 0 | ||||||
|  | 	for _, num := range mynums { | ||||||
|  | 		if contains(winning, num) { | ||||||
|  | 			n += 1 | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return n, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // one computes points based on matching numbers | ||||||
|  | func one(lines []string) (int, error) { | ||||||
|  | 	for _, line := range lines { | ||||||
|  | 		parseAllCards(line) | ||||||
|  | 	} | ||||||
|  | 	cards = make([]Card, len(lines)) | ||||||
|  | 
 | ||||||
|  | 	sum := 0 | ||||||
|  | 	for x, card := range allCards { | ||||||
|  | 		m, err := compareLists(card["winning"].(string), card["mynums"].(string)) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return 0, err | ||||||
|  | 		} | ||||||
|  | 		cards[x].matches = m | ||||||
|  | 		if cards[x].matches > 0 { | ||||||
|  | 			sum += (pow(2, cards[x].matches-1)) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return sum, nil | ||||||
|  | } | ||||||
							
								
								
									
										25
									
								
								day-4/one_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								day-4/one_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | |||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  | 
 | ||||||
|  | 	"github.com/go-playground/assert/v2" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func TestCompareLists(t *testing.T) { | ||||||
|  | 	//t.Skip("skipping test") | ||||||
|  | 	t.Run("Should find 4 matches", func(t *testing.T) { | ||||||
|  | 		res, _ := compareLists("41 48 83 86 17", "83 86  6 31 17  9 48 53") | ||||||
|  | 		assert.Equal(t, 4, res) | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	t.Run("Should find 2 matches", func(t *testing.T) { | ||||||
|  | 		res, _ := compareLists(" 1 21 53 59 44 ", "69 82 63 72 16 21 14  1") | ||||||
|  | 		assert.Equal(t, 2, res) | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	t.Run("Should find 0 matches", func(t *testing.T) { | ||||||
|  | 		res, _ := compareLists("87 83 26 28 32", "88 30 70 12 93 22 82 36") | ||||||
|  | 		assert.Equal(t, 0, res) | ||||||
|  | 	}) | ||||||
|  | } | ||||||
							
								
								
									
										5
									
								
								day-4/run.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										5
									
								
								day-4/run.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,5 @@ | |||||||
|  | #!/usr/bin/env bash | ||||||
|  | 
 | ||||||
|  | INPUT="input.txt" | ||||||
|  | 
 | ||||||
|  | cat $INPUT | go run . | ||||||
							
								
								
									
										22
									
								
								day-4/solution.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								day-4/solution.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | |||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"log" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func main() { | ||||||
|  | 	lines := readlines() | ||||||
|  | 
 | ||||||
|  | 	ans, err := one(lines) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	fmt.Printf("solution one: %d\n", ans) | ||||||
|  | 
 | ||||||
|  | 	ans, err = two(lines) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	fmt.Printf("solution two: %d\n", ans) | ||||||
|  | } | ||||||
							
								
								
									
										27
									
								
								day-4/two.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								day-4/two.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | |||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | // Cards represents a single card. | ||||||
|  | // it tracks its matching numbers and occurrences | ||||||
|  | type Card struct { | ||||||
|  | 	matches     int | ||||||
|  | 	occurrences int | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var cards = []Card{} | ||||||
|  | 
 | ||||||
|  | // two returns the total number of occurrences for all cards | ||||||
|  | func two(lines []string) (int, error) { | ||||||
|  | 	var sum = 0 | ||||||
|  | 
 | ||||||
|  | 	for i := range cards { | ||||||
|  | 		cards[i].occurrences++ | ||||||
|  | 
 | ||||||
|  | 		for j := i + 1; j <= i+cards[i].matches; j++ { | ||||||
|  | 			cards[j].occurrences += cards[i].occurrences | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		sum += cards[i].occurrences | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return sum, nil | ||||||
|  | } | ||||||
							
								
								
									
										63
									
								
								day-4/util.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								day-4/util.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,63 @@ | |||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"bufio" | ||||||
|  | 	"log" | ||||||
|  | 	"math" | ||||||
|  | 	"os" | ||||||
|  | 	"strconv" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // readlines reads lines from stdin. | ||||||
|  | // Then it returns them as an array of strings | ||||||
|  | func readlines() []string { | ||||||
|  | 	lines := []string{} | ||||||
|  | 
 | ||||||
|  | 	scanner := bufio.NewScanner(os.Stdin) | ||||||
|  | 	for scanner.Scan() { | ||||||
|  | 		lines = append(lines, scanner.Text()) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if err := scanner.Err(); err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return lines | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func parseAllCards(line string) { | ||||||
|  | 	groups := M{} | ||||||
|  | 	res := _regex_winning_numbers.FindStringSubmatch(line) | ||||||
|  | 	names := _regex_winning_numbers.SubexpNames() | ||||||
|  | 	for i := range res { | ||||||
|  | 		groups[names[i]] = res[i] | ||||||
|  | 	} | ||||||
|  | 	allCards = append(allCards, groups) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // numStrToArr converts a string of numbers or an array of numbers | ||||||
|  | func numStrToArr(nums string, arr []int) ([]int, error) { | ||||||
|  | 	for _, num := range _regex_nums.FindAllString(nums, -1) { | ||||||
|  | 		n, err := strconv.Atoi(num) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return []int{}, err | ||||||
|  | 		} | ||||||
|  | 		arr = append(arr, n) | ||||||
|  | 	} | ||||||
|  | 	return arr, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // contains returns true if an slice of elements contains a given element | ||||||
|  | func contains[T comparable](elems []T, v T) bool { | ||||||
|  | 	for _, s := range elems { | ||||||
|  | 		if v == s { | ||||||
|  | 			return true | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return false | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // pow returns the value of x to the n | ||||||
|  | func pow(x, n int) int { | ||||||
|  | 	return int(math.Pow(float64(x), float64(n))) | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user