# Method to get string combinations

**URL:** <https://www.ruby-forum.com/t/method-to-get-string-combinations/160054>\
**Category:** Ruby\
**Created:** [February 11, 2009, 11:23am UTC](https://www.ruby-forum.com/t/method-to-get-string-combinations/160054 "2009-02-11T11:23:35Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![sol](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ebca7d/32.png) [@sol](https://www.ruby-forum.com/u/sol)\
**Post date:** [February 11, 2009, 11:23am UTC](https://www.ruby-forum.com/t/method-to-get-string-combinations/160054/1 "2009-02-11T11:23:35Z")

</div>

Hi,

I have a text like this:

“This {is|was} a {good|nice} day” and want to generate possible  
combinations like:

This is a good day  
This was a good day  
This is a nice day  
This was a nice day

I tried using zsh functionality to output this, but it doesn’t seem that  
easy.  
Does anyone know an easy way how to do this in ruby?

Thank you.

---

<div class="post-metadata">

**Author:** ![sol](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ebca7d/32.png) [@sol](https://www.ruby-forum.com/u/sol)\
**Post date:** [February 11, 2009, 11:40am UTC](https://www.ruby-forum.com/t/method-to-get-string-combinations/160054/2 "2009-02-11T11:40:43Z")

</div>

On Wed, Feb 11, 2009 at 11:22 AM, Christoph B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> This was a nice day
> 
> I tried using zsh functionality to output this, but it doesn’t seem that  
> easy.  
> Does anyone know an easy way how to do this in ruby?

There was a similar question on this list recently, I’ll try to find  
it later for reference. For a ruby quiz  
([Ruby Quiz - Reverse the Polarity (#143)](http://rubyquiz.com/quiz143.html)) I built a regexp “generator”. It  
adds a method to the Regexp to generate all possible strings that  
match the regexp. If you use my code:

[http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/274375](http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/274375)

Then this works:

irb(main):001:0\> require ‘quiz143’  
=\> true  
irb(main):002:0\> a = “This {is|was} a {good|nice} day”  
=\> “This {is|was} a {good|nice} day”  
irb(main):006:0\> s = a.gsub(/{(.\*?)}/, “(\1)”)  
=\> “This (is|was) a (good|nice) day”  
irb(main):008:0\> Regexp.new(s).generate  
=\> [“This is a good day”, “This is a nice day”, “This was a good day”,  
“This was a nice day”]

I’m changing your string to a valid regexp, changing all occurrences  
of {} with () (depending on your case you might want to change that).  
Then I create a regexp with that and call my method.

This supports many constructs from regexps, which might be overkill  
for your problem. For sure there will be easier solutions for your  
specific case. Anyway, I hope you find it interesting.

Jesus.

---

<div class="post-metadata">

**Author:** ![sol](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ebca7d/32.png) [@sol](https://www.ruby-forum.com/u/sol)\
**Post date:** [February 11, 2009, 11:48am UTC](https://www.ruby-forum.com/t/method-to-get-string-combinations/160054/3 "2009-02-11T11:48:37Z")

</div>

Wow, this is really useful! Especially in a general way like that.

Thanks a lot for the quick and helpful answer!

greetings,  
Christoph

JesÃºs Gabriel y GalÃ¡n wrote:

> On Wed, Feb 11, 2009 at 11:22 AM, Christoph B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > This was a nice day
> > 
> > I tried using zsh functionality to output this, but it doesn’t seem that  
> > easy.  
> > Does anyone know an easy way how to do this in ruby?
> 
> There was a similar question on this list recently, I’ll try to find  
> it later for reference. For a ruby quiz  
> ([Ruby Quiz - Reverse the Polarity (#143)](http://rubyquiz.com/quiz143.html)) I built a regexp “generator”. It  
> adds a method to the Regexp to generate all possible strings that  
> match the regexp. If you use my code:
> 
> [http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/274375](http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/274375)
> 
> Then this works:
> 
> irb(main):001:0\> require ‘quiz143’  
> =\> true  
> irb(main):002:0\> a = “This {is|was} a {good|nice} day”  
> =\> “This {is|was} a {good|nice} day”  
> irb(main):006:0\> s = a.gsub(/{(.\*?)}/, “(\1)”)  
> =\> “This (is|was) a (good|nice) day”  
> irb(main):008:0\> Regexp.new(s).generate  
> =\> [“This is a good day”, “This is a nice day”, “This was a good day”,  
> “This was a nice day”]
> 
> I’m changing your string to a valid regexp, changing all occurrences  
> of {} with () (depending on your case you might want to change that).  
> Then I create a regexp with that and call my method.
> 
> This supports many constructs from regexps, which might be overkill  
> for your problem. For sure there will be easier solutions for your  
> specific case. Anyway, I hope you find it interesting.
> 
> Jesus.

---

<div class="post-metadata">

**Author:** ![sol](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ebca7d/32.png) [@sol](https://www.ruby-forum.com/u/sol)\
**Post date:** [February 11, 2009, 12:01pm UTC](https://www.ruby-forum.com/t/method-to-get-string-combinations/160054/4 "2009-02-11T12:01:48Z")

</div>

ciao  
I’m a beginner…  
this code produces a partial result; try to improve and finalize it

my\_text = “This {is|was} a {good|nice} day”  
r = /{(.\*?)}/  
elem = my\_text.split®  
elem.map! {|x| x.split("|")}  
p elem

output:  
[[“This “], [“is”, “was”], [” a “], [“good”, “nice”], [” day”]]

curious to see the complete solution

---

<div class="post-metadata">

**Author:** ![sol](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ebca7d/32.png) [@sol](https://www.ruby-forum.com/u/sol)\
**Post date:** [February 11, 2009, 12:14pm UTC](https://www.ruby-forum.com/t/method-to-get-string-combinations/160054/5 "2009-02-11T12:14:14Z")

</div>

On Wed, Feb 11, 2009 at 11:47 AM, Christoph B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Wow, this is really useful! Especially in a general way like that.
> 
> Thanks a lot for the quick and helpful answer!

BTW, I have found the other post that was similar. I don’t know how to  
find the link to the archive but  
if you search for this subject: “Describing degerate dna strings” you  
might be able to find it.  
People answered with custom solutions for that exact problem (which  
was pretty similar), so you might get other ideas there.

---

<div class="post-metadata">

**Author:** ![sol](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ebca7d/32.png) [@sol](https://www.ruby-forum.com/u/sol)\
**Post date:** [February 11, 2009, 12:54pm UTC](https://www.ruby-forum.com/t/method-to-get-string-combinations/160054/6 "2009-02-11T12:54:50Z")

</div>

Hi, this is my code just for unfolding braces in a string. It also  
tries to handle nested braces like Dir.glob. Seems working fine.

def unfold(string)  
def recursion(input, list)  
num\_groups = 0  
input.scan(/{([^{}]\*?)}/) do | group |  
prefix, suffix = $`, $’  
num\_groups += 1  
tokens = group[0].split(/[,|]/)  
tokens = [’’] if tokens.empty?  
tokens.each do | token |  
recursion(prefix + token + suffix, list)  
end  
break  
end  
list \<\< input if num\_groups == 0  
end  
list = []  
recursion(string, list)  
list.uniq  
end

puts unfold(“This {is|was} a {good|nice} day”)

# A more complex one

puts unfold(‘Who is {th{is,at},she,he,it} {?,!}{}’)

---

<div class="post-metadata">

**Author:** ![sol](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ebca7d/32.png) [@sol](https://www.ruby-forum.com/u/sol)\
**Post date:** [February 11, 2009, 3:42pm UTC](https://www.ruby-forum.com/t/method-to-get-string-combinations/160054/7 "2009-02-11T15:42:58Z")

</div>

my\_text = “This {is|was} a {good|nice} day”  
r = /{(.\*?)}/  
elem = my\_text.split®.map! {|x| x.split("|")}  
comb = []  
elem.each\_index do |i|  
if comb.empty?  
elem[i].each {|x| comb \<\< x}  
else  
comb\_size = comb.size  
0…comb\_size.times do |j|  
elem[i].each { |x| s = comb.first + x ; comb.push(s) }  
comb.shift  
end  
end  
end  
p comb

---

<div class="post-metadata">

**Author:** ![sol](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ebca7d/32.png) [@sol](https://www.ruby-forum.com/u/sol)\
**Post date:** [February 12, 2009, 2:21am UTC](https://www.ruby-forum.com/t/method-to-get-string-combinations/160054/8 "2009-02-12T02:21:13Z")

</div>

Christoph B. wrote:

> This was a nice day
> 
> I tried using zsh functionality to output this, but it doesn’t seem  
> that easy.  
> Does anyone know an easy way how to do this in ruby?
> 
> Thank you.

def comb ary  
ary.inject([[]]){|old,lst|  
lst.inject([]){|new,e| new + old.map{|c| c + [e] }}}  
end

s = “This {is|was|will be} a {good|nice} day to {surf|swim}.”

f = nil  
a,b = s.split( /{(.\*?)}/ ).partition{f=!f}

a = a.join( “%s” ) + “\n”  
b.map!{|s| s.split “|”}

comb(b).each{|x| printf a % x }

— output —  
This is a good day to surf.  
This was a good day to surf.  
This will be a good day to surf.  
This is a nice day to surf.  
This was a nice day to surf.  
This will be a nice day to surf.  
This is a good day to swim.  
This was a good day to swim.  
This will be a good day to swim.  
This is a nice day to swim.  
This was a nice day to swim.  
This will be a nice day to swim.

---

<div class="post-metadata">

**Author:** ![sol](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ebca7d/32.png) [@sol](https://www.ruby-forum.com/u/sol)\
**Post date:** [February 12, 2009, 10:55am UTC](https://www.ruby-forum.com/t/method-to-get-string-combinations/160054/9 "2009-02-12T10:55:51Z")

</div>

William’s code is amazing!  
A one line solution, inspired by his ideas:  
“This {is|was} a {good|nice} day”.split(/{(.\*?)}/).map! {|x|  
x.split("|")}.inject([[]]){|old,lst| lst.inject([]){|new,e| new +  
old.map{|c| c + [e] }}}.each {|x| p x.join}
