ruby 复杂的运费计算

mctunoxg  于 2023-01-16  发布在  Ruby
关注(0)|答案(2)|浏览(84)

我们的网站计算出订单的运费总额,我们数据库中的每一件商品都有一个立方体大小,而且一件商品使用快递和运费是有大小限制的。但我们收到多件商品的订单,我注意到它在不需要的时候称之为运费。
包裹限制是0.15立方米每快递票,如果大于他们必须去的运费代替。顺便说一句,运费成本较高的小托运只是因为有一个最低收费,如果没有,这将是一个问题。
我在这里问,因为我们的程序员有一个有限的时间之前,他离开这个国家,这不是我们给他的紧急任务之一,如果我们要得到它在所有然后我需要帮助他在正确的方向-但唉,我不是一个程序员。

    • 问题:**

收到一个订单,里面有两件商品,每件0.106美元,都发往一个本地地址

  • 网站称其总价格为0.212美元,运费为42美元
  • 我们可以用快递运送2盒,总共10美元

但需要只使用运费,如果任何一个项目是大于0.15的限制
因此,它将看到排序为(0.106 = $5)和(0.106 = $5)= $10
例如:
1.假设有更复杂的事情:
10件商品,每件0.02。网站会计算出0.2,称之为运费,但我们可以把它放在2个盒子里,支付10美元
1.购物车中有5件商品,分别为0.01 x 4和0.12 x 1。网站会将其计算为0.16,并称之为运费,但我们可以发送2个纸箱-0.04和0.12,成本为10美元
它能做到这一点吗:如果任何一个项目是大于0.15使它所有的运费,否则加多少票需要假设我们装进最大的箱子可能例2:

(0.01+0.01+0.01+0.01)=0.04=$5,
(0.12)=0.12=$5 
==$10

棘手的我知道,但它只是数学哈哈,它最重要的是,因为一个荒谬的航运价格可能会停止订单。

qxgroojn

qxgroojn1#

就像@AlistairIsrael说的,这是bin packing problem,解决起来并不完全是小事。
然而下面是这个问题的一个解决方案。
如果我们尝试了所有的 Package 方式组合,并试图找到最小的成本,那么我们就有了一个解决方案。注意,这个解决方案是一个蛮力解决方案,因此随着物品数量的增长,速度会很快变慢。
找到所有可能的方法将货物分入不同的箱子;我们可以使用这个答案的算法
Translating function for finding all partitions of a set from Python to Ruby
接下来,我们循环遍历所有不同的组合,寻找最小成本,求解过程如下:

> optimize_shipping([0.01, 0.01, 0.01, 0.01, 0.12])
Shipping type: courier
Total price  : $10
Packaging    : [[0.12], [0.01, 0.01, 0.01, 0.01]]

> optimize_shipping([0.01, 0.01, 0.12, 0.15, 0.12])
Shipping type: courier
Total price  : $15
Packaging    : [[0.01, 0.12], [0.15], [0.01, 0.12]]

> optimize_shipping([0.09, 0.09, 0.01, 0.12, 0.15, 0.12])
Shipping type: courier
Total price  : $25
Packaging    : [[0.12], [0.15], [0.12], [0.09, 0.01], [0.09]]

> optimize_shipping([0.01, 0.01, 0.01, 0.30])
Shipping type: freight

代码:

COURIER_LIMIT = 0.15
COURIER_PRICE = 5

class Array
  def sum
    inject(:+)
  end

  def partitions
    yield [] if self.empty?
    (0 ... 2 ** self.size / 2).each do |i|
      parts = [[], []]
      self.each do |item|
        parts[i & 1] << item
        i >>= 1
      end
      parts[1].partitions do |b|
        result = [parts[0]] + b
        result = result.reject do |e|
          e.empty?
        end
        yield result
      end
    end
  end
end

def optimize_shipping(boxes)
  if boxes.any? { |b| b > COURIER_LIMIT }
    puts "Shipping type: freight"
    return
  end

  # Try and find the cheapest most optimal combination of packaging
  smallest_box   = 9999
  cheapest_price = 9999
  cheapest_combination = []

  # Go through all paritions and find the optimal distribution
  boxes.partitions { |partition|
    # Add up sizes per box
    sizes = partition.map(&:sum)

    # Check if any box got too big for courier, and skip if so
    next if sizes.any? { |s| s > COURIER_LIMIT }

    # Calculate total price for this combination
    total_price = partition.length * COURIER_PRICE

    if total_price <= cheapest_price
      # Naive algo to try and find best average distriution of items
      next if total_price == cheapest_price && sizes.min < smallest_box

      # Save this new optimized shipment
      smallest_box         = sizes.min
      cheapest_price       = total_price
      cheapest_combination = partition
    end
  }

  puts "Shipping type: courier"
  puts "Total price  : $#{cheapest_price}"
  puts "Packaging    : #{cheapest_combination.inspect}"
end
wwtsj6pe

wwtsj6pe2#

这里没有显示代码,但基本上,你可以接受你的订单,它可能是一个集合,如数组,并执行以下操作:

orders = [0.01,0.16,0.01,0.01]
freight = orders.any? {|item| item > 0.15 }

当然,还需要更多的逻辑,但是您现在可以将运费作为true或false作为布尔值来继续所需的工作。
我相信count在这里也会成为你的朋友。

相关问题