简体   繁体   中英

How to count the number of characters between two characters in a string

This is the question's prompt:

Write a method that takes a string and returns true if the letter "z" appears within three letters after an "a" . You may assume that the string contains only lowercase letters.

I'm trying to use the ternary operator, and want to include the match or count methods. Any idea on how I can find the number of characters between "a" and "z" or the simplest way to solve this?

def nearby_az(string)
  string.count <= 3 ? true : false
end

Regex would be a good way to solve this problem.

You can use online regex testers to experiment with different regexes, inputs and outputs.

The first solution that comes to my mind is to come up with a pattern for each possible correct input:

  • az
  • a[az]z
  • a[az][az]z

Which means:

  • Match the string "az"
  • Match a string with "a" and then a character from "a" to "z" and then a "z" character
  • Match a string with an "a" and then 2 characters from "a" to "z" and then a "z"

and then combine them with the 'or' operator (|)

  • az|a[az]z|a[az][az]z

Which means match on all three of those conditions.

A link to this example is here .

Doing it this way is a bit verbose so it can be improved by expressing this in a more compact way:

  • a[az]{0,2}z

This means:

  • Match an "a" then match a character from "a" to "z" 0, 1 or 2 times and then match a "z"

A link to this example is here

You use the method on ruby strings called match which takes in a regex object and then check the boolean return value.

Edit:

The ruby code would look something like this:

def nearby_az(string)
  return string.match(/a[a-z]{0,2}z/) != nil
end

string.match() returns an object that you can query to get information about the match. If there is no match, string.match() will return nil.

!!("fjeioaeiz" =~ /a.{,2}z/) #=> true
!!("fjeioaz" =~ /a.{,2}z/) #=> true
!!("fjeioasbdz" =~ /a.{,2}z/) #=> false

Look, Ma! No regex!

def a_upto_4_z(str)
   str.each_char.with_index.any? { |c,i| c == ?a && str[i+1,3].include?(?z) }
end

a_upto_4_z "rvaxxzo"  #=> true 
a_upto_4_z "rvaxxxzo" #=> false 
a_upto_4_z "rvaxzo"   #=> true 
a_upto_4_z "rvazo"    #=> true 
a_upto_4_z "rvzao"    #=> false 

Edit : @Stefan makes a good point. Let's do it this way:

def mind_the_gap(str, max_gap=2)
  gap = max_gap + 1 # or larger
  str.each_char do |c|
    case c
    when ?z
      return true if gap <= max_gap
    when ?a
      gap = 0
    else
      gap += 1
    end
  end
  false
end

mind_the_gap "rvaxxzo"  #=> true 
mind_the_gap "rvaxxxzo" #=> false 
mind_the_gap "rvaxzo"   #=> true 
mind_the_gap "rvazo"    #=> true 
mind_the_gap "rvzao"    #=> false 

Note it is not necessary to increment gap when c == ?z and gap > max_gap .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM