Identify halves of Poker cards

20

2

A casino uses the following deck of cards. (* is one of the card suits D, S, C or H.)

 _________    _________    _________    _________    _________
|         |  |         |  |         |  |         |  |         |
|         |  |         |  |    *    |  |  *   *  |  |  *   *  |
|         |  |    *    |  |         |  |         |  |         |
|    *    |  |         |  |    *    |  |         |  |    *    |
|         |  |    *    |  |         |  |         |  |         |
|         |  |         |  |    *    |  |  *   *  |  |  *   *  |
|_________|  |_________|  |_________|  |_________|  |_________|

 _________    _________    _________    _________    _________
|         |  |         |  |         |  |         |  |         |
|  *   *  |  |  *   *  |  |  *   *  |  |  *   *  |  |  *   *  |
|         |  |         |  |  *   *  |  |  *   *  |  |  *   *  |
|  *   *  |  |  * * *  |  |         |  |    *    |  |  *   *  |
|         |  |         |  |  *   *  |  |  *   *  |  |  *   *  |
|  *   *  |  |  *   *  |  |  *   *  |  |  *   *  |  |  *   *  |
|_________|  |_________|  |_________|  |_________|  |_________|

 _________    _________    _________
|         |  |         |  |         |
|  *   *  |  |  *   *  |  |  * * *  |
|  *   *  |  |  * * *  |  |  *   *  |
|  * * *  |  |  *   *  |  |  * * *  |
|  *   *  |  |  * * *  |  |  *   *  |
|  *   *  |  |  *   *  |  |  * * *  |
|_________|  |_________|  |_________|

After each night, old decks are discarded, and cut in half to avoid reuse. As a result, the casino has a big room full of cut card halves.

Unfortunately the economy is bad, and the casino is in financial trouble. The most reasonable thing to save money seems to be recycling, so the casino owners decide to tape old cards back together. So they hire a team to build a machine which will do this.

You are part of the team, and your job is to help identifying the card.

Write a program or function which will take an ASCII art image of a card half in the form of a string, and will return a string of what card it is.

Input is an 11x5 string, plus line break characters (CR, LF or CRLF, you only need to support one). You may assume trailing whitespace at the end of each input line, if necessary. The input won't contain any invalid characters (any other than _|-HSCD and space and line break).

A card half will look like this:

 _________
|         |
|  H   H  |
|  H H H  |
---H---H---

which should be identified as the Queen of Hearts:

H12

The casino is on a limited budget, so this is code golf: the shortest program wins.

user694733

Posted 2015-05-07T13:19:37.190

Reputation: 765

@Optimizer Well, we all know casinos are poor underdogs of society :) I added some clarification on input. – user694733 – 2015-05-07T13:34:40.807

what methods of input are acceptable? – tfitzger – 2015-05-07T13:42:11.470

@tfitzger Any kind of string or character array that represents the card. I don't want to put too strict restrictions on that, as it's not "the meat" of the puzzle. – user694733 – 2015-05-07T13:44:42.250

Thanks. Also, what about inputs that don't match a card above. For example, _________\n| |\n| H H |\n| H H H |\n-------H---. – tfitzger – 2015-05-07T13:57:21.093

2@tfitzger You can ignore any invalid/impossible cards. We assume that there are only valid cards. So you need to only take previously mentioned 13 layouts in to consideration. – user694733 – 2015-05-07T14:00:17.553

2Can the output have a space between the two? Like H 12? – mbomb007 – 2015-05-07T18:41:41.820

What does budget have to do with the number of lines of code? :) – DA. – 2015-05-07T21:27:30.413

@DA. Maybe the programmers are paid by the line/byte... – mbomb007 – 2015-05-07T21:28:59.340

1@DA we forgot to mention they casino managers are stuck with 1980's business practices. – corsiKa – 2015-05-08T16:49:11.477

Answers

34

CJam, 16 15 13 12 bytes

