#+title: Task 4: [Exam 2022.08 (ITET/MATH/PHYS/RW)] Mini-Knapsack

#+author: JirR02
* Note
:PROPERTIES:
:CUSTOM_ID: note
:END:
I don't know if we have to solve this task recursively or not. It is in
the topic of week but the task does not state this explicitly.

* Task Description
:PROPERTIES:
:CUSTOM_ID: task-description
:END:
As part of a promotion of the local supermarket, you are allowed to get
exactly two items for free. You want to maximize the value of the items
you take, but you need to take the weight limit of your backpack into
account.

You get two integer vectors, one with the value of every item, and one
with its weight. Return the maximum value that you can get by choosing
exactly 2 different items from the supermarket.

* Function
:PROPERTIES:
:CUSTOM_ID: function
:END:
Implement the function =best_two_elements= in =functions.h= according to
its pre- and postconditions.

*Rules*:

- The functions must satisfy their respective postconditions.
- You are not allowed to change the function signatures.
- You are not allowed to use additional libraries.

*Hint*:

- You do not need to check the pre- and postconditions (no asserts
  necessary).

* Solution
:PROPERTIES:
:CUSTOM_ID: solution
:END:
#+begin_src cpp
#pragma once

#include <vector>

using vec = std::vector<int>;

// PRE:   The vector "weights" at position i contains the weight of element
// i.
//        The vector "values" at position i contains the value of element i.
//        The vectors have the same size and always contain at least two
//        items. The value and weight of every item is > 0.
//
// POST:  Returns the sum of the value of the two items that have the most
// value,
//        while the sum of their weight is at most `weight_limit`.
//        It is not allowed to pick only one item.
//        It is also not allowed to pick an item twice, but two different
//        items must be chosen. If there are no two items that can be chosen
//        (due to exceeding weight), return 0.
//
// Example:
//  * weights: [1, 2, 2], values: [3, 1, 9], weight_limit: 3  ~~> 12;

void recursion1(int &value, int count1, int count2, const vec &values,
                const vec &weights, int weight_limit) {
  if (count2 == int(values.size()))
  return;

  if (int((values.at(count1)) + int(values.at(count2))) >= value &&
    (int(weights.at(count1)) + int(weights.at(count2))) <= weight_limit)
  value = int(values.at(count1)) + int(values.at(count2));

  recursion1(value, count1, count2 + 1, values, weights, weight_limit);
}

void recursion2(int &value, int count1, const vec &values, const vec &weights,
                int weight_limit) {
  if (count1 == (int(values.size()) - 1))
  return;

  recursion1(value, count1, count1 + 1, values, weights, weight_limit);
  recursion2(value, count1 + 1, values, weights, weight_limit);
}

int best_two_elements(const vec &values, const vec &weights, int weight_limit) {
  int value = 0;

  if (values.size() == weights.size() && values.size() >= 2 &&
    weights.size() >= 2) {
    recursion2(value, 0, values, weights, weight_limit);
  }

  return value;
}
#+end_src

--------------

Made by JirR02 in Switzerland 🇨🇭
