GolfScript 54 53 52
Edit 1:
I just discovered an error in the code. It did not detect duplicate cards if the duplicates were the first two in the input (because I was using the * fold operator and not the / each operator for the first loop).
Now I fixed the code and also managed to strip off 1 char in the process. Here's the new version:
' '/{1$1$?){]?}{\+}if}/2%{"UOK0D"\?).0>+.4>5*+}%{+}*
The input has to be on the stack as a string, in the specified format (example: '7A UA DA').
In case the input is valid, the program prints the total value of the cards.
In case there's at least one duplicate card, the program throws the following exception:
(eval):1:in `block in initialize': undefined method `class_id' for nil:NilClass (NoMethodError)
Edit 2:
After seeing this post on the meta site, I decided to post a description of the code. This also helped me find and fix an error. So, here goes:
# Initially, we epect the input string to be on the stack # Example: "7A UA DA" ' '/ # split the input string by spaces # now we have on the stack an array of strings # (in our example: ["7A" "UA" "DA"]) # {1$1$?)!{\+}{]?}if}/ -> this piece of code checks for duplicate cards # # The trailing symbol (/) is the 'each' operator, meaning that the # preceding code block (enclosed in curly brackets) will be executed # for every cards in the previous array. # # Before each execution of the code block, the current card value # is pushed on the stack. # # Basically what this code does is concatenate cards into a string # and checks whether the current card is contained in the accumulated # value. # # So, for each card, this is what we execute: 1$ # copies the concatenated string on top of the stack # (initially this is an empty string) 1$ # copies the current card on top of the stack ? # returns (places on the stack) the 0-based index where # the current card is found in the concatenated string # or -1 if not found ) # increments the topmost stack value # Now we have 0 if the card is not a duplicate # or a value greater than 0 otherwise {]?}{\+}if # if the current stack value is non-0 (duplicate) # then execute the first code {]?} (generates an error) # Otherwise, if the card is valid, execute the {\+} block. # What this code does is essentially concatenate the current # card value: # \ -> swaps the two topmost stack values; now we have # the concatenated string and the current card value # + -> this is the concatenation operator # After the previous code block finishes execution (in case the input is) # valid, we end up having the concatenated card values on the stack # In our example, this value is "DAUAUB7A". # The next code fragment is the one that computes the card values # This is the code: 2%{"UOK0D"\?).0>+.4>5*+}%{+}* # And this is how it can be broken down: 2% # takes only the even indexed chars from the existing string # in our case, "DAUA7A" -> "DU7" # Only these characters are important for determining the # card values. # The following piece of code is: # {"UOK0D"\?).0>+.4>5*+}% # This code performs a map; it takes the individual chars, # computes the corresponding numeric value for each of them and outputs an # array containing those values # This is achieved using the map operator (%) which evaluates the preceding # code block, delimited by curly braces, so, essentially this is the code that # computes the value for a card: # "UOK0D"\?).0>+.4>5*+ # It can be broken down like this: "UOK0D" # pushes the "UOK0D" string on the stack \ # swaps the two topmost stack values # Now, these values are: "UOK0D" and "l" # (where "l" represents the current letter # that gives the card its value: U,O,K,0,D,7,8...) ? # Find the index of the card's letter in the # "UOK0D" string. # Remember, this is 0-based index, or -1 if not found. ) # increment the index value # Now we have the following value: # 1 if the card is U # 2 if the card is O # 3 if the card is K # 4 if the card is 0 # 5 if the card is D # 0 if it is anything else .0>+ # if the current value is greater than 0, # add 1 to it. .4>5*+ # if the current value is greater than 4, # add 5 to it. # Passing through these steps, we now have the following value: # 2 if the card is U # 3 if the card is O # 4 if the card is K # 10 if the card is 0 # 11 if the card is D # 0 if it is anything else # This is the exact value we were looking for. # Now we have an array containing the value of each card. # in our example, [0, 2, 11] # The next piece of code is easy: {+}* # uses the * (fold) operator to add up all the # values in the array. # This leaves the total value of the cards on the stack, # which is exactly what we were looking for (0+2+11=13). # Golfscript is awesome! :-)