2

I am trying to solve this problem: given a string, you are asked to sort it according to characters order in other string:

Example:

> sort_string('foos', 'of')
=> 'oofs'

> sort_string('string', 'gnirts')
=> 'gnirts'

> sort_string('banana', 'abn')
=> 'aaabnn'

I've tried following implementation:

def sort_string(f_string, s_string)
  sanitize(s_string)
  s_string.chars.each do |e|
    f_string.length.times do |n|
      if f_string[n] == e
        s_string[e], s_string[n] = s_string[n], s_string[e]
      end
    end
  end
end

private

def sanitize(string)
  string.chars.uniq.join
end

But it gives me following error:

4_AStringOfSorts.rb:6:in `[]=': no implicit conversion of nil into String (TypeError)
        from 4_AStringOfSorts.rb:6:in `block (2 levels) in sort_string'
        from 4_AStringOfSorts.rb:4:in `times'
        from 4_AStringOfSorts.rb:4:in `block in sort_string'
        from 4_AStringOfSorts.rb:3:in `each'
        from 4_AStringOfSorts.rb:3:in `sort_string'
        from 4_AStringOfSorts.rb:18:in `'
2
  • I don't understand the rules. Is sort_string('zaefc', 'fa') to return efcaz? Here 'f' and 'a' are at offsets 3 and 1 of 'zaefc'. Are those two letters to be swapped, but retain positions 1 and 3, and are the remaining characters, 'z', 'e' and 'c', to be ordered lexiographically but remain at offsets 0, 2 and 4? Commented Feb 17, 2015 at 20:14
  • @Cary Swoveland, sort_string('zaefc', 'fa') => 'fazec' Commented Feb 18, 2015 at 9:04

3 Answers 3

4

Notes:

  • Your approach is not idiomatic in Ruby (it's overly complicated even by imperative standards)

  • sanitize(s_string): you don't capture the result of this method, so it's doing nothing.

A more idiomatic and functional approach:

def sort_string(s, order)
  s.chars.sort_by { |c| order.index(c) || order.size }.join
end
Sign up to request clarification or add additional context in comments.

Comments

2

A similar approach:

def sort_string(s, order)
  order.chars.map { |c| c * s.count(c) }.join
end

1 Comment

If s = 'zaefcf' and order = 'fa', this returns ffa`. I understood the string returned was to contain the remaining characters as well.
0

If @tokland's interpretation of the question is correct, it can also be done thus, without sorting per se:

def sort_string(s, order)
  sa = s.chars
  order.each_char.with_object('') do |c,str|
    while (idx = sa.index(c))
      str << sa.delete_at(idx)
    end
  end + sa.join
end

sort_string('zaefcf', 'fa')
  #=>"ffazec"

Here's another way that uses sort_by, but only on the part of the string that requires sorting:

def sort_string(s, order)
  sa = s.chars
  e = sa - order.chars
  (sa - e).sort_by { |c| order.index(c) }.concat(e).join
end

sort_string('zaefcf', 'fa')
  #=> "ffazec" 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.