19
\$\begingroup\$

The dealer has been sloppy and lost track of what cards his/her deck contains and what cards are missing, can you help him/her?


A complete deck consists of 52 playing cards, namely:

Each color in the deck (hearts, diamonds, spades, clubs) contains:

  • The numbers [2 - 10]
  • A Jack
  • A Queen
  • A King
  • An Ace

Task

Your program will read the contents of the deck from STDIN until a newline is read. You can assume that the input will be in the form of "nX nX nX nX" etc. where:

  • n - any number between [2 - 10] or either 'J', 'Q', 'K' or 'A'. (You can assume upper case only for non-numeric characters)
  • X - any of the following : 'H', 'D', 'S', 'C' (You can assume upper case only)

Where:

  • 'J' = Jacks
  • 'Q' = Queen
  • 'K' = King
  • 'A' = Ace

And

  • 'H' = Hearts
  • 'D' = Diamonds
  • 'S' = Spades
  • 'C' = Clubs

You can assume that there will be no duplicates in the input.

Your program must then print the missing cards in the deck to STDOUT in the same fashion as the input ("nX nX nX") or print 'No missing cards' if all 52 cards are supplied. There is no constraint on the order of the output of the cards.

Example input:

9H AH 7C 3S 10S KD JS 9C 2H 8H 8C AC AS AD 7D 4D 2C JD 6S

Output:

3H 4H 5H 6H 7H 10H JH QH KH 2D 3D 5D 6D 8D 9D 10D QD 2S 4S 5S 7S 8S 9S QS KS 3C 4C 5C 6C 10C JC QC HC

Happy golfing!

\$\endgroup\$
  • 3
    \$\begingroup\$ Could we use T instead of 10? \$\endgroup\$ – Arnauld Apr 5 '17 at 19:11
  • \$\begingroup\$ @Arnauld I'm afraid this is all the information the dealer gave me so you'll have to stick with '10' or he'll get moody. \$\endgroup\$ – Sombrero Chicken Apr 5 '17 at 19:15
  • \$\begingroup\$ @GillBates Doesn't J represent 10, though? \$\endgroup\$ – Okx Apr 5 '17 at 19:28
  • \$\begingroup\$ @Okx 2 3 4 5 6 7 8 9 10 J Q K A. J represents 11. \$\endgroup\$ – HyperNeutrino Apr 5 '17 at 19:30
  • \$\begingroup\$ @Okx J is the 10th letter of the alphabet, but that's not what this is about. :) \$\endgroup\$ – mbomb007 Apr 5 '17 at 19:31

23 Answers 23

8
\$\begingroup\$

Windows Batch (CMD), 205 204 bytes

@set/pc=
@set d=
@for %%s in (H D S C)do @for %%r in (2 3 4 5 6 7 8 9 10 J Q K A)do @call set d=%%d%% %%r%%s
@for %%c in (%c%)do @call set d=%%d: %%c=%%
@if "%d%"=="" set d= No missing cards
@echo%d%

Loops over the suits and ranks building a complete deck, then deletes the input cards. Save 1 byte if T is allowed instead of 10. Save 11 bytes if command-line arguments are acceptable input. Edit: Saved 1 byte thanks to @user202729.

\$\endgroup\$
  • \$\begingroup\$ I count 200 bytes. \$\endgroup\$ – HyperNeutrino Apr 5 '17 at 19:20
  • \$\begingroup\$ @HyperNeutrino As I'm on Windows, I use Notepad to save the file, which means that newlines cost me 2 bytes instead of one. I'm too lazy to use a different editor to save bytes. \$\endgroup\$ – Neil Apr 5 '17 at 19:29
  • \$\begingroup\$ Oh lol okay. I get 200 bytes using Sublime Text. \$\endgroup\$ – HyperNeutrino Apr 5 '17 at 19:31
  • \$\begingroup\$ @Neil On Windows you can use LF instead of CR LF, saves 5 bytes (HyperNeutrino comment above) and it still work. \$\endgroup\$ – user202729 Dec 17 '17 at 3:37
  • \$\begingroup\$ Also, you can pass /v to CMD (+3 byte?) to EnableDelayedExpansion, eliminate call in the for loop. / Seems that you have an extra space between (%c%) and do? \$\endgroup\$ – user202729 Dec 17 '17 at 3:39
