2014-02-27 119 views
3

我想知道是否有一種簡單的方法以簡單的方式在ruby中完成所選字符替換的每個組合。ruby​​中字符串中所選字符替換的所有可能組合

一個例子:

string = "this is a test" 
    subs = ['a'=>'@','i'=>'!','s'=>'$'] 
    subs.combination.each { |c| 
     string.gsub c 
    } 

會產生

"this is @ test" 
    "th!s !s a test" 
    "thi$ i$ a te$t" 
    "th!s !s @ test" 
    "thi$ i$ @ te$t" 
    "th!$ !$ a te$t" 
    "th!$ !$ @ te$t" 

感謝您的幫助!

+1

只是好奇,爲什麼你要生成的組合? –

+0

它適用於我正在使用的計算機安全課程中的任務。我們要寫一個密碼破解器,給出一個單詞列表應該破解我們的教授給我們的散列密碼。以上是已經實現的,儘管以非常難看的方式將每個組合在腳本中進行硬編碼。 – user3207230

+0

你是否需要確切的預期產出,那麼我需要更多地回答我的問題? –

回答

1
string = "this is a test" 
subs = ['a'=>'@','i'=>'!','s'=>'$'] 

subs = subs.first.map(&:to_a) 
1.upto(subs.length).each do |n| 
    subs.combination(n).each do |a| 
    p a.each_with_object(string.dup){|pair, s| s.gsub!(*pair)} 
    end 
end 
+0

如果我沒有錯,OP做錯了結構..'['a'=>'@','i'=>'!','s'=>'$']'..應該是'Hash' .. 對 ? –

+0

@ArupRakshit這不是一個散列,它是一個包含一個散列的數組,省略了{}。 – sawa

+0

好的。它是一個哈希數組或只有哈希數組。 –

3

我下面做:

string = "this is a test" 
subs = {'a'=>'@','i'=>'!','s'=>'$'} 

keys = subs.keys 
combinations = 1.upto(subs.size).flat_map { |i| keys.combination(i).to_a } 

combinations.each do |ary| 
    new_string = string.dup 
    ary.each { |c| new_string.gsub!(c,subs) } 
    puts new_string 
end 

輸出

this is @ test 
th!s !s a test 
thi$ i$ a te$t 
th!s !s @ test 
thi$ i$ @ te$t 
th!$ !$ a te$t 
th!$ !$ @ te$t 
+1

+1這與我在打字前一直打字的內容類似(現在在通勤巴士上)。我注意到你有一個未使用的變量'new' –

+0

@MarkThomas謝謝,我首先想到的是,我會創建'#map',因此'new'在那裏。之後,我改變了我的決定,但忘了刪除'new'變量。現在我做到了。 –

+1

有趣的是對'sub!'使用散列參數,但我認爲您不需要將匹配模式轉換爲正則表達式,對嗎? – sawa

1

我會做使用String#gsub(pattern, hash)如下:

string = "this is a test" 
subs = {'a'=>'@','i'=>'!','s'=>'$'} # copied from @ArupRakshit 
keys = subs.keys 

和核心代碼:

