Combination for boolean value array

19 views
Skip to first unread message

Sapna Mishra

unread,
Feb 22, 2019, 7:36:43 AM2/22/19
to Ruby on Rails: Talk
def conditions_combination step_conditions_labels
    conditions_combination_hash = Hash.new
    1.upto(step_conditions_labels.size).flat_map do |n|
      conditions_combination = ""
      step_conditions_labels.permutation(n).map { |condition|  
        if condition.length == n
          conditions_combination += "( "
          condition.each do |condition_label|
            conditions_combination += condition_label+" && "
          end
          conditions_combination = conditions_combination.chomp(' && ')
          conditions_combination += " ) || "
        end
        conditions_combination_hash[n.to_s] = conditions_combination.chomp(' || ').chomp(' && ')   
      } 
    end
    cond = false
    condition_check = conditions_combination_hash[step_conditions_labels.length.to_s]

    if condition_check
      cond = true
    end
    return cond
  end

I have created this function 

conditions_combination_hash = conditions_combination(['true','false','true'])

which gives me different combination like this 

{"1"=>"( true ) || ( false ) || ( true )", "2"=>"( true && false ) || ( true && true ) || ( false && true ) || ( false && true ) || ( true && true ) || ( true && false )", "3"=>"( true && false && true ) || ( true && true && false ) || ( false && true && true ) || ( false && true && true ) || ( true && true && false ) || ( true && false && true )"}

Issue is now I am not able use this combination to check whether it satisfies the condition as it is consider as string class.

Tales Cione

unread,
Feb 22, 2019, 8:27:45 AM2/22/19
to rubyonra...@googlegroups.com
You probably could use something like eval. That being said, if you refactor in order to avoid this, it should lead to clearer, safer code
--
Tales.


--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-ta...@googlegroups.com.
To post to this group, send email to rubyonra...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/be2b5076-5a38-404a-a630-e7bfa9aeb30f%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Hassan Schroeder

unread,
Feb 22, 2019, 12:56:16 PM2/22/19
to rubyonrails-talk
On Fri, Feb 22, 2019 at 4:36 AM Sapna Mishra <sapna....@gmail.com> wrote:

> Issue is now I am not able use this combination to check whether it satisfies the condition as it is consider as string class.

If I saw something like that in a PR I would reject it in ~2 seconds.

What actual problem are you trying to solve?

--
Hassan Schroeder ------------------------ hassan.s...@gmail.com
twitter: @hassan
Consulting Availability : Silicon Valley or remote

Marco Antonio Almeida

unread,
Feb 22, 2019, 4:10:53 PM2/22/19
to Ruby on Rails: Talk
Hi Sapna,

This is a fun exercise to do and also to do some refactoring after I got to understand what you are aiming to do.

First of all, your code is not optimal yet. Let's look at the output of the example you gave:

{"1"=>"( true ) || ( false ) || ( true )", "2"=>"( true && false ) || ( true && true ) || ( false && true ) || ( false && true ) || ( true && true ) || ( true && false )", "3"=>"( true && false && true ) || ( true && true && false ) || ( false && true && true ) || ( false && true && true ) || ( true && true && false ) || ( true && false && true )"}

The combination of 2 and 3 have duplicated information. For example: (true && false && true) are the same as (true && true && false). I have provided a solution for what I understood from your problem below with some comments.

I am considering that you need to solve this in one method, otherwise, I would split in many different methods to make the code more clear. I am also being very cheeky here to introduce many features of the language that would make your life easier and your code much more understandable.

I hope this helps.

