diff --git a/src/main/tjava/com/r35157/libs/random/RandomValueGeneratorInt.tjava b/src/main/tjava/com/r35157/libs/random/RandomValueGeneratorInt.tjava new file mode 100644 index 0000000..e3c54e8 --- /dev/null +++ b/src/main/tjava/com/r35157/libs/random/RandomValueGeneratorInt.tjava @@ -0,0 +1,21 @@ +package com.r35157.libs.random; + +/** + * This interface provides a way to generate random integers. + */ +public interface RandomValueGeneratorInt { + /** + * Returns a random integer in the full range (min -231. to max 231-1) + * + * @return a random integer in full range + */ + int getSomeInt(); + + /** + * Returns a random integer in the range provided by the parameters. Both parameters are included in the range and + * {@code minInclusive} must be less than {@code maxInclusive}. + * + * @return a random integer in the provided range + */ + int getSomeInt(int minInclusive, int maxInclusive); +} diff --git a/src/main/tjava/com/r35157/libs/random/RandomValueGeneratorString.tjava b/src/main/tjava/com/r35157/libs/random/RandomValueGeneratorString.tjava new file mode 100644 index 0000000..d83c9c0 --- /dev/null +++ b/src/main/tjava/com/r35157/libs/random/RandomValueGeneratorString.tjava @@ -0,0 +1,14 @@ +package com.r35157.libs.random; + +import org.jetbrains.annotations.NotNull; + +public interface RandomValueGeneratorString { + /** + * Generate a random Alpha Numeric String of exactly the length given as the parameter. + * + * @param length Length of generated String - cannot be negative + * @return A non-null random String of the length given + * @throws IllegalArgumentException If length is negative + */ + @NotNull String getSomeStringAlphaNumericOnly(int length) throws IllegalArgumentException; +} diff --git a/src/main/tjava/com/r35157/libs/random/impl/ref/RandomValueGeneratorIntImpl.tjava b/src/main/tjava/com/r35157/libs/random/impl/ref/RandomValueGeneratorIntImpl.tjava new file mode 100644 index 0000000..def82c8 --- /dev/null +++ b/src/main/tjava/com/r35157/libs/random/impl/ref/RandomValueGeneratorIntImpl.tjava @@ -0,0 +1,54 @@ +package com.r35157.libs.random.impl.ref; + +import com.r35157.libs.random.RandomValueGeneratorInt; + +import java.util.concurrent.ThreadLocalRandom; + +import static java.lang.Integer.MAX_VALUE; +import static java.lang.Integer.MIN_VALUE; + +public class RandomValueGeneratorIntImpl implements RandomValueGeneratorInt { + @Override + public int getSomeInt() { + // Default: use the full int range + return getSomeInt(MIN_VALUE, MAX_VALUE); + } + + @Override + public int getSomeInt(int minInclusive, int maxInclusive) { + if (minInclusive > maxInclusive) { + String errorMessage = String.format("'minInclusive' (%d) must be less than or equal to 'maxInclusive' (%d)", + minInclusive, maxInclusive); + throw new IllegalArgumentException(errorMessage); + } + + if (minInclusive == maxInclusive) { + // Edge case: only one possible value + return minInclusive; + } + + // Fast path: full int range – ThreadLocalRandom.nextInt() already covers it + if (minInclusive == MIN_VALUE && maxInclusive == MAX_VALUE) { + return ThreadLocalRandom.current().nextInt(); + } + + // Use long to avoid overflow when calculating range size + long bound = ((long) maxInclusive - (long) minInclusive) + 1L; + + if (bound <= Integer.MAX_VALUE) { + // Normal case: the range fits in an int + // nextInt(bound) gives a uniform value in [0, bound], + // then shift it into the target range by adding minInclusive + return minInclusive + ThreadLocalRandom.current().nextInt((int) bound); + } else { + // Rare case: the range is larger than Integer.MAX_VALUE + // (e.g. almost the full int space). Use rejection sampling: + // draw values until one falls within the desired interval. + int r; + do { + r = ThreadLocalRandom.current().nextInt(); + } while (r < minInclusive || r > maxInclusive); + return r; + } + } +} \ No newline at end of file diff --git a/src/main/tjava/com/r35157/libs/random/impl/ref/RandomValueGeneratorStringImpl.tjava b/src/main/tjava/com/r35157/libs/random/impl/ref/RandomValueGeneratorStringImpl.tjava new file mode 100644 index 0000000..661720e --- /dev/null +++ b/src/main/tjava/com/r35157/libs/random/impl/ref/RandomValueGeneratorStringImpl.tjava @@ -0,0 +1,54 @@ +package com.r35157.libs.random.impl.ref; + +import com.r35157.libs.random.RandomValueGeneratorInt; +import com.r35157.libs.random.RandomValueGeneratorString; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +public class RandomValueGeneratorStringImpl implements RandomValueGeneratorString { + public RandomValueGeneratorStringImpl(@NotNull RandomValueGeneratorInt rvgi) { + Objects.requireNonNull(rvgi, "Cannot initialize with RandomValueGeneratorInt!"); + this.rvgi = rvgi; + } + + public @NotNull String getSomeStringAlphaNumericOnly(int length) throws IllegalArgumentException { + if(length < 0) { + throw new IllegalArgumentException("Cannot generate random Strings of size " + length + "!"); + } + + // ASCII Range size + // Numeric 48-57 10 + // Alpha upper 65-90 26 + // Alpha lower 97-122 26 + int totalNumberOfCandidates = 10 + 26 + 26; + + StringBuilder buffer = new StringBuilder(length); + for (int i = 0; i < length; i++) { + int randomInt = rvgi.getSomeInt(0, totalNumberOfCandidates - 1); + int asciiIndex = convertRandomIndexToASCIIIndex(randomInt); + + buffer.append((char) asciiIndex); + } + + return buffer.toString(); + } + + private static int convertRandomIndexToASCIIIndex(int randomIndex) { + // RandomIndex 0... ...9 - 10... ...35 - 36... ... 61 + // ASCII values: 48......57 - 65......90 - 97......122 + int asciiIndex; + + if(randomIndex >= 36) { + asciiIndex = 97 + (randomIndex - 36); + } else if(randomIndex >= 10) { + asciiIndex = 65 + (randomIndex - 10); + } else { + asciiIndex = 48 + randomIndex; + } + + return asciiIndex; + } + + private RandomValueGeneratorInt rvgi; +}