I am using this to generate a random number inside a method and return it:
int randomValue = ThreadLocalRandom.current().nextInt(0, filteredArrayList.size());
How can I make sure there are not two random numbers in a row? I don't care if I get a 3, then a 5, then a 3 again. Only if I get a 3 and then a 3.
int temp = -1; // This will be your value to be compared to random value
for(int i = 0; i < 10; i++) { // assuming your filteredArraylist is size 10
int randomValue = ThreadLocalRandom.current().nextInt(0, 10);
if(randomValue == temp) {
i--; // it will repeat the generation of random value if temp and randomValue is same
} else {
temp = randomValue; // you will put here the ne random value to be compared to next value
System.out.println(randomValue);
}
Try following sample
import java.util.Random;
public class RandomTest {
public static void main(String[] args) {
for(int i = 0; i < 10; i++) {
System.out.println("####### " + RandomUtil.getRandomInt(10));
}
}
}
class RandomUtil {
private static int lastInt = -1;
private static Random random = new Random();
public synchronized static int getRandomInt(int upperBound) {
return getRandomInt(0, upperBound);
}
public synchronized static int getRandomInt(int lowerBound, int upperBound) {
int newInt = -1;
while( (newInt = lowerBound + random.nextInt(upperBound - lowerBound)) == lastInt) {
//Keep looping
}
lastInt = newInt;
return newInt;
}
}
As Scary Wombat said, you'll want to compare the previous value to the newly randomized value in a loop (which I assume you are using, since we only see the one line.
Something like this...
int prevRandomNumber, currRandomNumber;
while (notFinished) {
currRandomNumber = getRandom(); // your random number generator
if (prevRandomNumber == currRandomNumber) { // if there would be two in a row
continue; // try again
} else { // otherwise, add to array
addNumberToArray(currRandomNumber);
prevRandomNumber = currRandomNumber;
}
}
Just remember the last generated value and if equals then reject. Here is an example:
int lastRandomValue = -1;
boolean stop = false;
int attempts = 0;
final int maxAttempts = 100_000;
while (!stop) {
int currentRandomValue = ThreadLocalRandom.current().nextInt(0, filteredArrayList.size());
if (currentRandomValue != lastRandomValue) {
// Use the value
...
// Reset the counter
attempts = 0;
...
// Stop the generation process if generated enough values
if (...) {
stop = true;
}
} else {
// Increment a counter
attempts++;
}
if (attempts >= maxAttempts) {
stop = true;
}
}
Edited:
I'd do something like this: (requires the last random value/a non-reachable number for the first time, e.g. -1)
private int notPreviousRandom(int previousRandomValue) {
int randomValue;
do {
randomValue = ThreadLocalRandom.current().nextInt(0, filteredArrayList.size());
} while (randomValue == previousRandomValue);
return randomValue;
}
Alternatively you could define previousRandomValue as an attribute:
// class
private int previousRandomValue = -1;
// ...
private int notPreviousRandom() {
int randomValue;
do {
randomValue = ThreadLocalRandom.current().nextInt(0, filteredArrayList.size());
} while (randomValue == previousRandomValue);
previousRandomValue = randomValue; // for the next time you're using the
// method
return randomValue;
}
Related
I wrote two pieces of code for knapsack problem. The first code gives me the correct answer (which is 16) and the second one doesn't. Is it something wrong with my recursive function?
First code (correct answer):
public class knapsackProblem {
static int[] weight = {1,2,4,2,5};
static int[] value = {5,3,5,3,2};
int result = 0;
// recursive function
public int sack(int i, int cap)
{
//base case
if(i<0 || cap == 0)
{
return 0;
} else if(weight[i] > cap)
{
return sack(i-1, cap);
} else
{
//get maximum value
return Math.max(sack(i-1, cap), value[i] + sack(i-1, cap - weight[i]));
}
}
public static void main(String[] args)
{
int capacity = 10;
int len = weight.length;
knapsackProblem kp = new knapsackProblem();
int total = kp.sack(len - 1, capacity);
System.out.println("sacked array is " + total);
}
}
Second code (incorrect answer):
public class knapsackProblem {
static int[] weight = {1,2,4,2,5};
static int[] value = {5,3,5,3,2};
int result = 0;
int tempNO = 0;
int tempYES = 0;
// recursive function
public int sack(int i, int cap)
{
//base case
if(i<0 || cap == 0)
{
return 0;
} else if(weight[i] > cap)
{
return sack(i-1, cap);
} else
{
//no case, move on to next value
tempNO = sack(i-1, cap);
//yes case, add the current value and move on to next value with decreased capacity
tempYES = value[i] + sack(i-1, cap - weight[i]);
//get maximum value
return Math.max(tempNO, tempYES);
}
}
public static void main(String[] args)
{
int capacity = 10;
int len = weight.length;
knapsackProblem kp = new knapsackProblem();
int total = kp.sack(len - 1, capacity);
System.out.println("sacked array is " + total);
}
}
The only difference is that in second code I put the results from recursion into variables before comparing for maximum value.
Thanks
Your variables are attributes of the class. The recursive calls are modifying those attributes every time, because you're using one single instance of the class to make the calls to the function. Declare the variables inside the method and remove them from the class to make it work. :)
The method should return true if the argument is even, or
false otherwise. The program’s main method should use a loop to generate 100 random integers. It should use the isEven method to determine whether each random number is even, or odd. All this is done!!!
This is the part where I can't figure it out!
When the loop is finished, the program should display the number of even numbers that were generated, and the number of odd numbers.
This is my code:
import java.util.Random;
public class EvenOdd
{
public static void main(String[] args)
{
Random random = new Random();
int randomInteger = 0;
for(int i = 0; i < 100; i++){
randomInteger = random.nextInt();
System.out.println("Random Integer: " + randomInteger);
EvenOdd(randomInteger);
}
}
public static void EvenOdd(int x)
{
int oddNumbers = 0;
int evenNumbers = 0;
if ((x % 2) == 0)
{
System.out.println("Even");
evenNumbers++;
}
else
{
System.out.println("Odd");
oddNumbers++;
}
}
}
Try with this:
public static void main(String[] args)
{
Random random = new Random();
int randomInteger = 0;
int oddNumbers = 0;
int evenNumbers = 0;
for(int i = 0; i < 100; i++){
randomInteger = random.nextInt();
System.out.println("Random Integer: " + randomInteger);
if(evenOdd(randomInteger)) evenNumbers++;
else oddNumbers++;
}
System.out.printf("Even numbers: %d - Odd numbers: %d", evenNumbers, oddNumbers);
}
public static boolean evenOdd(int x)
{
if ((x % 2) == 0)
{
System.out.println("Even");
return true;
}
else
{
System.out.println("Odd");
return false;
}
}
Your original approach doesn't work because you initialize to 0 the oddNumbers and evenNumbers variables everytime you call the method.
Define oddNumbers, evenNumbers variables as static class variables and after the loop you can print these 2 value.
Java is not JavaScript. Also, it does not have the ability of C++ as "Static variables in functions".
Variables declared inside a method are local. Variables initialization occurs every time your code reaches a variable definition inside the method and destroyed after exiting from the method.
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/variables.html
So you have such variants:
1) Count numbers inside your main method and return indicator from the utility method.
1.1) boolean
public static boolean isEven(int x){
return (x % 2) == 0;
};
1.2) enum
private enum NumberType {
EVEN,
ODD
}
public static NumberType getNumberType (int x) {
if ((x % 2) == 0) {
return NumberType.EVEN;
} else {
return NumberType.ODD;
}
};
2) Make your variables static:
public class EvenOdd {
private static int evenNumbersCount = 0;
private static int oddNumbersCount = 0;
public static void main(String[] args) {
// your code
}
public static void countNumberType (int x) {
if ((x % 2) == 0) {
++evenNumbersCount;
} else {
++oddNumbersCount;
}
}
}
3) In some sophisticated situations you will need to pass container to your method:
public class EvenOdd {
private static final String EVEN = "even";
private static final String ODD = "odd";
public static void main(String[] args) {
// initialize container
Map<String, Integer> evenOddCounts = new HashMap<>(2, 1);
evenOddCounts.put(EVEN, 0);
evenOddCounts.put(ODD, 0);
Random random = new Random();
int randomInteger = 0;
for (int i = 0; i < 100; i++) {
randomInteger = random.nextInt();
countNumberType(evenOddCounts, randomInteger);
}
System.out.println(evenOddCounts.toString());
}
public static void countNumberType(Map<String, Integer> counts, int x) {
if ((x % 2) == 0) {
counts.compute(EVEN, (numberType, count) -> ++count);
} else {
counts.compute(ODD, (numberType, count) -> ++count);
}
}
}
I have run into an interesting problem and wanted to know if anyone had any leads on how to solve it. When given a string of numbers, I want to find the highest number. So if the string is "2836", then the output should be 8, if the string is "12345" then the output should be 5 and so on. Here is the method I am working on:
public static void main(String[] args) {
max("215");
}
public static void max(String number) {
if (number.isEmpty()) {
System.out.println("The string is empty");
System.exit(0);
}
int compCount = 1;
int max = number.charAt(0);
int compare = number.charAt(compCount);
for (int i = 0; i < number.length(); i++) {
if (max > compare) {
compCount++;
} else if (compare > max) {
max = compare;
} else {
System.out.print(max);
}
}
System.out.print(max);
}
When this code executes it gives me 50 and I want 5
Well, you have a lot of wrong stuff going on. Firstly, you never change compare, Second, you take the int in ascii, and don't convert it to its Integer representation. Thirdly, you need only one if statement. All combined, it gives
int max = Character.getNumericValue(number.charAt(0));
for (int i = 1; i < number.length(); i++) {
int compare = Character.getNumericValue(number.charAt(i));
if (max < compare) {
max = compare;
}
}
return max;
I've used Character#getNumericValue to convert the char to int
Since ASCII codes of digits are sorted in ascending order you can easily do it with Java 8 like this:
public static void max(String number) {
if (number == null || number.isEmpty()) {
return;
}
int max = number.chars().max().getAsInt();
System.out.println(Character.getNumericValue((char) max));
}
If your input can has mix of digits and other symbols you also able to handle it:
public static void max(String number) {
if (number == null || number.isEmpty()) {
return;
}
OptionalInt max = number.chars().filter(Character::isDigit).max();
if (max.isPresent()) {
System.out.println(Character.getNumericValue((char) max.getAsInt()));
} else {
System.err.println("Provided string doesn't contain digits");
}
}
you have to modify your max method as given below
public static void max(String number) {
if (number.isEmpty()) {
System.out.println("The string is empty");
System.exit(0);
}
int max = Integer.parseInt(number.charAt(0)+"");
for (int i = 1; i < number.length(); i++) {
int compare = Integer.parseInt(number.charAt(i)+"");
if (compare > max) {
max = compare;
}
}
System.out.print(max);
}
I am a high school student in an introductory Computer Science course. Our assignment was the following:
The last digit of a credit card number is the check digit, which protects against transcription errors such as an error in a single digit or switching two digits. the following method is used to verify actual credit card numbers but, for simplicity, we will describe it for numbers with 8 digits instead of 16:
Starting from the rightmost digit, form the sum of every other digit. For example, if the credit card number is 4358 9795, then you form the sum 5+7+8+3 = 23.
Double each of the digits that were not included in the preceding step. Add all the digits of the resulting numbers. For example, with the numbers given above, doubling the digits, starting with the next-to-last one, yields 18 18 10 8. Adding all the digits in these values yields 1+8+1+8+1+0+8=27.
Add the sums of the two preceding steps. If the last digit of the result is 0, the number is valid. In our case, 23 + 27 = 50, so the number is valid.
Write a program that implements this algorithm. The user should supply an 8-digit number, and you should print out whether the number is valid or not. If it is not valid, you should print out the value of the check digit that would make the number valid.
I have everything done except for the part in bold. My code is listed below:
public class CreditCard
{
private String creditCardNumber;
private boolean valid;
private int checkDigit;
int totalSum;
/**
* Constructor for objects of class CreditCard
*/
public CreditCard(String pCreditCardNumber)
{
creditCardNumber = pCreditCardNumber;
checkDigit = Integer.parseInt(pCreditCardNumber.substring(creditCardNumber.length() - 1));
int sumOfDigits = checkDigit + Integer.parseInt(pCreditCardNumber.substring(6,7)) + Integer.parseInt(pCreditCardNumber.substring(3,4)) + Integer.parseInt(pCreditCardNumber.substring(1,2));
int dig7 = Integer.parseInt(pCreditCardNumber.substring(7,8));
int dig5 = Integer.parseInt(pCreditCardNumber.substring(5,6));
int dig3 = Integer.parseInt(pCreditCardNumber.substring(2,3));
int dig1 = Integer.parseInt(pCreditCardNumber.substring(0,1));
String string7 = Integer.toString(dig7);
int doubledDig7a = Integer.parseInt(string7.substring(0));
int doubledDig7b = 0;
if (dig7 * 2 >= 10)
{
doubledDig7a = Integer.parseInt(string7.substring(0));
doubledDig7b = 0;
}
String string5 = Integer.toString(dig5);
int doubledDig5a = Integer.parseInt(string7.substring(0));
int doubledDig5b = 0;
if (dig5 * 2 >= 10)
{
doubledDig5a = Integer.parseInt(string5.substring(0));
doubledDig5b = 0;
}
String string3 = Integer.toString(dig3);
int doubledDig3a = Integer.parseInt(string3.substring(0));
int doubledDig3b = 0;
if (dig3 * 2 >= 10)
{
doubledDig3a = Integer.parseInt(string3.substring(0));
doubledDig3b = 0;
}
String string1 = Integer.toString(dig1);
int doubledDig1a = Integer.parseInt(string1.substring(0));
int doubledDig1b = 0;
if (dig1 * 2 >= 10)
{
doubledDig1a = Integer.parseInt(string1.substring(0));
doubledDig1b = 0;
}
int doubleDigits = doubledDig1a + doubledDig1b + doubledDig3a + doubledDig3b + doubledDig5a + doubledDig5b + doubledDig7a + doubledDig7b;
totalSum = sumOfDigits + doubleDigits;
if (totalSum % 10 == 0)
{
valid = true;
}
else
{
valid = false;
}
}
public void makeItValid()
{
while (totalSum % 10 != 0)
{
checkDigit--;
if (totalSum % 10 == 0)
{
break;
}
}
}
public boolean isItValid()
{
return valid;
}
}
The loop is what I am having issues with. I always end up in an infinite loop whenever it compiles. It looks like everything should work, though. It's supposed to decrease the value of the check Digit (not increase so I don't end up with a check digit of 10 or higher), and then add that number back into the total sum until the total sum is divisible by 10, and then the loop would end. Is the type of loop I'm using wrong? Any advice would be appreciated.
Your problem is that both of your loop conditions involve totalSum but you only change checkDigit.
while (totalSum % 10 != 0)
{
checkDigit--;
if (totalSum % 10 == 0)
{
break;
}
}
You either need to recalculate totalSum or change the condition to be based on checkDigit. If you want to loop and decrement like you are doing you will need to add a method that performs the algorithm and call it every time. The way you have your class outlined makes this very inconvenient because you don't convert the numbers.
public static int[] cardToNumbers(String cardText) {
// \D is regex for non-digits
cardText = cardText.replaceAll("\\D", "");
int[] cardNumbers = new int[cardText.length()];
// convert unicode to corresponding integers
for (int i = 0; i < cardText.length(); i++)
cardNumbers[i] = cardText.charAt(i) - '0';
return cardNumbers;
}
public static int calcTotalSum(int[] cardNumbers) {
int sum = 0;
/* "every other one" loops
*
* I recommend against the "mod 2 index" scheme
* i % 2 relies on the card number being even
* you can't have your code blow up with unusual inputs
*
*/
for (int i = cardNumbers.length - 1; i >= 0; i -= 2) {
sum += cardNumbers[i];
}
for (int i = cardNumbers.length - 2; i >= 0; i -= 2) {
int dig = cardNumbers[i] * 2;
while (dig > 0) {
sum += dig % 10;
dig /= 10;
}
}
return sum;
}
Now you can do something like:
public void makeItValid() {
int[] invalidNumbers = cardToNumbers(creditCardNumber);
int sum = calcTotalSum(invalidNumbers);
while ((sum = calcTotalSum(invalidNumbers)) % 10 != 0)
invalidNumbers[invalidNumbers.length - 1]--;
totalSum = sum;
checkDigit = invalidNumbers[invalidNumbers.length - 1];
}
But you should be able to just subtract the difference to find the valid check digit:
if (totalSum % 10 != 0) checkDigit -= totalSum % 10;
Or something like:
public void makeItValid() {
int[] invalidNumbers = cardToNumbers(creditCardNumber);
checkDigit = invalidNumbers[invalidNumbers.length - 1] -= totalSum % 10;
totalSum = calcTotalSum(invalidNumbers);
valid = true;
}
Some asides,
I would recommend storing the digits as a field and have checkDigit represent an index in the array. This would simplify some of the operations you are doing.
I would also suggest not to be "silently" changing fields internally IE like in your makeItValid method unless this is a specification of the assignment. I think a better form is to let the "owning" code make the changes itself which is more clear externally. A somewhat complete implementation would look like this:
public class CreditCard {
public static void main(String[] args) {
if (args.length == 0) return;
CreditCard card = new CreditCard(args[0]);
if (!card.isValidNumber()) {
card.setCheckDigit(card.getValidCheckDigit());
}
}
private final String cardText;
private final int[] cardDigits;
private final int cdIndex;
public CreditCard(String ct) {
cardDigits = cardToNumbers(cardText = ct);
if ((cdIndex = cardDigits.length - 1) < 0) {
throw new IllegalArgumentException("# had no digits");
}
}
public boolean isValidNumber() {
return calcTotalSum(cardDigits) % 10 == 0;
}
public void setCheckDigit(int dig) {
cardDigits[cdIndex] = dig;
}
public int getValidCheckDigit() {
int sum = calcTotalSum(cardDigits);
if (sum % 10 != 0) {
return cardNumbers[cdIndex] - sum % 10;
} else {
return cardNumbers[cdIndex];
}
}
// above static methods
}
The best form IMO would be to disallow creation of a credit card object at all unless the check digit is valid. As an OOP principle it should not make sense to create invalid credit cards. The constructor should throw an exception if the card is invalid and have a static method to correct the number.
I would do something like the following (shortened):
public class CreditCard {
public CreditCard(String number) {
if (!validateCheckDigit(number)) {
throw new IllegalArgumentException("check digit failure");
}
}
}
public static void main(String[] args) {
String number = args[0];
CreditCard card = null;
boolean valid = false;
do {
try {
card = new CreditCard(number);
valid = true;
} catch (IllegalArgumentException e) {
number = CreditCard.correctCheckDigit(number);
}
} while (!valid);
}
I guess that's more or less doing your homework for you but I'm sure you can learn from it.
Unless I'm missing something major on how the validation works your makeitvalid method wont work in the way you are approaching it.
It makes more sense (at least to me) to extract everything you have in your constructor into a method ie.
boolean isValid(String cardNumber);
which would do everything that your constructor does except set the valid flag. your constructor then becomes
public CreditCard(String pCreditCardNumber){
valid = isValid(pCreditCardNumber);
}
and then to find what change would make it valid your check valid method does something like
change the value of check digit
if (isValid(Changed String))
return checkdigit
else
continue
repeat until you either find one that works or until you determine that it can't work.
Something along these lines should do. You'll still need to implement a few methods on your own.
public static void main(String[] args) {
String creditCardNumber = readCreditCardNumber();
String correctCreditCardNumber = getCorrectCreditCardNumber(creditCardNumber);
if (creditCardNumber.equals(correctCreditCardNumber)) {
System.out.println("Credit Card Valid");
} else {
System.out.println("Credit Card Invalid. Did you mean " + correctCreditCardNumber + "?");
}
}
public static String getCorrectCreditCardNumber(String creditCardNumber) {
int[] creditCardDigits = getCreditCardDigits(creditCardNumber);
int sum = 0;
for (int i = creditCardDigits.length - 2; i >= 0; i--) {
if (isOdd(i)) {
sum += creditCardDigits[i];
} else {
sum += digitSum(creditCardDigits[i] * 2);
}
}
int last = creditCardDigits.length - 1;
int remainder = sum % 10;
if (remainder != 0) {
creditCardDigits[last] = 10 - remainder;
}
return getCreditCardNumberAsString(creditCardDigits);
}
This program is very dynamic. I did not add too much error handling. You can enter any number that is divisible by 8.
Code in action:
Enter a card number: 4358 9795
Number is valid?: true
Continue? (y/n): y
Enter a card number: 4358 9796
Number is valid?: false
Continue? (y/n): y
Enter a card number: 43-58 97-95
Number is valid?: true
Continue? (y/n): n
Exiting...
CreditCardValidator.java
import java.text.ParseException;
import java.util.Scanner;
public class CreditCardValidator {
Integer[] digits;
public CreditCardValidator(String numberSequence) {
parseNumber(numberSequence);
}
private void parseNumber(String numberSequence) {
try {
String sequence = numberSequence.replaceAll("[\\s-]+", "");
int length = sequence.length();
if (length % 8 != 0) {
throw new IllegalArgumentException("Number length invalid.");
}
digits = new Integer[length];
int pos = 0;
for (Character c : sequence.toCharArray()) {
if (Character.isDigit(c)) {
digits[pos++] = Character.getNumericValue(c);
} else {
throw new ParseException("Invalid digit.", pos);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private boolean validateNumber() {
int sum = 0;
for (int i = digits.length - 1; i >= 0; i--) {
if (i % 2 == 1) {
sum += digits[i];
} else {
sum += NumberUtils.sumDigits(digits[i] * 2);
}
}
return sum % 10 == 0;
}
public static void main(String[] args) {
boolean stop = false;
CreditCardValidator c;
while (!stop) {
System.out.print("Enter a card number: ");
c = new CreditCardValidator(new Scanner(System.in).nextLine());
System.out.println("Number is valid?: " + c.validateNumber());
System.out.print("\nContinue? (y/n): ");
if (new Scanner(System.in).next().charAt(0) == 'n') {
stop = true;
}
System.out.println();
}
System.out.println("Exiting...");
System.exit(0);
}
}
I wrote a separate digit summation utility:
public class NumberUtils {
public static void main(String[] args) {
for(int i = 0; i < 2000; i+=75) {
System.out.printf("%04d: %02d\n", i, sumDigits(i));
}
}
public static int sumDigits(int n) {
if (n < 0)
return 0;
return sumDigitsRecursive(n, 0);
}
private static int sumDigitsRecursive(int n, int total) {
if (n < 10)
return total + n;
else {
return sumDigitsRecursive(n / 10, total + (n % 10));
}
}
}
I am trying to create a random sized array of 1's and 0's. I can get the program to run and compile if I remove the random aspect of the of it and enter the size of the array manually. For some reason when I bring in the random utility I can not get the program to compile.
mport java.util.Random;
public class Project1a {
int[][] sample={{0,0,1,1,1},
{1,1,0,1,1},
{1,1,1,0,1},
{0,1,0,1,1}};
int box[][];
Random randomNumbers = new Random();
int m = randomNumbers.nextInt(100);
int n = randomNumbers.nextInt(100);
int results[][] = new int [m][n];
int goodData = 1;
public static void main(String[] args){
analyzeTable();
printTable(results);
}
public void analyzeTable() {
int row=0;
while (row < sample.length) {
analyzeRow(row);
row++;
}
}
public void analyzeRow(int row) {
int xCol = 0;
int rCount = 0;
while (xCol < sample[row].length) {
rCount = analyzeCell(row,xCol);
results[row][xCol] = rCount;
xCol++;
}
}
int analyzeCell(int row, int col) {
int xCol = col;
int runCount = 0;
int rowLen = sample[row].length;
int hereData = sample[row][xCol];
while (hereData == goodData && xCol < rowLen) {
runCount++;
xCol++;
if (xCol < rowLen) { hereData = sample[row][xCol];}
}
return runCount;
}
public void printTable(int[][] aTable ) {
for (int[] row : aTable) {
printRow(row);
System.out.println();
}
}
public void printRow(int[] aRow) {
for (int cell : aRow) {
System.out.printf("%d ", cell);
}
}
}
Your class name conflicts with java.util.Random. Renaming your class is the easiest fix here.
the problem is you are declaring your instance variable in a block which makes it in-accessible in methods
check this : remove curly braces { } from here and the way you are accessing your results and goodData you need to declare them static
{ // remove this
Random randomNumbers = new Random();
int m = randomNumbers.nextInt(100);
int n = randomNumbers.nextInt(100);
static int results = new int [m][n];
static int goodData = 1;
} // remove this