8
\$\begingroup\$

Python, 147 146 145 138 131 129 127 125 120 bytes

print(' '.join(set(`x`+y for x in range(2,11)+list('JQKA')for y in'HDSC')-set(raw_input().split()))or'No missing cards')

Gets all possible cards as a set and subtracts the input cards.

-1 byte thanks to mbomb007 pointing out an extra space in my code.
-1 byte thanks to mbomb007 for pointing out some golfing that can be done with Python 2 (-5 bytes and +4 bytes for raw_ in raw_input)
-7 bytes by switching to using sets and set subtraction instead of list comprehensions
-7 bytes thanks to ValueInk for pointing out that I don't need to list the suites
-2 bytes thanks to Datastream for pointing out that just writing out all of the values is more byte-effective than the weird thing I had earlier
-2 bytes thanks to ValueInk for pointing out that sets can take generators so I don't need to put it in a list comprehension
-2 bytes thanks to Datastream for pointing out that I can golf it down even more if I switch to Python 3 again... (+2 for parens after for print, -4 for raw_)
-5 bytes thanks to Lulhum and myself for pointing out that by switching back to Python 2 (!!!) can help me save bytes (using range again, using backticks instead of str(, and +4 due to raw_)

\$\endgroup\$
  • 1
    \$\begingroup\$ You have an extra space you can remove, and you can use `d` instead of str(d) if you use Python 2, in addition to removing the parens for print. \$\endgroup\$ – mbomb007 Apr 5 '17 at 19:32
  • \$\begingroup\$ @mbomb007 Thanks! \$\endgroup\$ – HyperNeutrino Apr 5 '17 at 19:33
  • \$\begingroup\$ for y in 'HDSC' also works for getting all the characters in there. (You still need list('JQKA') for the other part, though.) \$\endgroup\$ – Value Ink Apr 5 '17 at 19:46
  • 1
    \$\begingroup\$ '1 2 3 4 5 6 7 8 9 10 J Q K A'.split() Might save a few bytes instead of the [dfor d in range(2,11)]+list('JQKA') manipulation you have going on. \$\endgroup\$ – Datastream Apr 5 '17 at 20:10
  • \$\begingroup\$ Agreed, it seems like it will save 2 bytes on account of the fact that 1 doesn't need to be added. Also, you can remove the outer brackets for your first list comprehension because the set constructor takes in generator objects just fine. \$\endgroup\$ – Value Ink Apr 5 '17 at 20:38
7
\$\begingroup\$

05AB1E, 39 bytes

ðIð¡YTŸ"JQKA"S«"CDHS"SâJsKðýDg>i“Noœ¶‡¶

Try it online!

Explanation

ðI                                       # push space and input
  ð¡                                     # split on spaces
    YTŸ                                  # push the range [2 ... 10]
       "JQKA"S«                          # append ['J','Q','K','A']
               "CDHS"Sâ                  # cartesian product with suits
                       J                 # join each card with its suit
                        sK               # remove any cards in input from the list of all cards
                          ðýDg>i         # if the length of the resulting list is 0
                                “Noœ¶‡¶  # push the string "No missing cards"
                                         # output top of stack
\$\endgroup\$
5
\$\begingroup\$

CJam, 49 47 bytes

B,2>"JQKA"+"HDSC"m*:slS/-S*"No missing cards"e|

Try it online!

Explanation

B,                    e# The range from 0 to 10
2>                    e# Slice after the first two elements, giving the range from 2 to 10
"JQKA"+               e# Concatenate with "JQKA", giving the array containing all ranks
"HDSC"                e# The string containing all suits
m*                    e# Take the Cartesian product
:s                    e# And cast each pair to a string. Now a full deck has been constructed
l                     e# Read a line of input
S/                    e# Split it on spaces
-                     e# Remove all cards from the deck that were in the input
S*                    e# Join the result with spaces
"No missing cards"    e# Push the string "No missing cards"
e|                    e# Take the logical OR of the result and the string, returning the
                      e#   first truthy value between the two. (empty arrays are falsy)
\$\endgroup\$
5
\$\begingroup\$

Jelly, 39 bytes

9R‘Ṿ€;“JQKA”p“CDHS”F€œ-ɠḲ¤Kȯ“¡¢ıḍĖ9ṭƥw»

Try it online!

How?

9R‘Ṿ€;“JQKA”p“CDHS”F€œ-ɠḲ¤Kȯ“¡¢ıḍĖ9ṭƥw» - Main link: no arguments
9R                                      - range(1,9)    [1,2,3,4,5,6,7,8,9]
  ‘                                     - increment     [2,3,4,5,6,7,8,9,10]
   Ṿ€                                   - uneval each  [['2'],['3'],['4'],['5'],['6'],['7'],['8'],['9'],['10']]
     ;“JQKA”                            - concatenate with char-list "JQKA" [['2'],['3'],['4'],['5'],['6'],['7'],['8'],['9'],['10'],['J'],['Q'],['K'],['A']]
            p“CDHS”                     - Cartesian product with char-list "CDHS" [[['2'],['C']],[['2'],['D']],...]
                   F€                   - flatten each [['2','C'],['2','S'],...]
                         ¤              - nilad followed by link(s) as a nilad
                       ɠ                -     read a line from STDIN
                        Ḳ               -     split on spaces
                     œ-                 - multi-set difference
                          K             - join with spaces
                            “¡¢ıḍĖ9ṭƥw» - compressed string "No missing cards"
                           ȯ            - logical or
                                        - implicit print
\$\endgroup\$
5
\$\begingroup\$

C#, 343 bytes

First time posting one of my golfs, not a very good contender though. I'm sure I can reduce this more.

The idea behind it is a sparse array storing occurrences of cards, with indexes calculated by the ASCII values of the different values and suits multiplied against each other (e.g. an ace of spades (AS) would be stored in the area at index (65 * 83 = 5395)). This way, each type of card gets a unique index that can be checked later for existance in the "map" array.

void M(string[]a){var c=new int[]
{50,51,52,53,54,55,56,57,49,74,81,75,65,72,68,83,67};var e=new 
int[9999];int i=0;int j=0;foreach(var s in a) e[s[0]*s[s.Length-
1]]++;int f=0;for(i=0;i<13;i++)for(j=13;j<17;j++)if(e[c[i]*c[j]]==0)
{f=1;Console.Write(((i<9)?(i+2)+"":(char)c[i]+"")+(char)c[j]+" 
");}if(f==0) Console.WriteLine("No missing cards");}
\$\endgroup\$
4
\$\begingroup\$

PowerShell, 114 111 110 bytes

param($n)('No missing cards',($a=(2..10+'JQKA'[0..3]|%{$i=$_;"CSHD"[0..3]|%{"$i$_"}}|?{$n-notmatch$_})))[!!$a]

Try it online!

Takes input $n as either a space-delimited or newline-delimited string. Constructs an array from the range 2..10 concatenated with JQKA (indexed with [0..3] to make it a char array). That array is fed into a loop |%{} that sets helper $i then loops over the suits to concatenate the results together with $i$_. At the end of this loop, we have an array of strings like ("2C", "2S", "2H", ... "AH", "AD"). That array is fed into a Where-Object (|?{}) with the filter as those elements $_ that regex -notmatch the input $n. The result of that filtering is stored into $a.

Then, we use a pseudo-ternary ( , )[] to select whether we output 'No missing cards' or $a, based on whether !!$a turns to a Boolean $false or $true. If $a is empty (meaning every card in the deck is in the input), then !!$a is 0, so the "No missing cards" is selected. Vice versa for $a being selected. In either case, that's left on the pipeline, and output is implicit.

\$\endgroup\$
4
\$\begingroup\$

Bash + coreutils, 89

sort|comm -3 <(printf %s\\n {10,{2..9},A,J,K,Q}{C,D,H,S}) -|grep .||echo No missing cards

I/O as a newline-delimited list.

Explanation

  • sort reads newline-delimited input from STDIN and sorts it
  • This is piped to comm
  • printf %s\\n {10,{2..9},A,J,K,Q}{C,D,H,S} is a brace-expansion to generate the full deck of cards. The printf prints each card on its own line. The order is given such that the output is the same as if it had been piped to sort
  • comm compares the full deck against the sorted input and outputs the difference. -3 suppresses output of column 3 (the common ones)
  • The whole output from comm is piped to grep .. If there was no output from comm (i.e. all cards were in the input), then the || "or" clause outputs the required message. Otherwise the grep . matches all lines output from comm.

Try it online.

\$\endgroup\$
4
\$\begingroup\$

Python 2,104,93,130,114 bytes

r=input()
print' '.join(n+x for n in list('23456789JQKA')+['10']for x in'HDSC'if n+x not in r)or'No missing cards'

Try it online!

  • -10 bytes with hardcoding the list instead of using range!
  • +37 bytes - missed printing 'No missing cards' if all cards are present in input!
  • -16 bytes by modifying the code into a list comprehension!
\$\endgroup\$
  • 1
    \$\begingroup\$ Doesn't print "No missing cards" \$\endgroup\$ – L3viathan Apr 6 '17 at 11:28
  • 1
    \$\begingroup\$ @L3viathan thanks for pointing that out. I've edited my answer! \$\endgroup\$ – Keerthana Prabhakaran Apr 6 '17 at 12:38
  • \$\begingroup\$ The list('23456789JQKA')+['10'] is clever. I was wracking my brain for a better way to split the 10 out of the list of single chars in the other python answer, but that works beautifully. \$\endgroup\$ – Datastream Apr 6 '17 at 12:48
2
\$\begingroup\$

Ruby, 108 + 1 = 109 bytes

Uses the -p flag.

a=[*?2..'10',?J,?Q,?K,?A].map{|i|%w"H D S C".map{|c|i+c}}.flatten-$_.split;$_=a==[]?"No missing cards":a*' '
\$\endgroup\$
2
\$\begingroup\$

PHP, 143 Bytes

foreach([H,D,S,C]as$c)foreach([2,3,4,5,6,7,8,9,10,J,Q,K,A]as$v)$r[]=$v.$c;echo join(" ",array_diff($r,explode(" ",$argn)))?:"No missing cards";
\$\endgroup\$
2
\$\begingroup\$

sed, 157 + 1 (-r flag) = 170 158 bytes

x
s/$/;A2345678910JQK/
s/.+/&H&D&S&C;No missing cards/
:
s/(10|\w)(\w+)(.);/\1\3 \2\3;/
t
G
:s
s/(10.|[^ ;1]{2})(.*\n.*)\1/\2/
ts
s/[ ;]+/ /g
s/^ //
s/ N.+//

Try it online!

This generates all possible cards and then remove each card in the input from the generated cards.

\$\endgroup\$
  • \$\begingroup\$ Doesn't print "No missing cards" \$\endgroup\$ – L3viathan Apr 6 '17 at 11:28
  • \$\begingroup\$ @L3viathan Fixed \$\endgroup\$ – Kritixi Lithos Apr 6 '17 at 11:41
2
\$\begingroup\$

C#, 282 bytes


Golfed

i=>{var o=new System.Collections.Generic.List<string>();string[] S={"H","D","S","C"},N="A 2 3 4 5 6 7 8 9 10 J Q K".Split(' ');foreach(var s in S){foreach(var n in N){if(!System.Linq.Enumerable.Contains(i,n+s)){o.Add(n+s);}}}return o.Count>0?string.Join(" ",o):"No missing cards";};

Ungolfed

i => {
    var o = new System.Collections.Generic.List<string>();
    string[] S = { "H", "D", "S", "C" }, N = "A 2 3 4 5 6 7 8 9 10 J Q K".Split(' ');

    foreach( var s in S ) {
        foreach( var n in N ) {
            if( !System.Linq.Enumerable.Contains( i, n + s ) ) {
                o.Add( n + s );
            }
        }
    }

    return o.Count > 0
        ? string.Join( " ", o )
        : "No missing cards";
};

Ungolfed readable

i => {
    // Initialize a list to contain the list of cards missing
    var o = new System.Collections.Generic.List<string>();

    // Initialize the list of suits and numbers of cards
    string[] S = { "H", "D", "S", "C" }, N = "A 2 3 4 5 6 7 8 9 10 J Q K".Split(' ');

    // Cycle through the suits...
    foreach( var s in S ) {
        // ... and the numbers ...
        foreach( var n in N ) {
            // ... and check it the combo number + suite is missing
            if( !System.Linq.Enumerable.Contains( i, n + s ) ) {
                // If it's missing, add it to the list of missing cards
                o.Add( n + s );
            }
        }
    }

    // If the count of missing cards is greater than 0...
    return o.Count > 0
        // Build a 'space' separated string with the missing cards
        ? string.Join( " ", o )
        // Or output the missing cards string
        : "No missing cards";
};

Full code

using System;
using System.Collections.Generic;
using System.Linq;

namespace Namespace {
   class Program {
      static void Main( String[] args ) {
         Func<String, Int32> f = i => {
            var o = new List<string>();
            string[] S = { "H", "D", "S", "C" }, N = "A 2 3 4 5 6 7 8 9 10 J Q K".Split(' ');

            foreach( var s in S ) {
               foreach( var n in N ) {
                  if( !i.Contains( n + s ) ) {
                     o.Add( n + s );
                  }
               }
            }

            return o.Count > 0
               ? string.Join( " ", o )
               : "No missing cards";
         };

         List<String>
            testCases = new List<String>() {
                "9H AH 7C 3S 10S KD JS 9C 2H 8H 8C AC AS AD 7D 4D 2C JD 6S"
            };

         foreach( String testCase in testCases ) {
            Console.WriteLine( $"{test}\n{f( test.Split( ' ' ) )}" );
         }

         Console.ReadLine();
      }
   }
}

Releases

  • v1.0 - 282 bytes - Initial solution.

Notes

Nothing to add

\$\endgroup\$
  • 1
    \$\begingroup\$ This is a very nice format for your answer, +1. \$\endgroup\$ – Rɪᴋᴇʀ Dec 17 '17 at 19:06
2
\$\begingroup\$

JavaScript (ES6), 117 114 111 bytes

s=>[...Array(52)].map((_,i)=>~s.search(c=('JQKA'[v=i>>2]||v-2)+'CDHS'[i&3])?_:c+' ').join``||'No missing cards'

This takes advantage of the fact that undefined entries in the array generated by map() are coerced to empty strings when join()'d.

Demo

let f =

s=>[...Array(52)].map((_,i)=>~s.search(c=('JQKA'[v=i>>2]||v-2)+'CDHS'[i&3])?_:c+' ').join``||'No missing cards'

console.log(f('9H AH 7C 3S 10S KD JS 9C 2H 8H 8C AC AS AD 7D 4D 2C JD 6S'))

\$\endgroup\$
2
\$\begingroup\$

Retina, 76 bytes

^
A2345678910JQK¶ 
\G(10|.)
 $&H $&D $&S $&C
Dr` \S+
G1`
^$
No missing cards

Input/output is a list of space-separated cards. Output has a leading space.

Try it online!

Explanation

Most of the code deals with building the full list of cards that should be in the deck:

^
A2345678910JQK¶ 
\G(10|.)
 $&H $&D $&S $&C

First, we prepend a newline to the input, with all possible values of cards, then for each character of this line (or the couple of characters 10) we build the list of all possible suits of that card.

Dr` \S+

This is a deduplication stage, it splits the string into chunks consisting of a space plus some non-spaces and keeps only one occurrence of each chunk. The modifier r makes this operate from right to left, keeping then the last occurrence of each chunk.

G1`

We keep only the first line, which now contains the missing cards.

^$
No missing cards

If the result is empty we replace it with "No missing cards"

\$\endgroup\$
1
\$\begingroup\$

Python 3, 106 bytes

Combination of the two previous python answers mixed with some string unpacking shenanigans.

print(' '.join({x+y for x in[*'23456789JQKA','10']for y in'HDSC'}-{*input().split()})or'No missing cards')
\$\endgroup\$
1
\$\begingroup\$

Julia, 116 bytes

print(join(setdiff(["$x$y"for x=∪(2:10,"JQKA")for y="HDSC"],readline()|>split),' ')|>s->s>""?s:"No missing cards")

Try it online!

Very similar to Kyle Gullions python solution. Setdiff instead of - and the lambda to test for the empty string make it worse though.

\$\endgroup\$
1
\$\begingroup\$

Japt, 39 bytes

"JQKA"¬c9õÄ)ï+"CHSD"q)kU ¸ª`No ÚÍg Ößs

Try it

\$\endgroup\$
1
\$\begingroup\$

Tcl, 270 228 chars

(Shortened with some help from Wît Wisarhd)

foreach s {H D S C} {foreach c {2 3 4 5 6 7 8 9 J Q K A} {dict set d $c$s 0}}
gets stdin l
foreach c $l {dict set d $c 1}
set m {}
dict for {c h} $d {if {!$h} {lappend m $c}}
if {![llength $m]} {set m "No missing cards"}
puts $m

Try it online!

Explanation:

This implementation builds a dictionary consisting of a boolean flag for each of the cards represented by the cartesian product of H D S C and 2-through-A. It reads the line from stdin, which if given as the spec as called for, is actually a well formed Tcl list. As each card is read, a boolean true is input in the dictionary for that card.

At the end a parser loops through the dictionary, and adds any card that did not have a true in the dictionary to a list of missing cards. If the missing cards list length is zero, output "No missing cards", otherwise output the list of missing cards.

\$\endgroup\$
1
\$\begingroup\$

PHP, 138 bytes

Ran with -n and -d error_reporting=0

I reuse some code from an old submition i made that asked for create a deck of cards

Code

<?$r=[];foreach([A,J,Q,K,2,3,4,5,6,7,8,9,10]as$t)array_push($r,$t.H,$t.S,$t.D,$t.C);
echo join(" ", array_diff($r,explode(" ",$argv[1])));

Try it online!

Explanation

<?$r=[];   # Declare the array that will contain the full deck
# the next line will generate the arry with the full deck  
foreach([A,J,Q,K,2,3,4,5,6,7,8,9,10]as$t)array_push($r,$t.H,$t.S,$t.D,$t.C);
# explode the input string on each blank space and using array_diff to get the
# different elements withing both arrays. (and "echo" of course) 
echo join(" ", array_diff($r,explode(" ",$argv[1])));
\$\endgroup\$
  • \$\begingroup\$ You can get it down to 120 with a few tweaks. 1) end the first line with a ?> replace the 'echo ' with <?= 2) entering the cards on regular command line with spaces will populate $argv as an array with each as an element, so you can remove the explode() entirely. Try it \$\endgroup\$ – 640KB Jan 9 at 21:30
  • \$\begingroup\$ i had no clue that $argv can work like that, thanks @gwaugh \$\endgroup\$ – Francisco Hahn Jan 10 at 12:36
  • \$\begingroup\$ Oh btw @gwaugh the question sayd that the argument is a string separated by spaces, can set the arguments one by one. \$\endgroup\$ – Francisco Hahn Jan 10 at 12:38
  • \$\begingroup\$ If you run it on the command line like: 'php deck.php 2S 5H JC' it's the same use as if you were to think of it as a space delimited string. You're just letting PHP parse it out for you. It's only the UI of TIO that makes you put them in separate. \$\endgroup\$ – 640KB Jan 10 at 12:46
  • \$\begingroup\$ Oh, i see. Will edit, thanks for the -bytes :D \$\endgroup\$ – Francisco Hahn Jan 10 at 12:48
1
\$\begingroup\$

C# (.NET Core), 197 bytes

Without LINQ.

s=>{var w="";for(var j=0;j<52;){var u="";int t=j%13;u=t<1?"K":t<2?"A":t<11?t+"":t<12?"J":"Q";t=j++/13;u+=t<1?"H":t<2?"D":t<3?"S":"C";w+=s.IndexOf(u)<0?u+" ":"";}return w==""?"No missing cards":w;};

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Perl 6, 73 bytes

put keys((<<{^9+2}J Q K A>>X~ <C S D H>)∖get.words)||"No missing cards"

Try it online!

Some pretty simple set subtraction between the deck of cards and the input.

\$\endgroup\$
1
\$\begingroup\$

Python 3, 102 bytes

lambda s:' '.join(i+j for i in[*'A23456789JQK','10']for j in'HDSC'if(i+j)not in s)or'No missing cards'

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.