## DEV Community is a community of 871,761 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

# Daily Challenge #198 - 21 Blackjack

Implement a function that determines the score of a hand in the card game 21 Blackjack.

The function will receive an array filled with strings that represent each card in the hand. Your function should return the score of the hand as an integer.

Number cards count as their face value (2 through 10). Jack, Queen and King count as 10. An Ace can be counted as either 1 or 11.

Return the highest score of the cards that is less than or equal to 21. If there is no score less than or equal to 21 return the smallest score more than 21.

### Examples

["A"] ==> 11
["5", "4", "3", "2", "A", "K"] ==> 25

### Tests

["A", "J"]

["A", "10", "A"]

["5", "3", "7"]

This challenge comes from jodymgustafson on CodeWars. Thank you to CodeWars, who has licensed redistribution of this challenge under the 2-Clause BSD License!

Want to propose a challenge idea for a future post? Email yo+challenge@dev.to with your suggestions!

## Discussion (11) Cent | Shannon Myers

Javascript

This solution doesn't consider the fact that an ace could be both a 1 and an 11 (2+ aces in a hand). But this solution does solve all of the tests

``````
const blackJack = (cards) => {
let total = [0, 0]
cards.forEach((card) => {
switch(card) {
case "2":
case "3":
case "4":
case "5":
case "6":
case "7":
case "8":
case "9":
case "10":
total += parseInt(card);
total += parseInt(card);
break;
case "J":
case "Q":
case "K":
total += 10;
total += 10;
break;
case "A":
total += 1;
total += 11;
break;
}
})

return Math.max(...total) <= 21 ? Math.max(...total) : Math.min(...total)
}

``````

Codepen @nobody

Clojure ✌🏿

``````(ns dailyChallenge.one-ninety-eight)

