Need help with sum of subsets

Problem Statement

  • The main goal of this task is to implement three generic functions: valid_sum, sum_of_one and sum_of_all .
  • The valid_sum is kind of a helper function which will create an array of valid non-negative intergers from the given 2d matrix.
  • One of the primary functions is sum_of_one , which computes all the possible subsets from an array of non-negative integers whose sum is equal to the provided integer sum.
  • Next comes the final function which is sum_of_all. This function computes all the possible subsets from an array of non-negative integers whose sum is equal to all valid non-negative integer elements from the given 2d matrix.

actually I’m getting these errors in test

Compiling 1 file (.ex)


  1) test check all expected sum of subsets for given array and matrix of sum (Task1aSumOfSubsetsTest)
     test/task1a_sum_of_subsets_test.exs:110
     ** (ArgumentError) the Access calls for keywords expect the key to be an atom, got: 12
     code: Enum.map(expected_sum_of_all_matrix,  fn ({k, v}) -> checkThreeCondtions(sum_of_all_result[k],k,array_of_digits,v) end)
     stacktrace:
       (elixir 1.13.4) lib/access.ex:310: Access.get/3
       test/task1a_sum_of_subsets_test.exs:156: anonymous fn/2 in Task1aSumOfSubsetsTest."test check all expected sum of subsets for given array and matrix of sum"/1
       (elixir 1.13.4) lib/enum.ex:1597: anonymous fn/3 in Enum.map/2
       (stdlib 4.0) maps.erl:411: :maps.fold_1/3
       (elixir 1.13.4) lib/enum.ex:2408: Enum.map/2
       test/task1a_sum_of_subsets_test.exs:156: (test)

.

  2) test checks all the expected sum of subsets for given array with one element as zero and matrix of sum (Task1aSumOfSubsetsTest)
     test/task1a_sum_of_subsets_test.exs:162
     ** (ArgumentError) the Access calls for keywords expect the key to be an atom, got: 12
     code: Enum.map(expected_sum_of_all_matrix,  fn ({k, v}) -> checkThreeCondtions(sum_of_all_result[k], k , array_of_digits,v) end)
     stacktrace:
       (elixir 1.13.4) lib/access.ex:310: Access.get/3
       test/task1a_sum_of_subsets_test.exs:206: anonymous fn/2 in Task1aSumOfSubsetsTest."test checks all the expected sum of subsets for given array with one element as zero and matrix of sum"/1
       (elixir 1.13.4) lib/enum.ex:1597: anonymous fn/3 in Enum.map/2
       (stdlib 4.0) maps.erl:411: :maps.fold_1/3
       (elixir 1.13.4) lib/enum.ex:2408: Enum.map/2
       test/task1a_sum_of_subsets_test.exs:206: (test)

..

  3) test check valid sum for the given matrix (Task1aSumOfSubsetsTest)
     test/task1a_sum_of_subsets_test.exs:40
     Assertion with == failed
     code:  assert Task1aSumOfSubsets.valid_sum(matrix_of_sum) == expected_list_of_valid_sums
     left:  []
     right: [21, 12, 12, 17, 22]
     stacktrace:
       test/task1a_sum_of_subsets_test.exs:49: (test)

...

Finished in 0.1 seconds (0.00s async, 0.1s sync)
9 tests, 3 failures

Randomized with seed 206453

