defmodule KnapsackProblem do def price_per_weight( items ), do: (for {name, weight, price} <-items, do: {name, weight, price / weight} ) def select( max_weight, items ) do {_remains, selected_items} = List.foldr( List.keysort(items, 2), {max_weight, []}, &select_until/2 ) selected_items end def task( max_weight, items ) do IO.puts "The robber takes the following to maximize the value" for {name, weight} <- select( max_weight, price_per_weight(items) ), do: :io.fwrite("~.2f of ~s~n", [weight, name]) end defp select_until( {name, weight, _price}, {remains, acc} ) when remains > 0 do selected_weight = select_until_weight( weight, remains ) {remains - selected_weight, [{name, selected_weight} | acc]} end defp select_until( _item, acc ), do: acc defp select_until_weight( weight, remains ) when weight < remains, do: weight defp select_until_weight( _weight, remains ), do: remains end items = [ {"beef", 3.8, 36}, {"pork", 5.4, 43}, {"ham", 3.6, 90}, {"greaves", 2.4, 45}, {"flitch", 4.0, 30}, {"brawn", 2.5, 56}, {"welt", 3.7, 67}, {"salami", 3.0, 95}, {"sausage", 5.9, 98} ] KnapsackProblem.task( 15, items )