Best shuffle: Difference between revisions

Content added Content deleted
(Added Crystal translation of Ruby version)
Line 1,198: Line 1,198:
a: (a 1)
a: (a 1)
</lang>
</lang>

== {{header|Crystal}} ==
{{trans|ruby}}

<lang ruby>def best_shuffle(s)
# Fill _pos_ with positions in the order
# that we want to fill them.
pos = [] of Int32
# g["a"] = [2, 4] implies that s[2] == s[4] == "a"
g = s.size.times.group_by { |i| s[i] }

# k sorts letters from low to high count
# k = g.sort_by { |k, v| v.length }.map { |k, v| k } # in Ruby
k = g.to_a.sort_by { |e| e[1].size }.map { |e| e[0] }

until g.empty?
k.each do |letter|
g.has_key?(letter) || next # g[letter] || next
pos << g[letter].pop
g[letter].empty? && g.delete letter
end
end
# Now fill in _new_ with _letters_ according to each position
# in _pos_, but skip ahead in _letters_ if we can avoid
# matching characters that way.
letters = s.dup
new = "?" * s.size

until letters.empty?
i, p = 0, pos.pop
while letters[i] == s[p] && i < (letters.size - 1); i += 1 end
# new[p] = letters.slice! i # in Ruby
new = new.sub(p, letters[i]); letters = letters.sub(i, "")
end
score = new.chars.zip(s.chars).count { |c, d| c == d }
{new, score}
end

%w(abracadabra seesaw elk grrrrrr up a).each do |word|
# puts "%s, %s, (%d)" % [word, *best_shuffle(word)] # in Ruby
new, score = best_shuffle(word)
puts "%s, %s, (%d)" % [word, new, score]
end</lang>

{{out}}
<pre>
abracadabra, baarrcadaab, (0)
seesaw, essewa, (0)
elk, lke, (0)
grrrrrr, rgrrrrr, (5)
up, pu, (0)
a, a, (1)
</pre>


=={{header|D}}==
=={{header|D}}==