# Balancing words

A word is balanced at the index if the sum of the alphabet positions of all the chars multiplied by the distance to the index is zero.

This description is equivalent to the one given by DailyProgrammer in the challenge info.

I did not code Input/Output as I found them not as interesting as the logic.

The code works for the given testcase.

def balanced_at?(string, index, alphabet=("a".."z").to_a)
string
.chars
.each_with_index
.map { |char, char_index| (alphabet.index(char) + 1) * (char_index - index)}
.inject(:+)
.zero?
end

def balanced_where(string)
(0..string.length)
.detect {|index| balanced_at?(string, index)}
end



1. You may use splat operator instead of .to_a
2. You may use .map.with_index instead of .each_with_index.map
3. You should (bug?) use ... instead of ..
def balanced_at? string, index, alphabet = [*"a".."z"]
string.chars.map.with_index do |char, char_index|
(alphabet.index(char) + 1) * (char_index - index)
end.inject(:+).zero?
end

def balanced_where string
(0...string.length).detect do |index|
balanced_at? string, index
end
end



But note, that your function is monotone, so you may get a perfomance profit by using find-any mode of .bsearch instead of .detect:

def balance string, index, alphabet = [*"a".."z"]
string.chars.map.with_index do |char, char_index|
(alphabet.index(char) + 1) * (char_index - index)
end.inject(:+)
end

def balanced_where string
(0...string.length).bsearch do |index|
balance string, index
end
end


Read Array#bsearch docs for explanation.

• 1. The same, not an improvement 2. ditto as 1 3. "z" is a letter of the alphabet (in Ruby .. is inclusive): irb(main):006:0> ("a".."z").to_a => ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"] 4. your function is monotone wrong, my function returns something like [false, true, false, false] that is not ok according to, citing the docs: the block returns false for any element whose index is less than i, and the block returns true for any element whose index is greater than or equal to i. – Caridorc Jul 9 '15 at 7:05
• 3. I mean 0..string.length 4. your function is monotone, until you wrap it in .zero? -- do not do it. – Nakilon Jul 9 '15 at 10:03
• Yes I think including the ending length is a bug considering that ruby will return nil at array[array.length], not wrapping it in zero is good and leads to refactoring: def balancement_value(string, index, alphabet=("a".."z").to_a) string .chars .each_with_index .map { |char, char_index| (alphabet.index(char) + 1) * (char_index - index)} .inject(:+) end and then def balanced_at?(string, index, alphabet=("a".."z").to_a) balancement_value(string, index, alphabet=("a".."z").to_a).zero? end I will call balancement_value from balanced_where (Ps: why this formatting?) – Caridorc Jul 9 '15 at 10:15