(defn scoreHand [hand]
(let [WIN 21
CARDS {:2 2, :3 3, :4 4, :5 5,
:6 6 :7 7, :8 8, :9 9,
[:J :Q :K] 10, :A [1 11]}] ;;this is why I ♥ Clojure
(for [card hand]
(apply + (CARDS card))...To be continued (need to save somewhere)))
`````` SavagePixie • Edited on

Elixir

Some recursion

``````defmodule Cards do
def blackjack(list), do: _blackjack(0, 0, list)

defp _blackjack(n, a, []), do: n + _get_as(n, a)
defp _blackjack(n, a, [ head | tail ]) do
cond do
head == "A" -> _blackjack(n, a + 1, tail)
Enum.member?([ "J", "Q", "K" ], head) -> _blackjack(n + 10, a, tail)
true -> _blackjack(n + String.to_integer(head), a, tail)
end
end

defp _get_as(_n, 0), do: 0
defp _get_as(n, a) when n + a - 1 < 11, do: a + 10
defp _get_as(_n, a), do: a
end
`````` Amin • Edited on

Elm

From what I understood about the game, the cards are revealed at each draw. I may have implemented a wrong version though.

``````module BlackJack exposing (score)

import List exposing (foldl)
import String exposing (toInt)
import Maybe exposing (withDefault)

cardToScore : String -> Int -> Int
cardToScore card accumulatedScore =
case card of
"A" ->
if accumulatedScore + 11 > 21 then
accumulatedScore + 1

else
accumulatedScore + 11

otherCard ->
accumulatedScore + ( otherCard |> toInt |> withDefault 10 )

score : List String -> Int
score cards =
foldl cardToScore 0 cards
``````

Tests

``````module BlackJackTest exposing (suite)

import Expect exposing (Expectation, equal)
import Test exposing (Test, describe, test)
import BlackJack exposing (score)

suite : Test
suite =
describe "BlackJack.elm"
[ describe "score"
[ test "It should return 11" <| \_ ->
equal 11 <| score [ "A" ]
, test "It should return 25" <| \_ ->
equal 25 <| score [ "5", "4", "3", "2", "A", "K" ]
, test "It should return 21" <| \_ ->
equal 21 <| score [ "A", "J" ]
, test "It should return 22" <| \_ ->
equal 22 <| score [ "A", "10", "A" ]
, test "It should return 15" <| \_ ->
equal 15 <| score [ "5", "3", "7" ]
]
]
`````` Kyle Jones

In Python:

``````import sys

FACE_CARDS = ['J', 'Q', 'K']

def score_hand(hand):
'''
Calculate the total score of the hand.
'''
hand_score = 0

for card in hand:
if card in FACE_CARDS:
hand_score += 10
continue

if card == 'A':
hand_score += 1
if hand_score < 12:
hand_score += 10
continue
try:
hand_score += int(card)
continue
except ValueError:
print('Invalid card in hand: {}'.format(card))
except TypeError:
print('Card is an invalid type: {}'.format(type(card)))
return hand_score

print(str(score_hand(['A'])))
print(str(score_hand(['5', '4', '3', '2', 'A', 'K'])))
print(str(score_hand(['5', '3', '7'])))
print(str(score_hand(['A', 'J'])))
print(str(score_hand(['A', '10', 'A'])))
`````` Shannon Crabill

In Ruby. Iterate over each card and total as you go. If it's a face card, count is as 10. If it's a number card, count is as what it is. If it's an ace and the current score is below 21 and counting an ace as a 11 wouldn't push it over 21, count is as 11. Otherwise, count is a 1.

``````def total(array)
count = 0
face_cards = ["J","Q","K"]

array.each do |card|
if face_cards.include?(card)
count = count + 10
elsif card == "A"
count = count + 1
else
count = count + card.to_i
end
end

if count < 21 && array.include?("A")
if count + 10 <= 21
count = count + 10
end
end

count

end
``````

The examples

``````total(["A"]) # ==> 11
total(["5", "4", "3", "2", "A", "K"]) # ==> 25
total(["A", "J"]) # ==> 21
total(["A", "10", "A"]) # ==> 12
total(["5", "3", "7"]) # ==> 21
``````

A possible flaw is that you should be seeing cards one at a time, instead of as a whole then deciding on how to handle aces.

A .map or .inject method could clean this up in Ruby. Python

``````var = input("Enter the string: ")
var = var.split(' ')

sum = 0;
a = 0
for i in var:
if i == 'K' or i == 'J' or i == 'Q':
sum += 10
elif i == 'A':
a += 1
else:
sum += int(i)

if sum + a*11 <= 21:
sum += a*11
elif sum + a <= 21:
sum += a
else:
for i in range(a):
if sum <= 21:
sum += 11
else:
sum += a-i
break

print(sum)
`````` Vidit Sarkar • Edited on

C++

``````int scoreHand(vector<string> cards){
unordered_map<string,int> scoreCount; // holds the score of each card
for(int i=2;i<=10;i++){
scoreCount[to_string(i)] = i;
}
scoreCount["A"] = 1; // store the score of A as 1 (minimum)
scoreCount["J"] = 10;
scoreCount["K"] = 10;
scoreCount["Q"] = 10;

unordered_map<string, int> cardCount; // holds the number of times cards are apperaing
int score = 0; // minimum score (i.e. score with A as 1)
for(string s : cards){
score += scoreCount[s];
cardCount[s]++;
}

// if score is 21 return 21
if(score == 21)
return score;

// if score < 21 try to maximize it
// but keep it less than or equal to 21
if(score < 21){
for(int i=0;i<cardCount["A"];i++){
if(score > 11){
return score;
}
// add score of A to score
// score = score - 1 + 11
score += 10;
}
}

// no need to write the case when score > 21
// because we are always starting from minimum score possible
return score;
}
``````

Code can be optimized by caculating `scoreCount` seperately and then passing
it as an argument in the function. Vidit Sarkar • Edited on

Test cases --

``````cout << scoreHand({"A"}) << "\n";
cout << scoreHand({"5", "4", "3", "2", "A", "K"}) << "\n";
cout << scoreHand({"A", "J"}) << "\n";
cout << scoreHand({"A", "10", "A"}) << "\n";
cout << scoreHand({"5", "3", "7"}) << "\n";
cout << scoreHand({"5", "5", "A"}) << "\n";
cout << scoreHand({"A", "A", "A"}) << "\n";
cout << scoreHand({"A", "A"}) << "\n";
cout << scoreHand({"5", "4", "3", "10", "K"}) << "\n";
``````

Output --

``````11
25
21
12
15
21
13
12
32
``````