Task: Knapsack problem_0-1






PHP: #########################################################
# 0-1 Knapsack Problem Solve with memoization optimize and index returns
# $w = weight of item
# $v = value of item
# $i = index
# $aW = Available Weight
# $m = Memo items array
# PHP Translation from Python, Memoization,
# and index return functionality added by Brian Berneker
#
#########################################################

function knapSolveFast2($w, $v, $i, $aW, &$m) {

	global $numcalls;
	$numcalls ++;


	if (isset($m[$i][$aW])) {
		return array( $m[$i][$aW], $m['picked'][$i][$aW] );
	} else {

		if ($i == 0) {
			if ($w[$i] <= $aW) { // Will this item fit?
				$m[$i][$aW] = $v[$i]; // Memo this item
				$m['picked'][$i][$aW] = array($i); // and the picked item
				return array($v[$i],array($i)); // Return the value of this item and add it to the picked list

			} else {

				$m[$i][$aW] = 0; // Memo zero
				$m['picked'][$i][$aW] = array(); // and a blank array entry...
				return array(0,array()); // Return nothing
			}
		}	


		list ($without_i, $without_PI) = knapSolveFast2($w, $v, $i-1, $aW, $m);

		if ($w[$i] > $aW) { // Does it return too many?
			
			$m[$i][$aW] = $without_i; // Memo without including this one
			$m['picked'][$i][$aW] = $without_PI; // and a blank array entry...
			return array($without_i, $without_PI); // and return it

		} else {

			list ($with_i,$with_PI) = knapSolveFast2($w, $v, ($i-1), ($aW - $w[$i]), $m);
			$with_i += $v[$i];  // ..and add the value of this one..

			if ($with_i > $without_i) {
				$res = $with_i;
				$picked = $with_PI;
				array_push($picked,$i);
			} else {
				$res = $without_i;
				$picked = $without_PI;
			}
						
			$m[$i][$aW] = $res; // Store it in the memo
			$m['picked'][$i][$aW] = $picked; // and store the picked item
			return array ($res,$picked); // and then return it
		}	
	}
}



$items4 = array("map","compass","water","sandwich","glucose","tin","banana","apple","cheese","beer","suntan cream","camera","t-shirt","trousers","umbrella","waterproof trousers","waterproof overclothes","note-case","sunglasses","towel","socks","book");
$w4 = array(9,13,153,50,15,68,27,39,23,52,11,32,24,48,73,42,43,22,7,18,4,30);
$v4 = array(150,35,200,160,60,45,60,40,30,10,70,30,15,10,40,70,75,80,20,12,50,10);

## Initialize
$numcalls = 0; $m = array(); $pickedItems = array();

## Solve
list ($m4,$pickedItems) = knapSolveFast2($w4, $v4, sizeof($v4) -1, 400, $m);

# Display Result 
echo "<b>Items:</b><br>".join(", ",$items4)."<br>";
echo "<b>Max Value Found:</b><br>$m4 (in $numcalls calls)<br>";
echo "<b>Array Indices:</b><br>".join(",",$pickedItems)."<br>";


echo "<b>Chosen Items:</b><br>";
echo "<table border cellspacing=0>";
echo "<tr><td>Item</td><td>Value</td><td>Weight</td></tr>";
$totalVal = $totalWt = 0;
foreach($pickedItems as $key) {
	$totalVal += $v4[$key];
	$totalWt += $w4[$key];
	echo "<tr><td>".$items4[$key]."</td><td>".$v4[$key]."</td><td>".$w4[$key]."</td></tr>";
}
echo "<tr><td align=right><b>Totals</b></td><td>$totalVal</td><td>$totalWt</td></tr>";
echo "</table><hr>";






Ada: with Ada.Text_IO;
with Ada.Strings.Unbounded;

