2017-03-15 18 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 == "!????!!" 
相關問題