knapsack_problem_0_1.sf 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. #!/usr/bin/ruby
  2. #
  3. ## https://rosettacode.org/wiki/Knapsack_problem/0-1
  4. #
  5. var raw = <<'TABLE'
  6. map, 9, 150
  7. compass, 13, 35
  8. water, 153, 200
  9. sandwich, 50, 160
  10. glucose, 15, 60
  11. tin, 68, 45
  12. banana, 27, 60
  13. apple, 39, 40
  14. cheese, 23, 30
  15. beer, 52, 10
  16. suntancream, 11, 70
  17. camera, 32, 30
  18. T-shirt, 24, 15
  19. trousers, 48, 10
  20. umbrella, 73, 40
  21. waterproof trousers, 42, 70
  22. waterproof overclothes, 43, 75
  23. note-case, 22, 80
  24. sunglasses, 7, 20
  25. towel, 18, 12
  26. socks, 4, 50
  27. book, 30, 10
  28. TABLE
  29. struct KnapsackItem {
  30. String name,
  31. Number weight,
  32. Number value,
  33. }
  34. var items = []
  35. raw.each_line{ |row|
  36. var fields = row.split(/\s*,\s*/)
  37. items << KnapsackItem(
  38. name: fields[0],
  39. weight: fields[1].to_n,
  40. value: fields[2].to_n,
  41. )
  42. }
  43. var max_weight = 400
  44. var p = [
  45. items.len.of { [[0, []], max_weight.of(nil)...] }...,
  46. max_weight.inc.of {[0, []]}
  47. ]
  48. func optimal(i, w) {
  49. if (!defined p[i][w]) {
  50. var item = items[i];
  51. if (item.weight > w) {
  52. p[i][w] = optimal(i.dec, w)
  53. }
  54. else {
  55. var x = optimal(i.dec, w)
  56. var y = optimal(i.dec, w - item.weight)
  57. if (x[0] > (y[0] + item.value)) {
  58. p[i][w] = x;
  59. }
  60. else {
  61. p[i][w] = [y[0] + item.value, [y[1]..., item.name]]
  62. }
  63. }
  64. }
  65. return p[i][w]
  66. }
  67. var sol = optimal(items.end, max_weight)
  68. say "#{sol[0]}: #{sol[1].join(' ')}"