/* This file is part of Eternity II Editor. * * Eternity II Editor is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Eternity II Editor is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Eternity II Editor. If not, see <http://www.gnu.org/licenses/>. * * Eternity II Editor project is hosted on SourceForge: * http://sourceforge.net/projects/eternityii/ * and maintained by Yannick Kirschhoffer <alcibiade@alcibiade.org> */ package org.alcibiade.eternity.editor.solver.collection; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.SortedSet; import java.util.TreeSet; import org.alcibiade.eternity.editor.solver.RandomFactory; public class WeightedSet<T extends Comparable<T>> { // Items in decreasing weight order private SortedSet<WeightedItem> items = new TreeSet<WeightedItem>(); public void put(T item, int weight) { items.add(new WeightedItem(item, weight)); } public boolean isEmpty() { return items.isEmpty(); } public int size() { return items.size(); } public T getFirst() { return items.first().getItem(); } public T pickRandomBest() { int bestWeight = items.first().getWeight(); List<T> bestItems = new ArrayList<T>(); for (WeightedItem item : items) { if (item.getWeight() == bestWeight) { bestItems.add(item.getItem()); } else { break; } } Random random = RandomFactory.getRandom(); int randIndex = random.nextInt(bestItems.size()); T result = bestItems.get(randIndex); return result; } public T pickRandom() { T result = null; Random random = RandomFactory.getRandom(); int totalWeight = computeTotalWeight(); int target = random.nextInt(totalWeight); for (WeightedItem item : items) { target -= item.getWeight(); result = item.getItem(); if (target < 0) { break; } } return result; } private int computeTotalWeight() { int total = 0; for (WeightedItem item : items) { total += item.getWeight(); } return total; } private class WeightedItem implements Comparable<WeightedItem> { private T item; private int weight; public WeightedItem(T item, int weight) { super(); this.item = item; this.weight = weight; } public T getItem() { return item; } public int getWeight() { return weight; } @Override public int compareTo(WeightedItem o) { int result = o.weight - weight; if (result == 0) { result = item.compareTo(o.item); } return result; } } @Override public String toString() { StringBuilder text = new StringBuilder(); text.append("WeightedSet{"); for (WeightedItem item : items) { text.append(item.getItem()); text.append(":"); text.append(item.getWeight()); text.append(", "); } text.append("}"); return text.toString(); } }