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
puts balanced_where("stead")
1 Answer 1
- You may use splat operator instead of
.to_a
- You may use
.map.with_index
instead of.each_with_index.map
- 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
puts balanced_where "stead"
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.
-
\$\begingroup\$ 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.
\$\endgroup\$Caridorc– Caridorc2015年07月09日 07:05:04 +00:00Commented Jul 9, 2015 at 7:05 -
\$\begingroup\$ 3. I mean
0..string.length
4. your function is monotone, until you wrap it in.zero?
-- do not do it. \$\endgroup\$Nakilon– Nakilon2015年07月09日 10:03:00 +00:00Commented Jul 9, 2015 at 10:03 -
\$\begingroup\$ 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 thendef balanced_at?(string, index, alphabet=("a".."z").to_a) balancement_value(string, index, alphabet=("a".."z").to_a).zero? end
I will callbalancement_value
frombalanced_where
(Ps: why this formatting?) \$\endgroup\$Caridorc– Caridorc2015年07月09日 10:15:03 +00:00Commented Jul 9, 2015 at 10:15