q2*A~<$e`3=(

Test it here.

Explanation

The basic idea is to manipulate the string such that we can make CJam's built-in run-length encoding work for us.

Let's go through an example (the one from the question). The input string is

 _________
|         |
|  H   H  |
|  H H H  |
---H---H---

We repeat that twice:

 _________
|         |
|  H   H  |
|  H H H  |
---H---H---
 _________
|         |
|  H   H  |
|  H H H  |
---H---H---

And remove the last line:

 _________
|         |
|  H   H  |
|  H H H  |
---H---H---
 _________
|         |
|  H   H  |
|  H H H  |

Then we sort this string. It'll now have a bunch of newlines at the start, and then this (shortened by a few spaces to avoid a horizontal scrollbar):

                                    ---------HHHHHHHHHHHH__________________||||||||||||

While the suit character will vary, it'll always be an upper case letter, found in the fourth run of the sorted string (accounting for the newline). When we run-length encode this we get

[8 '\n] [46 ' ] [9 '-] [12 'H] [18 '_] [12 '|]]

So all we need to do is pick out the fourth element and reverse it.

Here is a breakdown of the actual code:

q              e# Read the input.
 2*            e# Repeat twice.
   A~<         e# Remove the last 11 characters, i.e. the last line.
      $        e# Flatten into a single string and sort its characters.
       e`      e# Run-length encode: turns the sorted string into 5 pairs of numbers
               e# and characters.
         3=    e# Select the one corresponding to the suit.
           (   e# Pull off the number so that its printed after the suit.

Martin Ender

Posted 2015-05-07T13:19:37.190

Reputation: 184 808

7

Pyth (recent version), 16 bytes

p/KsP*2.zJ@S{K2J

Try it online: Pyth Compiler/Executor

Explanation:

       .z           read all lines from input
     *2             duplicate all lines
    P               remove the last line
   s                combine all lines to a big string
  K                 store in K

            {K      set(K), removes duplicate chars
           S        sort, this will result in the list [' ', '-', color, '_', '|']
          @   2     take the element at index 2
         J          and store it in J

p/K      J     J    print J + (count J in K)

Pyth 4.0, 13 bytes

jk@.rSsP*2.z2

Pyth had a build in run-length-encoding. But only for short time. If someone wants to try this: Clone the Pyth repo and checkout the commit 6a6dccd.

This program works pretty much the same way as Martin's CJam solution.

      sP*2.z        like in the 16 bytes solution
     S              sort
   .r               run-length-encoding
  @         2       element at index 2 
jk                  join by "" and print

Jakube

Posted 2015-05-07T13:19:37.190

Reputation: 21 462

6

CJam, 22 bytes

qN/)'--\s"_| "-_]s)\,)

Looking at more golfing options here. Here is how it works:

qN/                       e# Read the entire input from STDIN and split it on new lines
   )'--                   e# Take out the last line and remove - from it
       \                  e# Stack contains the half HSDC now. We swap this with rest of
                          e# the input
        s                 e# join the rest of the input array to a single string
         "_| "-           e# Remove anything other than HSCD
               _]s        e# Copy this and convert everything on stack into a single
                          e# string. Now we have the total HSCD in the complete card
                  )       e# Take out the last of HSCD. This serves as first character of
                          e# the output
                   \,)    e# Swap and take length of rest of the HSCD. Increment it by 1
                          e# as we removed 1 in the previous step.

Try it online here

Optimizer

Posted 2015-05-07T13:19:37.190

Reputation: 25 836

3

Python 2, 80 68 66 bytes

Try it here

Duplicate the input, find all the letters in all but the last line (the first couple chars in the last line cannot be letters), then print the first letter and how many.

s=(input()*2)[:-9]
for c in"CDHS":
    if c in s:print c+`s.count(c)`

Input: ' _________\n| |\n| H H |\n| H H H |\n---H---H---'

Output: H12

Previous version that uses regex (68):

import re
r=re.findall('[C-S]',(input()*2)[:-9])
print r[0]+`len(r)`

Thanks to Sp3000 for golf help.

mbomb007

