Initial upload

This commit is contained in:
2022-08-24 14:28:45 +02:00
parent c67653ddee
commit 57bc7b0289
370 changed files with 18479 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
{
"blurb": "Learn about conditionals by playing Blackjack.",
"authors": [
"andres-zartab"
],
"contributors": [
"tehsphinx",
"andrerfcsantos"
],
"forked_from": [],
"files": {
"solution": [
"blackjack.go"
],
"test": [
"blackjack_test.go"
],
"exemplar": [
".meta/exemplar.go"
]
}
}

View File

@@ -0,0 +1 @@
{"track":"go","exercise":"blackjack","id":"97a16a05d3a141a19fdb0db49be634a3","url":"https://exercism.org/tracks/go/exercises/blackjack","handle":"halfdan","is_requester":true,"auto_approve":false}

40
go/blackjack/HELP.md Normal file
View File

@@ -0,0 +1,40 @@
# Help
## Running the tests
To run the tests run the command `go test` from within the exercise directory.
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
flags:
go test -v --bench . --benchmem
Keep in mind that each reviewer will run benchmarks on a different machine, with
different specs, so the results from these benchmark tests may vary.
## Submitting your solution
You can submit your solution using the `exercism submit blackjack.go` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
- [Exercism's support channel on gitter](https://gitter.im/exercism/support)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
To get help if you're having trouble, you can use one of the following resources:
- [How to Write Go Code](https://golang.org/doc/code.html)
- [Effective Go](https://golang.org/doc/effective_go.html)
- [Go Resources](http://golang.org/help)
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)

39
go/blackjack/HINTS.md Normal file
View File

@@ -0,0 +1,39 @@
# Hints
## General
- Conditionals are used to check for certain conditions and/or criteria. The most basic way of performing a conditional operation is using a single `if` statement.
## 1. Calculate the score of any given card.
- The `ParseCard` function should take the `card` string (e.g. `ace`) and turn it into its value (e.g. 11).
- Use a big [`switch` statement][switch_statement] on the `card` variable.
- King, Queen, Jack and 10 can be handled with a single case.
- The switch can have a `default` case. In any case the function should return `0` for unknown cards.
## 2. Determine if two cards make up a Blackjack.
- `IsBlackJack` checks if 2 cards have the combined value of 21.
- Should use the `ParseCard` function to get the value for each card.
- Should sum up the values of the 2 cards.
- Should return `true` if the sum is equal to `21`.
- No `if` statement is needed here. The result for the comparison can be returned.
## 3. Implement the decision logic for hand scores larger than 20 points.
- As the `LargeHand` function is only called for hands with a value larger than 20, there are only 2 different possible hands: A **BlackJack** with a total value of `21` and **2 Aces** with a total value of `22`.
- The function should check [if][if_statement] `isBlackJack` is `true` and return "P" otherwise.
- If `isBlackJack` is `true`, the dealerScore needs to be checked for being lower than 10. [If][if_statement] it is lower, return "W" otherwise "S".
## 4. Implement the decision logic for hand scores with less than 21 points.
- The `SmallHand` function is only called if there are no Aces on the hand (`handScore` is less than 21).
- Implement every condition using [logical operators][logical_operators] if necessary.
- [If][if_statement] your cards sum up to 17 or higher you should always _stand_.
- [If][if_statement] your cards sum up to 11 or lower you should always _hit_.
- [If][if_statement] your cards sum up to a value within the range [12, 16] you should always _stand_ if the dealer has a 6 or lower.
- [If][if_statement] your cards sum up to a value within the range [12, 16] you should always _hit_ if the dealer has a 7 or higher.
[logical_operators]: https://golang.org/ref/spec#Logical_operators
[if_statement]: https://golang.org/ref/spec#If_statements
[switch_statement]: https://golang.org/ref/spec#Switch_statements

134
go/blackjack/README.md Normal file
View File

@@ -0,0 +1,134 @@
# Blackjack
Welcome to Blackjack on Exercism's Go Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :)
## Introduction
Like other languages, Go also provides a `switch` statement. Switch statements are a shorter way to write long `if ... else if` statements. To make a switch, we start by using the keyword `switch` followed by a value or expression. We then declare each one of the conditions with the `case` keyword. We can also declare a `default` case, that will run when none of the previous `case` conditions matched:
```go
operatingSystem := "windows"
switch operatingSystem {
case "windows":
// do something if the operating system is windows
case "linux":
// do something if the operating system is linux
case "macos":
// do something if the operating system is macos
default:
// do something if the operating system is none of the above
}
```
One interesting thing about switch statements, is that the value after the `switch` keyword can be omitted, and we can have boolean conditions for each `case`:
```go
age := 21
switch {
case age > 20 && age < 30:
// do something if age is between 20 and 30
case age == 10:
// do something if age is equal to 10
default:
// do something else for every other case
}
```
## Instructions
In this exercise we will simulate the first turn of a [Blackjack](https://en.wikipedia.org/wiki/Blackjack) game.
You will receive two cards and will be able to see the face up card of the dealer. All cards are represented using a string such as "ace", "king", "three", "two", etc. The values of each card are:
| card | value | card | value |
| :---: | :---: | :---: | :---: |
| ace | 11 | eight | 8 |
| two | 2 | nine | 9 |
| three | 3 | ten | 10 |
| four | 4 | jack | 10 |
| five | 5 | queen | 10 |
| six | 6 | king | 10 |
| seven | 7 | other | 0 |
**Note**: Commonly, aces can take the value of 1 or 11 but for simplicity we will assume that they can only take the value of 11.
Depending on your two cards and the card of the dealer, there is a strategy for the first turn of the game, in which you have the following options:
- Stand (S)
- Hit (H)
- Split (P)
- Automatically win (W)
Although not optimal yet, you will follow the strategy your friend Alex has been developing, which is as follows:
Category: Large Hand
- If you have a pair of aces you must always split them.
- If you have a Blackjack (two cards that sum up to a value of 21), and the dealer does not have an ace, a figure or a ten then you automatically win. If the dealer does have any of those cards then you'll have to stand and wait for the reveal of the other card.
Category: Small Hand
- If your cards sum up to 17 or higher you should always stand.
- If your cards sum up to 11 or lower you should always hit.
- If your cards sum up to a value within the range [12, 16] you should always stand unless the dealer has a 7 or higher, in which case you should always hit.
The overall logic has already been implemented. You have four tasks:
## 1. Calculate the score of any given card.
Implement a function to calculate the numerical value of a card given its name using conditionals.
```go
value := ParseCard("ace")
fmt.Println(value)
// Output: 11
```
## 2. Determine if two cards make up a Blackjack.
Implement a function that returns `true` if two cards form a Blackjack, `false` otherwise.
```go
isBlackjack := IsBlackjack("queen", "ace")
fmt.Println(isBlackjack)
// Output: true
```
## 3. Implement the decision logic for hand scores larger than 20 points.
Implement a function that returns the string representation of a decision given your cards. This function is only called if the `handScore` is larger than 20. It will receive 2 arguments: `isBlackJack` and `dealerScore`. It should implement the bulletpoints in the category "Large Hand" above.
```go
isBlackJack := true
dealerScore := 7
choice := LargeHand(isBlackJack, dealerScore)
fmt.Println(choice)
// Output: "W"
```
## 4. Implement the decision logic for hand scores with less than 21 points.
Implement a function that returns the string representation of a decision given your cards. This function is only called if the `handScore` is less than 21. It will receive 2 arguments: `handScore` and `dealerScore`. It should implement the bulletpoints in the category "Small Hand" above.
```go
handScore := 15
dealerScore := 12
choice := SmallHand(handScore, dealerScore)
fmt.Println(choice)
// Output: "H"
```
## Source
### Created by
- @andres-zartab
### Contributed to by
- @tehsphinx
- @andrerfcsantos

55
go/blackjack/blackjack.go Normal file
View File

@@ -0,0 +1,55 @@
package blackjack
// ParseCard returns the integer value of a card following blackjack ruleset.
func ParseCard(card string) int {
switch card {
case "ace":
return 11
case "two":
return 2
case "three":
return 3
case "four":
return 4
case "five":
return 5
case "six":
return 6
case "seven":
return 7
case "eight":
return 8
case "nine":
return 9
case "ten", "jack", "queen", "king":
return 10
default:
return 0
}
}
// IsBlackjack returns true if the player has a blackjack, false otherwise.
func IsBlackjack(card1, card2 string) bool {
return ParseCard(card1) + ParseCard(card2) == 21
}
// LargeHand implements the decision tree for hand scores larger than 20 points.
func LargeHand(isBlackjack bool, dealerScore int) string {
if !isBlackjack {
// Must have two aces
return "P"
} else if isBlackjack && dealerScore < 10 {
return "W"
}
return "S"
}
// SmallHand implements the decision tree for hand scores with less than 21 points.
func SmallHand(handScore, dealerScore int) string {
if handScore >= 17 {
return "S"
} else if handScore <= 11 || dealerScore >= 7 {
return "H"
}
return "S"
}

View File

@@ -0,0 +1,398 @@
package blackjack
import "testing"
func TestParseCard(t *testing.T) {
tests := []struct {
name string
card string
want int
}{
{
name: "parse ace",
card: "ace",
want: 11,
},
{
name: "parse two",
card: "two",
want: 2,
},
{
name: "parse three",
card: "three",
want: 3,
},
{
name: "parse four",
card: "four",
want: 4,
},
{
name: "parse five",
card: "five",
want: 5,
},
{
name: "parse six",
card: "six",
want: 6,
},
{
name: "parse seven",
card: "seven",
want: 7,
},
{
name: "parse eight",
card: "eight",
want: 8,
},
{
name: "parse nine",
card: "nine",
want: 9,
},
{
name: "parse ten",
card: "ten",
want: 10,
},
{
name: "parse jack",
card: "jack",
want: 10,
},
{
name: "parse queen",
card: "queen",
want: 10,
},
{
name: "parse king",
card: "king",
want: 10,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := ParseCard(tt.card); got != tt.want {
t.Errorf("ParseCard(%s) = %d, want %d", tt.card, got, tt.want)
}
})
}
}
func TestBlackjack(t *testing.T) {
type hand struct {
card1, card2 string
}
tests := []struct {
name string
hand hand
want bool
}{
{
name: "blackjack with ten (ace first)",
hand: hand{card1: "ace", card2: "ten"},
want: true,
},
{
name: "blackjack with jack (ace first)",
hand: hand{card1: "ace", card2: "jack"},
want: true,
},
{
name: "blackjack with queen (ace first)",
hand: hand{card1: "ace", card2: "queen"},
want: true,
},
{
name: "blackjack with king (ace first)",
hand: hand{card1: "ace", card2: "king"},
want: true,
},
{
name: "blackjack with ten (ace second)",
hand: hand{card2: "ace", card1: "ten"},
want: true,
},
{
name: "blackjack with jack (ace second)",
hand: hand{card2: "ace", card1: "jack"},
want: true,
},
{
name: "blackjack with queen (ace second)",
hand: hand{card2: "ace", card1: "queen"},
want: true,
},
{
name: "blackjack with king (ace second)",
hand: hand{card2: "ace", card1: "king"},
want: true,
},
{
name: "no blackjack with ace and five",
hand: hand{card2: "ace", card1: "five"},
want: false,
},
{
name: "no blackjack with ace and nine",
hand: hand{card2: "ace", card1: "nine"},
want: false,
},
{
name: "no blackjack with two aces",
hand: hand{card2: "ace", card1: "ace"},
want: false,
},
{
name: "no blackjack with two figures",
hand: hand{card2: "queen", card1: "jack"},
want: false,
},
{
name: "no blackjack with king and five",
hand: hand{card2: "king", card1: "five"},
want: false,
},
{
name: "no blackjack with eight and five",
hand: hand{card2: "eight", card1: "five"},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := IsBlackjack(tt.hand.card1, tt.hand.card2); got != tt.want {
t.Errorf("IsBlackjack(%s, %s) = %t, want %t", tt.hand.card1, tt.hand.card2, got, tt.want)
}
})
}
}
func TestFirstTurn(t *testing.T) {
type hand struct {
card1, card2 string
}
tests := []struct {
name string
hand hand
dealer string
want string
}{
{
name: "pair of aces",
hand: hand{card1: "ace", card2: "ace"},
dealer: "ace",
want: "P",
},
{
name: "pair of jacks",
hand: hand{card1: "jack", card2: "jack"},
dealer: "ace",
want: "S",
},
{
name: "pair of kings",
hand: hand{card1: "king", card2: "king"},
dealer: "ace",
want: "S",
},
{
name: "pair of twos",
hand: hand{card1: "two", card2: "two"},
dealer: "ace",
want: "H",
},
{
name: "pair of fives",
hand: hand{card1: "five", card2: "five"},
dealer: "ace",
want: "H",
},
{
name: "blackjack with ace for dealer",
hand: hand{card1: "ace", card2: "jack"},
dealer: "ace",
want: "S",
},
{
name: "blackjack with queen for dealer",
hand: hand{card1: "king", card2: "ace"},
dealer: "queen",
want: "S",
},
{
name: "blackjack with five for dealer",
hand: hand{card1: "ace", card2: "ten"},
dealer: "five",
want: "W",
},
{
name: "blackjack with nine for dealer",
hand: hand{card1: "ace", card2: "king"},
dealer: "nine",
want: "W",
},
{
name: "score of 20",
hand: hand{card1: "ten", card2: "king"},
dealer: "ace",
want: "S",
},
{
name: "score of 19",
hand: hand{card1: "ten", card2: "nine"},
dealer: "ace",
want: "S",
},
{
name: "score of 18",
hand: hand{card1: "ten", card2: "eight"},
dealer: "ace",
want: "S",
},
{
name: "score of 17",
hand: hand{card1: "seven", card2: "king"},
dealer: "ace",
want: "S",
},
{
name: "score of 16 with six for dealer",
hand: hand{card1: "ten", card2: "six"},
dealer: "six",
want: "S",
},
{
name: "score of 16 with seven for dealer",
hand: hand{card1: "ten", card2: "six"},
dealer: "seven",
want: "H",
},
{
name: "score of 16 with ace for dealer",
hand: hand{card1: "ten", card2: "six"},
dealer: "ace",
want: "H",
},
{
name: "score of 15 with six for dealer",
hand: hand{card1: "ten", card2: "five"},
dealer: "six",
want: "S",
},
{
name: "score of 15 with seven for dealer",
hand: hand{card1: "ten", card2: "five"},
dealer: "seven",
want: "H",
},
{
name: "score of 15 with king for dealer",
hand: hand{card1: "ten", card2: "five"},
dealer: "king",
want: "H",
},
{
name: "score of 14 with six for dealer",
hand: hand{card1: "ten", card2: "four"},
dealer: "six",
want: "S",
},
{
name: "score of 14 with seven for dealer",
hand: hand{card1: "ten", card2: "four"},
dealer: "seven",
want: "H",
},
{
name: "score of 14 with queen for dealer",
hand: hand{card1: "ten", card2: "four"},
dealer: "queen",
want: "H",
},
{
name: "score of 13 with six for dealer",
hand: hand{card1: "ten", card2: "three"},
dealer: "six",
want: "S",
},
{
name: "score of 13 with seven for dealer",
hand: hand{card1: "ten", card2: "three"},
dealer: "seven",
want: "H",
},
{
name: "score of 13 with queen for dealer",
hand: hand{card1: "ten", card2: "three"},
dealer: "queen",
want: "H",
},
{
name: "score of 12 with six for dealer",
hand: hand{card1: "ten", card2: "two"},
dealer: "six",
want: "S",
},
{
name: "score of 12 with seven for dealer",
hand: hand{card1: "ten", card2: "two"},
dealer: "seven",
want: "H",
},
{
name: "score of 12 with queen for dealer",
hand: hand{card1: "ten", card2: "two"},
dealer: "queen",
want: "H",
},
{
name: "score of 11 with queen for dealer",
hand: hand{card1: "nine", card2: "two"},
dealer: "queen",
want: "H",
},
{
name: "score of 10 with two for dealer",
hand: hand{card1: "eight", card2: "two"},
dealer: "two",
want: "H",
},
{
name: "score of 5 with queen for dealer",
hand: hand{card1: "three", card2: "two"},
dealer: "queen",
want: "H",
},
{
name: "score of 4 with five for dealer",
hand: hand{card1: "two", card2: "two"},
dealer: "five",
want: "H",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := FirstTurn(tt.hand.card1, tt.hand.card2, tt.dealer); got != tt.want {
t.Errorf("FirstTurn(%s, %s, %s) = %s, want %s", tt.hand.card1, tt.hand.card2, tt.dealer, got, tt.want)
}
})
}
}
// FirstTurn returns the semi-optimal decision for the first turn, given the cards of the player and the dealer.
// This function is already implemented and does not need to be edited. It pulls the other functions together in a
// complete decision tree for the first turn.
func FirstTurn(card1, card2, dealerCard string) string {
handScore := ParseCard(card1) + ParseCard(card2)
dealerScore := ParseCard(dealerCard)
if 20 < handScore {
return LargeHand(IsBlackjack(card1, card2), dealerScore)
}
return SmallHand(handScore, dealerScore)
}

3
go/blackjack/go.mod Normal file
View File

@@ -0,0 +1,3 @@
module blackjack
go 1.13