2017-03-15 21 views
1

我有一个编码问题,我解决了,并希望重构。我知道我必须做得更干净一些。红宝石,通过一个字符串循环删除字符组,直到达到所需的输出

我们的目标是编写一个采用字符串"!""?"的方法,并通过消除每个符号的所有奇数分组来减少字符串。

示例 - 字符串"????!!!"将具有奇数分组"!!!",因为在一行中有三个。这些将从字符串中删除。

如果只有一个"!""?"它的左边,因为它不在一个组中。

防爆 -

remove("!????!!!?") answer == "!"  
# => ("!????!!!?" --> "!?????" --> "!") 

在第一个字符串,唯一奇怪的是分组"!!!",一旦去掉,它的叶子有一个奇怪的分组"?????"一个新的字符串。您删除了下一个奇怪的分组,因此您只剩下"!"。这符合所需的输出。

又如

remove("!???!!") == "" 
# => ("!???!!" --> "!!!" --> "") 

当前代码:

def remove(s) 
    arr = [s] 
    i = 0 

    until i == arr[0].length 
    s = s.chars.chunk{|c|c}.map{ |n,a| a.join }.select{|x| x if x.length.even? || x.length <= 1}.join 
    arr << s 
    i += 1 
    end 

    return arr[-1] 
end 

我的代码解决了这个问题,所有的测试用例。我有一个怀疑,我的直到循环可以删除/重构,以便我可以解决这个问题在一行,花了几个小时试图找出它没有运气。

+0

你对你的问题有足够的重视,欣赏给定的时间。 –

回答

1

假设

str = "???!!!???!" 

如果我们首先删除两组"???"我们留下"!!!!",不能被进一步减小。

如果我们第一次删除组"!!!"我们剩下"??????!",这是不能进一步减少。

如果我们被允许移除任何一个字符的所有奇怪群体,而没有提到另一个字符的效果,我们获得!,这不能进一步减少。

目前还不清楚使用什么规则。这里有三个可能性和代码来实现每个。

我将使用以下两个正则表达式,并在前两种情况下使用一个辅助方法。

Rq =/
    (?<!\?) # do not match a question mark, negative lookbehind 
    \?  # match a question mark 
    (\?{2})+ # match two question marks one or more times 
    (?!\?) # do not match a question mark, negative lookahead 
    /x  # free-spacing regex definition mode 

它通常写成。

同样,

Rx = /(?<!!)!(!{2})+(?!!)/ 

def sequential(str, first_regex, second_regex) 
    s = str.dup 
    loop do 
    size = s.size 
    s = s.gsub(first_regex,'').gsub(second_regex,'') 
    return s if s.size == size 
    end 
end 

予应用的每个的三种方法的以下两个示例字符串:

str1 = "???!!!???!" 
str2 = 50.times.map { ['?', '!'].sample }.join 
    #=> "?!!!?!!!?!??????!!!?!!??!!???!?!????!?!!!?!?!???!?" 

替换"?""!"然后奇数群组的所有奇数组然后重复直到没有进一步的清除是可能的

def question_before_exclamation(str) 
    sequential(str, Rq, Rx) 
end 

question_before_exclamation str1 #=> "!!!!" 
question_before_exclamation str2 #=> "??!??!?!!?!?!!?" 

更换"!""?"然后奇组的所有奇数组,然后重复,直到没有进一步的清除有可能

def exclamation_before_question(str) 
    sequential(str, Rx, Rq) 
end 

exclamation_before_question str1 #=> "??????!" 
exclamation_before_question str2 #=> "??!????!!?!?!!?!?!!?" 

更换两个"?""!"的所有奇数组再重复,直到没有进一步的清除有可能

Rqx = /#{Rq}|#{Rx}/ 
    #=> /(?-mix:(?<!\?)\?(\?{2})+(?!\?))|(?-mix:(?<!!)!(!{2})+(?!!))/ 

def question_and_explanation(str) 
    s = str.dup 
    loop do 
    size = s.size 
    s = s.gsub(Rqx,'') 
    return s if s.size == size 
    end 
end 

question_and_explanation str1 #=> "!" 
question_and_explanation str2 #=> "??!?!!?!?!!?!?!!?" 
1

我可能是错的(毕竟这是红宝石),但我不认为你会找到一个单线,因为ruby的效用函数通常不是递归的。但是你可以使用正则表达式来简化你的逻辑,至少是:

def remove(s) 
    while s =~ /(?<!\!)\!([\!]{2})+(?!\!)/ || s =~ /(?<!\?)\?([\?]{2})+(?!\?)/ 
    s.gsub! /(?<!\!)\!([\!]{2})+(?!\!)/, "" # remove odd ! 
    s.gsub! /(?<!\?)\?([\?]{2})+(?!\?)/, "" # remove odd ? 
    end 
    return s 
end 

为了使正则表达式少令人难以置信,它有助于看待他们与“一”,而不是“?”和'!“:

/(?<!a)a([a]{2})+(?!a)/ #regex for 'a' 

(?<!a) #negative lookbehind: the match cannot start with an 'a' 

a([a]{2})+ #the match should be an 'a' followed by 1 or more pairs 

(?!a) #negative lookahead: the match cannot end with an 'a' 
1

我不知道这个确切的Ruby语法,但你可以通过使用正则表达式简化您的解决方案:

  1. 收集的连续字符
    • 如果所有比赛所有匹配都是偶数长度或1个出口
  2. 测试匹配是否奇数长度
    • 如果一个奇数长度,用空字符串
    • 别的什么也不做
  3. 转到第1步

取代Perl中的一个解决办法是:

#!perl 

use strict; 
use warnings; 

use feature qw(say); 

my $string = '!????!!!?'; 
sub reduce { 
    my ($s) = @_; 
    while (my @matches = $s =~ m/((.)\2+)/g) { 
    last if ! grep { length($_) > 1 && length($_) % 2 == 1 } @matches; 
    foreach my $match (@matches) { 
     $s =~ s/\Q$match// if length($match) > 1 && length($match) % 2 == 1; 
    } 
    } 

    return $s; 
} 

say reduce($string); 
1

它用正则表达式替换应该很简单

def remove(string) 
    begin 
    original = string 
    string.gsub!(/(\!{3,})|(\?{3,})/) { |s| s.length.even? ? s : '' } 
    end until original == string 
    string 
end 

puts remove("!????!!!?").inspect # answer == "!" 
puts remove("!???!!").inspect # answer == "" 
puts remove("!????!!").inspect # answer == "!????!!" 
相关问题