knapsack_problem_unbounded.sf 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. #!/usr/bin/ruby
  2. #
  3. ## https://rosettacode.org/wiki/Knapsack_problem/Unbounded
  4. #
  5. struct KnapsackItem {
  6. Number volume,
  7. Number weight,
  8. Number value,
  9. String name,
  10. }
  11. var items = [
  12. KnapsackItem(25, 3, 3000, "panacea")
  13. KnapsackItem(15, 2, 1800, "ichor" )
  14. KnapsackItem( 2, 20, 2500, "gold" )
  15. ]
  16. var (
  17. max_weight = 250,
  18. max_vol = 250,
  19. vsc = 1000,
  20. wsc = 10
  21. )
  22. func solve(i, w, v) is cached {
  23. return [0, []] if i.is_neg;
  24. var x = solve(i.dec, w, v);
  25. var (w1, v1);
  26. for t in (1..Inf) {
  27. var item = items[i];
  28. break if ((w1 = (w - t*item.weight)) < 0)
  29. break if ((v1 = (v - t*item.volume)) < 0)
  30. var y = solve(i.dec, w1, v1);
  31. if ((var tmp = (y[0] + t*item.value)) > x[0]) {
  32. x = [tmp, [y[1]..., [i, t]]];
  33. }
  34. }
  35. return x
  36. }
  37. var x = solve(items.end, max_weight, max_vol)
  38. print <<"EOT"
  39. Max value #{x[0]}, with:
  40. Item Qty Weight Vol Value
  41. #{"-" * 50}
  42. EOT
  43. var (wtot=0, vtot=0);
  44. x[1].each { |s|
  45. var item = items[s[0]];
  46. " #{item.name}:\t% 3d % 8d% 8g% 8d\n".printf(
  47. s[1],
  48. item.weight * s[1] / wsc,
  49. item.volume * s[1] / vsc,
  50. item.value * s[1]
  51. );
  52. wtot += (item.weight * s[1]);
  53. vtot += (item.volume * s[1]);
  54. }
  55. print <<"EOT"
  56. #{"-" * 50}
  57. Total:\t #{"%8d%8g%8d" % (wtot/wsc, vtot/vsc, x[0])}
  58. EOT