Love calculation

As a kid my sister showed me this little love calculation to see how much chance you have of getting in a successful relationship with your crush. All you need is 2 names and a piece of paper.

• John
• Jane

Then, you separate these names with the word Loves. You can either write this on one line or on new lines.

John
Loves
Jane

Then the calculating begins. You start off by counting how many times a character occurs from left to right and in case you use new lines also from top to bottom. Each character is counted once, So after counting the J of John you don't have to count them again when you start with Jane. The result of this example will be as follows:

J: 2 ([J]ohn | [J]ane)
O: 2 (J[o]hn | L[o]ves)
H: 1 (Jo[h]n)
N: 2 (Joh[n] | Ja[n]e)
__
L: 1 ([L]oves)
O: skipped
V: 1 (Lo[v]es)
E: 2 (Lov[e]s | Jan[e])
S: 1 (Love[s])
__
J: skipped
A: 1 (J[a]ne)
N: skipped
E: skipped
__
Final result: 2 2 1 2 1 1 2 1 1

The next step will be adding the digits working from the outside to the middle.

2 2 1 2 1 1 2 1 1 (2+1=3)
2 2 1 2 1 1 2 1 1 (2+1=3)
2 2 1 2 1 1 2 1 1 (1+2=3)
2 2 1 2 1 1 2 1 1 (2+1=3)
2 2 1 2 1 1 2 1 1 (1)
__
Result: 3 3 3 3 1

You will keep doing this until you have an integer left less or equal to 100.

3 3 3 3 1
4 6 3
76%

It can happen that the sum of 2 digits becomes ≥ 10, in this case the number will be split in 2 on the next row.
Example:

5 3 1 2 5 4 1 8
13 (Will be used as 1 3)
1 3 4 5 7
8 8 4 (8+4=12 used as 1 2)
1 2 8
92%

Requirements

• Your program should be able to accept any name with reasonable length (100 characters)
• [A..Z, a..z] characters are allowed.
• Case insensitive so A == a

Free for you to decide

• How to handle special characters (Ö, è, etc.)
• Include last names yes or no, spaces will be ignored
• Any language is allowed.

Winner will be determined by votes on the 28th 14th of February.

Happy coding

P.s. This is the first time I put something up here, if there is any way to improve it feel free to let me know =3

Edit: Changed end date to valentines day, thought that would be more appropriate for this challenge :)

• Your example doesn't show what happens when an even number of numbers need to be added, or when you have a number with 2 digits. Better add those to clarify. – Kendall Frey Jan 30 '14 at 13:05
• <thinking volume="aloud">So calculation stops at 91%. Strange. I know quite many cases where continuing to 10% or even better 1% would give much more realistic score. With such a clearly commercial manipulation of the calculation I bet this is actually the one used by the SMS love calculator services.</thinking> – manatwork Jan 30 '14 at 14:22
• inb4 somebody posts code in the shape of a heart and wins popularity – Cruncher Jan 30 '14 at 15:04
• @user2509848 the columns on the first few letters were a coincidence, and not a requirement. You just count the number of occurrences of the letter. – Danny Jan 31 '14 at 3:03
• Wonder how the results change if you convert the names (and "love") to their ASCII integer codes. For that matter, what happens if you replace "love" with "hate" -- you'd hope to get 1-love_result :-) – Carl Witthoft Jan 31 '14 at 15:07

Sclipting

글⓵닆뭶뉗밃變充梴⓶壹꺃뭩꾠⓶꺐合合替虛終梴⓷縮⓶終併❶뉀大套鈮⓶充銻⓷加⓶鈮⓶終併❶뉀大終깐


Expects the input as two space-separated words (e.g. John Jane). It’s case-insensitive, but supports only characters that are not special regex characters (so don’t use ( or * in your name!). It also expects only two words, so if your love interest is “Mary Jane”, you have to put MaryJane in one word; otherwise it will evaluate "YourName loves Mary loves Jane".

Explanation

The hardest part was to handle the case of odd number of digits: you have to leave the middle digit alone instead of adding it with itself. I think my solution is interesting.

글⓵닆뭶뉗밃變 | replace space with "loves"

梴 | get length of string
⓶壹 | get first character of string (let’s say it’s “c”)
꺃뭩꾠⓶꺐合合 | construct the regex “(?i:c)”
替虛終 | replace all matches with empty string
梴 | get new length of that
⓷縮 | subtract the two to get a number
⓶ | move string to front

❶뉀大 | > 100

鈮⓶ | chop off the first digit
充 | while non-empty... (false if that digit was the only one!)
銻⓷加 | chop off last digit and add them
⓶鈮⓶ | chop off the first digit again
(returns the empty string if the string is empty!)
終 | end while
併 | Put all the numbers (± an empty string ;-) ) on the stack into a single string
❶뉀大 | > 100



When you’re left with something ≤ 100, the loop will just end, the answer will be on the stack and therefore output.

• And I thought APL was difficult to read ... – Dr. belisarius Jan 30 '14 at 17:16
• Hi Timwi, I can see you're back in the game :p nice solution – Pierre Arlaud Jan 30 '14 at 18:19
• Wait, he invented his own language for codegolf?! That's cheating! – Mooing Duck Jan 31 '14 at 1:12
• Actually this language is (sort of) readable (if you know Chinese). – eiennohito Jan 31 '14 at 3:09
• @MooingDuck: My understanding of the rule is that you can’t use a language that was published after the challenge was published. Therefore, I make a point of always using only instructions I introduced before. For example, I introduced 改 (case-insensitive string-replace) in response to this challenge, but I’m not going to make use of it here. – Timwi Jan 31 '14 at 12:52

Funciton

