Working day07, huge mess

This commit is contained in:
Davide Oddone 2023-12-08 13:12:41 +00:00
parent 745d95771c
commit f48bae3bc3

View File

@ -1,44 +1,58 @@
package main package main
import ( import (
"fmt" "bufio"
"strings" "fmt"
"bufio" "math"
"math" "strings"
// "math/rand" "os"
"os" "strconv"
"strconv"
// "regexp"
"sync" "sync"
) )
var mapSeeds = map[string]int{ var mapSeedsFirst = map[string]int{
"A": 12, "A": 12,
"K": 11, "K": 11,
"Q": 10, "Q": 10,
"J": 9, "J": 9,
"T": 8, "T": 8,
"9": 7, "9": 7,
"8": 6, "8": 6,
"7": 5, "7": 5,
"6": 4, "6": 4,
"5": 3, "5": 3,
"4": 2, "4": 2,
"3": 1, "3": 1,
"2": 0, "2": 0,
}
var mapSeedsSecond = map[string]int{
"A": 12,
"K": 11,
"Q": 10,
"T": 9,
"9": 8,
"8": 7,
"7": 6,
"6": 5,
"5": 4,
"4": 3,
"3": 2,
"2": 1,
"J": 0,
} }
type Game struct { type Game struct {
mu sync.Mutex mu sync.Mutex
ranks []int ranks []int
// 0: High card, 1: One pair, 2: Two pair, 3: Three of a kind // 0: High card, 1: One pair, 2: Two pair, 3: Three of a kind
// 4: Full house, 5: Four of a kind, 6: Five of a kind // 4: Full house, 5: Four of a kind, 6: Five of a kind
typeOfHand [7][]string typeOfHand [7][]string
indexOfHand [7][]int indexOfHand [7][]int
baseThirteen [7][]int baseThirteen [7][]int
} }
func (g *Game) ChangeBase(hType, index int, wg *sync.WaitGroup) { func (g *Game) ChangeBase(hType, index int, mapSeeds map[string]int, wg *sync.WaitGroup) {
// Starting from the first char [0], we create the base13 num // Starting from the first char [0], we create the base13 num
chars := len(g.typeOfHand[hType][index]) chars := len(g.typeOfHand[hType][index])
baseTN := g.typeOfHand[hType][index] baseTN := g.typeOfHand[hType][index]
@ -46,159 +60,220 @@ func (g *Game) ChangeBase(hType, index int, wg *sync.WaitGroup) {
for i := 0; i < chars; i++ { for i := 0; i < chars; i++ {
// This should be refactored to be a bit more legible // This should be refactored to be a bit more legible
// It just computes N * 13^i and adds it over // It just computes N * 13^i and adds it over
decNum += int(float64(mapSeeds[string(baseTN[i])]) * math.Pow(13, float64(chars - i))) } decNum += int(float64(mapSeeds[string(baseTN[i])]) * math.Pow(13, float64(chars-i)))
}
g.baseThirteen[hType][index] = decNum g.baseThirteen[hType][index] = decNum
wg.Done() wg.Done()
} }
func (g *Game) DetermineType(cards string, index int, wg *sync.WaitGroup) int { func (g *Game) AnalyzeMap(cards string, index, mapSize, offset int) {
// We create a map and we check the length. Depending on the length, we // The offset defaults to 0 for the regular game
// insert the string in a specific type // it is +1 for a game with Jokers\
mapSeed := mapSeedsFirst
if offset != 0 {
mapSeed = mapSeedsSecond
}
switch mapSize {
// Five of a kind
case 1:
g.mu.Lock()
g.typeOfHand[6] = append(g.typeOfHand[6], cards)
g.indexOfHand[6] = append(g.indexOfHand[6], index)
g.mu.Unlock()
// Four of a kind || Full House
case 2:
i := FullOrFour(cards, offset, mapSeed)
g.mu.Lock()
g.typeOfHand[i] = append(g.typeOfHand[i], cards)
g.indexOfHand[i] = append(g.indexOfHand[i], index)
g.mu.Unlock()
// Three of a kind || Two pair
case 3:
i := ThreeOrTwo(cards, offset, mapSeed)
g.mu.Lock()
g.typeOfHand[i] = append(g.typeOfHand[i], cards)
g.indexOfHand[i] = append(g.indexOfHand[i], index)
g.mu.Unlock()
// One pair
case 4:
g.mu.Lock()
g.typeOfHand[1] = append(g.typeOfHand[1], cards)
g.indexOfHand[1] = append(g.indexOfHand[1], index)
g.mu.Unlock()
// High card
case 5:
g.mu.Lock()
g.typeOfHand[0] = append(g.typeOfHand[0], cards)
g.indexOfHand[0] = append(g.indexOfHand[0], index)
g.mu.Unlock()
}
}
func (g *Game) DetermineType(cards string, index int, wg *sync.WaitGroup) {
// We create a map and we check the length. Depending on the length, we
// insert the string in a specific type
m := make(map[string]int) m := make(map[string]int)
for i := 0; i < len(cards); i++ { for i := 0; i < len(cards); i++ {
key := string(cards[i]) key := string(cards[i])
m[key] = mapSeeds[key] m[key] = mapSeedsFirst[key]
} }
// Now, depending on the number of elements in the map, we can assign // Now, depending on the number of elements in the map, we can assign
// append cards to a specific rank // append cards to a specific rank
mapSize := len(m) mapSize := len(m)
g.AnalyzeMap(cards, index, mapSize, 0)
switch mapSize { wg.Done()
// Five of a kind
case 1:
g.mu.Lock()
g.typeOfHand[6] = append(g.typeOfHand[6], cards)
g.indexOfHand[6] = append(g.indexOfHand[6], index)
g.mu.Unlock()
// Four of a kind || Full House
case 2:
i := FullOrFour(cards)
g.mu.Lock()
g.typeOfHand[i] = append(g.typeOfHand[i], cards)
g.indexOfHand[i] = append(g.indexOfHand[i], index)
g.mu.Unlock()
// Three of a kind || Two pair
case 3:
i := ThreeOrTwo(cards)
g.mu.Lock()
g.typeOfHand[i] = append(g.typeOfHand[i], cards)
g.indexOfHand[i] = append(g.indexOfHand[i], index)
g.mu.Unlock()
// One pair
case 4:
g.mu.Lock()
g.typeOfHand[1] = append(g.typeOfHand[1], cards)
g.indexOfHand[1] = append(g.indexOfHand[1], index)
g.mu.Unlock()
// High card
case 5:
g.mu.Lock()
g.typeOfHand[0] = append(g.typeOfHand[0], cards)
g.indexOfHand[0] = append(g.indexOfHand[0], index)
g.mu.Unlock()
}
wg.Done()
return 1
} }
func ThreeOrTwo(cards string) int { func (g *Game) SecondGame(cards string, index int, wg *sync.WaitGroup) {
m := make(map[string]int) // If I don't have Js, run the standard DetermineType
for i := 0; i < len(cards); i++ { m := make(map[string]int)
key := string(cards[i]) n := make(map[string]int)
m[key] += 1 for i := 0; i < len(cards); i++ {
} key := string(cards[i])
// m[i] returns 0 if the element is not in the map. I take advantage // We need to track the number of Js
// of that m[key] += 1
for i := range mapSeeds { // This is to track the type of hand, knowing the number of Js
// If an element has 3 values, we have a three of a kind n[key] = mapSeedsSecond[key]
if m[i] == 3 { }
return 3 mapSize := len(n)
/// If an element has 2 values, we have a two pair switch m["J"] {
} else if m[i] == 2 { case 0:
return 2 // We have a hand without Js
} wg.Add(1)
} g.DetermineType(cards, index, wg)
return -1 case 1:
// If there is a J, J can be use is not adding information, therefore -1
g.AnalyzeMap(cards, index, (mapSize - 1), 1)
case 2:
g.AnalyzeMap(cards, index, (mapSize - 1), 2)
case 3:
g.AnalyzeMap(cards, index, (mapSize - 1), 3)
case 4:
g.AnalyzeMap(cards, index, (mapSize - 1), 4)
case 5:
wg.Add(1)
g.DetermineType(cards, index, wg)
}
wg.Done()
} }
func FullOrFour(cards string) int {
m := make(map[string]int) func ThreeOrTwo(cards string, offset int, mapSeed map[string]int) int {
for i := 0; i < len(cards); i++ { m := make(map[string]int)
key := string(cards[i]) for i := 0; i < len(cards); i++ {
m[key] += 1 key := string(cards[i])
} m[key] += 1
// m[i] returns 0 if the element is not in the map. I take advantage }
// of that // If we are in the second game, remove J
for i := range mapSeeds { if mapSeed["J"] == 0 {
// If an element has four values, we have a Four of a kind m["J"] = 0
if m[i] == 4 { }
return 5 // m[i] returns 0 if the element is not in the map. I take advantage
/// If an element has 3 values, we have a Full House // of that
} else if m[i] == 3 { tempNum := 0
return 4 for i := range mapSeed {
} if m[i] > tempNum {
} tempNum = m[i]
return -1 }
}
// If an element has 3 values, we have a three of a kind
if tempNum+offset == 3 {
return 3
/// If an element has 2 values, we have a two pair
} else if tempNum+offset == 2 {
return 2
}
PrintAndWait("This has run for ", cards)
return -1
}
func FullOrFour(cards string, offset int, mapSeed map[string]int) int {
m := make(map[string]int)
for i := 0; i < len(cards); i++ {
key := string(cards[i])
m[key] += 1
}
// If we are in the second game, remove J
if mapSeed["J"] == 0 {
m["J"] = 0
}
// m[i] returns 0 if the element is not in the map. I take advantage
// of that
// Better to save the maximum number
tempNum := 0
for i := range mapSeed {
if m[i] > tempNum {
tempNum = m[i]
}
}
// If an element has four values, we have a Four of a kind
if tempNum+offset == 4 {
return 5
/// If an element has 3 values, we have a Full House
} else if tempNum+offset == 3 {
return 4
}
return -1
} }
func check(e error) { func check(e error) {
if e != nil { if e != nil {
panic(e) panic(e)
} }
} }
func PrintAndWait(x ...any) { func PrintAndWait(x ...any) {
fmt.Print(x...) fmt.Print(x...)
fmt.Scanln() fmt.Scanln()
} }
// https://www.golangprograms.com/golang-program-for-implementation-of-quick-sort.html // https://www.golangprograms.com/golang-program-for-implementation-of-quick-sort.html
// I need to learn how this shing works // I need to learn how this shing works
func quicksort(a, h []int, hType int) []int { func quicksort(a, h []int, hType int) []int {
if len(a) < 2 { if len(a) < 2 {
return a return a
} }
left, right := 0, len(a)-1 left, right := 0, len(a)-1
pivot := 0 pivot := 0
a[pivot], a[right] = a[right], a[pivot] a[pivot], a[right] = a[right], a[pivot]
h[pivot], h[right] = h[right], h[pivot] h[pivot], h[right] = h[right], h[pivot]
for i, _ := range a { for i, _ := range a {
if a[i] < a[right] { if a[i] < a[right] {
a[left], a[i] = a[i], a[left] a[left], a[i] = a[i], a[left]
h[left], h[i] = h[i], h[left] h[left], h[i] = h[i], h[left]
left++ left++
} }
} }
a[left], a[right] = a[right], a[left] a[left], a[right] = a[right], a[left]
h[left], h[right] = h[right], h[left] h[left], h[right] = h[right], h[left]
quicksort(a[:left], h[:left], hType)
quicksort(a[:left], h[:left], hType) quicksort(a[left+1:], h[left+1:], hType)
quicksort(a[left+1:], h[left+1:], hType)
return a
return a
} }
func main() { func main() {
file, err := os.Open("./inputs/day07_input") file, err := os.Open("./inputs/day7_try")
check(err) check(err)
defer file.Close() defer file.Close()
// Struct for multiple races // Struct for regular game
g := Game{} g := Game{}
// Struct for the Joker game
jo := Game{}
// Variable where we store every line in the file // Variable where we store every line in the file
lines := make([]string, 0) lines := make([]string, 0)
scanner := bufio.NewScanner(file) scanner := bufio.NewScanner(file)
for scanner.Scan() { for scanner.Scan() {
lines = append(lines, scanner.Text()) lines = append(lines, scanner.Text())
} }
// Array of strings, set of cards // Array of strings, set of cards
var cards []string var cards []string
@ -206,13 +281,14 @@ func main() {
var bet []int var bet []int
// Now, split the lines // Now, split the lines
for i := 0; i < len(lines); i++ { for i := 0; i < len(lines); i++ {
tempString := strings.Split(lines[i], " ") tempString := strings.Split(lines[i], " ")
cards = append(cards, tempString[0]) cards = append(cards, tempString[0])
tempNum, _ := strconv.Atoi(tempString[1]) tempNum, _ := strconv.Atoi(tempString[1])
bet = append(bet, tempNum) bet = append(bet, tempNum)
} }
// Rank will be from 1 to len(lines) // Rank will be from 1 to len(lines)
g.ranks = make([]int, len(lines)) g.ranks = make([]int, len(lines))
jo.ranks = make([]int, len(lines))
// What do we know for sure? 5 identical seeds are the highest ranks, // What do we know for sure? 5 identical seeds are the highest ranks,
// 5 completely different seeds are the lowest ranks. // 5 completely different seeds are the lowest ranks.
// We can iterate for every set of cards, and do different things // We can iterate for every set of cards, and do different things
@ -225,9 +301,10 @@ func main() {
// //
// With this, I put every typeOfHand in a different array // With this, I put every typeOfHand in a different array
var wg sync.WaitGroup var wg sync.WaitGroup
wg.Add(len(lines)) wg.Add(2 * len(lines))
for i := 0; i < len(lines); i++ { for i := 0; i < len(lines); i++ {
go g.DetermineType(cards[i], i, &wg) g.DetermineType(cards[i], i, &wg)
jo.SecondGame(cards[i], i, &wg)
} }
wg.Wait() wg.Wait()
@ -238,46 +315,52 @@ func main() {
// For every type of hand // For every type of hand
for i := range g.typeOfHand { for i := range g.typeOfHand {
// As many wait groups as the element we will iterate // As many wait groups as the element we will iterate
wg.Add(len(g.typeOfHand[i])) wg.Add(len(g.typeOfHand[i]))
// We also need to initialize the array g.baseThirteen so we can wg.Add(len(jo.typeOfHand[i]))
// keep the same index // We also need to initialize the array g.baseThirteen so we can
g.baseThirteen[i] = make([]int, len(g.typeOfHand[i])) // keep the same index
// For every element in a single type of hand g.baseThirteen[i] = make([]int, len(g.typeOfHand[i]))
for j := range g.typeOfHand[i] { jo.baseThirteen[i] = make([]int, len(jo.typeOfHand[i]))
go g.ChangeBase(i, j, &wg) // For every element in a single type of hand
} for j := range g.typeOfHand[i] {
g.ChangeBase(i, j, mapSeedsFirst, &wg)
}
for j := range jo.typeOfHand[i] {
jo.ChangeBase(i, j, mapSeedsSecond, &wg)
}
} }
wg.Wait() wg.Wait()
// PrintAndWait(g.typeOfHand[0])
// PrintAndWait(g.typeOfHand[1])
// PrintAndWait(g.typeOfHand[2])
// PrintAndWait(g.typeOfHand[3])
// PrintAndWait(g.typeOfHand[4])
// PrintAndWait(g.typeOfHand[5])
// PrintAndWait(g.typeOfHand[6])
// A sort of some kind. Important is to also move the index with the number as // A sort of some kind. Important is to also move the index with the number as
// well. // well.
//
for i := range g.baseThirteen { for i := range g.baseThirteen {
quicksort(g.baseThirteen[i], g.indexOfHand[i], i) quicksort(g.baseThirteen[i], g.indexOfHand[i], i)
quicksort(jo.baseThirteen[i], jo.indexOfHand[i], i)
} }
curRank := 1 curRank := 1
rank := 0 rank := 0
// Iter every array // Iter every array
for i := range g.typeOfHand { for i := range g.typeOfHand {
for j := range g.typeOfHand[i] { for j := range g.typeOfHand[i] {
//fmt.Printf("For the array %d, element %d, ", i, j) index := g.indexOfHand[i][j]
index := g.indexOfHand[i][j] rank += curRank * bet[index]
//fmt.Printf("I gather index %d ", index) curRank++
rank += curRank * bet[index] }
//fmt.Printf("and finally I multiply %d and %d.\n", curRank, bet[index])
//fmt.Scanln()
curRank++
}
} }
fmt.Print(rank) fmt.Printf("Rank: %d\n", rank)
curRank = 1
rank = 0
// Iter every array
for i := range jo.typeOfHand {
for j := range jo.typeOfHand[i] {
index := jo.indexOfHand[i][j]
rank += curRank * bet[index]
curRank++
}
}
fmt.Printf("Rank: %d\n", rank)
} }