Reputation: 2845
This was asked me in a coding quesiton, and I gave kind of an ugly, though working solution. Would love to see a master's beautiful solution to this question.
Given a string that includes letters and numbers i.e. "abCd1_k"
, return an array of every variant string with the capitalization of the letters changed, i.e., "AbCd1_k"
, "ABcd1_k"
....
A more simple problem case then 'AbCd1_k' would be 'ab', which should return ->
['ab', 'Ab', 'aB' 'AB']
It seems to me that even the most beautiful solution will still have an expensive time complexity by definition. (at worst, you could 2 combinations for each character, which would mean 2^n growth). Even if this is true, there must be a really beautiful way to do this in Ruby.
Upvotes: 0
Views: 950
Reputation: 1
How about:
class String
def case_combinations
downcased = self.downcase
[0, 1].repeated_permutation(self.size).to_a.map do |binary_casing|
permutation = downcased.dup
binary_casing.each_with_index.map do |binary_case, index|
permutation[index] = permutation[index].upcase if binary_case == 1
end
permutation
end
end
end
Basically it creates all possible combinations of 0 and 1 given a length of string, taking that it takes the 1s as representing upcase.
'abc'.case_combinations # ["abc", "abC", "aBc", "aBC", "Abc", "AbC", "ABc", "ABC"]
If some characters are not letters, it would return duplicates but adding uniq
would fix it.
Upvotes: 0
Reputation: 803
def every_combination(str = '')
return unless str
str.chars.permutation(str.size).map do |perm|
perm_char_case_pair = perm.map do |c|
[c.downcase, c.upcase]
end
perm_char_case_pair[0].product(*perm_char_case_pair[1..-1]).map(&:join)
end.flatten.uniq
end
Upvotes: 0
Reputation: 1944
def case_combos(str)
c = str.split('').map { |x| [x.upcase, x.downcase]}
(0...1<<str.size).to_a.map do |x|
z = ""
0.upto(c.size-1) do |y|
z += c[y][0] if (1<<y)&x == 0
z += c[y][1] if (1<<y)&x != 0
end
z
end.uniq
end
Upvotes: 2
Reputation: 111
How about this:
def case_permutations(string)
string
.each_char
.reduce(['']) do |acc, char_string|
acc.flat_map do |prefix|
[char_string.upcase, char_string.downcase]
.uniq
.map do |modified_char|
"#{prefix}#{modified_char}"
end
end
end
end
You're not going to do better than (2^n)*n time complexity because your return value will have 2^n items of length n in the worst case.
Upvotes: 5