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! :-)
2I believe you mean "bells", not "bellys". Very different, that. – boothby – 2012-05-30T03:37:39.650
Is additional output to stderr (e.g. warnings) ok? – Ventero – 2011-06-09T09:02:54.500
@Ventero: Yes, it is. Any way to err out is okay, but it must be clearly visible to the user, that there is an error. – FUZxxl – 2011-06-09T17:40:36.233
Jack, Queen, and Ace are called Unter, Ober, King and Daus? Is a king supposed to be in there? – Ry- – 2011-06-13T19:51:03.283
@minitech No, it is not. – FUZxxl – 2011-06-14T06:45:34.450