I am trying to take input as a string.
Then I need to find all the possible combination and distinct combination but I am unable to do so.
input = "aabb"
Output I need to print all Combination =
'a','a','b','b','aa','ab','bb','aab','abb','aabb'
Now Distinct combination
'a','b','aa','ab','bb','aab','abb','aabb'
Then I need to count the letters and do a summation
'a','a','b','b','aa','ab','bb','aab','abb','aabb'
For this
result = 1+1+1+1+2+2+2+3+3+4
Similarly for the other combination I need to find summation.
You can use Array#combination.
To get all combinations:
input = "aabb"
res = []
input.size.times { |n| res << input.chars.combination(n+1).map { |a| a.join } }
res.flatten
#=> ["a", "a", "b", "b", "aa", "ab", "ab", "ab", "ab", "bb", "aab", "aab", "abb", "abb", "aabb"]
distinct combinations:
res.flatten.uniq
#=> ["a", "b", "aa", "ab", "bb", "aab", "abb", "aabb"]
to count the letters and do a summation:
res.flatten.uniq.map(&:size)
#=> [1, 1, 2, 2, 2, 3, 3, 4]
res.flatten.uniq.map(&:size).reduce(:+)
# => 18
To get all the substrings of your input (or more generally to get all subsequences of an Enumerable) you can use something like this:
def subsequences(e)
a = e.to_a
indices = (0..a.length - 1).to_a
indices.product(indices)
.reject { |i, j| i > j }
.map { |i, j| a[i..j] }
end
You would use that on your string like this: subsequences(input.chars).map(&:join). The chars and join are only necessary because Strings are not Enumerable, but the subsequences function does not really need that. You can just take out the first line and it should still work for strings (anything that has a "slicing" subscript operator, really ...).
Note also that this is not the only way to do this. The basic problem here is to iterate over all ordered pairs of indices of a sequence. You could also do that with basic loops. I just happen to find the cartesian product method very elegant. ;)
Once you have your first list in a variable, say list, the second task is as easy as list.uniq, and the third one is solved by
list.map(&:size).reduce(:+)
Related
I have this code that works well
def self.select_some_elements(some_value)
return elements.select { |element| element.some_value > some_value}
end
This code returns an array of elements class instances/objects. However, I would like to return the array of element.to_s instances/propeties, not the whole class objects, just strings/string properties
Is there a quick way to do it without going extra steps?
Introduction:
So, what you have achieved is a set (array in this case) of objects, which is great. What you have to do now is to transform this set into a different one: namely, replace each object with what that object's method to_s returns. There's a perfect method for that, called map. It goes through all the items, calls a block with each item as an argument and puts in the resulting array what the block has returned:
Open irb console and play around:
>> [1,2,3].map{|x| 1}
=> [1, 1, 1]
>> [1,2,3].map{|x| x+1}
=> [2, 3, 4]
>> [1,2,3].map{|x| "a"}
=> ["a", "a", "a"]
>> [1,2,3].map{|x| x.to_s}
=> ["1", "2", "3"]
>> [1,2,3].map(&:to_s)
=> ["1", "2", "3"]
The last transformation seems to be what you need:
The answer:
Add .map(&:to_s) at the end like this
def self.select_some_elements(some_value)
return elements.select { |element| element.some_value > some_value}.map(&:to_s)
end
.map(&:to_s) is a short version of .map { |element| element.to_s }. And you can read about Arra3#map in the docs
And when you wrap your head around the #map, check out Stefan's answer which shows how select{}.map can be "compressed" into one filter_map call (doing both things: filter, and mapping in one iteration over the set instead of two).
Starting with Ruby 2.7 there's filter_map:
elements = [1, 2, 3, 4, 5]
elements.filter_map { |e| e.to_s if e > 2 }
#=> ["3", "4", "5"]
Let's say you have something like this:
my_array = ['some_rather', 'long_named', 'array_element', 'entry']
I want to remove arbitrary entries by index from my_array without changing it and I want the filtered (i.e. array with indices removed) to be returned from my call. Furthermore, I want to avoid chaining 4 separate calls and write a block doing so.
Example:
filtered_array = my_array.drop_indices(1,3)
You could chain Enumerable's with_index onto Array's reject method to do what you want, though this might violate your desire to not chain separate method calls or write a block to do this:
my_array = ['some_rather', 'long_named', 'array_element', 'entry', 'long_named']
indices_to_remove = [1, 3]
filtered = my_array.reject.with_index { |_, index| indices_to_remove.include?(index) }
p filtered # => ["some_rather", "array_element", "long_named"]
p my_array # => ["some_rather", "long_named", "array_element", "entry", "long_named"]
If this isn't acceptable, the only other thing I can think of right now, to keep duplicate items (as noted in my comment to your solution), is to change from indices_to_remove to indices_to_keep:
my_array = ['some_rather', 'long_named', 'array_element', 'entry', 'long_named']
indices_to_remove = [1, 3]
indices_to_keep = [*(0...my_array.length)] - indices_to_remove
filtered = my_array.values_at(*indices_to_keep)
p filtered # => ["some_rather", "array_element", "long_named"]
p my_array # => ["some_rather", "long_named", "array_element", "entry", "long_named"]
For Arrays with duplicate Elements the best I know is:
array = [0,15,8,15,8]
indices_to_remove = [1,4]
res = array.reject.with_index{ |_,i| indices_to_remove.include?(i) }
returns
[0,8,15]
Additionally for arrays with unique entries such as a set of users
(using variable definitions from the question)
filtered_array = my_array - my_array.values_at(1,3)
Bonus, if your indices are inside an array themselves:
indices_to_remove = [1,3]
filtered_array = my_array - my_array.values_at(*indices_to_remove)
I think this is rather descriptive, not awkward and not shorter than needed.
One more possible solution with some addition, now it's also will work with negative indexes:
array = %w( a b c d e f )
indexes = [1, 2, -1, -9, -6, 6]
def array_except(array, *indexes)
indexes = indexes.map { |e| e.negative? ? e + array.length : e }
array.values_at(*((0...array.length).to_a - indexes))
end
array_except(array, *indexes)
=> ["d", "e"]
array_except(array, 0, -1)
=> ["b", "c", "d", "e"]
Let's say I have a list of elements in an array, but there is a logical way to divide them into two groups. I want to put those elements into two smaller arrays based on that criteria. Here is some code that works and helps illustrate what I mean:
foo = ['a', 'bb', 'c', 'ddd', 'ee', 'f']
=> ["a", "bb", "c", "ddd", "ee", "f"]
a = foo.select{|element| element.length == 1}
=> ["a", "c", "f"]
b = foo.reject{|element| element.length == 1}
=> ["bb", "ddd", "ee"]
I seem to remember seeing some way by which a single method call would assign both a and b, but I don't remember what it was. It would look something like
matching, non_matching = foo.mystery_method{|element| element.length == 1}
Am I crazy, or does such a method exist in Ruby and/or Rails?
Yes! http://ruby-doc.org/core-1.9.3/Enumerable.html#method-i-partition
matching, non_matching = foo.partition {|element| element.length == 1}
One of my objects ('item') has an ID ('letter_id') in the format of "a", "b", ..., "aa", "ab", etc. To generate it I am using ruby's String#succ in an instance method like this:
def set_letter_id
last = parent.items.all(:order => "letter_id ASC").last
if last.nil?
self.letter_id = 'a'
else
self.letter_id = last.letter_id.succ
end
end
Now this works great until the 28th letter. The 27th will properly generate "aa", but then the value of last will always return the item with the letter_id of 'z' because the ordering of the returned items doesn't follow the same rules as String#succ.
I found this out from a comment over here - but now I'm struggling to find a nice solution around this issue. The problem is basically this:
"aa".succ #=> "ab" - great, that's what I want.
"z"<=>"aa" #=> 1 - not so great, "z" should actually be less than "aa"
Obviously this isn't necessarily a bug, but it makes sorting and ordering a list of letter_ids in this format quite difficult. Has anyone encountered this and found a workaround, or any suggestions that I might try? Thanks!
There was a solution in answers at link you've posted - you have to write own <=> in way to sort_by{|i|[i.length,i]}
irb> %w{a b c z aa ab zz aaa}.shuffle.sort_by { |i| [i.length,i] }
=> ["a", "b", "c", "z", "aa", "ab", "zz", "aaa"]
You can override the <=> method for your Item model to compare first by ID length, then by alphanumeric.
Something like this:
class Item < ActiveRecord::Base
# stuff
def <=>(other)
len_comp = self.letter_id.length <=> other.letter_id.length
return len_comp if len_comp != 0
self.letter_id <=> other.letter_id
end
end
That way you first compare for shorter ID length (i.e., "z" before "aa"), then lexicographically.
This sort of issue is exactly why some people discourage the use of String#succ. It clashes with Range, Object#to_a, and others.
Anyway, you probably know this, but things like this might help...
>> t
=> ["x", "y", "z", "aa", "ab", "ac", "ad", "ae", "af", "ag"]
>> t.shuffle.sort_by { |e| "%3s" % [e] }
=> ["x", "y", "z", "aa", "ab", "ac", "ad", "ae", "af", "ag"]
You could even renormalize this way and dispense with sort_by.
I'm hopelessly trying to write a method to manipulate an array in ruby. I'm trying to generate all in-order permutations of an array where each item is in turn replaced by an outside item. An example...
Given input:
arr = ["a", "b", "c"]
Desired output:
newArr = [ ["a", "b", "c"], ["a", "b", "*"], ["a", "*", "c"], ["a", "*", "*"], ["*", "b", "c"], ["*", "b", "*"], ["*", "*", "c"], ["*", "*", "*"] ]
Any help would be greatly appreciated. Thank you!
I don't understand your example order, either, but ignoring that, here's a solution in one line:
(0...(2**a.size)).map {|x| (0...a.size).map {|y| x & 2**y == 0 ? a[y] : val}}
I'm not sure permutation is the right word. If you count in binary, then you are replacing the things if there is a one. Here's that in Ruby:
def mike(arr, sub)
format = sprintf("%%0%db", arr.length)
m = Array.new
0.upto(2**arr.length-1) { |i|
bits = sprintf(format, i).split('')
a = Array.new
0.upto(arr.length-1) { |j|
if bits[j] == '0' then
a << arr[j]
else
a << sub
end
}
m[i] = a
}
return m
end
arr = ["a", "b", "c"]
p mike(arr, '*')
Is that if-then-else better with a ternary operator?
a <<= bits[j] == '0' ? arr[j] : sub
There must be a cleverer (or, at least more Rubyesque) way to do this, but it seems to produce the desired output.
ETA: Oops! My second and third items don't agree with yours. I guess I don't know what order you mean.
Similar to oylenshpeegui's method:
def toggle(arr, sub)
format = "%0#{arr.length}b"
(0...2**(arr.length)).to_a.map do |i|
sprintf(format,i).split('').zip(arr).map { |x| x[0] == "0" ? x[1] : sub }
end
end
The split/zip combo matches each digit of the binary expansion of the index with the element it is selecting. The map at the end uses the digit to decide if it should return the array element or the substitution.