This program expects the input separated by a space (e.g. John Jane). It is case-insensitive for characters A-Z/a-z; for any other Unicode character, it will “confuse” two characters that are equal when or’ed with 32 (e.g. Ā and Ġ, or ? and _). Furthermore, I have no idea what this program will do if the input contains a NUL (\0) character, so don’t use that :)

Also, since StackExchange adds too much line spacing, here is the raw text on pastebin. Alternatively, run the following code in your browser’s JavaScript console to fix it right here: $('pre').css('line-height',1)  ╓───╖ ╓───╖ ╓───╖ ╓───╖ ╓───╖ ╓───╖ ║ Ḷ ║┌╢ Ọ ╟┐║ Ṿ ║ ║ Ẹ ║┌╢ Ṛ ╟┐║ Ṣ ╟┐ ╙─┬─╜│╙───╜│╙─┬─╜ ╙─┬─╜│╙─┬─╜│╙─┬─╜│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └───────────┐ │ │ │ │ │ │ │ │ └─────────────┐│ ┌───────┘ │ │ │ │ │ │ └───────────────┐││ │┌─────────┘ │ │ │ │ └─────────────────┐│││ ││┌──────────────┘ │ │ └───────────────────┐││││ │││ ┌───────────┘ └──────────────────┐ │││││ │││ ┌───┴───┐ ┌─────────────────────────────┴─┐ │││││ │││ │ ╔═══╗ │ │ │ ││││└─────────┐ │││ │ ║ 2 ║ │ │ ┌───┐ ┌───┐ │ │││└─────────┐│ │││ │ ║ 1 ║ │ │ ┌┴┐ │ ┌┴┐ │ │ ││└─────────┐││ │││ │ ║ 1 ║ │ │ └┬┘ │ └┬┘ │ │ │└─────────┐│││ ┌────────────────────────┘││ │ ║ 1 ║ │ │ ┌─┴─╖ │ ┌─┴─╖ │ ┌───╖ │ └─────────┐││││ │┌────────────────────────┘│ │ ║ 0 ║ │ │ │ ♯ ║ │ │ ♯ ║ ├─────┤ ℓ ╟───┴─┐ │││││ ││┌────────────────────────┘ │ ║ 6 ║ │ │ ╘═╤═╝ │ ╘═╤═╝ │ ╘═══╝ ┌─┴─╖ │││││ │││ ┌─────┘ ║ 3 ║ │ │ ┌┴┐ │ ┌┴┐ └─────────────┤ · ╟──────┐│││││ │││┌───────────────────┴┐┌───╖ ║ 3 ║ │ │ └┬┘ │ └┬┘ ╘═╤═╝ ││││││ ││││ ┌┴┤ = ╟─╢ 3 ║ │ │ ┌───┘ └───┴─────┐ ┌───┴───┐ ││││││ ││││ ╔════╗ ┌───╖ │ ╘═╤═╝ ║ 1 ║ │ │ │ ╔═══╗ ┌─┴─╖ │ ╔═══╗ │ ││││││ ││││ ║ 37 ╟─┤ ‼ ╟─┘ ┌─┘ ║ 9 ║ │ │ │ ║ 1 ║ ┌───────┤ · ╟─┐ │ ║ 0 ║ │ ││││││ ││││ ╚════╝ ╘═╤═╝ ┌┴┐ ║ 6 ║ │ │ │ ╚═╤═╝ │ ╘═╤═╝ ├─────┘ ╚═╤═╝ │ ││││││ ││││ ┌───╖ ┌───╖ ┌─┴─╖ └┬┘ ║ 3 ║ │ │ │ ┌─┴─╖ │ ╔═══╗ ┌─┴─╖ │ ╔═══╗ ┌─┴─╖ │ ││││││ │││└─┤ Ẹ ╟─┤ Ṿ ╟─┤ ? ╟───┤ ║ 3 ║ │ │ └─┤ ʃ ╟─┘ ║ 1 ╟─┤ ʃ ╟─┘ ║ 1 ╟─┤ ʃ ╟─┘ ││││││ │││ ╘═══╝ ╘═══╝ ╘═╤═╝ ┌┴┐ ║ 7 ║ │ │ ╘═╤═╝ ╚═══╝ ╘═╤═╝ ╚═══╝ ╘═╤═╝ ││││││ │││ │ └┬┘ ╚═══╝ │ │ │ ┌──────────┘ └──────┐ ││││││ │││ ╔═══╗ ┌─┴─╖ ┌───╖ │ │ │ │ ┌─────────╖ ┌───╖ ┌─────────╖ │ ││││││ │││ ║ 3 ╟─┤ > ╟─┤ ℓ ╟───┘ │ │ └─┤ str→int ╟─┤ + ╟─┤ str→int ╟─┘ ││││││ │││ ╚═══╝ ╘═══╝ ╘═══╝ │ │ ╘═════════╝ ╘═╤═╝ ╘═════════╝ ││││││ ││└───────────────────────────────────┐ │ │ ┌────┴────╖ ││││││ │└───────────────────────────────┐ │ │ │ │ int→str ║ ││││││ │ ╔═══╗ │ │ │ │ ┌───╖ ┌───╖ ╘════╤════╝ ││││││ │ ║ 0 ║ │ │ │ └─┤ Ẹ ╟─┤ ‼ ╟──────┘ ││││││ │ ╚═╤═╝ │ │ │ ╘═══╝ ╘═╤═╝ ┌────────────────────┘│││││ │ ╔═══╗ ┌─┴─╖ │ │ │ ┌─┴─╖ ┌─┴─╖ ╔═══╗ │││││ │ ║ 1 ╟─┤ ʃ ╟─────────────────┴┐ │ └─────────────┤ ? ╟─┤ ≤ ║ ║ 2 ║ │││││ │ ╚═══╝ ╘═╤═╝ │ │ ╘═╤═╝ ╘═╤═╝ ╚═╤═╝ │││││ │ ┌─┴─╖ │ │ │ └─────┘ │││││ │ ┌─┤ Ṣ ╟──────────────────┴┐ │ ╔═══╗ ┌────────────────────────────────┘││││ │ │ ╘═╤═╝ │ │ ║ ║ │ ┌──────────────────────────────┘│││ │ │ ┌─┴─╖ │ │ ╚═╤═╝ │ │ ┌──────────────────────────┘││ │ └─┤ · ╟─────────────┐ │ │ ┌─┴─╖ │┌─┴─╖┌─┴─╖ ││ │ ╘═╤═╝ │ │ │ │ Ḷ ║ └┤ · ╟┤ · ╟┐ ││ │ ┌─────┴───╖ ┌─┴─╖ ┌─┴─╖│ ╘═╤═╝ ╘═╤═╝╘═╤═╝│ ││ │ │ int→str ║ ┌───────┤ · ╟─┤ · ╟┴┐ │ ┌─┴─╖ │ │ ││ │ ╘═════╤═══╝ │ ╘═╤═╝ ╘═╤═╝ │ ┌┤ · ╟──┘ │ ││ │ │ ┌─┴─╖ ┌───╖ │ │ │ ┌─┘╘═╤═╝ ┌─┴─╖ ││ │ │ │ ‼ ╟─┤ Ọ ╟─┘ │ │ │ ┌──┴─────┤ · ╟───────┐ ││ │ │ ╘═╤═╝ ╘═╤═╝ │ │ │ │ ╔════╗ ╘═╤═╝ ╔═══╗ │ ││ │ └─────┘ │ │ │ │ │ ║ 21 ║ │ ║ 2 ║ │ ││ │ ┌───╖ ┌─┴─╖ │ │ ┌──────┘ │ ╚═══╤╝ │ ║ 0 ║ │ ││ │ ┌───┤ Ṿ ╟─┤ ? ╟───────┘ │ │┌───╖ ┌─┴─╖ ┌─┴──╖ │ ║ 9 ║ │ ││ │ │ ╘═══╝ ╘═╤═╝ │ ┌┴┤ ♯ ╟─┤ Ṛ ╟─┤ >> ║ │ ║ 7 ║ │ ││ │ │ │ │ │ ╘═══╝ ╘═╤═╝ ╘══╤═╝ │ ║ 1 ║ │ ││ │ └─────────┐ ┌───────────┘ │ ╔═══╗ ┌─┴─╖ ├───┴─┬─╢ 5 ║ │ ││ └───────────────────┐ └───┘ │ ║ 0 ╟─┤ ? ╟────┘ │ ║ 1 ║ │ ││ ╔════╗ │ │ ╚═══╝ ╘═╤═╝ ┌──────┤ ╚═══╝ │ ││ ║ 21 ║ │ │ ┌─┴─╖ ┌─┴─╖ ╔══╧══╗ │ ││ ╚═╤══╝ │ └───────┤ ? ╟─┤ ≠ ║ ║ −33 ║ │ ││ ┌─┴─╖ ┌────╖ │ ╘═╤═╝ ╘═╤═╝ ╚══╤══╝ ┌┴┐ ││ │ × ╟─┤ >> ╟────────┴────────────┐ │ └──────┤ └┬┘ ││ ╘═╤═╝ ╘═╤══╝ ┌───╖ ╔═════════╗ │ └───────┘ ││ ┌─┴─╖ └────┤ ‼ ╟───╢ 2224424 ║ │ ┌────────────────────────────────────┘│ │ ♯ ║ ╘═╤═╝ ║ 4396520 ║ │ │ ┌────────────────────────────────┘ ╘═╤═╝ ┌─┴─╖ ║ 1237351 ║ │ │ │ ┌─────────────────────┐ └──────────┤ · ╟─┐ ║ 2814700 ║ │ │ ┌─┴─╖ │ ┌─────┐ │ ╘═╤═╝ │ ╚═════════╝ │ ┌─┴──┤ · ╟──┤ │ ┌┴┐ │ ╔═══╗ ┌───╖ ┌─┴─╖ │ ╔════╗ │ ┌─┴─╖ ╘═╤═╝┌─┴─╖ │ └┬┘ │ ║ 0 ╟─┤ Ọ ╟─┤ ‼ ║ │ ║ 32 ║ │ ┌────────┤ · ╟────┴──┤ Ṛ ╟───┤ ┌─┴─╖ │ ╚═══╝ ╘═╤═╝ ╘═╤═╝ │ ╚═╤══╝ │ │ ╘═╤═╝ ╘═╤═╝ │ │ ♯ ║ │ │ ┌─┴─╖ ├─┐ ┌─┴─╖ │ ┌─┴─╖ ┌─┴─╖ ╔═╧═╗ │ ╘═╤═╝ │ ┌─┤ ʃ ╟─┘ └─┤ ʘ ║ │┌┤ · ╟──────┤ · ╟───┐ ║ 1 ║ │ ┌┴┐ │ │ ╘═╤═╝ ╘═╤═╝ ││╘═╤═╝ ╘═╤═╝ │ ╚═══╝ │ └┬┘ │ │ ╔═╧═╗ ├───────┘│ │ ┌──┴─╖ ┌─┴─╖ ┌───╖ ┌─┴─╖ ┌─┴─╖ ╔═══╗ │ │ ║ 0 ║ │ │ │ │ >> ╟─┤ Ṣ ╟─┤ ‼ ╟─┤ · ╟─┤ ʃ ╟─╢ 0 ║ │ │ ╚═══╝ │ │ │ ╘══╤═╝ ╘═╤═╝ ╘═╤═╝ ╘═╤═╝ ╘═╤═╝ ╚═══╝ │ └─────────────┘ │ │ ╔════╗ ┌─┴─╖ ┌─┴─╖ ┌─┴─╖ ┌─┘ ├─────────┘ │ │ ║ 21 ╟─┤ × ╟─┤ · ╟─┤ · ╟─┴─┐ │ │ │ ╚════╝ ╘═══╝ ╘═╤═╝ ╘═╤═╝ │ │ │ └────────────────┘ ┌─┴─╖ │ │ │ ┌───┤ ? ╟───┴┐ │ │ │ ╘═╤═╝ │ │ │ ┌───╖ ┌─┴─╖ │ ┌─┴─╖ │ └───────────┤ ♯ ╟─┤ · ╟─┐ ┌──┤ ? ╟─ │ ╘═══╝ ╘═╤═╝ └───┘ ╘═╤═╝ │ │ ╔═╧═╗ │ │ ║ 0 ║ │ │ ╚═══╝ │ └─────────────────┘  Quick explanation • The program just takes STDIN and calls Ḷ with it. • Ḷ finds the first space in the string, replaces it with loves and passes the result to Ọ. • Ọ repeatedly takes the first character from the input string, calls Ṣ with it and concatenates the numbers of occurrences onto a result string. When the input string is empty, it calls Ṿ with the result string. • Ṿ repeatedly calls Ẹ until it gets a result that is either equal to "100" or has length less than 3. (100 can actually occur: consider the input lovvvv eeeeeess.) When it does, it adds "%" and returns that. • Ẹ computes one complete iteration of the love-computation algorithm; i.e., it takes a string of digits and returns the next string of digits. • Ṛ takes a haystack and a needle and finds the index of the first occurrence of needle in haystack using the faux case-insensitivity criterion (or 32). • Ṣ takes a haystack and a needle and repeatedly applies Ṛ to remove all instances of the needle. It returns the final result after all the removals as well as the number of removals made. • I have no idea what's going on here, but it looks very impressive! – squeamish ossifrage Feb 1 '14 at 23:37 Ruby  f=IO. read( __FILE__) .gsub(/[^ \s]/x,?#);s=$**'loves';s
.upcase!;i=1;a =s.chars.uniq.
map{|c|s.count(c)};loop{b='';
b<<"#{a.shift.to_i+a.pop.to_i
}"while(a.any?);d=b.to_i;a=
b.chars;d<101&&abort(d>
50?f:f.gsub(/^.*/){
|s|i=13+i%3;s[\
i...i]=040.
chr*3;s
})}
V


