I was working on implementing a recursive powerset algorithm in Ruby and I came across this Stack Overflow post.
def powerset(set)
return [set] if set.empty?
p = set.pop
subset = powerset(set)
subset | subset.map { |x| x | [p] }
end
powerset(['a'], ['b'], ['c']) ---> [[], ["a"], ["b"], ["a", "b"], ["c"], ["a", "c"], ["b", "c"], ["a", "b", "c"]]
Basically, I'm at a loss in understanding the last line. I understand that this is the 'bitwise or' operator, and I generally understand what this does, but I'm having a lot of trouble comprehending how it works in this last line works here.
Can someone show me what the equivalent would be in easier to read Ruby?
Here's an equivalent in easier to read words :)
If the set is empty:
return a list with one empty set
Remove an element from the set and call it "p"
Call "subset" the powerset of the new set (that excludes p)
Return the union of this new powerset and another
version of it, where p is added to each of its sets
Related
I am browsing through the ruby Array iterators. And I can't find what I am looking for and I think it already exists:
I have two arrays:
["a", "b", "c"]
[0,1,2]
And I want to merge as so:
[ [0, "a"], [1, "b"], [2, "c"] ]
I think the iterator exists in the standard library (I used it before) but I am having trouble finding its name.
This should work:
[0,1,2].zip(["a", "b", "c"]) # => [[0, "a"], [1, "b"], [2, "c"]]
From the official documentation of the Array#zip function:
Converts any arguments to arrays, then merges elements of self with corresponding elements from each argument.
This generates a sequence of ary.size n-element arrays, where n is one more than the count of arguments.
For more info and some other examples, refer to:
https://ruby-doc.org/core-2.4.2/Array.html#method-i-zip
You are looking for the zip function
https://apidock.com/ruby/Array/zip
I think you could use https://apidock.com/ruby/Enumerator/each_with_index
See this post difference between each.with_index and each_with_index in Ruby?
or if you have specific values and you want to map them you would use map or zip. It explains it well in this post
Combine two Arrays into Hash
I'm looking for an elegant way to partition an array by using index in ruby
eg:
["a","b",3,"c",5].partition_with_index(2)
=> [["a","b",3],["c",5]]
So far the best that I can think is using the below
["a","b",3,"c",5].partition.each_with_index{|val,index| index <= 2}
=> [["a","b",3],["c",5]]
Is there any other elegant way to accomplish this?
Thanks!
You can do:
["a","b",3,"c",5].partition.with_index { |_, index| index <= 2 }
Following #toro2k advice, I think this is a better solution because you are combining the two Enumerators to get the desired output.
If you don’t pass a block of code to partition, it returns an Enumerator object instead. Enumerators have a with_index method that will maintain the current loop index.
Why don't you use array.slice!
array#slice! Deletes the element(s) given by an index (optionally up to length elements) or by a range.
> a = ['a', 'b', 'c', 5]
> b = a.slice! 0, 2 # => ['a', 'b']
> a # => ['c', 5]
In your case,
> [a.slice!(0, index), a]
You could use Enumerable's take and drop methods:
a = ["a","b",3,"c",5]
[a.take(3), a.drop(3)] # => [["a", "b", 3], ["c", 5]]
I made an Enumerable quick reference sheet you might want to consult for questions like this.
This can be done, but not sure if it elegant or not :
a = ["a","b",3,"c",5]
index = 2
[a[0..index], a[index+1..-1]]
Thanks
You can try the below :
a = ["a","b",3,"c",5]
par = a.slice_before(sum: -2) do |elem, state|
state[:sum] += 1
state[:sum] == 2
end.to_a
par
# => [["a", "b", 3], ["c", 5]]
For your particular case, 'pyper' gem is usable:
require 'pyper' # gem install pyper if necessary
include Pyper
ary = ["a", "b", 3, "c", 5]
ary.τ3τ #=> ["a", "b", 3]
ary.τfτ #=> ["c", 5]
It only works easily on small n (number of chopped-off elements), but Pyper provides many other frequently encountered tasks on collections. It was inspired by lisp's car and cdr functions (see details by an anonymous donor), and the letters can be combined together into a control string, a bit like in APL. Greek tau (τ) is used to denote methods instead of c and r, so car, cdr become τaτ, τdτ:
ary.τaτ #=> "a"
ary.τdτ #=> ["b", 3, "c", 5]
# Instead of τfτ, one can write
ary.τdddτ #=> ["c", 5]
etc.
I have a challenge, im trying to write a method that takes in an array and returns the subset and permutation of twos, including the initial array. How do I check for particular patterns in the array. For example, given this array:
[a,b,c]
subset return will be:
[a,b,c,], [a,b], [b,c], [c,a]
and I also need to check if each subset contains a particular letter. Here's my code:
def conflict_free?(a)
return a.permutation(2).to_a
end
Here's how to get the subsets you're looking for:
def subsets(a)
2.upto(a.length).flat_map {|n| a.combination(n).to_a}
end
irb(main):023:0> subsets(["a", "b", "c"])
=> [["a", "b"], ["a", "c"], ["b", "c"], ["a", "b", "c"]]
Anything else you want, you'll have to edit your question and provide more detail.
Here is a very compact and fast solution :
def conflict(a)
a.combination(2).to_a << a
end
>> [["a", "b"], ["a", "c"], ["b", "c"], ["a", "b", "c"]]
If you did want the initial array at the beginning you sacrificing a fair bit of speed. Nevertheless the best way to do it :
def conflict(a)
temp = [a]
a.combination(2).each { |com| temp << com}
temp
end
>> [["a", "b", "c"], ["a", "b"], ["a", "c"], ["b", "c"]]
If the input is not 3 then this will work :
def conflict(a)
temp = []
2.upto(a.size-1) {|i| temp += a.combination(i).to_a}
temp << a
end
The initial array can be added at the beginning or end. Above it's at the end.
Ok, i've searched the internet for answers and also searched for hours in my ruby programmer but i cant sort this out. I'm writing a script for making all sorts of combinations from elements in an array.
ar = ["a","b","c","d"]
At this point I am able to make these combinations:
["a"],["a","b"],["a","b","c"],["a","b","c","d"],["b"],["b","c"],["b","c","d"],["c"],["c","d"],["d"]
This is OK, but I can't find a way for searching these combinations, for example ["a","c"] or ["a","c","d"] or ["a","d"], etc...
For now my code looks like:
def combinaties(array)
combinaties = []
i=0
while i <= array.length-1
combinaties << array[i]
unless i == array.length-1
array[(i+1)..(array.length-1)].each{|volgend_element|
combinaties<<(combinaties.last.dup<<volgend_element)
}
end
i+=1
end
end
Functional approach (needs Ruby >= 1.9) to create the powerset of an array (except for the empty element you don't seem to need):
xs = ["a", "b", "c", "d"]
yss = 1.upto(xs.size).flat_map do |n|
xs.combination(n).to_a
end
#[
# ["a"], ["b"], ["c"], ["d"],
# ["a", "b"], ["a", "c"], ["a", "d"], ["b", "c"], ["b", "d"], ["c", "d"],
# ["a", "b", "c"], ["a", "b", "d"], ["a", "c", "d"], ["b", "c", "d"],
# ["a", "b", "c", "d"],
#]
There is a trivial correspondence (bijection) between such combinations and the numbers in [1..(2^m - 1)] (m being the array length).
Consider such a number n. It's binary representation has m digits (including leading zeros). The positions of the digits that are 1 are the indices of the elements in the corresponding combination.
The code would be:
def combinations(array)
m = array.length
(1...2**m).map do | n |
(0...m).select { | i | n[i] == 1 }.map { | i | array[i] }
end
end
Or in ruby 1.9
%w(a b c d e).combination(3).to_a
will give you all the combinations of size 3.
Given array [a, b, c, d, e, f]
I want to match each letter with any other letter except itself, resulting in something like:
a - c
b - f
d - e
The catch is that each letter may be restricted to being matched with one or more of the other letters.
So let's say for example,
a cannot be matched with c, d
c cannot be matched with e, f
e cannot be matched with a
Any guidance on how to go about this? I'm using Ruby, but any pseudo code would be helpful.
Thanks!
The problem you are describing is a graph problem called maximum matching (or more specifically perfect matching). The restrictions correspond to vertexes in the graph that do not have a line between them.
You can use Edmond's matching algorithm.
Let's assume for now that a solution exists. It may not.
Pick one of your elements, and try to match it.
If it breaks one of your rules, try again until you do.
Choose another element, and try to match that. If you run through all other elements and break a rule each time, then go back, unmatch your previous match, and try another one.
Continue until all of your elements are used up.
If you don't know whether a solution exists or not, then you'll need to keep track of your attempts and figure out when you've tried them all. Or, use some checking at the beginning to see if there are any obvious contradictions in your rule set.
I'm not sure I understand the problem, but this seems to fit the question:
%w[a b c d e f].combination(2).to_a - [%w[a c],%w[a d],%w[c e],%w[c f],%w[e a]]
# => [["a", "b"], ["a", "e"], ["a", "f"], ["b", "c"], ["b", "d"], ["b", "e"], ["b", "f"], ["c", "d"], ["d", "e"], ["d", "f"], ["e", "f"]]
$letters = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j');
$exclusions = array('a' => array('e', 'd', 'c'), 'b' => array('a','b', 'c','d'));
foreach ($letters as $matching) {
foreach ($letters as $search) {
if(!in_array($search,$exclusions[$matching])){
if($search!=$matching){
$match[$matching][] = $search;
}
}
}
}
print_r($match);
The innermost EVAL could be added to the next outer one...
you can see this in action at
http://craigslist.fatherstorm.com/stackoverflow2.php