# Evaluate the combinations of conditions.
#
# step_conditions_labels - The Array of conditions.
#
# Examples
#
# conditions_combination(%w[true false true])
# # => {1=>true, 2=>true, 3=>false}
#
# conditions_combination(%w[true false true false true])
# # => {1=>true, 2=>true, 3=>true, 4=>false, 5=>false}
#
# Returns a hash of the evaluation of respective combinations.
def conditions_combination(step_conditions_labels)
  # Reduce the Array to the result Hash.
  step_conditions_labels.each_with_index.reduce({}) do |hash, (_, index)|
    # Update each of the Hash keys with the evalutation of the combination.
    hash.update(
      index + 1 =>
        # Eval is the way to go here as Tales mentioned, but it's a very
        # dangerous method. Be careful!
        eval(
          # Array#combination is what does the trick for you. Check it out:
          # The other lines just help on building the condition String.
          step_conditions_labels
            .combination(index + 1)
            .map { |combination| "(#{combination.join(' && ')})" }
            .join(' || ')
        )
    )
  end
end
conditions_combination(%w[true false true])

Best regards,
/ Marco

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-ta...@googlegroups.com.
To post to this group, send email to rubyonra...@googlegroups.com.

Steve Alex

unread,
Feb 24, 2019, 2:58:34 AM2/24/19
to rubyonra...@googlegroups.com

I also had a little fund with this. Still not sure what the purpose of the method is but I’m assuming getting the State of an array of booleans. Maybe even, well I don’t know. When I get stuck with what should be a simple combinations of boolean, I go back to ancient methods and draw a picture!  The picture is a Decision Logic Table (DLT) or Truth Table.

Basically if you have an array of N booleans, there are:
 
    2**N combinations

An array with 2 booleans has 2**2 or 4 combinations of 2 variables

  a  yynn
  b  ynyn


An array with 3 booleans has 2**3 or 8 combinations of 3 variables

  a  yyyynnnn
  b  yynnyynn
  c  ynynynyn

An array with 5 booleans has 2**5 or 32 combinations of 5 variables

  a  yyyyyyyyyyyyyyyynnnnnnnnnnnnnnnn
  b  yyyyyyyynnnnnnnnyyyyyyyynnnnnnnn
  c  yyyynnnnyyyynnnnyyyynnnnyyyynnnn
  d  yynnyynnyynnyynnyynnyynnyynnyynn
  e  ynynynynynynynynynynynynynynynyn

Your really don’t want to write and IF statement with 32 combinations! Your example output seemed to be doing some shortcut with OR conditions. Below is a short class I threw together (I did have to go find some old stuff I had written about DLTs [http://stevealex.us/code/2010/08/10/AFOLDS-DAD-DUEL.html]) that return all possible options (not using  OR)

class Truth

  def give_me_the_truth(array)
    # return array of arrays by size of input array
    indexes = array.count
    combos = 2 ** indexes
    truth =  Array.new(indexes,Array.new)
    indexes.times do |v|
      half = (2 ** (indexes - (v-1))/2)
      pick = Array.new(half/2,true)+ Array.new(half/2,false)
      (combos/half).times do |c|
        truth[v] += pick
      end
    end
    truth
  end

  def the_whole_truth(array)
    # returns an array of arrays by size of all possibilites (states?)
    whole = give_me_the_truth(array).transpose
  end

  def nothing_but_the_truth(array)
    # returns the index (state?) of a query
    nothing = the_whole_truth(array).index(array)
  end

end

Truth.new.give_me_the_truth([true,false,true])
=> [[true, true, true, true, false, false, false, false], [true, true, false, false, true, true, false, false], [true, false, true, false, true, false, true, false]]

Gives the possible combination in three arrays (if you need a hash just map it)

Truth.new.the_whole_truth([true,false,true])
=> [[true, true, true], [true, true, false], [true, false, true], [true, false, false], [false, true, true], [false, true, false], [false, false, true], [false, false, false]]

Give the 8 possible conditions as a transposed array.

Truth.new.nothing_but_the_truth([true,false,true])
=> 2

Gives an index into were that array is in the whole truth array.

Not sure if it has any use, 

Steve

Sapna Mishra

unread,
Feb 25, 2019, 12:09:28 AM2/25/19
to Ruby on Rails: Talk
Hello Marco,

Thank you for replying to the query with detailed explanation. This is what I wanted to do in my code but the code was not clear but you tried to understand my issue and provided the solution so thanks for that. I was not aware with the combination method before.
Reply all
Reply to author
Forward
0 new messages