Posted 2015-05-07T13:19:37.190

Reputation: 21 944

@Sp3000 This is as short as I could get it using that method. It's 15 longer. i=input()*2;s="CDSH";r=[i[:-9].count(x)for x in s];n=sum(r);print s[r.index(n)]+`n` – mbomb007 – 2015-05-08T15:47:35.373

Ah, I couldn't figure out how to get the suit better. – mbomb007 – 2015-05-08T16:03:51.033

3

J, 26 bytes

(],[:":@(+/)]=[,_9}.[)4{~.

Usage:

   ((],[:":@(+/)]=[,_9}.[)4{~.) input
H12

Reading the code from left to right:

  • We get the suit from the input as the 5th distinct character in it (4{~.).
  • Count (+/) the number that character occurs total in the input ([) and the input without the last 9 characters (_9}.[).
  • Finally we concatenate the suit (]) to the resulting sum's string representation (":) .

randomra

Posted 2015-05-07T13:19:37.190

Reputation: 19 909

3

APL, 39 bytes

I'm sure this could be made much shorter, but it's a start.

f←{X←(∊⍵[⍳46]⍵)∩'HDCS'⋄((⊃X),0⍕⍴X)~' '}

This creates a named monadic function that accepts an input string and returns a string containing the card's suit and value. You can try it online!

Explanation:

f ← {                         ⍝ Define the function f.
     X←                       ⍝ Assign X as
       (∊⍵[⍳46]⍵)             ⍝ the right input duplicated, no center line
                 ∩ 'HDCS'     ⍝ intersect 'HDCS'.
                              ⍝ X is now a vector like 'HHHHHH'.
     ((⊃X)                    ⍝ Return the first element of X
          ,                   ⍝ concatenated with
           0⍕⍴X)              ⍝ the length of X as a string
                ~' '          ⍝ without a space.
}

Suggestions are welcome as always!

Alex A.

Posted 2015-05-07T13:19:37.190

Reputation: 23 761

How about (⊃,≢)'HDCS'∩⍨¯11↓,⍨?

– Adám – 2017-01-04T10:49:46.087

Shorter, but more bytes: 5⌷{⍺,≢⍵}⌸¯11↓,⍨⍞

– Adám – 2017-01-04T11:08:53.907

3

Perl, 75 bytes

@r=();foreach ((<>)[2,2,3,3,4]){push@r,$1 while(/([CDSH])/g)}print $r[0].@r

Ungolfed version

@r=(); # Collect matches in this array
foreach ((<>)               # Read stdin as a single array of lines
                            # Note that for a subroutine use @_ for (<>)
         [2,2,3,3,4]) {     # Look at the 3rd, 4th rows twice, 5th row once
    push @r, $1             # Collect individual character matches
        while (/([CDSH])/g) # As long as one of the suits matches
}
print $r[0]                 # Each element of array is matching letter
      .@r                   # Array reference in scalar context gives length

Ralph Marshall

Posted 2015-05-07T13:19:37.190

Reputation: 729

2

Bash + coreutils, 73

sed '$q;s/.*/&&/'|fold -1|sort|uniq -c|sed -nr 's/ +(\w+) ([C-S])/\2\1/p'

Digital Trauma

Posted 2015-05-07T13:19:37.190

Reputation: 64 644

2

Julia, 58 bytes

s->(m=matchall(r"[A-Z]",s*s[1:46]);join([m[1],length(m)]))

This creates an unnamed function that takes a string as input and returns the card's suit and value. To call it, give it a name, e.g. f=s->(...).

Ungolfed + explanation:

function f(s)
    # Find all alphabetic characters in the input joined with itself
    # excluding the second center line, which begins at the 47th
    # character

    m = matchall(r"[A-Z]", s * s[1:46])

    # Take the first match and the number of matches as an array,
    # collapse the array into a string, and return it

    join([m[1], length(m)])
end

Suggestions are welcome as always!

Alex A.

Posted 2015-05-07T13:19:37.190

Reputation: 23 761