






def       _lowerCAmelCase       (      lowerCAmelCase	,      lowerCAmelCase	,      lowerCAmelCase	,      lowerCAmelCase		):







       '''simple docstring'''
       global f  # a global dp table for knapsack
       if f[i][j] < 0:
              if j < wt[i - 1]:
                     UpperCAmelCase	    =			mf_knapsack(i - 1	,      lowerCAmelCase	,      lowerCAmelCase	,      lowerCAmelCase		)
              else:
                     UpperCAmelCase	    =			max(
                         mf_knapsack(i - 1	,      lowerCAmelCase	,      lowerCAmelCase	,      lowerCAmelCase		)	,      mf_knapsack(i - 1	,      lowerCAmelCase	,      lowerCAmelCase	,      j - wt[i - 1]		) + val[i - 1]	,      )
              UpperCAmelCase	    =			val
       return f[i][j]






def       _lowerCAmelCase       (      lowerCAmelCase	,      lowerCAmelCase	,      lowerCAmelCase	,      lowerCAmelCase		):







       '''simple docstring'''
       UpperCAmelCase	    =			[[0] * (w + 1) for _ in range(n + 1		)]

       for i in range(1	,      n + 1		):
              for w_ in range(1	,      w + 1		):
                     if wt[i - 1] <= w_:
                            UpperCAmelCase	    =			max(val[i - 1] + dp[i - 1][w_ - wt[i - 1]]	,      dp[i - 1][w_]		)
                     else:
                            UpperCAmelCase	    =			dp[i - 1][w_]

       return dp[n][w_], dp






def       _lowerCAmelCase       (      lowerCAmelCase	,      lowerCAmelCase	,      lowerCAmelCase		):







       '''simple docstring'''
       if not (isinstance(lowerCAmelCase	,      (list, tuple)		) and isinstance(lowerCAmelCase	,      (list, tuple)		)):
              raise ValueError(
                  """Both the weights and values vectors must be either lists or tuples"""		)

       UpperCAmelCase	    =			len(lowerCAmelCase		)
       if num_items != len(lowerCAmelCase		):
              UpperCAmelCase	    =			(
                  """The number of weights must be the same as the number of values.\n"""
                  F'''But got {num_items} weights and {len(lowerCAmelCase		)} values'''
              )
              raise ValueError(lowerCAmelCase		)
       for i in range(lowerCAmelCase		):
              if not isinstance(wt[i]	,      lowerCAmelCase		):
                     UpperCAmelCase	    =			(
                         """All weights must be integers but got weight of """
                         F'''type {type(wt[i]		)} at index {i}'''
                     )
                     raise TypeError(lowerCAmelCase		)

       UpperCAmelCase    ,       UpperCAmelCase	    =			knapsack(lowerCAmelCase	,      lowerCAmelCase	,      lowerCAmelCase	,      lowerCAmelCase		)
       UpperCAmelCase	    =			set()
       _construct_solution(lowerCAmelCase	,      lowerCAmelCase	,      lowerCAmelCase	,      lowerCAmelCase	,      lowerCAmelCase		)

       return optimal_val, example_optional_set






def       _lowerCAmelCase       (      lowerCAmelCase	,      lowerCAmelCase	,      lowerCAmelCase	,      lowerCAmelCase	,      lowerCAmelCase		):







       '''simple docstring'''
       # for the current item i at a maximum weight j to be part of an optimal subset,
       # the optimal value at (i, j) must be greater than the optimal value at (i-1, j).
       # where i - 1 means considering only the previous items at the given maximum weight
       if i > 0 and j > 0:
              if dp[i - 1][j] == dp[i][j]:
                     _construct_solution(lowerCAmelCase	,      lowerCAmelCase	,      i - 1	,      lowerCAmelCase	,      lowerCAmelCase		)
              else:
                     optimal_set.add(lowerCAmelCase		)
                     _construct_solution(lowerCAmelCase	,      lowerCAmelCase	,      i - 1	,      j - wt[i - 1]	,      lowerCAmelCase		)


if __name__ == "__main__":
 lowerCAmelCase_	:    Optional[Any]            =      [3, 2, 4, 4]
 lowerCAmelCase_	:    List[Any]            =      [4, 3, 2, 3]
 lowerCAmelCase_	:    Tuple            =      4
 lowerCAmelCase_	:    Optional[int]            =      6
 lowerCAmelCase_	:    Dict            =      [[0] * (w + 1)] + [[0] + [-1] * (w + 1) for _ in range(n + 1)]
 lowerCAmelCase_	:    Dict            =      knapsack(w, wt, val, n)
 print(optimal_solution)
 print(mf_knapsack(n, wt, val, w))  # switched the n and w

 # testing the dynamic programming problem with example
 # the optimal subset for the above example are items 3 and 4
 lowerCAmelCase_	:    Optional[Any]            =      knapsack_with_example_solution(w, wt, val)
 assert optimal_solution == 8
 assert optimal_subset == {3, 4}
 print('''optimal_value = ''', optimal_solution)
 print('''An optimal subset corresponding to the optimal value''', optimal_subset)








"""simple docstring"""







def       _lowerCAmelCase       (      lowerCAmelCase		):







       '''simple docstring'''
       if not isinstance(lowerCAmelCase	,      lowerCAmelCase		):
              UpperCAmelCase	    =			F'''Input value of [number={number}] must be an integer'''
              raise TypeError(lowerCAmelCase		)
       if number < 0:
              return False
       UpperCAmelCase	    =			number * number
       while number > 0:
              if number % 10 != number_square % 10:
                     return False
              number //= 10
              number_square //= 10
       return True


if __name__ == "__main__":
 import doctest

 doctest.testmod()
