I am working on an algorithm, and I need to be able to pass in a List and see if there are four numbers in a row at any point in the list.
I have been struggling with an easy way to do this... Here is the basic idea.. I would like the fourNumbersInARow() method to return true:
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Numbers {
/**
* #param args
*/
public static void main(String[] args) {
List<Integer> numbers = new ArrayList<Integer>();
for(int i = 0; i<10; i++){
numbers.add((new Random().nextInt()));
}
numbers.add(1);
numbers.add(2);
numbers.add(3);
numbers.add(4);
System.out.println(fourNumbersInARow());
}
private static boolean fourNumbersInARow() {
}
}
Use two variables: last_value and row_count. Going through the list one by one, always look whether the current value is exactly one bigger than the last_value; if yes, increase row_count, if no, reset it to 1. In any case, set last_value to the current value and loop. If at any point row_count becomes 4, return true. If you reach the end of the list, return false.
EDIT: changed counter range to start at 1
Here's an implementation in Java.
static boolean fourNumbersInARow(List<Integer> list) {
int last = 0xFACADE; // can be any number
int count = 0; // important!
for (int i : list) {
if (i == last + 1) {
if (++count == 4) return true;
} else {
count = 1;
}
last = i;
}
return false;
}
Unlike others, this resets the count of numbers in a row to 1 when the sequence is broken (because a number on its own is 1 number in a row). This allows for easier treatment of the first iteration where technically there is no previous number.
In pseudocode:
consecutiveCount = 1
lastNumber = firstElementInList(list)
for (number in list.fromSecondElement()):
if (number - lastNumber == 1):
consecutiveCount++
else:
consecutiveCount = 1
if (consecutiveCount == 4):
return true
lastNumber = number
return false
The bottom line is, you'll want to keep track of the last number in that was in the list, and compare it with the current number to see if the difference is 1. In order to remember the last number, a variable such as lastNumber is needed.
Then, in order to keep track of how many consecutive numbers there have been there should be a counter for that as well, which in the example about is the consecutiveCount.
When the condition where four consecutive numbers have occurred, then the method should return true.
This sounds a little like a homework question, so I don't want to write out a complete solution. But in your method just iterate through the list. Take the first number and see if the next number comes after the current, if so then set a variable flag with the start position and the current number, on the next iteration through the loop check to see if that value is before the previous the value etc... Once four in a row are found, break out of the loop and return true. If you encounter a number that is no chronologically correct then set a flag(start location) to null or negative and start the process over from the current location in the list.
Check this Code, this will return true if there a sequence of 4 numbers and else false otherwise
public class FindFourSequence {
public boolean isFourinRow(ArrayList seqList) {
boolean flag = false;
int tempValue = 0;
int tempValue2 = 0;
int tempValue3 = 0;
int tempValue4 = 0;
Iterator iter = seqList.iterator();
while(iter.hasNext()){
String s1 = (String)iter.next();
tempValue=Integer.valueOf(s1).intValue();
if(!(iter.hasNext())){
break;
}
String s2 = (String)iter.next();
tempValue2=Integer.valueOf(s2).intValue();
if(((tempValue2-tempValue)==1) || (tempValue-tempValue2)==1){
if(!(iter.hasNext())){
break;
}
String s3 = (String)iter.next();
tempValue3=Integer.valueOf(s3).intValue();
if((tempValue3-tempValue2)==1 || (tempValue2-tempValue3)==1){
if(!(iter.hasNext())){
break;
}
String s4 = (String)iter.next();
tempValue4=Integer.valueOf(s4).intValue();
if((tempValue3-tempValue4==1) || (tempValue4-tempValue3)==1){
flag = true;
return flag;
}
}
}
}
return flag;
}
public static void main(String[] args) throws Exception {
ArrayList aList = new ArrayList();
boolean flag = false;
FindFourSequence example = new FindFourSequence();
Random random = new Random();
for (int k = 0; k < 25; k++) {
int number = random.nextInt(20);
System.out.println(" the Number is :" + number);
aList.add("" + number);
}
/* aList.add("" + 1);
aList.add("" + 2);
aList.add("" + 3);
aList.add("" + 4);*/
flag = example.isFourinRow(aList);
System.out.println(" the result value is : " + flag);
}
}
Related
I have to backtracking with numbers in a list that represent restrictions, such as: "x1 + x2> = 1". And if it meets all the conditions, that array is added to another array, in addition there is another list that represents the sum that I must make with all the variables "x1 + x2 + x3 + x4" and with that search for the one with the minimum value.
good what I should do in backtraking is to make a binary matrix with all the possibilities that the restrictions meet. What I have done is this but I get the error: "Exception in thread" main "java.lang.IndexOutOfBoundsException: Index 2 out of bounds for length 0" and I don't know where my problem is.
import java.util.ArrayList;
public class Pra_hacer_pruebas {
public static void main(String[] args) {
Pra_hacer_pruebas a = new Pra_hacer_pruebas();
ArrayList<Integer> conf1= new ArrayList<>(); // conf1 is the list that will contain one of the possibilities that may or may not be added to the binary matrix.
ArrayList<ArrayList<Integer>>pos_v = new ArrayList<>();// pos_v is where the possibilities will be added, binary matrix
int[][] restric = new int[2][2];// restric is the list with restrictions
restric[0][0]=2;
restric[0][1]=1;
restric[1][0]=4;
restric[1][1]=2;
for(int t=0;t<4;t++){
conf1.set(t, -1);
}
//System.out.println(conf.get(i));
a.binario(conf1,restric,0,0,0,pos_v,0,4,-1);
}
public void binario(ArrayList<Integer> conf1, int[][] restric, int suma,int filas,int columnas,ArrayList<ArrayList<Integer>> pos_validas,int posicion, int cont,int bin){
//filas = rows, suma= sum is to see if it meets the condition, columnas = columns, pos_validas = pos_v, posicion is to advance the rows of the matrix, cont: is the amount of different variables, bin is the binary variable
Boolean booleano = false; // booleano is the flag that if it is true it is because there was a null position (-1)
for (int[] restric1 : restric) {
suma=0;
for (int co = 0; co < restric1.length; co++) {
if ((conf1.get(restric1[co]) == 1) || (conf1.get(restric1[co]) == 0)) {
suma = suma + conf1.get(restric1[co]);
} else {
booleano = true;
}
}
if (booleano == false) {
if (suma < 1){
break;
}
}
}
if (booleano == false) {
pos_validas.set(posicion, conf1);
posicion++;
}
for (int f = 0; f < cont; f++) {
if (conf1.get(f) < 1) {
bin++;
conf1.set(f, bin);
binario(conf1,restric,suma,filas,columnas,pos_validas,posicion,cont,bin);
}
bin--;
}
}
}
Try add method. Even if you create ArrayList with initialCapacity, It won't works as you intended. If you print ArrayList size before set, You can check it.
System.out.println(conf1.size());
for(int t=0; t<4; t++){
conf1.set(t, Integer.valueOf(-1));
}
Modify code to use add
for(int t=0; t<4; t++){
conf1.add(-1);
}
your Arraylist objects start out as empty objects. YOu can't call .set() on them at all: Those UPDATE existing entries, they don't make new ones. Try add.
Even though my method operationsNeeded prints the correct value for my return-int "count1", the very next line it returns something else to my main method. I did not include the rest of my code, if needed I'd gladly provide it.
For example if operationsNeeded is executed 4 times, count1 is on 4 which is printed out as well. But for reasons unknown to me the System.out.println("check: " +count1); Statement is executed 4 times like this:
check: 4
check: 4
check: 3
check: 2
I would expect my program to execute this only once and then continue to the return statement.
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int testcases = sc.nextInt();
int count =0;
while (count<testcases){
int numberOfColleagues = sc.nextInt();
sc.nextLine();
String startPieces = sc.nextLine();
int[] listOfcolleagues = listOfColleagues(numberOfColleagues, startPieces);
int count2 = operationsNeeded(listOfcolleagues, 1);
count++;
System.out.println(count2);
}
}
public static int operationsNeeded (int[] listOfColleagues, int count1){
//remove duplicates first
ArrayList<Integer> relevantList=removeDuplicatesAndSort(listOfColleagues);
System.out.println("relevantlist" + relevantList);
//check for smallestdelta & index
int [] deltaAndIndex = smallestDeltaHigherIndex(relevantList);
int delta = deltaAndIndex[0];
int index = deltaAndIndex[1];
if (delta==1){
for (int i=0;i<relevantList.size();i++){
if (i!=index){
relevantList.set(i,relevantList.get(i)+1);
}
}
}
if (delta>1 && delta<5){
for (int i=0;i<relevantList.size();i++){
if (i!=index){
relevantList.set(i,relevantList.get(i)+2);
}
}
}
if (delta>4){
for (int i=0;i<relevantList.size();i++){
if (i!=index){
relevantList.set(i,relevantList.get(i)+5);
}
}
}
System.out.println(count1);
int[] updatedList = new int[relevantList.size()];
for (int i=0; i<relevantList.size();i++){
updatedList[i]=relevantList.get(i);
}
if (!isAllTheSame(relevantList)) {
count1 +=1;
operationsNeeded(updatedList,count1);
}
System.out.println("check: " + count1);
return count1;
}
Your method is recursive. The "check: " line is printed on each level of that recursion, with the value that it currently has on that level. It first prints the "inner-most" value (4), than that of the level above (also 4), and finally hte value in the top-level, which is 2 after being incremented in the if above. And the value it returns is always the value from to top-level.
If you want to print it only once, you could print it on the inner-most level only, using else. However, that will still return the value from the top-level iteration; instead, keep track of the value returned from the recirsive call and update count1 accordingly.
if (! isAllTheSame(relevantList)) {
// we have to go deeper!
count1 = operationsNeeded(updatedList, count1 + 1);
} else {
// phew, finally done
System.out.println("check: " + count1);
}
Perhaps i wasn't clear enough. I apologize. I tried condensing and adding images in this edit to make it more clear.
50 Seed Value, 1200 RNG Value.
60 Seed Value, 1200 RNG Value.
In the examples above (for clarity instead of writing it all out), you can see the outputs you get for 50 vs 60. It's not the distinct values I'm concerned. It's the display now. As you can see, the number gets bigger since I put in a new seed value. I want it to display what the 50 seed value is, but have the properties of whatever seed value I put in.
If I put in for example 60, I want to get:
H1 T1 H1 T1 HHH3 TTTTT5 H1 T1 HHHH4 T1 HH2 T1 H1 T1 H1 T1 H1 T1 H1 TTT3 H1 TTT3 H1 TTTT4 H1 T1 HHH3 TT2 H1 T... (just like with the 50 seed value).
BUT it would get 35 distinct values instead of the 30. Let me know if I can be clearer I apologize for being so confusing.
import java.util.Scanner;
import java.util.Random;
public class CoinFlipAnalyzer{
private static final Scanner
stdIn = new Scanner(System.in);
public static void main (String[] args){
// Integer Values:
int totalNumberOfRuns = 0;
int run = 1;
// Boolean Values:
boolean theCoin;
boolean tempVal = false;
// Gathering the Users Input:
System.out.println("Welcome to the coin flip analyzer.\n"
+ "How many flips?");
int numberOfFlips = stdIn.nextInt();
System.out.println("What do you want to seed the random number generator with?");
int rngSeed = stdIn.nextInt();
Random rng = new Random(rngSeed); // Initiates the Random Number Generator.
System.out.println();
// Loop and Array to Decide Whether the Value is Heads or Tail.
long[] runLength = new long[numberOfFlips];
for (int i = 0; i < numberOfFlips; i++) {
theCoin = rng.nextBoolean(); // As requested, I used the nextBoolean expression.
if (theCoin != tempVal) {
if (i > 0) {
System.out.print(run + " ");
}
runLength[run - 1]++;
totalNumberOfRuns++;
run = 1;
}
else {
run++;
}
if (theCoin) {
System.out.print("H");
tempVal = true;
}
else {
System.out.print("T");
tempVal = false;
}
}
System.out.print("...");
System.out.println();
System.out.println("There were a total of " + totalNumberOfRuns +
" distinct runs in the simulation.\nTheir breakdown follows:");
System.out.println();
I think I understand the requirement. In essence, there is some desired width, and if the number of outputs exceeds the width, then print using an ellipses.
There is the StringUtils from Apache Commons that has an 'Abbreviate' method.
public static String abbreviate(String str,
int maxWidth)
Abbreviates a String using ellipses. This will turn "Now is the time for all good men" into "Now is the time for..."
To use this (or the other suggestion below), I would remove the immediate output that is being generated in the run, and instead build a String. One could build a char[] as well, but here we will go with a String (or a StringBuilder). There is another advantage to so doing -- it is generally a good practice to separate some of the logic from the output. Plus it would be more testable.
So, if one can use the StringUtils.abbreviate(...), then take the result from the doFlips(...) and pass it to the method, and the result will be done.
/*
* moved the flipping into a method; allow it to build the
* results rather than immediately outputting them
*/
private static StringBuilder doFlips(int numberOfFlips, Random rng)
{
long[] runLength = new long[numberOfFlips];
boolean theCoin;
boolean tempVal = false;
int run = 1;
int totalNumberOfRuns = 0;
// Here we will collect the output; use better name in production
StringBuilder sb = new StringBuilder();
for (int i = 0; i < numberOfFlips; i++) {
theCoin = rng.nextBoolean(); // As requested, I used the nextBoolean
// expression.
if (theCoin != tempVal) {
if (i > 0) {
sb.append(run);
sb.append(" ");
}
runLength[run - 1]++;
totalNumberOfRuns++;
run = 1;
}
else {
run++;
}
if (theCoin) {
sb.append("H");
tempVal = true;
}
else {
sb.append("T");
tempVal = false;
}
}
return sb;
}
If one cannot use the library, it is easy enough to write a chop method:
/**
* Chop the input StringBuilder and give "..." at
* maxOutput.
*
* NOTE: no error checking
*/
private static String ourChop(StringBuilder sb, int maxOutput)
{
if (sb.length() <= maxOutput) {
return sb.toString();
}
// we chop everything past maxOutput - 3
sb.setLength(maxOutput - 3);
sb.append("...");
return sb.toString();
}
So, we can then do the following:
public static void main(String[] args)
{
int seed = 1200;
int maxOutput = 25;
// 50 flips, 25 length max, including ... if needed
StringBuilder res = doFlips(50, new Random(seed));
System.out.println(ourChop(res, maxOutput));
res = doFlips(60, new Random(seed));
System.out.println(ourChop(res, maxOutput));
And we get this output (at 25):
H1 T1 H1 T1 HHH3 TTTTT...
H1 T1 H1 T1 HHH3 TTTTT...
Now, if the goal is to align to the max output of some given run, then one would need to collect all of the runs (50, 60, etc.), and then find the particular value (say the shortest of the outputs; note that in theory in a truly random setting, 60 could have a shorter output than 50, but not when using the same seed). One could then use that determined value to chop to a given output length.
If I have misunderstood the approach, I apologize.
I just discovered the project euler website, I have done challenges 1 and 2 and have just started number 3 in java... here is my code so far:
import java.util.ArrayList;
public class IntegerFactorise {
private static int value = 13195;
private static ArrayList<Integer> primeFactors = new ArrayList<Integer>();
private static int maxPrime = 0;
/**
* Check whether a give number is prime or not
* return boolean
*/
public static boolean isPrimeNumber(double num) {
for(int i = 2; i < num; i++) {
if(num % i == 0) {
return false;
}
}
return true;
}
/*Multiply all of the prime factors in the list of prime factors*/
public static int multiplyPrimeFactors() {
int ans = 1;
for(Integer i : primeFactors) {
ans *= i;
}
return ans;
}
/*Find the maximum prime number in the list of prime numbers*/
public static void findMaxPrime() {
int max = 0;
for(Integer i : primeFactors) {
if(i > max) {
max = i;
}
}
maxPrime = max;;
}
/**
* Find all of the prime factors for a number given the first
* prime factor
*/
public static boolean findPrimeFactors(int num) {
for(int i = 2; i <= num; i++) {
if(isPrimeNumber(i) && num % i == 0 && i == num) {
//could not possibly go further
primeFactors.add(num);
break;
}
else if(isPrimeNumber(i) && num % i == 0) {
primeFactors.add(i);
findPrimeFactors(num / i);
}
}
int sumOfPrimes = multiplyPrimeFactors();
if(sumOfPrimes == value) {
return true;
}
else {
return false;
}
}
/*start here*/
public static void main(String[] args) {
boolean found = false;
for(int i = 2; i < value; i++) {
if(isPrimeNumber(i) && value % i == 0) {
primeFactors.add(i);
found = findPrimeFactors(value / i);
if(found == true) {
findMaxPrime();
System.out.println(maxPrime);
break;
}
}
}
}
}
I am not using the large number they ask me to use yet, I am testing my code with some smaller numbers, with 13195 (their example) i get down to 29 in this bit of my code:
else if(isPrimeNumber(i) && num % i == 0) {
primeFactors.add(i);
findPrimeFactors(num / i);
}
}
int sumOfPrimes = multiplyPrimeFactors();
if(sumOfPrimes == value) {
return true;
}
It gets to the break statement then finally the check and then the return statement.
I am expecting the program to go back to the main method after my return statement, but it jumps up to:
findPrimeFactors(num / i);
and tries to finish the iteration...I guess my understanding is a flawed here, could someone explain to me why it is behaving like this? I can't wait to finish it of :) I'll find a more efficient way of doing it after I know I can get this inefficient one working.
You are using recursion, which means that a function will call itself.
So, if we trace what your function calls are when you call return, we will have something like that:
IntegerFactorise.main()
|-> IntegerFactorise.findPrimeFactors(2639)
|-> IntegerFactorise.findPrimeFactors(377)
|-> IntegerFactorise.findPrimeFactors(29) -> return true;
So, when you return in the last findPrimeFactors(), you will only return from this call, not from all the stack of calls, and the execution of the previous findPrimeFactors() will continue just after the point where you called findPrimeFactors().
If you want to return from all the stack of calls, you have to modify your code to do something like that:
else if(isPrimeNumber(i) && num % i == 0) {
primeFactors.add(i);
return findPrimeFactors(num / i);
}
So that when the last findPrimeFactors() returns, all the previous findPrimeFactors() which called it will return too.
I think the problem is that you are ignoring the return value from your recursive call to findPrimeFactors().
Let's walk through this. We start with the initial call to findPrimeFactors that happens in main. We then enter the for loop as it's the first thing in that method. Now let's say at some point we get into the else statement and thus recursively call frindPrimeFactors(num / i). This will suspend the looping, but as this recursive call starts to run you enter the for loop again (remember, the previous loop is merely paused and not finished looping yet). This time around you encounter the break, which allows this recursive call to finish out, returning true of false. When that happens you are now back to the original loop. At this point the original loop continues even if the recursive call returned true. So, you might try something like this:
if (findPrimeFactors(num / i))
return true;
I'm assuming that you need to continue looping if the recursive call returned false. If you should always finish looping upon return (whether true or false) then try this:
return findPrimeFactors(num / i);
Time for my daily newbie Java question :-D
I must not be understanding conditionals in a while loop correctly.
I have this:
while (true){
if (){
...
} else {
...
}
if (){
...
} else {
...
}
if (SENTINEL){
break;
}
}
The first if/else statement is working, and the sentinel is working, but the second if statement gets skipped. If I flip the first and second if statement, then the first if statement still always gets executed and skips the second. What am I missing?
Can I have two if/else statements in one block like this?
I'll include the whole code, though it's pretty ugly, and I'm sure I'll get lots of people telling me better ways of doing this. I don't mind learning better ways, but for now, I just want an answer to this looping question. thanks!
public class FindRange extends ConsoleProgram {
private static final int SENTINEL = 0;
int value = 0;
int highNumber = 0;
int latestValue = 0;
int lowNumber = 0;
public void run() {
addNumbers();
}
private void addNumbers(){
value = readInt("Enter number:");
while(true){
if (value == SENTINEL){
break;
}
latestValue = readInt("Enter number:");
getHighNumber();
getLowNumber();
if (latestValue == SENTINEL){
break;
}
}
println("High Number is "+highNumber+".");
println("Low Number is "+lowNumber+".");
}
private void getHighNumber(){
if (latestValue >= value){
highNumber = latestValue;
}else {
highNumber = value;
}
}
private void getLowNumber(){
if (latestValue <= value){
lowNumber = latestValue;
}else {
lowNumber = value;
}
}
}
Are you trying to find the minimum and maximum of a series of numbers? If so, you should definitely use Math.min() and Math.max(). It's much clearer that way and you can do away with the if statements. It's also simple enough to do it in the loop with local variables instead of fields.
The common idiom is something like this:
minValue = Math.min(minValue, candidateValue);
maxValue = Math.max(maxValue, candidatevalue);
It's possible that the behavior you're seeing comes from the fact that you are always comparing the latest value to the initial value. The initial value will never change-- so if you put in the following input:
20, 60, 50
the high value that gets reported would be 50. That's because 50 is the most recent value to be greater than 20. I think you probably mean to compare the latest value to the high value, no?
You can definitely have 2 if/else blocks within the loop; however if your sentinel gets hit the loop will exit.
Posting the entire block would help.
What will happen (after reading the posted code) is when any new value you enter within the loop is greater than the original value, lowNumber is set back to the original. So for example if your input is:
7 6 5 8
Your corresponding low number values will be:
7 6 5 7
Which is incorrect. What you could do is toast the "value" variable altogether, set your low and high to the original value, then compare latest with low and high in the get* methods.
Shouldn't you be setting value = latestValue at the bottom of your while loop?
Value never gets updated after the initial read... maybe something like this:
public class FindRange extends ConsoleProgram {
private static final int SENTINEL = 0;
public void run() {
addNumbers();
}
private void addNumbers() {
int value = 0;
// Set this to highest possible value
int highNumber = Integer.MIN_VALUE;
// Set this to lowest possible value
int lowNumber = Integer.MAX_VALUE;
while (true) {
value = readInt("Enter number:");
if (value == SENTINEL)
break;
lowNumber = Math.min(lowNumber, value);
highNumber = Math.max(highNumber, value);
}
println("High Number is " + Integer.toString(highNumber) + ".");
println("Low Number is " + Integer.toString(lowNumber) + ".");
}
}