This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Java code with tests - infinite loop?
Here is my code that I want to get the relationship between people, however, when I run unit test, the test ran forever and couldn't get the result, and my cpu using was high.
Here is my code. Could someone see what's wrong with it?
the string relations are multiple line inputs of string with a format "A , B" +\n" +
"C , D" where A is the parent of B and C is the parent of D.
this is the default constructor for the code and is the input format of string, we don't need to check if the format is correct
public SeeRelations(String relations){
this.relations = relations;
}
//helper function to get each line of the string
private ArrayList<String> lineRelations(){
int i;
ArrayList<String> lineRelations = new ArrayList<String>();
String[] lines = relations.split("\n");
for(i = 0; i < lines.length; i++){
lineRelations.add(lines[i]);
}
return lineRelations;
}
//helper function to put each of the relationship in arraylists
private ArrayList<ArrayList<String>> allRelations(){
int i;
ArrayList<ArrayList<String>> allRelations = new ArrayList<ArrayList<String>>();
ArrayList<String> lineRelations = lineRelations();
for(i = 0; i < lineRelations.size(); i++){
ArrayList<String> eachLine = new ArrayList<String>(Arrays.asList(lineRelations.get(i).split("\\s*,\\s*")));
allRelations.add(eachLine);
}
return allRelations;
}
this is the method to check if the input name is existent
//helper function to see if the name exist for seeRelations()
private boolean hasThisName(String name){
ArrayList<ArrayList<String>> allRelations = allRelations();
int i;
int j;
for(i = 0; i < allRelations.size(); i++){
for(j = 0; j < allRelations.get(i).size(); j++){
if(name.equals(allRelations.get(i).get(j))){
return true;
}
}
}
return false;
}
this is the function to get the generation number between two people
//helper function to get Generation number of seeRelations()
private int getGenerationNum(String person, String ancestor){
ArrayList<ArrayList<String>> allRelations = allRelations();
String name;
int i;
int j;
int generationNum = 0;
for(i = 0, j = 0, name = ancestor; i < allRelations.size(); i++){
if(name.equals(allRelations.get(i).get(0)) && !person.equals(allRelations.get(i).get(1))){
generationNum++;
ancestor = allRelations.get(i).get(1);
i = 0;
j = 1;
}
else if(ancestor.equals(allRelations.get(i).get(0)) && person.equals(allRelations.get(i).get(1))){
generationNum++;
j = 1;
break;
}
}
if(j == 0){
return 0;
}
else{
return generationNum;
}
}
this is the method to get multiple of "great" for the final output
private String great(int num){
int i;
String great = "";
for(i = 0; i < num; i++){
great += "great";
}
return great;
}
this is my final method to check the relationship between two people
public String seeRelations(String person, String ancestor){
int generationNum = getGenerationNum(person, ancestor);
String great = great(generationNum - 2);
if(!(hasThisName(person) && hasThisName(ancestor))){
return null;
}
else{
if(generationNum == 0){
return null;
}
else if(generationNum == 1){
return ancestor + " is the parent of " + person;
}
else if(generationNum == 2){
return ancestor + " is the grandparent of " + person;
}
else{
return ancestor + " is the" + " " + great +"grandparent of " + person;
}
}
}
This piece of code looks suspicious to me. It is inside a loop that depends for termination on incrementing i, but conditionally resets i back to zero. What guarantees i will ever get past 1?
if(name.equals(allRelations.get(i).get(0)) && !person.equals(allRelations.get(i).get(1))){
generationNum++;
ancestor = allRelations.get(i).get(1);
i = 0;
j = 1;
}
In general, I suggest simplifying your code until it works, then adding gradually so that you only have to debug a small piece of code at a time.
Related
I created a program that takes a score from American Football and generates all possible ways to get that score in American Football. I just created a conversion-less touchdown method (that decrements the score value by 6) that combines a field goal method(decrements the value by 3) and a safety(decrements the value by 2). A problem is, when an even value is typed, there are no proper combinations that contains touchdowns, field goals, and safeties. The program works fine for odd values. I suspect an issue could be how fieldgoalsnumbersprinted returns its String value.
static int sixtouchdownnumbers(int c) //return type doesn't matter
{
int touchdowns6 = c;
int touch6counter = 0;
int touch6divided = touchdowns6/6;
int lesserdowns6 = touch6divided -1;
String booth;
String box;
String scoreboard;
String boothbox;
String seat;
String boothboxseat;
if(touchdowns6 < 6)
{
return touchdowns6; //this value doesn't matter. I just have this here so the method stops if the score is less than 6.
}
touchdowns6 = c;
touch6counter = 0;
for(int i = 0; i <= lesserdowns6; i++)
{
touchdowns6 = touchdowns6-6;
touch6counter++;
booth = "there were " + touch6counter + " touchdowns without conversion";
box = Safetynumbersprinted(touchdowns6);
seat = Fieldgoalnumbersprinted(touchdowns6);
boothbox = booth+box;
boothboxseat = boothbox+seat;
if(boothboxseat.contains("safeties")) //fixes an issue with field goal loop generating bad scores.
System.out.println(boothboxseat);
}
return 0;
}
static String Fieldgoalnumbersprinted(int d)
{
int fieldgoals = d;
int goalcounter = 0;
int fielddivided = fieldgoals/3;
int lessergoals = fielddivided -1;
String scoreb;
String oard;
String scoreboard;
String nosebleed = "Error"; //if this is printed, the for loop didn't assign the right value.
if(fieldgoals < 3)
{
return "";
}
fieldgoals = d;
goalcounter = 0;
for(int i = 0; i <= lessergoals; i++)
{
fieldgoals = fieldgoals-3;
goalcounter++;
scoreb = ", " + goalcounter + " field goals";
oard = Safetynumbersprinted(fieldgoals);
scoreboard = scoreb+oard;
if(scoreboard.contains("safeties")) //fixes an issue with field goal loop generating bad scores.
nosebleed = scoreboard; //potential cause of the problem.
}
return nosebleed;
}
static String Safetynumbersprinted(int a)
{
int safeties = a;
int safetycounter = 0;
int safedivided;
String scorehalf;
if ( (a & 1) == 0 ) //only even scores can be reduced to zero.
{
safedivided = a/2;
for(int i = 0; i < safedivided; i++)
{
safeties = safeties-2;
safetycounter++;
}
scorehalf = " and " + safetycounter + " safeties: ";
return scorehalf;
}
else
{
return "";
}
}
I am doing a Lotto application in a jForm/GUI in Netbeans with 3 rows of 5 numbers, and I don't want duplicates to be allowed on each line. To have one number on line 1 and the same on line 3 is OK, but to have those numbers on the same line is not OK.
The only way I can think of doing it that I know will work is to hard code it, and preferably, I don't want that.
I have tried:
boolean dup = false;
for (int k = 0; k < num[0].length){ //loop through columns
for (i = 0; i < num.length-1; i++) {
for (int j = i; j < inArray.length; j++){
if (num[k][i] == num[k][j]){
dup = true;
break;
}
}
}
}
and this:
public static boolean hasDuplicates(int [][] num) {
for (int row = 0; row < num.length; row++) {
int curRow = num[row];
Set set = Sets.newHashSet(Arrays.asList(curRow));
if (set.size() < curRow.length) {
return true;
}
}
return false;
}
I have also looked at other coding extensively and I can't get one that works.
The exact thing I'm trying to do is:
Get user's input for three lines of Lotto via text field, check each line for duplicates, print to a jLabel if it's a duplicate or leave the jLabel blank and run the rest of the code if there's no duplicates.
The current code I have is:
private void playBtnActionPerformed(java.awt.event.ActionEvent evt) {
num[0][0] = Integer.parseInt(line00Tf.getText());
num[0][1] = Integer.parseInt(line01Tf.getText());
num[0][2] = Integer.parseInt(line02Tf.getText());
num[0][3] = Integer.parseInt(line03Tf.getText());
num[0][4] = Integer.parseInt(line04Tf.getText());
num[1][0] = Integer.parseInt(line10Tf.getText());
num[1][1] = Integer.parseInt(line11Tf.getText());
num[1][2] = Integer.parseInt(line12Tf.getText());
num[1][3] = Integer.parseInt(line13Tf.getText());
num[1][4] = Integer.parseInt(line14Tf.getText());
num[2][0] = Integer.parseInt(line20Tf.getText());
num[2][1] = Integer.parseInt(line21Tf.getText());
num[2][2] = Integer.parseInt(line22Tf.getText());
num[2][3] = Integer.parseInt(line23Tf.getText());
num[2][4] = Integer.parseInt(line24Tf.getText());
duplicateLbl.setText("");
LottoPhase1 p1 = new LottoPhase1();
p1.setNum(num);
p1.createSecret();
secret = p1.getSecret();
p1.computeCheckInput();
correctL1 = p1.getCorrectL1();
correctL2 = p1.getCorrectL2();
correctL3 = p1.getCorrectL3();
//prints secret to output
System.out.println("Phase 1 Main Secret: " + Arrays.toString(secret));
System.out.println();
displayResults0Lbl.setText(Integer.toString(secret[0]) + ", " + Integer.toString(secret[1]) + ", " + Integer.toString(secret[2]) + ", " + Integer.toString(secret[3]) + ", " + Integer.toString(secret[4]));
matched1NumLbl.setText(Integer.toString(correctL1));
matched2NumLbl.setText(Integer.toString(correctL2));
matched3NumLbl.setText(Integer.toString(correctL3));
}
public static boolean hasDuplicates(int[][] num)
{
boolean hasDuplicate = false;
// for each line in num
for(int[] line : num)
{
// for every number in the row
for(int i = 0; i < line.length && !hasDuplicate; i++)
{
// for every number in the row
for(int j = 0; j < line.length; j++)
{
// if we are not comparing the same number
if(i != j)
{
// check for equality
if(line[i] == line[j])
{
hasDuplicate = true; // we have found a duplicate
break; // no need to keep checking; break the loop and return
}
}
}
}
}
return hasDuplicate;
}
The second method has a couple of errors, for instance,
int curRow = num[row];
Should actually be:
int[] curRow = num[row];
Also, you appear to be using Sets, which probably comes from some library you're using (Guava, Google Common, etc.). Assuming you were not using any library, you could change your code to something similar to:
public static boolean hasDuplicates(int [][] num) {
for (int[] curRow : num) {
Set<Integer> set = new HashSet<>();
for (int n : curRow) {
if (!set.add(n)) {
return true;
}
}
}
return false;
}
If you're using Java 8, one way to remove the second for loop is by using a Stream:
public static boolean hasDuplicates(int [][] num) {
for (int[] curRow : num) {
Set<Integer> set = IntStream.of(curRow).boxed().collect(Collectors.toSet());
if (set.size() < curRow.length) {
return true;
}
}
return false;
}
Other alternatives to the Stream can be found in threads like these.
Testing with the following input produces what I think you would expect:
int[][] testA = {{0,1,2,3,4}, {0,1,2,3,4}, {0,1,2,3,4}}; //false
int[][] testB = {{0,1,2,3,4}, {0,2,2,3,4}, {0,1,2,3,4}}; //true
int[][] testC = {{0,1,2,3,4}, {0,1,2,3,4}, {0,4,3,3,4}}; //true
int[][] testD = {{0,1,2,3,4}, {5,6,7,8,9}, {10,11,12,13,14}}; //false
I need to do a method to check two string for example bod and bot or crab and rab. The method needs to print out what the user must do in order to make them equal. For example in bod and bot it will print "replace,2,d in the string". I used this code which seems to work.
if(a.length()==b.length()){
int i;
for(i=0; i<=a.length(); i++){
if(a.charAt(i)!=b.charAt(i)){
return "replace,"+ i + "," + b.charAt(i);
}
}
}
But I am having troubles if the two string are not equal in size. I use this but it doesn't work because one of the strings is bigger.
int aS = a.length();
int bS = b.length();
if(bS - aS == 1){
int i;
for(i=0; i<=b.length(); i++){
if(b.charAt(i)!=a.charAt(i)){
return "remove," + i;
}
}
}
Can you guys give me a suggestion what method I can use to check which is the extra letter or vice versa a letter I can add and then return a string saying either to remove a character or add an extra one. Thank you
Maybe something like this?
public ArrayList<String> createConversionList(String primary, String secondary){
//Determine which string is shorter.
String shorter;
String longer;
boolean primaryIsShorter = false;
if (primary.length() >= secondary.length()){
longer = primary;
shorter = secondary;
} else{
longer = secondary;
shorter = primary;
primaryIsShorter = true;
}
//Fills an array with all the character positions that differ between the
//two strings, using the shorter string as the base.
int[] posOfCharsToChange = new int[shorter.length()];
for(int i = 0; i < shorter.length(); i++){
if(shorter.charAt(i) != longer.charAt(i)){
posOfCharsToChange[i] = i;
} else{
posOfCharsToChange[i] = -1;
}
}
//Adds to an ArrayList all of the "Replace" strings.
ArrayList<String> conversionList = new ArrayList();
for(int pos: posOfCharsToChange){
if(pos != -1){
String s = "Replace " + secondary.charAt(pos) + " with " + primary.charAt(pos) + ". \n";
conversionList.add(s);
}
}
//Depending on which string was bigger, either adds "Add" or "Remove"
//strings to the ArrayList. If the strings were the same size, does
//nothing.
if(primary.length() != secondary.length()){
if(primaryIsShorter){
for(int i = primary.length(); i < secondary.length(); i++){
String s = "Remove " + secondary.charAt(i) + ". \n";
conversionList.add(s);
}
}
else{
for(int i = secondary.length(); i < primary.length(); i++){
String s = "Add " + primary.charAt(i) + ". \n";
conversionList.add(s);
}
}
}
return conversionList;
}
My Approach works as follows
1) We take the smaller string and put all its contents in an arraylist
2) We take the bigger string and put its contents in the arraylist only if its not present in the arraylist
3) The last character in the arraylist must be removed from the bigger string to make them equal
Ex 1:
a = rab
b = crab
1) arraylist = rab -> contents of a added
2) arraylist = rabc -> only unique content of b is added
Ex 2:
a = crab
b = rab
1) arraylist = rab
2) arraylist = rabc
similarly if the positions are in the middle or not at start ,
ex : a = racb
b = rab
1) arraylist = rab
2) arraylist = rabc
public class Replace {
public static void main(String args[]) {
int p = 0, j = 0;
String a = "rab";
String b = "crab";
if (b.length() < a.length()) {
ArrayList al = new ArrayList();
for (j = 0; j < b.length(); j++) {
if (!al.contains(b.charAt(j))) {
al.add(b.charAt(j));
}
}
for (j = 0; j < a.length(); j++) {
if (!al.contains(a.charAt(j))) {
al.add(a.charAt(j));
}
}
System.out.println("Remove " + al.get(al.size() - 1)
+ " from String a");
} else {
ArrayList al = new ArrayList();
for (j = 0; j < a.length(); j++) {
if (!al.contains(a.charAt(j))) {
al.add(a.charAt(j));
}
}
for (j = 0; j < b.length(); j++) {
if (!al.contains(b.charAt(j))) {
al.add(b.charAt(j));
}
}
System.out.println("Remove " + al.get(al.size() - 1)
+ " from String b");
}
}
}
Note - The program only works under your given contraints that strings only differ in one character and the ordering of both the strings is not different if we remove or add that charcter.
Please find below a function in my code:
private static List<String> formCrfLinesWithMentionClass(int begin, int end, String id,
List<String> mList, int mListPos, List<String> crf) {
List<String> crfLines = crf;
int yes = 0;
mListPosChanged = mListPos;
//--------------------------------------------------------------------------
for (int crfLinesMainIter = begin; crfLinesMainIter < end; ) {
System.out.println(crfLines.get(crfLinesMainIter));
//---------------------------------------------------------------------------
//the total number of attributes without orthographic features
//in a crfLine excluding the class attribute is 98
if (!crfLines.get(crfLinesMainIter).equals("") && crfLines.get(crfLinesMainIter).split("\\s").length == 98) {
//in mList parenthesis are represented by the symbol
//in crfLines parenthesis are represented by -LRB- or -RRB-
//we make a check to ensure the equality is preserved
if(val.equals(crfLines.get(crfLinesMainIter).split("\\s")[0])) {
yes = checkForConsecutivePresence(crfLinesMainIter, mList, mListPos, id, crfLines);
if (yes > 0) {
mListPosChanged += yes;
System.out.println("formCrfLinesWithMentionClass: "+mListPosChanged);
for (int crfLinesMentionIter = crfLinesMainIter;
crfLinesMentionIter < crfLinesMainIter + yes;
crfLinesMentionIter++) {
String valString = "";
if (crfLinesMentionIter == crfLinesMainIter) {
valString += crfLines.get(crfLinesMentionIter);
valString += " B";
crfLines.add(crfLinesMentionIter, valString);
}
else {
valString += crfLines.get(crfLinesMentionIter);
valString += " I";
crfLines.add(crfLinesMentionIter, valString);
}
}
crfLinesMainIter += yes;
}
else {
++crfLinesMainIter;
}
}
else {
++crfLinesMainIter;
}
}
else {
++crfLinesMainIter;
}
}
return crfLines;
}
The problem I face is as follows:
crfLines is a List collections interface.
When the for loop (between //-----) starts out, the crfLines.get(crfLinesMainIter) works fine. But once, it enters into the if and other processing is carried out on it, even though "crfLinesMainIter" changes the crfLines.get(crfLinesMainIter) seems to get a certain previous value. It does not retrieve the actual value at the index. Has anyone faced such a scenario? Would anyone be able to tell me why this occurs?
My actual question is, when does it occur that even though the indexes might be different a list.get() function still retrieves a value from before which was at another index?
For example:
List crfLines = new LinkedList<>();
if crfLinesMainIter = 2
crfLines.get(crfLinesMainIter) brings me a value say 20 and this value 20 satisfies the if loop condition. So then further processing happens. Now when the for loop executes the values of crfLinesMainIter changes to say 5. In this case, crfLines.get(5) should actually bring me a different value, but it still brings me the previous value 20.
(Not an answer.)
Reworked (more or less) for some modicum of readability:
private static List<String> formCrfLinesWithMentionClass(int begin, int end, String id, List<String> mList, int mListPos, List<String> crf) {
List<String> crfLines = crf;
mListPosChanged = mListPos;
int i = begin;
while (i < end) {
if (crfLines.get(i).equals("") || (crfLines.get(i).split("\\s").length != 98)) {
++i;
continue;
}
if (!val.equals(crfLines.get(i).split("\\s")[0])) {
++i;
continue;
}
int yes = checkForConsecutivePresence(i, mList, mListPos, id, crfLines);
if (yes <= 0) {
++i;
continue;
}
mListPosChanged += yes;
for (int j = i; j < i + yes; j++) {
String valString = crfLines.get(j);
valString += (j == i) ? " B" : " I";
crfLines.add(j, valString);
}
i += yes;
}
return crfLines;
}
What is mListPostChanged? I find it confusing that it's being set to the value of a parameter named mListPos--it makes me think the m prefix is meaningless.
What is val in the line containing the split?
I created a class for a bingo game. I get an error saying "'class' expected". How could I return the values in the array to the main starter?
Any other comments would also be helpful.
Thank you.
import java.util.Random;
public class Card
{
Random generator = new Random();
private final int BOARDMAX = 4;
private final int NUMMAX = 59;
int i, j, m, n;
private int [][] ArrayBoard = new int[BOARDMAX][BOARDMAX];
String [][] StrArrayBoard = new String [BOARDMAX][BOARDMAX];
public void RandomNumGenerator()
{
for (i = 0; i<BOARDMAX; i++)
{
for (j = 0; j<BOARDMAX; j++)
{
ArrayBoard[i][j] = generator.nextInt (NUMMAX+1);
}
}
}
public String ShowBoard()
{
for (i = 0; i<BOARDMAX; i++)
{
for (j = 0; j<BOARDMAX; j++)
{
m=i;
n=j;
if (j != BOARDMAX)
StrArrayBoard[m][n] = ArrayBoard[m][n] + " ";
else
StrArrayBoard[m][n] = ArrayBoard[m][n] + " \n";
}
}
return StrArrayBoard[i][j];
}
public void ShowMark()
{
for (i = 0; i<BOARDMAX; i++)
{
for (j = 0; j<BOARDMAX; j++)
{
if (CardCheck [i][j] == 1)
StrArrayBoard[i][j] = ArrayBoard[i][j] + "* ";
else
StrArrayBoard[i][j] = ArrayBoard[i][j] + " ";
if (j == BOARDMAX)
ArrayBoard[i][j] = ArrayBoard[i][j] + "\n";
}
}
}
public String toString()
{
return ArrayBoard[][];
}
}
With toString() you need to return a String object but actually you try to return an int[][]. The same is true for ShowBoard, you try to return an array of Stringarrays which is not a compatible type.
Here's the fix:
public String ShowBoard() {
// your code to populate StrArrayBoard
StringBuilder boardBuilder = new StringBuilder();
for (String[] row:StrArrayBoard)
for (String cell:row)
sb.append(cell);
return boardBuilder.toString();
}
public String toString() {
return ShowBoard();
}
I suggest to refactor the code and rename methods and fields:
ShowBoard() --> getBoardAsString()
ArrayBoard --> arrayBoard
StrArrayBoard --> strArrayBoard
And there's no need to declare StrArrayBoard as a field (class member) just because you only need it inside the ShowBoard method. Declare it there as a local variable.
Adding to the bugs others have pointed:
You have if (CardCheck [i][j] == 1), but the array CardCheck is not declared anywhere.
You have ArrayBoard[i][j] = ArrayBoard[i][j] + "\n"; but ArrayBoard is an int array, you cannot add a string "\n" to it's member.
The compiler will complain because of the error on your code:
public String toString()
{
return ArrayBoard[][];
}
It can't convert int[][] (which is your ArrayBoard) to String. My suggestion is that you populate all values stored in StrArrayBoard in a StringBuffer and return the StringBuffer.toString() in the toString() method.
The toString() method requires a String.
Hope this helps.
public String toString()
{
return ArrayBoard[][];
}
This method expects to return a String but you are returning a 2D Integer array, what you need is a String. the toString() method returns a string representation of the object, so in this case, what you can do is to use a StringBuilder to build the string representation of the array and then, use the .toString() of the StringBuilder to return the string representing the 2D Array.
Also, as noted by Alois Cochard, you variable naming does not follow convention. Variable names in Java use a camel case notation.
I for one don't really understand your question but I've got a couple of comments.
The class variables i and j should be local variables in each method.
Your naming convention is nonstandard, seems like a more C# convention. Start variable and method names with a lower case.
CardCheck isn't defined anywhere. I presume it is meant to indicate if a number on a square has been checked, in which case it should be a boolean and not an int.
toString doesnt return a string. You can use Arrays.toString to help you.
Similarily, ShowBoard just returns one element of an array, you probably wanted to show the entire board there.
For your toString and ShowBoard methods you probably want to use a StringBuilder to build up the string representation.
StringBuilder builder = new StringBuilder();
for (int i=0; i<BOARDMAX; i++) {
for (int j=0; j<BOARDMAX; j++) {
builder.append(StrArrayBoard[i][j]);
}
builder.append('\n');
}
return builder.toString();
Here's a version of your class that compiles (and I changed some field names and modifiers to adhere to standard conventions). Try this:
public class Card{
private final Random generator = new Random();
private static final int BOARDMAX = 4;
private static final int NUMMAX = 59;
int i, j, m, n;
private final int[][] arrayBoard = new int[BOARDMAX][BOARDMAX];
private final String[][] strArrayBoard = new String[BOARDMAX][BOARDMAX];
// do something here please
private int[][] CardCheck;
public void RandomNumGenerator(){
for(i = 0; i < BOARDMAX; i++){
for(j = 0; j < BOARDMAX; j++){
arrayBoard[i][j] = generator.nextInt(NUMMAX + 1);
}
}
}
public String ShowBoard(){
for(i = 0; i < BOARDMAX; i++){
for(j = 0; j < BOARDMAX; j++){
m = i;
n = j;
if(j != BOARDMAX){
strArrayBoard[m][n] = arrayBoard[m][n] + " ";
} else{
strArrayBoard[m][n] = arrayBoard[m][n] + " \n";
}
}
}
return strArrayBoard[i][j];
}
public void ShowMark(){
for(i = 0; i < BOARDMAX; i++){
for(j = 0; j < BOARDMAX; j++){
if(CardCheck[i][j] == 1){
strArrayBoard[i][j] = arrayBoard[i][j] + "* ";
} else{
strArrayBoard[i][j] = arrayBoard[i][j] + " ";
}
if(j == BOARDMAX){
// this is probably what you mean:
strArrayBoard[i][j] = arrayBoard[i][j] + "\n";
}
}
}
}
#Override
public String toString(){
// this is probably what you mean:
return Arrays.deepToString(strArrayBoard);
}
}