Skip to content

Instantly share code, notes, and snippets.

@trestletech
Last active December 17, 2015 00:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save trestletech/5518670 to your computer and use it in GitHub Desktop.
Save trestletech/5518670 to your computer and use it in GitHub Desktop.
Project to compute the minimum integer > 1 which is not representable by combining an integer using the (parenthesized) +, -, /, and * operations.
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
public class Main {
public static void main(String[] args){
try{
//Write out to file assuming IntelliJ project layout.
PrintStream out = new PrintStream(new FileOutputStream("src/timing.txt"));
//out = System.out;
String header = "N\tY\tmin\tElapsed Time";
out.println("Given Examples:");
out.println(header);
out.println(logTest(2,5)); // should be 2
out.println(logTest(3,5)); // should be 3
out.println();
out.println("Benchmarking tests:");
out.println(header);
for (int i = 1; i <= 9; i++){
out.println(logTest(i,i));
}
} catch(FileNotFoundException e){
System.err.println(e);
}
}
/**
* Log the run specified.
* @param N The number of values to consider in the expression.
* @param Y The integer to use in the expressions.
* @return A string describing N, Y, the returned result, and the run-time.
*/
private static String logTest(int N, int Y){
long startTime = System.nanoTime();
int min = MinNotRepresentable.minNotRepresentable(N,Y);
long duration = System.nanoTime() - startTime;
return (String.format("%d\t%d\t%d\t%.3fms", N, Y, min, duration/1000.0/1000.0));
}
}
import java.util.Arrays;
import java.util.HashSet;
public class MinNotRepresentable {
/**
* Given two integers N and Y, where N and Y are integers between 1 and 9 (inclusive), write a program that finds
* the smallest integer X > 1 that CANNOT be represented with an expression composed of exactly N many, Ys.
* The expression may be parenthesized, and the only operations allowed in the expression are the arithmetic
* operations of addition, subtraction, multiplication, and division.
* @param N The number of integers to consider in the expressions.
* @param Y The integer to use in the expressions.
* @return The minimum integer which cannot be expressed through some combination of N many Y's.
*/
public static int minNotRepresentable(int N, int Y){
HashSet<Double> vals = buildLevels(N, Y);
//find the first integer that's not present in the hash.
for (double i = 2; true; i++){
if (!vals.contains(i)){
return (int)i;
}
}
}
/**
* Progressively compute each level up the the maximum level specified.
* @param N the number of values to permit in the formula
* @param Y the number to use in the formula
* @return an array containing all of the values at each level.
*/
private static HashSet<Double> buildLevels(int N, int Y){
HashSet<Double>[] levels = new HashSet[N];
//populate the first level -- all you can have is the value of Y.
levels[0] = new HashSet<Double>(Arrays.asList((double)Y));
//iteratively compute the numbers in each level.
for (int i = 1; i < N; i++){
levels[i] = populateLevel(i, levels);
}
return levels[N-1];
}
/**
* Compute the values for the specified level
* @param level the level to compute
* @param levels the array of the other levels. It is expected that all of the previous levels before 'level' have
* been computed already.
* @return The values in the requested level.
*/
private static HashSet<Double> populateLevel(int level, HashSet<Double>[] levels){
HashSet<Double> toReturn = new HashSet<Double>();
//loop through all valid combinations of `level` Y's. Set 'a' to the number of Y's in the first group
for (int a = 0; a < level; a++){
//set 'b' to the number of Y's in the second group.
int b = level - a - 1;
//extract the numbers that existed at each level.
HashSet<Double> levelA = levels[a];
HashSet<Double> levelB = levels[b];
//only compute commutative operations if a <= b
boolean includeCommutative = true;
if (a > b){
includeCommutative = false;
}
combineLevels(levelA, levelB, toReturn, includeCommutative);
}
return toReturn;
}
/**
* Calculate all combinations of level a with level b
* @param levelA the values present in the first level
* @param levelB the values present in the second level
* @param newLevel the Hash into which we should add the values computed by combining levelA and levelB.
*/
private static void combineLevels(HashSet<Double> levelA,
HashSet<Double> levelB,
HashSet<Double> newLevel,
boolean includeCommutative){
//loop through all combinations of all values in A and B
for (Double a : levelA){
for (Double b : levelB){
//attempt to add, no-op if it already exists.
newLevel.add(a - b);
newLevel.add(a / b);
if (includeCommutative){
newLevel.add(a + b);
newLevel.add(a * b);
}
}
}
}
}
Given Examples:
N Y min Elapsed Time
2 5 2 0.804ms
3 5 3 0.061ms
Benchmarking tests:
N Y min Elapsed Time
1 1 2 0.009ms
2 2 2 0.019ms
3 3 5 0.059ms
4 4 10 0.252ms
5 5 13 1.183ms
6 6 22 6.400ms
7 7 38 10.582ms
8 8 91 13.143ms
9 9 195 33.031ms
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment