Task: Playing cards




Go: package cards

import (
	"math/rand"
)


type Suit uint8


const (
	Spade   Suit = 3
	Heart   Suit = 2
	Diamond Suit = 1
	Club    Suit = 0
)

func (s Suit) String() string {
	const suites = "CDHS" 
	return suites[s : s+1]
}


type Rank uint8


const (
	Ace   Rank = 1
	Two   Rank = 2
	Three Rank = 3
	Four  Rank = 4
	Five  Rank = 5
	Six   Rank = 6
	Seven Rank = 7
	Eight Rank = 8
	Nine  Rank = 9
	Ten   Rank = 10
	Jack  Rank = 11
	Queen Rank = 12
	King  Rank = 13
)

func (r Rank) String() string {
	const ranks = "A23456789TJQK"
	return ranks[r-1 : r]
}




type Card uint8


func NewCard(r Rank, s Suit) Card {
	return Card(13*uint8(s) + uint8(r-1))
}


func (c Card) RankSuit() (Rank, Suit) {
	return Rank(c%13 + 1), Suit(c / 13)
}


func (c Card) Rank() Rank {
	return Rank(c%13 + 1)
}


func (c Card) Suit() Suit {
	return Suit(c / 13)
}

func (c Card) String() string {
	return c.Rank().String() + c.Suit().String()
}


type Deck []Card


func NewDeck() Deck {
	d := make(Deck, 52)
	for i := range d {
		d[i] = Card(i)
	}
	return d
}



func (d Deck) String() string {
	s := ""
	for i, c := range d {
		switch {
		case i == 0: 
		case i%13 == 0:
			s += "\n"
		default:
			s += " "
		}
		s += c.String()
	}
	return s
}


func (d Deck) Shuffle() {
	for i := range d {
		j := rand.Intn(i + 1)
		d[i], d[j] = d[j], d[i]
	}
}


func (d Deck) Contains(tc Card) bool {
	for _, c := range d {
		if c == tc {
			return true
		}
	}
	return false
}


func (d *Deck) AddDeck(decks ...Deck) {
	for _, o := range decks {
		*d = append(*d, o...)
	}
}


func (d *Deck) AddCard(c Card) {
	*d = append(*d, c)
}



func (d *Deck) Draw(n int) Deck {
	old := *d
	*d = old[n:]
	return old[:n:n]
}




func (d *Deck) DrawCard() (Card, bool) {
	if len(*d) == 0 {
		return 0, false
	}
	old := *d
	*d = old[1:]
	return old[0], true
}








func (d *Deck) Deal(cards int, hands ...Deck) ([]Deck, bool) {
	for i := 0; i < cards; i++ {
		for j := range hands {
			if len(*d) == 0 {
				return hands, false
			}
			hands[j] = append(hands[j], (*d)[0])
			*d = (*d)[1:]
		}
	}
	return hands, true
}






COBOL:        identification division.
       program-id. playing-cards.

       environment division.
       configuration section.
       repository.
           function all intrinsic.

       data division.
       working-storage section.
       77 card             usage index.
       01 deck.
          05 cards occurs 52 times ascending key slot indexed by card.
             10 slot       pic 99.
             10 hand       pic 99.
             10 suit       pic 9.
             10 symbol     pic x(4).
             10 rank       pic 99.

       01 filler.
          05 suit-name     pic x(8) occurs 4 times.

      
       01 base-s           constant as 4036985504.
       01 base-h           constant as 4036985520.
       01 base-d           constant as 4036985728.
       01 base-c           constant as 4036985744.

       01 sym              pic x(4) comp-x.
       01 symx             redefines sym pic x(4).
       77 s                pic 9.
       77 r                pic 99.
       77 c                pic 99.
       77 hit              pic 9.
       77 limiter          pic 9(6).

       01 spades           constant as 1.
       01 hearts           constant as 2.
       01 diamonds         constant as 3.
       01 clubs            constant as 4.

       01 players          constant as 3.
       01 cards-per        constant as 5.
       01 deal             pic 99.
       01 player           pic 99.

       01 show-tally       pic zz.
       01 show-rank        pic z(5).
       01 arg              pic 9(10).
       
       procedure division.
       cards-main.
       perform seed
       perform initialize-deck
       perform shuffle-deck
       perform deal-deck
       perform display-hands
       goback.
      
      
       seed.
           accept arg from command-line
           if arg not equal 0 then
               move random(arg) to c
           end-if
       .

       initialize-deck.
           move "spades" to suit-name(spades)
           move "hearts" to suit-name(hearts)
           move "diamonds" to suit-name(diamonds)
           move "clubs" to suit-name(clubs)

           perform varying s from 1 by 1 until s > 4
                     after r from 1 by 1 until r > 13
                   compute c = (s - 1) * 13 + r
                   evaluate s
                       when spades compute sym = base-s + r
                       when hearts compute sym = base-h + r
                       when diamonds compute sym = base-d + r
                       when clubs compute sym = base-c + r
                   end-evaluate
                   if r > 11 then compute sym = sym + 1 end-if
                   move s to suit(c)
                   move r to rank(c)
                   move symx to symbol(c)
                   move zero to slot(c)
                   move zero to hand(c)
           end-perform
       .

       shuffle-deck.
           move zero to limiter
           perform until exit
               compute c = random() * 52.0 + 1.0
               move zero to hit
               perform varying tally from 1 by 1 until tally > 52
                   if slot(tally) equal c then
                       move 1 to hit
                       exit perform
                   end-if
                   if slot(tally) equal 0 then
                       if tally < 52 then move 1 to hit end-if
                       move c to slot(tally)
                       exit perform
                   end-if
               end-perform
               if hit equal zero then exit perform end-if
               if limiter > 999999 then
                   display "too many shuffles, deck invalid" upon syserr
                   exit perform
               end-if
               add 1 to limiter
           end-perform
           sort cards ascending key slot
       .

       display-card.
       >>IF ENGLISH IS DEFINED
               move rank(tally) to show-rank
               evaluate rank(tally) 
                   when 1 display "  ace" with no advancing
                   when 2 thru 10 display show-rank with no advancing
                   when 11 display " jack" with no advancing
                   when 12 display "queen" with no advancing
                   when 13 display " king" with no advancing
               end-evaluate
               display " of " suit-name(suit(tally)) with no advancing
       >>ELSE
               display symbol(tally) with no advancing
       >>END-IF
       .

       display-deck.
           perform varying tally from 1 by 1 until tally > 52
               move tally to show-tally
               display "Card: " show-tally
                       " currently in hand " hand(tally)
                       " is " with no advancing
               perform display-card
               display space
           end-perform
       .

       display-hands.
           perform varying player from 1 by 1 until player > players
               move player to tally
               display "Player " player ": " with no advancing
               perform varying deal from 1 by 1 until deal > cards-per
                  perform display-card
                  add players to tally
               end-perform
               display space
           end-perform
           display "Stock: " with no advancing
           subtract players from tally
           add 1 to tally
           perform varying tally from tally by 1 until tally > 52
               perform display-card
       >>IF ENGLISH IS DEFINED
               display space
       >>END-IF
           end-perform
           display space
       .

       deal-deck.
           display "Dealing " cards-per " cards to " players " players"
           move 1 to tally
           perform varying deal from 1 by 1 until deal > cards-per
                     after player from 1 by 1 until player > players
               move player to hand(tally)
               add 1 to tally
           end-perform
       .

       end program playing-cards.