Prints a heart if the chance of a relation is over 50%

$ruby ♥.rb sharon john ##### ##### ######### ######### ############ ############ ############## ############## ############################# ############################# ########################### ####################### ################### ############### ########### ####### ### #  And prints a broken heart if chances are below 50% :( $ ruby ♥.rb sharon epidemian
#####            #####
#########        #########
############      ############
##############    ##############
###############   ##############
#############   ################
#############   ##############
############   ###########
########   ###########
#######   ########
######   #####
##   #####
#   ##
#


Frigging John...

Anyways, it's case-insensitive and supports polygamous queries (e.g. ruby ♥.rb Alice Bob Carol Dave).

• That is pure art :) – user16991 Jul 31 '14 at 7:05

APL, 80

{{n←⍎∊⍕¨(⍵[⌈m]/⍨m≠⌊m),⍨+/(⌊m←2÷⍨≢⍵)↑[1]⍵,⍪⌽⍵⋄n≤100:n⋄∇⍎¨⍕n}∪⍦32|⎕UCS⍺,'Loves',⍵}


Because love is love is (even when it's not)

Obligatory ♥︎-shaped version:

    {f←{m←  2÷⍨≢⍵
n←+/(⌊m)↑[1]⍵,⍪⌽⍵
n←⍎∊⍕¨n,(⍵[⌈m]/⍨m≠⌊m)
n≤100:n⋄∇⍎¨⍕n}⋄u←⎕UCS
s←u⍺,'Loves',⍵
f∪⍦32|s
}


The golfed version gives me somewhat erratic behaviour, because of a bug with ∪⍦ that I'm investigating with NARS's developers:

      'John'{{n←⍎∊⍕¨(⍵[⌈m]/⍨m≠⌊m),⍨+/(⌊m←2÷⍨≢⍵)↑[1]⍵,⍪⌽⍵⋄n≤100:n⋄∇⍎¨⍕n}∪⍦32|⎕UCS⍺,'Loves',⍵}'Jane'
VALUE ERROR


But I was able to run it piecewise and get the correct result:

      'John'{∪⍦32|⎕UCS⍺,'Loves',⍵}'Jane'
2 2 1 2 1 1 2 1 1
{n←⍎∊⍕¨(⍵[⌈m]/⍨m≠⌊m),⍨+/(⌊m←2÷⍨≢⍵)↑[1]⍵,⍪⌽⍵⋄n≤100:n⋄∇⍎¨⍕n}2 2 1 2 1 1 2 1 1
76


Javascript

Probably could be cleaner, but it works. Verbose example

function z(e) {
for (var t = 0, c = '', n = e.length - 1; n >= t; n--, t++) {
c += n != t ? +e[t] + (+e[n]) : +e[t];
}
return c
}
for (var s = prompt("Name 1").toLowerCase() + "loves" + prompt("Name 2").toLowerCase(),b = '', r; s.length > 0;) {
r = new RegExp(s[0], "g");
b+=s.match(r).length;
s = s.replace(r, "")
}
for (; b.length > 2; b = z(b)) {}
console.log("Chances of being in love are: " + b + "%")


Python

Well, I thought it was a ...

a=filter(str.isalpha,raw_input()+"loves"+raw_input()).lower();a=[x[1]for x in sorted(set(zip(a,map(str.count,[a]*len(a),a))),key=lambda(x,y):a.index(x))]
while reduce(lambda x,y:x*10+y,a)>100:a=reduce(list.__add__,map(lambda x: x<10 and[x]or map(int,str(x)),[a[n]+a[-n-1]for n in range(len(a)/2)]+(len(a)%2 and[a[len(a)/2]]or[])))
print str(reduce(lambda x,y:x*10+y,a))+"%"


Ungolfed:

a = filter(str.isalpha,
raw_input() + "loves" + raw_input()).lower()

a = [x[1] for x in sorted(set(zip(a,
map(str.count, [a] * len(a), a))),
key=lambda (x, y): a.index(x))]

while reduce(lambda x, y: x * 10 + y, a) > 100:
map(lambda x: x < 10 and [x] or map(int, str(x)),
[a[n] + a[-n - 1] for n in range(len(a) / 2)] + (len(a) % 2 and [a[len(a) / 2]] or [])))

