How to resolve the algorithm Poker hand analyser step by step in the Go programming language

Published on 12 May 2024 09:40 PM
#Go

How to resolve the algorithm Poker hand analyser step by step in the Go programming language

Table of Contents

Problem Statement

Create a program to parse a single five card poker hand and rank it according to this list of poker hands.

A poker hand is specified as a space separated list of five playing cards. Each input card has two characters indicating face and suit.

Faces are:    a, 2, 3, 4, 5, 6, 7, 8, 9, 10, j, q, k Suits are:    h (hearts),   d (diamonds),   c (clubs),   and   s (spades),   or alternatively,   the unicode card-suit characters:    ♥ ♦ ♣ ♠

Duplicate cards are illegal. The program should analyze a single hand and produce one of the following outputs:

The programs output for the above examples should be displayed here on this page.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Poker hand analyser step by step in the Go programming language

This code is a program written in the Go programming language that analyzes poker hands. It takes a string representing a hand of five cards and returns the best possible hand that can be made from that hand.

The code begins by defining a card type that represents a single card with a face value and a suit. It then defines two constant strings, faces and suits, that contain the valid face values and suits for a card.

The isStraight function checks if a hand of cards is a straight. It takes an array of cards and an integer representing the number of jokers in the hand. A straight is a hand of five cards with consecutive face values. The function sorts the cards by face value and then checks if the face value of the highest card is four greater than the face value of the lowest card. If the hand contains a joker, the joker can be used to fill in any gaps in the sequence.

The isFlush function checks if a hand of cards is a flush. It takes an array of cards. A flush is a hand of five cards with the same suit. The function sorts the cards by suit and then checks if all of the cards have the same suit.

The analyzeHand function takes a string representing a hand of cards and returns the best possible hand that can be made from that hand. It first splits the string into an array of strings, one for each card. It then creates a map from each unique card in the hand to the number of times that card appears in the hand.

The function then checks the number of unique cards in the hand. If there are only two unique cards, the hand is either a four-of-a-kind or a full house. If there are three unique cards, the hand is either a three-of-a-kind, a two-pair, or a one-pair. If there are four unique cards, the hand is a one-pair.

If the hand is not a four-of-a-kind, a full house, a three-of-a-kind, a two-pair, or a one-pair, the function checks if it is a straight flush, a flush, or a straight. A straight flush is a straight that is also a flush. A flush is a hand of five cards with the same suit. A straight is a hand of five cards with consecutive face values.

If the hand is not a straight flush, a flush, or a straight, the function checks if it is a high card. A high card is a hand of five cards that do not form any of the other types of hands.

The function returns the best possible hand that can be made from the given hand.

The main function is the entry point for the program. It creates an array of strings, each of which represents a hand of five cards. It then iterates over the array, calling the analyzeHand function on each hand and printing the result.

Source code in the go programming language

package main

import (
    "fmt"
    "sort"
    "strings"
)

type card struct {
    face byte
    suit byte
}

const faces = "23456789tjqka"
const suits = "shdc"

func isStraight(cards []card) bool {
    sorted := make([]card, 5)
    copy(sorted, cards)
    sort.Slice(sorted, func(i, j int) bool {
        return sorted[i].face < sorted[j].face
    })
    if sorted[0].face+4 == sorted[4].face {
        return true
    }
    if sorted[4].face == 14 && sorted[0].face == 2 && sorted[3].face == 5 {
        return true
    }
    return false
}

func isFlush(cards []card) bool {
    suit := cards[0].suit
    for i := 1; i < 5; i++ {
        if cards[i].suit != suit {
            return false
        }
    }
    return true
}

