package com.shekhargulati.tadm.ch03; import java.util.*; /** * <p>In the bin-packing problem, we are given n metal objects, each weighing between zero and one kilogram. * Our goal is to find the smallest number of bins that will hold the n objects, with each bin holding one kilogram at most.</p> * <p> * <p>* The best-fit heuristic for bin packing is as follows. Consider the objects in the order in which they are given. * For each object, place it into the partially filled bin with the smallest amount of extra room after the object is inserted. * If no such bin exists, start a new bin. Design an algorithm that implements the best-fit heuristic * (taking as input the n weights w1,w2,...,wn and outputting the number of bins used) in O(n log n) time.</p> * <p> * <p>* Repeat the above using the worst-fit heuristic, where we put the next object in the partially filled bin with the * largest amount of extra room after the object is inserted.</p> */ public class Problem3_10 { public static void main(String[] args) { Problem3_10 p = new Problem3_10(); // System.out.println(p.numberOfBins(new int[]{100, 200, 600, 500, 400, 1000})); // System.out.println(p.numberOfBins(new int[]{100, 200, 600, 500, 400, 1000})); int bestCaseBins = p.numberOfBins_bestCase(new int[]{500, 600, 300, 500}); int worstCaseBins = p.numberOfBins_worstCase(new int[]{500, 600, 300, 500}); System.out.println("best case: " + bestCaseBins); System.out.println("worst case: " + worstCaseBins); } public int numberOfBins_bestCase(int[] weights) { return numberOfBins(weights, (b1, b2) -> b1.remaining() - b2.remaining()); } public int numberOfBins_worstCase(int[] weights) { return numberOfBins(weights, (b1, b2) -> b2.remaining() - b1.remaining()); } public int numberOfBins(int[] weights, Comparator<Bin> comparator) { TreeSet<Bin> bins = new TreeSet<>(comparator); /* * Iterate over all the weights in an array * For each weight find the bin which will have least remaining space after weight is put * If the bin is found then update its data * else create a new bin and add it to the set */ for (int weight : weights) { Optional<Bin> foundBin = Optional.empty(); if (!bins.isEmpty()) { foundBin = findBin(bins, weight); } if (foundBin.isPresent()) { foundBin.get().updateCurrentConsumption(weight); } else { bins.add(new Bin(weight)); } } return bins.size(); } private Optional<Bin> findBin(TreeSet<Bin> bins, int weight) { return bins.stream().filter(b -> b.remaining() >= weight).findFirst(); } } class Bin { final int max = 1000; int currentConsumption = 0; List<Integer> weights = new ArrayList<>(); public Bin(int currentConsumption) { weights.add(currentConsumption); this.currentConsumption = currentConsumption; } public Bin updateCurrentConsumption(int weight) { if (this.remaining() - weight >= 0) { this.currentConsumption += weight; weights.add(weight); } return this; } public int remaining() { return this.max - this.currentConsumption; } }