(note: I fixed the formatting on the original post, the opening ``` was missing)

For the first two errors, it’s hard to say for certain - but that error message is what happens when you try to index into a list like it’s an array in other languages:

iex(3)> b = [1,2,3]
[1, 2, 3]

iex(4)> b[12]
** (ArgumentError) the Access calls for keywords expect the key to be an atom, got: 12
    (elixir 1.14.0) lib/access.ex:313: Access.get/3
    iex:4: (file)

My guess is that sum_of_all_result is not a map like those tests expect.

For the last error, it’s impossible to even speculate without seeing some code; all the test tells us is that the results don’t match expectations.

2 Likes

here is my code

defmodule Task1aSumOfSubsets do
       @spec valid_sum(maybe_improper_list) :: list
       def valid_sum([]), do: []

       def valid_sum(list) when is_list(list) do
         Enum.filter(list, fn element -> is_integer(element) and element > 0 end)
       end

       def sum_of_one(list, provided_integer_sum, list_sanitizer \\ &valid_sum/1)
       def sum_of_one([], _, _), do: []

       def sum_of_one(list, provided_integer_sum, list_sanitizer) do
         sanitized_list = list_sanitizer.(list)
         combinations = _combinations(sanitized_list)

         Enum.filter(
           combinations,
           fn e -> List.flatten(e) |> Enum.sum() == provided_integer_sum end
         )
       end

       defp _combinations(list) do
         List.foldl(
           Enum.to_list(1..length(list)),
           [],
           fn length, acc -> acc ++ _combinations(list, length) end
         )
       end

       defp _combinations(list, 1), do: for(e <- list, do: [e])

       defp _combinations(list, length) when length(list) == length, do: [list]

       defp _combinations([h | t], length) do
         for(sub_sum <- _combinations(t, length - 1), do: [h | sub_sum]) ++ _combinations(t, length)
       end

       def sum_of_all(list, matrix_2d, list_sanitizer \\ &valid_sum/1) do
         calculated_integer_sum = list_sanitizer.(matrix_2d) |> Enum.sum()
         sum_of_one(list, calculated_integer_sum)
       end
end

hi @SRIVATSAV11! friendly tip: don’t call anything you pretty much copied from elsewhere, “yours” :slight_smile:
you will go further with people this way. :wink:

For the first two failures, it’s still impossible to tell exactly what’s wrong - there’s no direct connection between the failing line:

Enum.map(expected_sum_of_all_matrix,  fn ({k, v}) -> checkThreeCondtions(sum_of_all_result[k],k,array_of_digits,v) end)

and the module’s code you posted. Presumably sum_of_all_result is computed using sum_of_all, but it’s not clear how. My guess is that expected_sum_of_all_matrix is a Map, and that sum_of_all_result is also supposed to be a Map. The posted sum_of_all can’t return a map, though… :thinking:

There’s a slight connection to the posted code in the third failure: a call to valid_sum. It’s hard to say exactly what’s wrong without knowing more about what’s in matrix_of_sum, but one thing that stands out is the naming. What shape are these things named “matrix” supposed to be?

Purpose Finds the all possible subsets from given array of digits for a 2 digit sum value
Input Arguments array_of_digits : Array containing single digit numbers to satisty sum value sum_val : Any 2 digit value for which subsets are to be created
Return List of list of all possible subsets. If no possible subsets exists then return empty list
Example Call Task1aSumOfSubsets.sum_of_one(array_of_digits, 10)
  • Note that the function can have multiple valid solutions. The conditions for VALID solution are as follows:
    • Sum of individual subset in the solution should be equal to sum_val provided to the function
      Eg. array_of_digits=[6,2,3,4,5,2,1] and sum_val is 10
      Few possible VALID subsets are [6,4] , [5,2,3], [4,1,2,3]
      INVALID subsets that does not satisfy the condition: [6,5] [5,4,3]
    • Occurrences of individual numbers within a subset should be less than or equal to occurrences of the number in the array_of_digits
      Eg. array_of_digits=[6,2,3,4,5,2,3,1,1] and sum_val is 10
      Few possible VALID subsets are [2,2,3,3], [4,1,2,3]
      INVALID subset that does not satisfy the second condition: [4,1,4,1] (Even though the sum turns out to be 10, 4 doesn’t occur twice in the array_of_digits )
    • At least one unique permutation of the each individual VALID subsets should exists.
      Eg. array_of_digits=[6,2,3,4,5,2,1] and sum_val is 10
      Few VALID Solutions are:
      [[5,4,1],[5,3,2],[5,2,2,1],[6,4],[6,2,2],[6,3,1],[2,3,4,1]]
      [[5,4,1],[5,3,2],[3,5,2],[5,2,2,1],[4,6],[6,2,2],[1,6,3],[6,1,3],[2,3,4,1]]
      INVALID solution that does not satisfy the condition: [[5,4,1],[5,3,2],[5,2,2,1],[6,4],[6,3,1],[2,3,4,1]] (It’s missing [6,2,2])
  • For example, if the following commands are executed, the output for the above function should be the same as shown below:
iex(1)> array_of_digits = [3, 5, 2, 7, 4, 2, 3]
iex(2)> Task1aSumOfSubsets.sum_of_one(array_of_digits, 10)
[[3, 7], [3, 2, 5], [3, 2, 5], [3, 4, 3], [7, 3], [3, 2, 2, 3], [2, 5, 3], [2, 5, 3]]

iex(3)> array_of_digits = [3, 5, 2, 7, 4, 2, 3]           
iex(4)> Task1aSumOfSubsets.sum_of_one(array_of_digits, 10)
[[3, 7], [3, 2, 5], [3, 4, 3], [3, 2, 2, 3]]

iex(5)> array_of_digits = [3, 5, 2, 7, 4]                 
iex(6)> Task1aSumOfSubsets.sum_of_one(array_of_digits, 10)
[[7, 3], [2, 5, 3], [5, 3, 2], [3, 2, 5], [3, 7]]

iex(7)> array_of_digits = [3, 5, 2, 7, 4]                 
iex(8)> Task1aSumOfSubsets.sum_of_one(array_of_digits, 10)
[[7, 3], [2, 5, 3]]

@SRIVATSAV11 based on the full problem statement posted here I don’t think the code in sum_for_all from fmn’s repo is correct; the return type expected from sum_of_one (list of lists of integers) is quite different from the one expected from sum_of_all (map with integers as keys and lists of lists of integers as values).

Given that this is asking for help with some homework, I will only give some hints for one possible solution.

There are only two possible choices for each element in the list: either to add it to the sum, or ignore it. This can be easily translated into a binary question, and we can use 0s and 1s to represent the answer. For example,

say the input list is [0, 1, 2], and the representation is 101, then it means to take 0 and 2 from the input list. If we don’t take any elements, then the representation is 000. If we are going to take all elements in the input list, the representation will be 111.