print str(reduce(lambda x, y: x * 10 + y, a)) + "%"

• If you want to make it as short as possible, you can replace reduce(list.__add__,xyz) with sum(xyz,[]). :) – flornquake Feb 1 '14 at 15:34

PHP

<?php

$name1 =$argv[1];
$name2 =$argv[2];

echo "So you think {$name1} and {$name2} have any chance? Let's see.\nCalculating if \"{$name1} Loves {$name2}\"\n";

//prepare it, clean it, mince it, knead it
$chances = implode('', array_count_values(str_split(preg_replace('/[^a-z]/', '', strtolower($name1.'loves'.$name2))))); while(($l = strlen($chances))>2 and$chances !== '100'){
$time = time();$l2 = intval($l/2);$i =0;
$t = ''; while($i<$l2){$t.=substr($chances,$i, 1) + substr($chances, -$i-1, 1);
$i++; } if($l%2){
$t.=$chances[$l2]; } echo '.';$chances = $t; while(time()==$time){}
}

echo "\nTheir chances in love are {$chances}%\n";$chances = intval($chances); if ($chances === 100){
echo "Great!!\n";
}elseif($chances > 50){ echo "Good for you :) !!\n"; }elseif($chances > 10){
echo "Well, it's something.\n";
}else{
echo "Ummm.... sorry.... :(\n";
}


