Using String#count is relatively inefficient, as the entire string is traversed for each unique letter. It would be more efficient, at the expense of more lines of code, to create a counting hash, which can be done as follows (see Hash::new).
s1 = "hello"
s2 = "goodbye"
h1 = s1.each_char.with_object(Hash.new(0)) { |c,h| h[c] += 1 }
#=> {"h"=>1, "e"=>1, "l"=>2, "o"=>1}
h2 = s2.each_char.with_object(Hash.new(0)) { |c,h| h[c] += 1 }
#=> {"g"=>1, "o"=>2, "d"=>1, "b"=>1, "y"=>1, "e"=>1}
hmx = (h1.keys | h2.keys).each_with_object({}) do |c,h| h[c] =
case h1[c] <=> h2[c]
when 1 then [-h1[c], -1]
when 0 then [-h1[c], 0]
else [-h2[c], 1]
end
end
#=> {"h"=>[-1, -1], "e"=>[-1, 0], "l"=>[-2, -1], "o"=>[-2, 1],
# "g"=>[-1, 1], "d"=>[-1, 1], "b"=>[-1, 1], "y"=>[-1, 1]}
We can now sort using
Enumerable#sort_by
(s1+s2).each_char.sort_by { |c| [*hmx[c], c] }.join
#=> "lloooheebdgy"
See Array#<=> (third paragraph) for an explanation of how arrays are sorted.
I've made the assumption that if two characters tie for the most occurrences in one of the two strings, each character is assigned a score of -1, 0 or 1. The character with the lowest score (if they don't have the same score) precedes the other character in the sort. A character c is assigned a score of -1 if the string s1 contains more c's than does string s1; a score of 0 if both strings contain the same number of c's; and a score of 1 if s2 contains more c's than does s1.
s1, equal number ins1ands2(In my answer and greater number ins2. How are these to be ordered in the sort? (In my answer I assumed the order in which I listed the three possibilities applies.) Please clarify by editing as not everyone may notice an explanatory comment.