I'm working on a a game where I have to generate an int array of 4 elements randomly. My problem is that the mean of all the array elements always have to be a whole number.
Example :
array 1 {4 , 2 , 3, 7} , the mean of the array is 28,75 which is not what I'm looking for,
array 2 {3 , 7 , 6 , 4} , the mean is 20 which is good
Now I could make a loop where I check if the mean of the randomly generated numbers is a whole number but that doesn't seems like an efficient way to do that.
The game I'm working for is mean sum for those who know it.
If the mean is a whole number, then the sum must be divisible by 4.
int[] n = new int[4];
Pick four numbers, and calculate their sum:
int sum = 0;
for (int i = 0; i < 4; ++i) {
sum += (n[i] = random.nextInt());
}
Calculate the remainder of sum / 4:
int r = sum % 4;
So you now need to adjust the sum so that sum % 4 == 0. You can either:
subtract r from any of the elements of the array:
n[random.nextInt(4)] -= r;
or add 4 - r to any element:
n[random.nextInt(4)] += 4 - r;
Ideone demo
Pick a target mean m and random integers n1, n2.
Your array is [m-n1, m+n1, m-n2, m+n2]. Haven't thought about what the properties of this distribution would be, but it should work.
I believe the following function does what you want, given arguments of how many values you want to generate (n) and what's an upper limit for the sum of the values (max).
private static Random r = new Random();
public static int[] makeSet(int n, int max) {
// The next line guarantees the result is divisible by n
int currentMax = n * (1 + r.nextInt(max / n));
Set<Integer> s = new HashSet<Integer>();
// Generate a set of unique values between 0 and the currentMax,
// containing those bounds
s.add(0);
s.add(currentMax);
do {
s.add(r.nextInt(currentMax));
} while(s.size() <= n);
Integer[] values = new Integer[n + 1];
/*
* Convert to array, sort the results, and find successive
* differences. By construction, those differences WILL sum
* to the currentMax, which IS divisible by the number of
* values generated by differencing!
*/
s.toArray(values);
Arrays.sort(values);
int[] results = new int[n];
for(int i = 0; i < n; ++i) {
results[i] = values[i+1] - values[i];
}
return results;
}
Related
I was asked this question in an interview -
Maximum number of chocolates to be distributed equally among k students
Given n boxes containing some chocolates arranged in a row. There are k number of students. The problem is to distribute maximum number of chocolates equally among k students by selecting a consecutive sequence of boxes from the given lot. Consider the boxes are arranged in a row with numbers from 1 to n from left to right. We have to select a group of boxes which are in consecutive order that could provide maximum number of chocolates equally to all the k students. An array arr[] is given representing the row arrangement of the boxes and arr[i] represents number of chocolates in that box at position i.
Examples:
Input : arr[] = {2, 7, 6, 1, 4, 5}, k = 3
Output : 6
The subarray is {7, 6, 1, 4} with sum 18.
Equal distribution of 18 chocolates among 3 students is 6.
Note that the selected boxes are in consecutive order with indexes {1, 2, 3, 4}.
I found the solution in Geekforgeeks --
static int maxNumOfChocolates(int arr[], int n, int k)
{
// Hash table
HashMap <Integer,Integer> um = new HashMap<Integer,Integer>();
// 'sum[]' to store cumulative sum, where
// sum[i] = sum(arr[0]+..arr[i])
int[] sum=new int[n];
int curr_rem;
// To store sum of sub-array having maximum sum
int maxSum = 0;
// Building up 'sum[]'
sum[0] = arr[0];
for (int i = 1; i < n; i++)
sum[i] = sum[i - 1] + arr[i];
// Traversing 'sum[]'
for (int i = 0; i < n; i++) {
// Finding current remainder
curr_rem = sum[i] % k;
// If true then sum(0..i) is divisible
// by k
if (curr_rem == 0) {
// update 'maxSum'
if (maxSum < sum[i])
maxSum = sum[i];
}
// If value 'curr_rem' not present in 'um'
// then store it in 'um' with index of its
// first occurrence
else if (!um.containsKey(curr_rem) )
um.put(curr_rem , i);
else
// If true, then update 'max'
if (maxSum < (sum[i] - sum[um.get(curr_rem)]))
maxSum = sum[i] - sum[um.get(curr_rem)];
}
// Required maximum number of chocolates to be
// distributed equally among 'k' students
return (maxSum / k);
}
This works but I needed some explanation WHY this works, i could understand the part --
if (curr_rem == 0) {
// update 'maxSum'
if (maxSum < sum[i])
maxSum = sum[i];
}
Will work if consecutive sum of array elements are divisible by k, but trying to understand this part --
else if (!um.containsKey(curr_rem) )
um.put(curr_rem , i);
else
// If true, then update 'max'
if (maxSum < (sum[i] - sum[um.get(curr_rem)]))
maxSum = sum[i] - sum[um.get(curr_rem)];
Any explanation here would be very helpful
Very short explanation:
In the main loop you look at all sums from index 0 to the current index. If you have a remainder you have to check if you can “make it go away” by starting from another index than 0.
Checking for that is exactly the same thing as finding an equal remainder stored before.
E. g. you had remainder 3 at index 7. If you have remainder 3 again at index 13 you have no remainder by adding between 7 and 13.
What remains is taking the max. sum of all solutions found.
class Solve
{
//arr -> chocolates values, n = len(arr), k->no of students
//Idea:
//1.to use prefix sum and find the subarray whose sum is divisible by k.
//2.when we find the subarray we try to find the sum of this subarray by using
//precomputation sum of arr
//3.we keep a max variable to record the max sum and return max that's it!!!!!
static int maxNumOfChocolates(int arr[], int n, int k)
{
if(n==0)return 0;
int []prefix = new int[n];
prefix[0] = arr[0];
for(int i=1;i<n;++i){
prefix[i] = prefix[i-1]+arr[i];
}
HashMap<Integer,Integer> map = new HashMap<>();
map.put(0,-1);
int ans = -1;
int sum = 0;
for(int i=0;i<n;i++){
sum+=arr[i];
if(map.containsKey(sum%k)){
int j = map.get(sum%k);
ans = Math.max(ans,prefix[i]-((j>=0)?prefix[j]:0));
}
map.putIfAbsent(sum%k,i);
}
if(ans==-1)return -1;
return ans/k;
}
}
I was looking over some basic questions that might be asked in an interview. Using basic for loops (No hash maps etc)I want to sum up all the matching elements in an array.For example, 6 matching elements will result in (Matched: 6) and a total of 36 in the example below.An example of this could be rolling dice, and the score is the total of all the dice that match.
public static void main(String[] args) {
int arr[] = {6,6,6,6,6,6};
int matched = 1;
int value = 0;
int total = 0;
for(int i=0;i<arr.length;i++){
for(int j=(i+1);j<arr.length;j++){
if(ar[i] == ar[j]){
matched++;
value = ar[i];
break;
}
}
total = (matched * value);
} // End for loop
System.out.println("Matched:"+(matched)+"");
System.out.println("Total:"+total);
}
But, if the array was for example...
int arr[] = {6,1,1,6,6,6};
The output I get will be (Matched:5) and an a total of 30.Can could I store the matching pair of 1's and add them to the total using as little basic code as possible?
Interpreting the question as "provide the total number of values that occur more than once and their sum", and taking into account that nothing "fancy" (sic) such as a map can be used:
int[] array = {6, 1, 1, 6, 6, 6};
int sum = 0;
int matches = 0;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length; j++) {
if (i != j && array[i] == array[j]) {
sum += array[i];
matches++;
break;
}
}
}
System.out.println(matches); // 6
System.out.println(sum); // 26
If you are allowed to use arrays - if not too fancy - then you could use 3 loops:
The first finds minimum and maximum elements
The second determines the occurrence of each item
The third calculates the totals
In Java this would look like this:
public static void main(String[] args) {
int[] array = {6, 3, 3, 6, 6, 6, 4, 4, 20};
int min = array[0];
int max = array[0];
// Find min max
for (int i : array) {
if (i < min) {
min = i;
}
if (i > max) {
max = i;
}
}
// Use array to sum up all elements
int[] holderArray = new int[max - min + 1];
for (int i : array) {
holderArray[i - min]++;
}
// Calculate occurrence and sums
for(int i = 0; i < holderArray.length; i++) {
if(holderArray[i] > 0) {
System.out.printf("number: %2d; count: %2d; sum: %2d%n", i + min, holderArray[i], (i + min) * holderArray[i]);
}
}
}
This prints out:
number: 3; count: 2; sum: 6
number: 4; count: 2; sum: 8
number: 6; count: 4; sum: 24
number: 20; count: 1; sum: 20
I don't completely understand your question, but based from what I understood, you want to get the sum of all matched numbers if its greater than 1? In that case there is a O(n) solution that you could use.
Create an empty Map then iterate over the array, and if the current number is not within the map add it to the map with value 1, if the current element is already existing in the map then just increment it's value (val++), at the end you will have a map and for each key (each distinct number) you will have the number of matched numbers from the array as the value. All you need to do is iterate over the pairs of key,val multiply each key*val then sum up the multiplied values and you get your correct total. And if you need just the number of matched, you can in another variable sum up just the vals.
So for lets say array [1,1,5,1,5,2,2,5,1], your map will something like:
{1:4, 2:2, 5:3},
and your totals:
total matches: 9
total: 23
I hope this helps!
Here is a code fragment I just wrote. This method takes in an array of integers and creates a map of each unique integer and it's count in the list. In the second part of the method, the HashMap object countOfNumbersMap is iterated and the sum of each element is printed.
private void findSumOfMatchingNumbers(int array[]) {
HashMap<Integer, Integer> countOfNumbersMap = new HashMap<>();
// Setting up the map of unique integers and it's count
for (int i = 0 ; i < array.length ; i++) {
if (countOfNumbersMap.containsKey(array[i])) {
int currentCount = countOfNumbersMap.get(array[i]);
countOfNumbersMap.put(array[i], currentCount + 1);
} else {
countOfNumbersMap.put(array[i], 1);
}
}
for (Integer integer : countOfNumbersMap.keySet()) {
int sum = countOfNumbersMap.get(integer) * integer;
System.out.println(String.format("Number = %d, Sum = %d", integer, sum));
}
}
The worst case runtime of the program is O(n).
If the range of your integers is limited, the easiest way to do this would be to create a histogram (i.e. create an array, where under index i you store the number of occurrences of the number i).
From that, it's easy to find elements that occur more than once, and sum them up. This solution has a complexity of O(n+k), where k is the range of your integers.
Another solution is to sort the array,then the matching numbers will be next to each other, and it's easy to count them. This has O(nlogn) complexity.
If these methods are not allowed, here is a solution in O(n^2) that only uses for loops:
Sum up the whole array
With a double loop, find all elements that are unique, subtract them from the sum, and count their number.
The remaining sum is the sum of all elements occurring more than once, and the count of unique elements subtracted from the length of the array gives the number of matching element.
I want to generate 6 different random numbers by using Math.random and store them into an array.
How can I make sure that they are different? I know I need to use for-loop to check the array but how...
This is the range. I only need numbers between 1 and 49.
( 1 + (int) (Math.random() * 49) )
In Java 8:
final int[] ints = new Random().ints(1, 50).distinct().limit(6).toArray();
In Java 7:
public static void main(final String[] args) throws Exception {
final Random random = new Random();
final Set<Integer> intSet = new HashSet<>();
while (intSet.size() < 6) {
intSet.add(random.nextInt(49) + 1);
}
final int[] ints = new int[intSet.size()];
final Iterator<Integer> iter = intSet.iterator();
for (int i = 0; iter.hasNext(); ++i) {
ints[i] = iter.next();
}
System.out.println(Arrays.toString(ints));
}
Just a little messier. Not helped by the fact that it's pretty tedious to unbox the Set<Integer> into an int[].
It should be noted that this solution should be fine of the number of required values is significantly smaller than the range. As 1..49 is quite a lot larger than 6 you're fine. Otherwise performance rapidly degrades.
Create a list containing the numbers 1 to 49.
Create a random number x between 0 and the size of the list, take the number being at index x in the list, and remove it from the list.
Repeat the previous step 5 times. And you're done. Note that java.util.Random has a nextInt(int max) method that you should use instead of Math.random().
Note regarding performance: this solution has an advantage compared to the "try until you get 6 different numbers" various solutions: it runs in a O(n) time. It doesn't matter much for 6 unique numbers out of 50, but if you want to get 48 or 49 unique random numbers out of 50, you'll start seeing a difference, because you might have to generate many random numbers before getting one that isn't already in the set.
EDIT:
to reduce the cost induced by the removal of the elements in the list, you could instead simply replace the element at index x with the last element of the list (and at the second iteration, with the element at size - 2, etc.)
You can use a Set.
Set<Integer> s = new HashSet<>();
while(s.size() != 6){
s.add(1 + (int) (Math.random() * 49));
}
Integer[] arr = s.toArray(new Integer[s.size()]);
This is enough to do this in your case because the number of distinct random numbers is relatively small compared to the size of the range you generate them.
Otherwise I would go with #JBNizet approach.
Generate any 6 numbers (not necessarily different). Order them.
a1 <= a2 <= a3 <= a4 <= a5 <= a6
Now take these 6 numbers
a1 < a2 + 1 < a3 + 2 < a4 + 3 < a5 + 4 < a6 + 5
These 6 are different and random.
The idea of this construct comes from some combinatorial proofs.
Its advantage is that it's simple, fast, and deterministic.
I think the time complexity is O(count*log(count)).
I wonder if it can be improved.
import java.util.TreeMap;
public class Test005 {
public static void main(String[] args) {
int count = 6;
int min = 1;
int max = 49;
// random number mapped to the count of its occurrences
TreeMap<Integer, Integer> mp = new TreeMap<Integer, Integer>();
for (int i=0; i<count; i++){
int d = ( min + (int) (Math.random() * (max-count+1)) );
if (!mp.containsKey(d)){
mp.put(d, 0);
}
mp.put(d, mp.get(d) + 1);
}
// now ensure the output numbers are different
int j = 0;
for (int num : mp.keySet()){
int cnt = mp.get(num);
for (int i=0; i<cnt; i++){
System.out.println(num + j);
j++;
}
}
}
}
I've just came up with a small idea for Java 8-.
Set<Integer> set = new LinkedHashSet<>();
while(set.size() != 6)
set.add(rnd.nextInt(49) + 1);
Instead of checking that the array has no duplicates, you can use a bit more smartness while generating the numbers, such that uniqueness is enforced at the outset.
Create a boolean[] as long as your range (49 entries);
generate a random number from the full range;
put that number into your output array;
"cross out" the corresponding index in the boolean[];
now generate another random number, but curtail the range by one (now 48);
instead of directly using that number as output, scan your boolean[], counting all the non-crossed entries. Stop when you reach the count equal to the random number generated in step 5. The number corresponding to that entry is your output number;
go to step 4.
in your case n=6
public static int[] chooseAny(int n){
int[] lottery = new int[n];
int[] chooseFrom = new int[49];
for(int i=1 ; i <= 49 ; i++)
chooseFrom[i-1] = i;
Random rand = new Random();
int N = 49;
int index;
for(int i=0 ; i < n ; i++){
//pick random index
index = rand.nextInt(N);
lottery[i] = chooseFrom[index];
chooseFrom[index] = chooseFrom[N-1];
N--;
}
return lottery;
}
Just keep generating numbers and adding them to the array as long as they are unique; psuedocode:
num = genNextRand()
For (array length)
If (num not in array)
addToArray()
Repeat while length not equal 6
Create a variable last; initialize it to 0.
Next, in a loop x from 0 to 5, create a random number between last+1 and 49-6+x. Store this number in a list, and set last to the number generated this way.
You will end up with an ordered list of 6 random numbers in the range of 1..49 with no repeats.
That code generate numbers from 6 to 0 and save in ArrayList.
If generated number was duplicated the program generate numbers again.
If generated number is different that number is added.
Code:
private ArrayList<Integer> arraylist = new ArrayList<Integer>();
private Random rand = new Random();
public void insertNumber() {
while (true) {
int i = generateNumber();
if(!isGenerateNumberExists(i)){
addNumber(i);
break;
}
}
}
//Generate numbers
private int generateNumber() {
return rand.nextInt(6);
}
//Confirm if that number exists
private boolean isGenerateNumberExists(int y) {
for (int num : arraylist) {
if (num == y) {
return true;
}
}
return false;
}
//Add number to arrayList
private void addNumber(int x) {
arraylist.add(x);
}
I need to randomly generate an array with 7 slots in Java. All these slots must have a value of at LEAST 1, but combined, have a total value of another defined number. They also all need to be an int value, no 1.5 or 0.9816465684646 numbers.
Example:
int a=10;
int[] ar = new int[7]
ar[0] = 1
ar[1] = 1
ar[2] = 2
ar[3] = 2
ar[4] = 1
ar[5] = 2
ar[6] = 1
I want it to generate something like that, but if int a=15, all the numbers would total 15 in any order
The standard way to generate N random numbers that add to a given sum is to think of your sum as a number line, generate N-1 random points on the line, sort them, then use the differences between the points as your final values. To get the minimum 1, start by subtracting N from your sum, run the algorithm given, then add 1 back to each segment.
public class Rand {
public static void main(String[] args) {
int count = 8;
int sum = 100;
java.util.Random g = new java.util.Random();
int vals[] = new int[count];
sum -= count;
for (int i = 0; i < count-1; ++i) {
vals[i] = g.nextInt(sum);
}
vals[count-1] = sum;
java.util.Arrays.sort(vals);
for (int i = count-1; i > 0; --i) {
vals[i] -= vals[i-1];
}
for (int i = 0; i < count; ++i) { ++vals[i]; }
for (int i = 0; i < count; ++i) {
System.out.printf("%4d", vals[i]);
}
System.out.printf("\n");
}
}
A good way to achieve uniformity is, for example, to fill up a = 15 units into an 8 element array:
Put 1 in each element in the array as this is your requirement, you have now 7 values left to distribute
Roll a random number between 0 and the max index of the array, and add 1 to that element, and subtract 1 from 7. Do this until 7 goes down to zero.
In this way, you'll meet your minimum conditions by having each element have minimum value 1. Then you distribute the remaining totals in a completely random way.
Adding on to what #Kon said, you could use two random numbers rather than one for more randomness. That is:
Fill every element in the array with the value 1
valuesToDistribute = a - array.length-1
randomIndex = Roll a number between 0 and array.length-1
randomValue = Roll a number between 1 and valuesToDistribute
Add to randomIndex the value randomValue
Subtract randomValue from valuesToDistribute
Repeat until valuesToDistribute = 0
My java is horrible, so I'm not providing the actual code here, as it would probably be wrong. I've done this exact thing in SQL before though, so I know it works...
Let Y be the Total value you want the elements to add up to
Begin a loop with variable Z going from 1 to X where X is the number elements in your array (here called AR)
In the loop, set AR(Z) to a random number between 1 and Y-X+Z
Subtract the new value from Y, so Y = Y - AR(Z)
End loop : back to step 2, advancing Z by 1
I've been playing around a bit with the algorithms for getting the largest sum with no two adjacent elements in an array but I was thinking:
If we have an array with n elements and we want to find the largest sum so that 3 elements never touch. That's to say if we have the array a = [2, 5, 3, 7, 8, 1] we can pick 2 and 5 but not 2, 5 and 3 because then we have 3 in a row. The larget sum with these rules for this array would be: 22 (2 and 5, 7 and 8. 2+5+7+8=22)
I'm not sure how I would implement this, any ideas?
Edit:
I've only come so far as to think about what might be good to do:
Let's just stick to the same array:
int[] a = {2, 5, 3, 7, 8, 1};
int{} b = new int[n}; //an array to store results in
int n = a.length;
// base case
b[1] = a[1];
// go through each element:
for(int i = 1; i < n; i++)
{
/* find each possible way of going to the next element
use Math.max to take the "better" option to store in the array b*/
}
return b[n]; // return the last (biggest) element.
This is just a thought I got in my head, hasn't reached longer than this.
Algorithm for Maximum sum such that no two elements are adjacent:
Loop for all elements in arr[] and maintain two sums incl and excl where incl = Max sum including the previous element and excl = Max sum excluding the previous element.
Max sum excluding the current element will be max(incl, excl) and max sum including the current element will be excl + current element (Note that only excl is considered because elements cannot be adjacent).
At the end of the loop return max of incl and excl.
Implementation:
#include<stdio.h>
/*Function to return max sum such that no two elements
are adjacent */
int FindMaxSum(int arr[], int n)
{
int incl = arr[0];
int excl = 0;
int excl_new;
int i;
for (i = 1; i < n; i++)
{
/* current max excluding i */
excl_new = (incl > excl)? incl: excl;
/* current max including i */
incl = excl + arr[i];
excl = excl_new;
}
/* return max of incl and excl */
return ((incl > excl)? incl : excl);
}
/* Driver program to test above function */
int main()
{
int arr[] = {5, 5, 10, 100, 10, 5};
printf("%d \n", FindMaxSum(arr, 6));
getchar();
return 0;
}
Time Complexity: O(n)
Space Complexity: O(1)
Edit 1:
If you understand the above code, we can easily do this problem by maintaining the count of already adjacent numbers for previous position.
Here is a working implementation to the required question
//We could assume we store optimal result upto i in array sum
//but we need only sum[i-3] to sum[i-1] to calculate sum[i]
//so in this code, I have instead maintained 3 ints
//So that space complexity to O(1) remains
#include<stdio.h>
int max(int a,int b)
{
if(a>b)
return 1;
else
return 0;
}
/*Function to return max sum such that no three elements
are adjacent */
int FindMaxSum(int arr[], int n)
{
int a1 = arr[0]+arr[1];//equivalent to sum[i-1]
int a2 =arr[0];//equivalent to sum[i-2]
int a3 = 0;//equivalent to sum [i-3]
int count=2;
int crr = 0;//current maximum, equivalent to sum[i]
int i;
int temp;
for (i = 2; i < n; i++)
{
if(count==2)//two elements were consecutive for sum[i-1]
{
temp=max(a2+arr[i],a1);
if(temp==1)
{
crr= a2+arr[i];
count = 1;
}
else
{
crr=a1;
count = 0;
}
//below is the case if we sould have rejected arr[i-2]
// to include arr[i-1],arr[i]
if(crr<(a3+arr[i-1]+arr[i]))
{
count=2;
crr=a3+arr[i-1]+arr[i];
}
}
else//case when we have count<2, obviously add the number
{
crr=a1+arr[i];
count++;
}
a3=a2;
a2=a1;
a1=crr;
}
return crr;
}
/* Driver program to test above function */
int main()
{
int arr[] = {2, 5, 3, 7, 8, 1};
printf("%d \n", FindMaxSum(arr, 6));
return 0;
}
Time Complexity: O(n)
Space Complexity: O(1)
adi's solution can be easily generalized to allow up to n adjacent elements to be included in the sum. The trick is to maintain an array of n + 1 elements, where the k-th element in the array (0 ≤ k ≤ n) gives the maximum sum assuming that the k previous inputs are included in the sum and the k+1-th isn't:
/**
* Find maximum sum of elements in the input array, with at most n adjacent
* elements included in the sum.
*/
public static int maxSum (int input[], int n) {
int sums[] = new int[n+1]; // new int[] fills the array with zeros
int max = 0;
for (int x: input) {
int newMax = max;
// update sums[k] for k > 0 by adding x to the old sums[k-1]
// (loop from top down to avoid overwriting sums[k-1] too soon)
for (int k = n; k > 0; k--) {
sums[k] = sums[k-1] + x;
if (sums[k] > newMax) newMax = sums[k];
}
sums[0] = max; // update sums[0] to best sum possible if x is excluded
max = newMax; // update maximum sum possible so far
}
return max;
}
Like adi's solution, this one also runs in linear time (to be exact, O(mn), where m is the length of the input and n is the maximum number of adjacent elements allowed in the sum) and uses a constant amount of memory independent of the input length (O(n)). In fact, it could even be easily modified to process input streams whose length is not known in advance.
I would imagine putting the array into a binary tree in that order. That way you can keep track of which element is next to each other. Then just simply do an if (node is not directly linked to each other) to sum the nodes which are not next to each other. You can potentially do it with recursion and return the maximum number, makes things easier to code. Hope it helps.
For a set with n entries, there are 2^n ways to partition it. So to generate all possible sets, just loop from 0:2^n-1 and pick the elements from the array with those entries set to 1 (bear with me; I'm getting to your question):
max = 0;
for (i = 0; i < 1<<n; ++i) {
sum = 0;
for (j = 0; j < n; ++j) {
if (i & (1<<j)) { sum += array[j]; }
}
if (sum > max) { /* store max and store i */ }
}
This will find the maximum way to sum the entries of an array. Now, the issue you want is that you don't want to allow all values of i - specifically those that contain 3 consecutive 1's. This can be done by testing if the number 7 (b111) is available at any bit-shift:
for (i = 0; i < 1<<n; ++i) {
for (j = 0; j < n-2; ++j) {
if ((i & (7 << j)) == (7 << j)) { /* skip this i */ }
}
...