@Test public void testNextSetBit() { BitSet bitSet = new BitSet(NUM_BITS); assertEquals(-1, bitSet.nextSetBit(0)); bitSet.set(3); assertEquals(3, bitSet.nextSetBit(0)); assertEquals(3, bitSet.nextSetBit(2)); assertEquals(3, bitSet.nextSetBit(3)); assertEquals(-1, bitSet.nextSetBit(4)); bitSet.set(5); bitSet.set(7); assertEquals(5, bitSet.nextSetBit(4)); assertEquals(5, bitSet.nextSetBit(5)); assertEquals(7, bitSet.nextSetBit(6)); bitSet.set(64); assertEquals(64, bitSet.nextSetBit(8)); assertEquals(64, bitSet.nextSetBit(63)); assertEquals(64, bitSet.nextSetBit(64)); assertEquals(-1, bitSet.nextSetBit(65)); assertEquals(-1, bitSet.nextSetBit(NUM_BITS - 1)); }
@Test public void testNextBitSetRandom() { RandomGenerator random = RandomManager.getRandom(); for (int i = 0; i < 100; i++) { BitSet bitSet = new BitSet(NUM_BITS); for (int j = 0; j < 20 + random.nextInt(50); j++) { bitSet.set(random.nextInt(NUM_BITS)); } int from = random.nextInt(NUM_BITS); int nextSet = bitSet.nextSetBit(from); if (nextSet == -1) { for (int j = from; j < NUM_BITS; j++) { assertFalse(bitSet.get(j)); } } else { for (int j = from; j < nextSet; j++) { assertFalse(bitSet.get(j)); } assertTrue(bitSet.get(nextSet)); } } }
double minimumSpend() { final Search<State> search = new AStarSearch<>( state -> { final BitSet itemsToBuy = state.itemsToBuy; if (itemsToBuy.isEmpty()) return state.store.goStorePrice(home); int itemsMinPrice = 0; for (int index = itemsToBuy.nextSetBit(0); index >= 0; index = itemsToBuy.nextSetBit(index + 1)) itemsMinPrice += items.get(index).getMinPrice(); final double goHomePrice = state.store.goStorePrice(home); return itemsMinPrice + goHomePrice; }); final double minimumSpend = search .search( new StateSpaceSearchProblem<State>() { @Override public Iterable<State> initialStates() { final BitSet itemsToBuy = new BitSet(items.size()); itemsToBuy.set(0, items.size()); return Collections.singleton(new State(itemsToBuy, home, false, -1)); } @Override public boolean isGoal(final State state) { return state.itemsToBuy.isEmpty(); } @Override public Iterable<ActionStatePair<State>> successor(final State state) { final Store stateStore = state.store; final BitSet stateItemsToBuy = state.itemsToBuy; if (stateStore == home) return stores .stream() .filter(store -> store != home) .map( store -> new ActionStatePair<>( new BuyAndGo(home.goStorePrice(store)), new State(stateItemsToBuy, store, false, -1))) .collect(Collectors.toList()); final ArrayList<ActionStatePair<State>> successors = new ArrayList<>(); final Store.Item[] storeItems = stateStore.items; for (int storeItemIndex = state.lastBought + 1, storeItemsLength = storeItems.length; storeItemIndex < storeItemsLength; storeItemIndex++) { final Store.Item storeItem = storeItems[storeItemIndex]; final Item item = storeItem.item; final int itemIndex = item.index; if (stateItemsToBuy.get(itemIndex)) { final BitSet itemsToBuy3 = stateItemsToBuy.cloneClear(itemIndex); final short price = storeItem.price; final double goHomePrice = stateStore.goStorePrice(home); if (itemsToBuy3.isEmpty()) return Collections.singleton( new ActionStatePair<>( new BuyAndGo(price + goHomePrice), new State(itemsToBuy3, home, false, -1))); final boolean hasPerishable3 = state.hasPerishable || item.perishable; for (int i = 0, storesSize = stores.size() - 1; i < storesSize; i++) { final Store store3 = stores.get(i); if (stateStore == store3) successors.add( new ActionStatePair<>( new BuyAndGo((double) price), new State( itemsToBuy3, store3, hasPerishable3, storeItemIndex))); else if (hasPerishable3) successors.add( new ActionStatePair<>( new BuyAndGo(price + goHomePrice + home.goStorePrice(store3)), new State(itemsToBuy3, store3, false, -1))); else successors.add( new ActionStatePair<>( new BuyAndGo(price + stateStore.goStorePrice(store3)), new State(itemsToBuy3, store3, false, -1))); } } } return successors; } }) .stream() .mapToDouble(Action::cost) .sum(); System.out.println("States explored: " + search.statesExplored()); return minimumSpend; }