sample result

php loves.php John Jane So you think John and Jane have any chance? Let's see. Calculating if "John Loves Jane" ... Their chances in love are 76% Good for you :) !!  GolfScript Obligatory code golf answer in GolfScript: ' '/'loves'*{65- 32%65+}%''+:x.|{{=}+x\,,}%{''\{)\(@+@\+\.(;}do 0+{+}*+{[]+''+~}%.,((}do{''+}%''+  Accepts input as space-separated names e.g. echo 'John Jane' | ruby golfscript.rb love.gs -> 76  C# using System; using System.Collections.Generic; using System.Linq; namespace LovesMeWhat { class Program { static void Main(string[] args) { if (args.Length < 2) throw new ArgumentException("Ahem, you're doing it wrong."); Func<IEnumerable<Int32>, String> fn = null; fn = new Func<IEnumerable<Int32>, String> (input => { var q = input.SelectMany(i => i.ToString().Select(c => c - '0')).ToArray(); if (q.Length <= 2) return String.Join("", q); IList<Int32> next = new List<Int32>(); for (int i = 0, j = q.Length - 1; i <= j; ++i, --j) { next.Add(i == j ? q[i] : q[i] + q[j]); } return fn(next); }); Console.Write(fn(String.Concat(args[0], "LOVES", args[1]).ToUpperInvariant().GroupBy(g => g).Select(g => g.Count()))); Console.Write("%"); Console.ReadKey(true); } } }  • Does this work correctly when q[i] + q[j] is 10 or greater? – Danny Jan 30 '14 at 19:58 • @Danny The first line in fn takes each integer in input, converts each of them to string, then converts all characters in this string to integer from 0 to 9 (c - '0' part) and returns it... IOW, it will construct an array of integers consisting of each digit in the input. If it doesn't the requirements are invalid :-) – Luc Jan 30 '14 at 20:18 • ah missed that. – Danny Jan 30 '14 at 20:23 Haskell My version is pretty long, it's because I decided to focus on readability, I thought it would be interesting to formalize your algorithm in code. I aggregate character counts in a left fold, it basically snowballs them together and order is in order of their occurrence in the string. I also managed to replace the part of algorithm that would normally require array indexing with list bending. It turns out your algorithm basically involves folding list of numbers in half and adding aligned numbers together. There two cases for bending, even lists split in the middle nicely, odd lists bend around a center element and that element doesn't participate in addition. Fission is taking the list and splitting up numbers that are no longer single digits, like >= 10. I had to write my own unfoldl, I'm not sure if it's actually an unfoldl, but it seems to do what i need. Enjoy. import qualified Data.Char as Char import qualified System.Environment as Env -- | Takes a seed value and builds a list using a function starting -- from the last element unfoldl :: (t -> Maybe (t, a)) -> t -> [a] unfoldl f b = case f b of Just (new_b, a) -> (unfoldl f new_b) ++ [a] Nothing -> [] -- | Builds a list from integer digits number_to_digits :: Integral a => a -> [a] number_to_digits n = unfoldl (\x -> if x == 0 then Nothing else Just (div x 10, mod x 10)) n -- | Builds a number from a list of digits digits_to_number :: Integral t => [t] -> t digits_to_number ds = number where (number, _) = foldr (\d (n, p) -> (n+d*10^p, p+1)) (0,0) ds -- | Bends a list at n and returns a tuple containing both parts -- aligned at the bend bend_at :: Int -> [a] -> ([a], [a]) bend_at n xs = let (left, right) = splitAt n xs in ((reverse left), right) -- | Takes a list and bends it around a pivot at n, returns a tuple containing -- left fold and right fold aligned at the bend and a pivot element in between bend_pivoted_at :: Int -> [t] -> ([t], t, [t]) bend_pivoted_at n xs | n > 1 = let (left, pivot:right) = splitAt (n-1) xs in ((reverse left), pivot, right) -- | Split elements of a list that satisfy a predicate using a fission function fission_by :: (a -> Bool) -> (a -> [a]) -> [a] -> [a] fission_by _ _ [] = [] fission_by p f (x:xs) | (p x) = (f x) ++ (fission_by p f xs) | otherwise = x : (fission_by p f xs) -- | Bend list in the middle and zip resulting folds with a combining function. -- Automatically uses pivot bend for odd lists and normal bend for even lists -- to align ends precisely one to one fold_in_half :: (b -> b -> b) -> [b] -> [b] fold_in_half f xs | odd l = let middle = (l-1) div 2 + 1 (left, pivot, right) = bend_pivoted_at middle xs in pivot:(zipWith f left right) | otherwise = let middle = l div 2 (left, right) = bend_at middle xs in zipWith f left right where l = length xs -- | Takes a list of character counts ordered by their first occurrence -- and keeps folding it in half with addition as combining function -- until digits in a list form into any number less or equal to 100 -- and returns that number foldup :: Integral a => [a] -> a foldup xs | n > 100 = foldup fission $reverse$ (fold_in_half (+) xs)
| otherwise = n
where
n = (digits_to_number xs)
fission = fission_by (>= 10) number_to_digits