1.upto(keys.length).flat_map { |i| 
    keys.combination(i).flat_map { |c| string.gsub(/[#{c.join}]/, subs) } 
} 

輸出:

=> ["this is @ test", 
"th!s !s a test", 
"thi$ i$ a te$t", 
"th!s !s @ test", 
"thi$ i$ @ te$t", 
"th!$ !$ a te$t", 
"th!$ !$ @ te$t"] 
+1

好的解決方案,Abdo,+1。我不知道'gsub'可以把一個散列作爲一個參數。很高興知道。 –

+0

@CarySwoveland是!我們的解決方案可以組合成以下內容:'keys.repeated_combination(keys.length).map {| c | string.gsub(/ [#{c.uniq.join}] /,subs)} .uniq' – Abdo

+0

我喜歡那樣。你會爲我的皇室提出什麼建議? –

0

單行官能溶液

string = "this is a test" 
subs = {'a'=>'@','i'=>'!','s'=>'$'} 

(1..subs.size).flat_map { |n| subs.keys.combination(n).to_a }.map { |c| string.gsub(/[#{c.join}]/, subs) } 
# => ["this is @ test", "th!s !s a test", "thi$ i$ a te$t", "th!s !s @ test", "thi$ i$ @ te$t", "th!$ !$ a te$t", "th!$ !$ @ te$t"] 
+0

礦是一個班輪...我只縮進它,你不必滾動。 – Abdo

+1

我同意最好多行以獲得可讀性 –

+0

根據官方規定,如果僅爲了避免水平滾動的需要而顯示在多行上,則其符合作爲單行程的條件。我這樣做的好方法是從.map開始第二行,位於.flat_map下面。 Ruby將沒有問題(儘管IRB/Pry會)。 –

1

的另一種方法:

string = "this is a test" 
subs = [{"a"=>"@"}, {"i"=>"!"}, {"s"=>"$"}] 

subs.repeated_combination(subs.size) 
    .map {|e| string.gsub(/./) {|c| (g = e.find {|h| h.key?(c)}) ? g[c] : c}} 
    .uniq 
    #=> ["this is @ test", "th!s !s @ test", "thi$ i$ @ te$t", "th!$ !$ @ te$t", 
    # "th!s !s a test", "th!$ !$ a te$t", thi$ i$ a te$t"] 

說明:

a = subs.repeated_combination(subs.size) 
    # Enumerator... 
    a.to_a 
    # [[{"a"=>"@"},{"a"=>"@"},{"a"=>"@"}], [{"a"=>"@"},{"a"=>"@"},{"i"=>"!"}], 
    # [{"a"=>"@"},{"a"=>"@"},{"s"=>"$"}], [{"a"=>"@"},{"i"=>"!"},{"i"=>"!"}], 
    # [{"a"=>"@"},{"i"=>"!"},{"s"=>"$"}], [{"a"=>"@"},{"s"=>"$"},{"s"=>"$"}], 
    # [{"i"=>"!"},{"i"=>"!"},{"i"=>"!"}], [{"i"=>"!"},{"i"=>"!"},{"s"=>"$"}], 
    # [{"i"=>"!"},{"s"=>"$"},{"s"=>"$"}], [{"s"=>"$"},{"s"=>"$"},{"s"=>"$"}]] 

b = a.map {|e| string.gsub(/./) {|c| (g = e.find {|h| h.key?(c)}) ? g[c] : c}} 
    #=> ["this is @ test", "th!s !s @ test", "thi$ i$ @ te$t", "th!s !s @ test", 
    # "th!$ !$ @ te$t", "thi$ i$ @ te$t", "th!s !s a test", "th!$ !$ a te$t", 
    # "th!$ !$ a te$t", "thi$ i$ a te$t"] 

要了解b的計算方式,傳遞給該塊的a第二元件:

e = [{"a"=>"@"},{"a"=>"@"},{"i"=>"!"}] 

由於該正則表達式的,/./gsub傳遞的string每個字符c到塊

{|c| (g = e.find {|h| h.key?(c)}) ? g[c] : c} 

搜索結果由e來確定如果三個哈希中的任何一個都有c作爲關鍵字。如果找到一個,即g,則將字符c替換爲g[c];否則,角色保持不變。

請注意,e的前兩個元素是相同的。通過將第一行改爲:

subs.repeated_combination(subs.size).map(&:uniq) 

可以提高效率,但效率不是這種方法的優點之一。

返回到主計算,最後的步驟是:

b.uniq 
    #=> ["this is @ test", "th!s !s @ test", "thi$ i$ @ te$t", "th!$ !$ @ te$t", 
    # "th!s !s a test", "th!$ !$ a te$t", "thi$ i$ a te$t"] 
+0

哦,是的!大量使用repeat_combination! +1 – Abdo

相關問題