procedure Knapsack_01 is
   package US renames Ada.Strings.Unbounded;

   type Item is record
      Name   : US.Unbounded_String;
      Weight : Positive;
      Value  : Positive;
      Taken  : Boolean;
   end record;

   type Item_Array is array (Positive range <>) of Item;

   function Total_Weight (Items : Item_Array; Untaken : Boolean := False) return Natural is
      Sum : Natural := 0;
   begin
      for I in Items'Range loop
         if Untaken or else Items (I).Taken then
            Sum := Sum + Items (I).Weight;
         end if;
      end loop;
      return Sum;
   end Total_Weight;

   function Total_Value (Items : Item_Array; Untaken : Boolean := False) return Natural is
      Sum : Natural := 0;
   begin
      for I in Items'Range loop
         if Untaken or else Items (I).Taken then
            Sum := Sum + Items (I).Value;
         end if;
      end loop;
      return Sum;
   end Total_Value;

   function Max (Left, Right : Natural) return Natural is
   begin
      if Right > Left then
         return Right;
      else
         return Left;
      end if;
   end Max;

   procedure Solve_Knapsack_01 (Items : in out Item_Array;
                                Weight_Limit : Positive := 400) is
      type W_Array is array (0..Items'Length, 0..Weight_Limit) of Natural;
      W : W_Array := (others => (others => 0));
   begin
      
      for I in Items'Range loop
         for J in 1 .. Weight_Limit loop
            if Items (I).Weight > J then
               W (I, J) := W (I - 1, J);
            else
               W (I, J) := Max (W (I - 1, J),
                                W (I - 1, J - Items (I).Weight) + Items (I).Value);
            end if;
         end loop;
      end loop;
      declare
         Rest : Natural := Weight_Limit;
      begin
         for I in reverse Items'Range loop
            if W (I, Rest) /= W (I - 1, Rest) then
               Items (I).Taken := True;
               Rest := Rest - Items (I).Weight;
            end if;
         end loop;
      end;
   end Solve_Knapsack_01;

   All_Items : Item_Array :=
     ( (US.To_Unbounded_String ("map"),                      9, 150, False),
       (US.To_Unbounded_String ("compass"),                 13,  35, False),
       (US.To_Unbounded_String ("water"),                  153, 200, False),
       (US.To_Unbounded_String ("sandwich"),                50, 160, False),
       (US.To_Unbounded_String ("glucose"),                 15,  60, False),
       (US.To_Unbounded_String ("tin"),                     68,  45, False),
       (US.To_Unbounded_String ("banana"),                  27,  60, False),
       (US.To_Unbounded_String ("apple"),                   39,  40, False),
       (US.To_Unbounded_String ("cheese"),                  23,  30, False),
       (US.To_Unbounded_String ("beer"),                    52,  10, False),
       (US.To_Unbounded_String ("suntan cream"),            11,  70, False),
       (US.To_Unbounded_String ("camera"),                  32,  30, False),
       (US.To_Unbounded_String ("t-shirt"),                 24,  15, False),
       (US.To_Unbounded_String ("trousers"),                48,  10, False),
       (US.To_Unbounded_String ("umbrella"),                73,  40, False),
       (US.To_Unbounded_String ("waterproof trousers"),     42,  70, False),
       (US.To_Unbounded_String ("waterproof overclothes"),  43,  75, False),
       (US.To_Unbounded_String ("note-case"),               22,  80, False),
       (US.To_Unbounded_String ("sunglasses"),               7,  20, False),
       (US.To_Unbounded_String ("towel"),                   18,  12, False),
       (US.To_Unbounded_String ("socks"),                    4,  50, False),
       (US.To_Unbounded_String ("book"),                    30,  10, False) );

begin
   Solve_Knapsack_01 (All_Items, 400);
   Ada.Text_IO.Put_Line ("Total Weight: " & Natural'Image (Total_Weight (All_Items)));
   Ada.Text_IO.Put_Line ("Total Value:  " & Natural'Image (Total_Value  (All_Items)));
   Ada.Text_IO.Put_Line ("Items:");
   for I in All_Items'Range loop
      if All_Items (I).Taken then
         Ada.Text_IO.Put_Line ("   " & US.To_String (All_Items (I).Name));
      end if;
   end loop;
end Knapsack_01;