-- | Accumulate counts of keys in an associative array
count_update :: (Eq a, Integral t) => [(a, t)] -> a -> [(a, t)]
count_update [] x = [(x,1)]
count_update (p:ps) a
| a == b = (b,c+1) : ps
| otherwise = p : (count_update ps a)
where
(b,c) = p

-- | Takes a string and produces a list of character counts in order
--   of their first occurrence
ordered_counts :: Integral b => [Char] -> [b]
ordered_counts s = snd $unzip$ foldl count_any_alpha [] s
where
count_any_alpha m c
| Char.isAlpha c = count_update m (Char.toLower c)
| otherwise = m

-- | Take two names and perform the calculation
love_chances n1 n2 =  foldup $ordered_counts (n1 ++ " loves " ++ n2) main = do args <- Env.getArgs if (null args) || (length args < 2) then do putStrLn "\nUSAGE:\n" putStrLn "Enter two names separated by space\n" else let n1:n2:_ = args in putStrLn$ show (love_chances n1 n2) ++ "%"


Some Results:

"Romeo" "Juliet" 97% - Empirical testing is important
"Romeo" "Julier" 88% - Modern abridged version...
"Horst Draper" "Jane" 20%
"Horst Draper" "Jane(Horse)" 70% - There's been a development...
"Bender Bender Rodriguez" "Fenny Wenchworth" 41% - Bender Says "Folding is for women!"
"Philip Fry" "Turanga Leela" 53% - Well you can see why it took 7 Seasons for them to marry
"Maria" "Abraham" - 98%
"John" "Jane" 76%

Ruby

math = lambda do |arr|
result = []
while arr.any?
val = arr.shift + (arr.pop || 0)
result.push(1) if val >= 10
result.push(val % 10)
end
result.length > 2 ? math.call(result) : result
end
puts math.call(ARGV.join("loves").chars.reduce(Hash.new(0)) { |h, c| h[c.downcase] += 1; h }.values).join


Minified:

l=->{|a|r=[];while a.any?;v=a.shift+(a.pop||0);r.push(1) if v>=10;r.push(v%10) end;r[2]?l[r]:r}
puts l[ARGV.join("loves").chars.reduce(Hash.new(0)){|h, c| h[c.downcase]+=1;h}.values].join


Call it:

$ruby love.rb "John" "Jane" 76  • To minify more, you could use l=->a{...} instead of l=lambda do|a|...end, and you could also do l[...] instead of l.call(...). – Doorknob Jan 31 '14 at 0:59 • Good point Doorknob. – Andrew Hubbs Jan 31 '14 at 17:34 Python 3 A simple solution that uses no modules. I/O is pretty enough. I used error catching as a backup for when the second iterator is out of bounds; if it catches Python's index error, it assumes 1. Weird, but it works. names = [input("Name 1: ").lower(), "loves", input("Name 2: ").lower()] checkedLetters = [] def mirrorAdd(n): n = [i for i in str(n)] if len(n) % 2: n.insert(int(len(n)/2), 0) return(int(''.join([str(int(n[i]) + int(n[len(n)-i-1])) for i in range(int(len(n)/2))]))) cn = "" positions = [0, 0] for i in [0, 1, 2]: checkAgainst = [0, 1, 2] del checkAgainst[i] positions[0] = 0 while positions[0] < len(names[i]): if not names[i][positions[0]] in checkedLetters: try: if names[i][positions[0]] in [names[checkAgainst[0]][positions[1]], names[checkAgainst[1]][positions[1]]]: positions[1] += 1 cn = int(str(cn) + "2") else: cn = int(str(cn) + "1") except: cn = int(str(cn) + "1") checkedLetters.append(names[i][positions[0]]) positions[0] += 1 print("\n" + str(cn)) while cn > 100: cn = mirrorAdd(cn) print(cn) print("\n" + str(cn) + "%")  Here's a sample run: Name 1: John Name 2: Jane 221211211 33331 463 76 76%  • wouldn't it be clearer to run the for on names directly? – Einacio Jan 30 '14 at 15:05 • @Einacio Then how would I know which ones to check it to so concisely? – cjfaure Jan 30 '14 at 15:07 • what is your result with "Maria" and "Abraham"? – Einacio Jan 30 '14 at 15:08 • @Einacio I got 75%. – cjfaure Jan 30 '14 at 15:11 • i got 98, this are the steps 25211111111.363221.485.98. i think you code fails to add the 5 "a" – Einacio Jan 30 '14 at 15:16 Java It can happen that the sum of 2 digits becomes greater than 10, in this case the number will be split in 2 on the next row. What if the number is equal to 10? I just added 1 and 0, is that correct? I decided to ignore case. public class LoveCalculation { public static void main(String[] args) { String chars = args[0].toLowerCase() + "loves" + args[1].toLowerCase(); ArrayList<Integer> charCount = new ArrayList<Integer>(); HashSet<Character> map = new HashSet<Character>(); for(char c: chars.toCharArray()){ if(Pattern.matches("[a-z]", "" + c) && map.add(c)){ int index = -1, count = 0; while((index = chars.indexOf(c, index + 1)) != -1) count++; charCount.add(count); } } while(charCount.size() > 2){ ArrayList<Integer> numbers = new ArrayList<Integer>(); for(int i = 0; i < (charCount.size()/2);i++) addToArray(charCount.get(i) + charCount.get(charCount.size()-1-i), numbers); if(charCount.size() % 2 == 1){ addToArray(charCount.get(charCount.size()/2), numbers); } charCount = new ArrayList<Integer>(numbers); } System.out.println(Arrays.toString(charCount.toArray()).replaceAll("[\\]\\[,\\s]","") + "%"); } public static ArrayList<Integer> addToArray(int number, ArrayList<Integer> numbers){ LinkedList<Integer> stack = new LinkedList<Integer>(); while (number > 0) { stack.push(number % 10); number = number / 10; } while (!stack.isEmpty()) numbers.add(stack.pop()); return numbers; } }  input: Maria Abraham  output: 98%  input: Wasi codegolf.stackexchange.com  output: 78%  • I would enjoy seeing this answer golfed for kicks and giggles! – Josh Jan 30 '14 at 20:18 • That makes minus 144 characters and a few lines. I'm just to used to program readable and memory efficient... – Rolf ツ Jan 30 '14 at 20:26 • That's why seeing Java golfed always cracks me up. – Josh Jan 30 '14 at 20:27 • For me it's the fun in making a language like this golfed.. just imagine how funny it would be trying to golf a random java class it would become at least 2 times smaller XD – Rolf ツ Jan 30 '14 at 20:30 • Java is about the worst language for golfing. Unfortunately it's only language I know well, haha. Oh well, at least I can read stuff here. – Andrew Gies Feb 2 '14 at 4:36 C There might be lots of improvement, but this was fun to code. #include <stdio.h> #include <string.h> int i, j, k, c, d, r, s = 1, l[2][26]; char a[204], *p, *q; main(int y, char **z) { strcat(a, z[1]); strcat(a, "loves"); strcat(a, z[2]); p = a; q = a; for (; *q != '\0'; q++, p = q, i++) { if (*q == 9) { i--; continue; } l[0][i] = 1; while (*++p != '\0') if ((*q | 96) == (*p | 96)&&*p != 9) { (l[0][i])++; *p = 9; } } for (;;) { for (j = 0, k = i - 1; j <= k; j++, k--) { d = j == k ? l[r][k] : l[r][j] + l[r][k]; if (d > 9) { l[s][c++] = d % 10; l[s][c++] = d / 10; } else l[s][c++] = d; if (k - j < 2)break; } i = c; if (c < 3) { printf("%d", l[s][0]*10 + l[s][1]); break; } c = r; r = s; s = c; c = 0; } }  And of course, mandatory golfed version: 496 #include <stdio.h> #include <string.h> int i,j,k,c,d,r,s=1,l[2][26];char a[204],*p,*q;main(int y,char **z){strcat(a,z[1]);strcat(a,"loves");strcat(a,z[2]);p=q=a;for(;*q!='\0';q++,p=q,i++){if(*q==9){i--;continue;}l[0][i]=1;while(*++p!='\0')if((*q|96)==(*p|96)&&*p!=9){(l[0][i])++;*p=9;}}for(;;){for(j=0,k=i-1;j<=k;j++,k--){d=j==k?l[r][k]:l[r][j]+l[r][k];if(d>9){l[s][c++]=d%10;l[s][c++]=d/10;}else l[s][c++]=d;if(k-j<2)break;}i=c;if(c<3){printf("%d",l[s][0]*10+l[s][1]);break;}c=r;r=s;s=c;c=0;}}  Python 3 This will take two names as input. strip extra spaces and then calculate love. Check out Input output for more details. s=(input()+'Loves'+input()).strip().lower() a,b=[],[] for i in s: if i not in a: a.append(i) b.append(s.count(i)) z=int(''.join(str(i) for i in b)) while z>100: x=len(b) t=[] for i in range(x//2): n=b[-i-1]+b[i] y=n%10 n//=10 if n:t.append(n) t.append(y) if x%2:t.append(b[x//2]) b=t z=int(''.join(str(i) for i in b)) print("%d%%"%z)  input: Maria Abraham  output: 98%  Or, try this one ;) input: Wasi Mohammed Abdullah code golf  output: 99%  k, 80 {{$[(2=#x)|x~1 0 0;x;[r:((_m:(#x)%2)#x+|x);$[m=_m;r;r,x@_m]]]}/#:'.=x,"loves",y}  Here is a run of it: {{$[(2=#x)|x~1 0 0;x;[r:((_m:(#x)%2)#x+|x);$[m=_m;r;r,x@_m]]]}/#:'.=x,"loves",y}["john";"jane"] 7 6  J Here's a straightforward one in J: r=:({.+{:),$:^:(#>1:)@}:@}.
s=:$:^:(101<10#.])@("."0@(#~' '&~:)@":"1)@r c=:10#.s@(+/"1@=)@(32|3&u:@([,'Loves',])) exit echo>c&.>/2}.ARGV  It takes the names on the command line, e.g: $ jconsole love.ijs John Jane
76


Groovy

Here's the groovy version, with tests.

countChars = { res, str -> str ? call(res+str.count(str[0]), str.replace(str[0],'')) : res }
addPairs = { num -> def len = num.length()/2; (1..len).collect { num[it-1].toInteger() + num[-it].toInteger() }.join() + ((len>(int)len) ? num[(int)len] : '') }
reduceToPct = { num -> /*println num;*/ num.length() > 2 ? call( addPairs(num) ) : "$num%" } println reduceToPct( countChars('', args.join('loves').toLowerCase()) ) assert countChars('', 'johnlovesjane') == '221211211' assert countChars('', 'asdfasdfateg') == '3222111' assert addPairs('221211211') == '33331' assert addPairs('33331') == '463' assert addPairs('463') == '76' assert addPairs('53125418') == '13457' assert addPairs('13457') == '884' assert addPairs('884') == '128' assert addPairs('128') == '92' assert reduceToPct( countChars('','johnlovesjane') ) == '76%'  Explanation: • "countChars" simply recurses and removes while build a string of digits • "addPairs" takes one string of digits adding the digits from the outside in ** the "collect..join" does the addition of the digits working outside in and rejoins them as a string ** the "+ (... c[(int)len])" throws in the middle digit again when c is an odd length • "recudeToPct" calls itself adding pairs until it gets down to less than 3 digits CodeGolf Groovy, 213 char Seeing this is we can inline the closures and get it down to this: println({c->l=c.length()/2;m=(int)l;l>1?call((1..m).collect{(c[it-1]as int)+(c[-it]as int)}.join()+((l>m)?c[m]:'')):"$c%"}({r,s->s?call(r+s.count(s[0]),s.replace(s[0],'')):r}('',args.join('loves').toLowerCase())))


save it as lovecalc.groovy. run "groovy lovecalc john jane"

Output:

$groovy lovecalc john jane 76%$ groovy lovecalc romeo juliet
97%
$groovy lovecalc mariah abraham 99%$ groovy lovecalc maria abraham
98%
$groovy lovecalc al bev 46%$ groovy lovecalc albert beverly
99%


Java

This takes 2 String parameters on start and prints out the count of each character and the result.

import java.util.ArrayList;

public class LUV {
public static void main(String[] args) {
String str = args[0].toUpperCase() + "LOVES" + args[1].toUpperCase();
for (int i = 0; i < str.length(); i++) {
if (!map.containsKey(String.valueOf(str.charAt(i)))) {
map.put(String.valueOf(str.charAt(i)), 1);
} else {
map.put(String.valueOf(str.charAt(i)), map.get(String.valueOf(str.charAt(i))).intValue() + 1);
}
}
System.out.println(map.toString());
}

private static int addValues(ArrayList<Integer> list) {
if ((list.size() < 3) || (Integer.parseInt((String.valueOf(list.get(0)) + String.valueOf(list.get(1))) + String.valueOf(list.get(2))) == 100)) {
return Integer.parseInt((String.valueOf(list.get(0)) + String.valueOf(list.get(1))));
} else {
ArrayList<Integer> list2 = new ArrayList<Integer>();
int size = list.size();
for (int i = 0; i < size / 2; i++) {
int temp = list.get(i) + list.get(list.size() -1);
if (temp > 9) {
} else {
}
list.remove(list.get(list.size()-1));
}
if (list.size() > list2.size()) {
}
}
}
}


Surely not the shortest one (it's Java), but a clear and readable one.

So if you call

java -jar LUV.jar JOHN JANE


you get the output

{J=2, O=2, H=1, N=2, L=1, V=1, E=2, S=1, A=1}
76%


R

Not going to win any compactness awards, but I had fun anyway:

problove<-function(name1,name2, relation='loves') {
sfoo<-tolower( unlist( strsplit(c(name1,relation,name2),'') ) )
startrow <- table(sfoo)[rank(unique(sfoo))]
# check for values > 10 . Not worth hacking an arithmetic approach
startrow <- as.integer(unlist(strsplit(as.character(startrow),'')))
while(length(startrow)>2 ) {
tmprow<-vector()
# follow  by tacking on middle element if length is odd
srlen<-length(startrow)
halfway<-trunc( (srlen/2))
tmprow[1: halfway] <- startrow[1:halfway] + rev(startrow[(srlen-halfway+1):srlen])
if ( srlen%%2) tmprow[halfway+1]<-startrow[halfway+1]
startrow <- as.integer(unlist(strsplit(as.character(tmprow),'')))
}
as.numeric(paste(startrow,sep='',collapse=''))
}


Tested: valid for 'john'&'jane' and for 'romeo'&'juliet' . per my comment under the question,

Rgames> problove('john','jane','hates')
[1] 76
Rgames> problove('romeo','juliet','hates')
[1] 61