Link to home
Start Free TrialLog in
Avatar of PHIL Sawyer
PHIL SawyerFlag for United Kingdom of Great Britain and Northern Ireland

asked on

Array filtering

Hi
I have an array of numbers and want to find the numbers that can add up to the max number in the array if possible.
E.g.
my_array=[2,4,5,7,10,24,50]
So, my max number = 50 and the numbers that can add up to 50 are [4,5,7,10,24] … is this possible and how?
Regards
Avatar of Gertone (Geert Bormans)
Gertone (Geert Bormans)
Flag of Belgium image

so you need the maximum from the array?
And then you need all the sets that add up to the max number?
Or would there only be one set?
Avatar of PHIL Sawyer

ASKER

Yes need maximum from array and yes there could be more than one set - for example...
myarray=[25,15,60,50,2,50,100]
possible answers …
[50,50],[25,15,60] … both arrays add up to maximum in myarray

Regards
interesting, sounds you need some sort of a recursive solution, let me think of an algorithm
sounds interesting
arr = [25,15,60,50,2,50,100]

arr_max = arr.max()

def find_graph(arr_local, arr_res, mx)
  arr_local.each_index do |i|
    new_arr_local = arr_local.values_at(i + 1 .. (arr_local.length - 1))
    new_arr_res = arr_res + arr_local.values_at(i)
    new_mx = mx - arr_local.values_at(i)[0]
    if new_mx == 0 then
      puts new_arr_res
      puts "-"
    elsif new_mx > 0 and new_arr_local.length > 0 then
      find_graph(new_arr_local, new_arr_res, new_mx)
    end
  end
end

find_graph(arr, Array.new(), arr_max)

Open in new window

the find_graph is a recursive method that returns all the arrays that comply

you likely need to tweek it so
puts new_arr_res

Open in new window

actually returns an array instead of a stringified one

but the logic works well
tested some edgecases

eg. arr = [1,1,1,1,1,1,1,1,1,1,3] gives quiet a few combinations, no I don't test for unique ones ;-)
Hi Gertone
This is very good - I tested it and works great. One other question if I may - say I have 2 arrays as per the following:
ma1=[1,2,3,4,5,6,7]
ma2=[25,15,60,50,2,50,100]
.. your code working on ma2 would not include the number 2 - so, what if I now wanted to show the 2 arrays (ma1 & ma2a) as per the following:
ma1=[1,2,3,4,5,6,7]
ma2a=[null,null,null,null,2,null,null]
.. what I am now trying to achieve are the numbers that do not make up the sum of the max in array ma2.
Hope I am not asking too much.
Regards
will look into this later
Two questions
- what happens when ma2=[25,15,60,50,2,50,100]? Two result sets, what is null?
- why ma1? non null members of ma2a need to be in ma1?
Hi Gertone
OK - here is what I am trying to achieve. I already have a connection to sql server using the DBI.connect etc.
Eg
##connection string etc
sth = conn.execute("SELECT ID, Values FROM Products")
ma1=[]
ma2=[]
   sth.fetch do |row|
   ma1<<row[0]
   ma2<<row[1]
   end
   sth.finish
………………...……..etc
In one of the columns there is an ID and the other column are values. Some ID's have 2 or more values and this is where I am trying to identify any value that that does or does not sum up to the max value for any given ID.

Below are the values returned to arrays ma1 & ma2 ….now I need another array that is my identifier (True or False) - let's call it ma3
The True value is a value that can be used as part of the sum that adds up to the max in any given ID (the max in any ID is always True)
ma1   ma2        ma3
ID      Value      Identifier
1        25           True
1        15           True
1        60           True
1        50           True
1          2           False
1       50           True
1     100           True   ## the max for ID 1

2        4            True
2        6            True ## the max for ID 2
2        2            True
2        5            False
2        5            False

Once I have the ma3 array I can then load this back into a table in SQL server database.
Note: the above is a simple data set example as some ID's can have 100s or values

Hopefully this makes more sense
Regards
Bit vague Phil, do you imply that you basically have two fields of a database table stored each in an array and expect the ruby code to actually align them?
It feels like a better approach would be
- forget about ma1
- make a first query to get a set of unique ids from the database (a condensed version of ma1)
- iterate over this set of unique ids and query for all the value fields for this particular id (a smaller ma2 that would be)
- do the magic of the graph function, altered to create a new false/true array in sync... although that should not be a new array, find_graph() creates all the summation true arrays, you can linearize that into one array and use it as a lookup when writing back to the database

That is I guess the approach I would take if I understand your issue well enough.
All this sync management of long arrays based on indexes is not good
Hi Gertone
OK - I sort of get what you are saying but how can I change your magic graph function to return only values that don't get used in the sum of max value.
Eg
arr = [25,15,12,13] … your function returns #
25
-
12
13
-

which is great - but how can I change it to return …. [null,15,null,null].. this way I only get the value/s which are not used in the sum of max.

Regards

Regards
pass an array where you pussh all the valid arrays, flatten the result into a single array

after that you can use a map to fill a new array... but better, write directly to the database there

arr = [25,15,12,13]

arr_max = arr.max()
arr_end = Array.new()

def find_graph(arr_local, arr_res, mx, arr_e)
  arr_local.each_index do |i|
    new_arr_local = arr_local.values_at(i + 1 .. (arr_local.length - 1))
    new_arr_res = arr_res + arr_local.values_at(i)
    new_mx = mx - arr_local.values_at(i)[0]
    if new_mx == 0 then
      arr_e.push(new_arr_res)
    elsif new_mx > 0 and new_arr_local.length > 0 then
      find_graph(new_arr_local, new_arr_res, new_mx, arr_e)
    end
  end
end

find_graph(arr, Array.new(), arr_max, arr_end)
arr_end.flatten!()
arr.map! { |x|
  if arr_end.find_index(x) != nil then true
    else false
  end
}

Open in new window

Hi
When I use … find_graph(arr, Array.new(), arr_max, arr_end) at the end of your new code I get an error...
 true can't be coerced into Integer (TypeError)


Regards
the arr has changed

arr.map! changes the map in place
so after this the array with numbers has gone.
it is just a mockup, you can easily change that code so it writes to a new array
but you should not call the find_graph() again
Hi Gertone
Unfortunately my Ruby is basic and I have been trying to get this to work with no success.
Regards
Hi Phil,

Currently in the middle of something. Will find time this afternoon
Many thanks but will keep trying to understand
ASKER CERTIFIED SOLUTION
Avatar of Gertone (Geert Bormans)
Gertone (Geert Bormans)
Flag of Belgium image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
so, instead of overwriting the array, this code creates an ma3 like you wanted in the first place
Thanks Gertone - great work and much appreciated