From: w_a_x_man Date: 2010-11-04T01:45:22+09:00 Subject: Re: Regular Expression On Nov 3, 7:31 am, Robert Klemme wrote: > 2010/11/3 Jesús Gabriel y Galán : > > > > > > > On Wed, Nov 3, 2010 at 11:10 AM, Robert Klemme > > wrote: > >> Interesting approach.  I would simply have done > > >> def check(input) > >>  raise ArgumentError, "Illegal chars in sequence: %p" % input unless > >> /\A[A-D]{0,4}\z/ =~ input > >>  cnt = Hash.new 0 > >>  input.scan /./ do |m| > >>    raise ArgumentError, "Illegal sequence %p" % input if (cnt[m] += 1) > 1 > >>    # alt: return false > >>  end > >>  # alt: true > >> end > > > There are different requirements for each letter. Adapting your solution: > > Good point!  I overlooked that. > > > def check(input) > >  limits = {'A' => 1, 'B' => 1, 'C' => 1, 'D' => 2} > >  raise ArgumentError, "Illegal chars in sequence: %p" % input unless > > /\A[A-D]{0,4}\z/ =~ input > >  cnt = Hash.new 0 > >  input.scan /./ do |m| > >    cnt[m] += 1 > >  end > > >  cnt.each do |letter, amount| > >    raise ArgumentError, "Illegal chars in sequence: %p" % input if > > amount > limits[letter] > >  end > > end > > I'd rather do: > > def check(input) >  raise ArgumentError, "Illegal chars in sequence: %p" % input unless > /\A[A-D]{0,4}\z/ =~ input >  cnt = {'A' => 1, 'B' => 1, 'C' => 1, 'D' => 2} >  input.scan /./ do |m| >    raise ArgumentError, "Illegal sequence %p" % input if (cnt[m] -= 1) < 0 >    # alt: return false >  end >  # alt: true > end "We don't need no stinkin' loops!" def check input return false unless /\A[A-D]{0,4}\z/ =~ input %w(A B C D).map{|s| input.count s}.zip( [1,1,1,2] ). map{|a,b| b-a}.all?{|n| n >= 0} end