GolfScript 54 53 52
Edycja 1:
Właśnie odkryłem błąd w kodzie. Nie wykrył duplikatów kart, jeśli duplikaty były pierwszymi dwoma na wejściu (ponieważ użyłem *
operatora składania, a nie /
każdego operatora dla pierwszej pętli).
Teraz poprawiłem kod, a także udało mi się usunąć 1 znak w tym procesie. Oto nowa wersja:
' '/{1$1$?){]?}{\+}if}/2%{"UOK0D"\?).0>+.4>5*+}%{+}*
Dane wejściowe muszą znajdować się na stosie jako ciąg znaków, w określonym formacie (przykład '7A UA DA'
:).
Jeśli dane wejściowe są prawidłowe, program drukuje całkowitą wartość kart.
W przypadku, gdy istnieje co najmniej jedna zduplikowana karta, program zgłasza następujący wyjątek:
(eval):1:in `block in initialize': undefined method `class_id' for nil:NilClass (NoMethodError)
Edycja 2:
Po obejrzeniu tego postu na stronie meta postanowiłem opublikować opis kodu. Pomogło mi to również znaleźć i naprawić błąd. Oto więc:
# 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! :-)