Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to split a string into consecutive substrings of length at most 3 in all possible ways?

Tags:

variables

ruby

I am trying to take a string, between length 1 and 10, and output all possible ways of breaking up the string into consecutive substrings that are of sizes 1, 2, or 3. For example:

Input: 123456

Slice the integer into individual characters, then proceed through to find combinations. The code would return all of the following arrays.

    [1, 2, 3, 4, 5, 6]  
    [12, 3, 4, 5, 6]  
    [1, 23, 4, 5, 6]  
    [1, 2, 34, 5, 6]  
    [1, 2, 3, 45, 6]  
    [1, 2, 3, 4, 56]  
    [12, 34, 5, 6]  
    [12, 3, 45, 6]  
    [12, 3, 4, 56]  
    [1, 23, 45, 6]  
    [1, 2, 34, 56]  
    [1, 23, 4, 56]  
    [12, 34, 56]  
    [123, 4, 5, 6]  
    [1, 234, 5, 6]  
    [1, 2, 345, 6]  
    [1, 2, 3, 456]  
    [123, 456]  
    [1, 23, 456]  
    [1, 234, 56]  
    [12, 345, 6]  
    [12, 3, 456]  
    [123, 4, 56]  
    [123, 45, 6]

I'm trying to do this in ruby. Thanks!

like image 609
Drizzit12 Avatar asked Jul 27 '11 21:07

Drizzit12


People also ask

How do I split a string into substrings?

The split() method splits a string into an array of substrings. The split() method returns the new array. The split() method does not change the original string. If (" ") is used as separator, the string is split between words.

How do you split a string into 3 parts in Python?

Python 3 - String split() Method The split() method returns a list of all the words in the string, using str as the separator (splits on all whitespace if left unspecified), optionally limiting the number of splits to num.

Which of the following can be used to break a string into two substrings of desirable length?

Remarks. Split is used to break a delimited string into substrings. You can use either a character array or a string array to specify zero or more delimiting characters or strings. If no delimiting characters are specified, the string is split at white-space characters.


3 Answers

Here's a working function. May be not optimal as I didn't spend much time on it.

str = "1234567890"

def f(s, n)
    return [[]] if s.empty?

    (1..[n, s.length].min).map{|c| f(s[c..-1], n).map{|a| [s[0, c]] + a}}.inject(&:+)
end

puts f(str, 3).collect{|l| l * "\t"}

EDIT: Made it a bit shorter and the length is now passed as second parameter to function for flexibility.

like image 101
RocketR Avatar answered Oct 06 '22 00:10

RocketR


It took me quite a while to figure this out, its a much harder problem then I first though. But eventually I hit upon this solution:

def combinations(s)
  c = (s.length > 3) ? [] : [[s]]
  max = [4, s.length].min
  (1...max).inject(c) do |c, i|
    combinations(s[i..-1]).inject(c) do |c, tail|
      c.push([s[0...i]] + tail)
    end
  end
end

combinations("12345").each { |c| p c }

Produces:

["1", "2", "345"]
["1", "2", "3", "45"]
["1", "2", "3", "4", "5"]
["1", "2", "34", "5"]
["1", "23", "45"]
["1", "23", "4", "5"]
["1", "234", "5"]
["12", "345"]
["12", "3", "45"]
["12", "3", "4", "5"]
["12", "34", "5"]
["123", "45"]
["123", "4", "5"]
like image 27
Connor McKay Avatar answered Oct 06 '22 00:10

Connor McKay


Here's another:

class String
  def splitup(prefix=nil)
    parts = []
    if size <= 3
      parts << [prefix,self].compact * ","
    end
    (1..([size,3].min)).each do |p|
      next if p >= size
      parts << slice(p..-1).splitup([prefix,slice(0,p)].compact * ",")
    end
    parts
  end

  def report
    flat = splitup.flatten.sort_by {|x| [-x.size,x]}
    puts
    puts "#{flat.size} permutations of #{self}"
    puts flat
  end
end

and then

>> "123456".report

24 permutations of 123456
1,2,3,4,5,6
1,2,3,4,56
1,2,3,45,6
1,2,34,5,6
1,23,4,5,6
12,3,4,5,6
1,2,3,456
1,2,34,56
1,2,345,6
1,23,4,56
1,23,45,6
1,234,5,6
12,3,4,56
12,3,45,6
12,34,5,6
123,4,5,6
1,23,456
1,234,56
12,3,456
12,34,56
12,345,6
123,4,56
123,45,6
123,456
like image 42
glenn mcdonald Avatar answered Oct 05 '22 22:10

glenn mcdonald