func analyzeHand(hand string) string {
    temp := strings.Fields(strings.ToLower(hand))
    splitSet := make(map[string]bool)
    var split []string
    for _, s := range temp {
        if !splitSet[s] {
            splitSet[s] = true
            split = append(split, s)
        }
    }
    if len(split) != 5 {
        return "invalid"
    }
    var cards []card

    for _, s := range split {
        if len(s) != 2 {
            return "invalid"
        }
        fIndex := strings.IndexByte(faces, s[0])
        if fIndex == -1 {
            return "invalid"
        }
        sIndex := strings.IndexByte(suits, s[1])
        if sIndex == -1 {
            return "invalid"
        }
        cards = append(cards, card{byte(fIndex + 2), s[1]})
    }

    groups := make(map[byte][]card)
    for _, c := range cards {
        groups[c.face] = append(groups[c.face], c)
    }

    switch len(groups) {
    case 2:
        for _, group := range groups {
            if len(group) == 4 {
                return "four-of-a-kind"
            }
        }
        return "full-house"
    case 3:
        for _, group := range groups {
            if len(group) == 3 {
                return "three-of-a-kind"
            }
        }
        return "two-pair"
    case 4:
        return "one-pair"
    default:
        flush := isFlush(cards)
        straight := isStraight(cards)
        switch {
        case flush && straight:
            return "straight-flush"
        case flush:
            return "flush"
        case straight:
            return "straight"
        default:
            return "high-card"
        }
    }
}

func main() {
    hands := [...]string{
        "2h 2d 2c kc qd",
        "2h 5h 7d 8c 9s",
        "ah 2d 3c 4c 5d",
        "2h 3h 2d 3c 3d",
        "2h 7h 2d 3c 3d",
        "2h 7h 7d 7c 7s",
        "th jh qh kh ah",
        "4h 4s ks 5d ts",
        "qc tc 7c 6c 4c",
        "ah ah 7c 6c 4c",
    }
    for _, hand := range hands {
        fmt.Printf("%s: %s\n", hand, analyzeHand(hand))
    }
}


package main

import (
    "fmt"
    "sort"
    "strings"
)

type card struct {
    face byte
    suit byte
}

func isStraight(cards []card, jokers int) bool {
    sorted := make([]card, 5)
    copy(sorted, cards)
    sort.Slice(sorted, func(i, j int) bool {
        return sorted[i].face < sorted[j].face
    })
    switch jokers {
    case 0:
        switch {
        case sorted[0].face+4 == sorted[4].face,
            sorted[4].face == 14 && sorted[3].face == 5:
            return true
        default:
            return false
        }
    case 1:
        switch {
        case sorted[0].face+3 == sorted[3].face,
            sorted[0].face+4 == sorted[3].face,
            sorted[3].face == 14 && sorted[2].face == 4,
            sorted[3].face == 14 && sorted[2].face == 5:
            return true
        default:
            return false
        }
    default:
        switch {
        case sorted[0].face+2 == sorted[2].face,
            sorted[0].face+3 == sorted[2].face,
            sorted[0].face+4 == sorted[2].face,
            sorted[2].face == 14 && sorted[1].face == 3,
            sorted[2].face == 14 && sorted[1].face == 4,
            sorted[2].face == 14 && sorted[1].face == 5:
            return true
        default:
            return false
        }
    }
}

func isFlush(cards []card) bool {
    sorted := make([]card, 5)
    copy(sorted, cards)
    sort.Slice(sorted, func(i, j int) bool {
        return sorted[i].face < sorted[j].face
    })
    suit := sorted[0].suit
    for i := 1; i < 5; i++ {
        if sorted[i].suit != suit && sorted[i].suit != 'j' {
            return false
        }
    }
    return true
}

func analyzeHand(hand string) string {
    temp := strings.Fields(strings.ToLower(hand))
    splitSet := make(map[string]bool)
    var split []string
    for _, s := range temp {
        if !splitSet[s] {
            splitSet[s] = true
            split = append(split, s)
        }
    }
    if len(split) != 5 {
        return "invalid"
    }
    var cards []card
    var jokers = 0

    for _, s := range split {
        if len(s) != 4 {
            return "invalid"
        }
        cp := []rune(s)[0]
        var cd card
        switch {
        case cp == 0x1f0a1:
            cd = card{14, 's'}
        case cp == 0x1f0b1:
            cd = card{14, 'h'}
        case cp == 0x1f0c1:
            cd = card{14, 'd'}
        case cp == 0x1f0d1:
            cd = card{14, 'c'}
        case cp == 0x1f0cf:
            jokers++
            cd = card{15, 'j'} // black joker
        case cp == 0x1f0df:
            jokers++
            cd = card{16, 'j'} // white joker
        case cp >= 0x1f0a2 && cp <= 0x1f0ab:
            cd = card{byte(cp - 0x1f0a0), 's'}
        case cp >= 0x1f0ad && cp <= 0x1f0ae:
            cd = card{byte(cp - 0x1f0a1), 's'}
        case cp >= 0x1f0b2 && cp <= 0x1f0bb:
            cd = card{byte(cp - 0x1f0b0), 'h'}
        case cp >= 0x1f0bd && cp <= 0x1f0be:
            cd = card{byte(cp - 0x1f0b1), 'h'}
        case cp >= 0x1f0c2 && cp <= 0x1f0cb:
            cd = card{byte(cp - 0x1f0c0), 'd'}
        case cp >= 0x1f0cd && cp <= 0x1f0ce:
            cd = card{byte(cp - 0x1f0c1), 'd'}
        case cp >= 0x1f0d2 && cp <= 0x1f0db:
            cd = card{byte(cp - 0x1f0d0), 'c'}
        case cp >= 0x1f0dd && cp <= 0x1f0de:
            cd = card{byte(cp - 0x1f0d1), 'c'}
        default:
            cd = card{0, 'j'} // invalid
        }
        if cd.face == 0 {
            return "invalid"
        }
        cards = append(cards, cd)
    }

    groups := make(map[byte][]card)
    for _, c := range cards {
        groups[c.face] = append(groups[c.face], c)
    }

    switch len(groups) {
    case 2:
        for _, group := range groups {
            if len(group) == 4 {
                switch jokers {
                case 0:
                    return "four-of-a-kind"
                default:
                    return "five-of-a-kind"
                }
            }
        }
        return "full-house"
    case 3:
        for _, group := range groups {
            if len(group) == 3 {
                switch jokers {
                case 0:
                    return "three-of-a-kind"
                case 1:
                    return "four-of-a-kind"
                default:
                    return "five-of-a-kind"
                }
            }
        }
        if jokers == 0 {
            return "two-pair"
        }
        return "full-house"
    case 4:
        switch jokers {
        case 0:
            return "one-pair"
        case 1:
            return "three-of-a-kind"
        default:
            return "four-of-a-kind"
        }
    default:
        flush := isFlush(cards)
        straight := isStraight(cards, jokers)
        switch {
        case flush && straight:
            return "straight-flush"
        case flush:
            return "flush"
        case straight:
            return "straight"
        default:
            if jokers == 0 {
                return "high-card"
            } else {
                return "one-pair"
            }
        }
    }
}

func main() {
    hands := [...]string{
        "🃏 🃂 🂢 🂮 🃍",
        "🃏 🂵 🃇 🂨 🃉",
        "🃏 🃂 🂣 🂤 🂥",
        "🃏 🂳 🃂 🂣 🃃",
        "🃏 🂷 🃂 🂣 🃃",
        "🃏 🂷 🃇 🂧 🃗",
        "🃏 🂻 🂽 🂾 🂱",
        "🃏 🃔 🃞 🃅 🂪",
        "🃏 🃞 🃗 🃖 🃔",
        "🃏 🃂 🃟 🂤 🂥",
        "🃏 🃍 🃟 🂡 🂪",
        "🃏 🃍 🃟 🃁 🃊",
        "🃏 🃂 🂢 🃟 🃍",
        "🃏 🃂 🂢 🃍 🃍",
        "🃂 🃞 🃍 🃁 🃊",
    }
    for _, hand := range hands {
        fmt.Printf("%s: %s\n", hand, analyzeHand(hand))
    }
}


  

You may also check:How to resolve the algorithm Repeat step by step in the Racket programming language
You may also check:How to resolve the algorithm Call a foreign-language function step by step in the Maple programming language
You may also check:How to resolve the algorithm Singly-linked list/Traversal step by step in the OCaml programming language
You may also check:How to resolve the algorithm LZW compression step by step in the Phix programming language
You may also check:How to resolve the algorithm Loops/Continue step by step in the Clipper programming language