This might be a stupid question but we're beginners and I didn't find an answer to my problem so here it is: We're developping a file system (small based) and we have this method that is supposed to move files from one Directory to another. (Deleting the file or directory from one and adding to another.)
We're using ArrayLists to store the Items (Item is then superclass of Directory and File).
Because of the fact that everything has to be sorted alphabetically, the method to move contains a while loop to verify where the item has to be placed (no preferences to Directories or Files) but for some reason the break statement I inserted is ALWAYS executed (or at least that's what I think is the reason.) Thanks!
Here's the code:
if(item != null){
boolean bool = false;
int i = 0;
loop: while(!bool && i <= items.size()-1) {
if(i==0) {
if(checkIfAlphabetic(item.getName(), items.get(0).getName())){ items.add(0,item);
bool = true;
}
else{
break loop;
}
}
else if(checkIfAlphabetic(items.get(i-1).getName(), item.getName()) && checkIfAlphabetic(item.getName(), items.get(i).getName() )) {
items.add(i, item);
bool = true;
}
else i++;
}
if(!bool){
items.add(item);
}
setModificationTime();
}
I already excuse myself if there are some things unclear.
PS. Also for some reason the Item I want to add always gets added twice.
As requested, the code for checkIfAlphabetic:
private boolean checkIfAlphabetic(String search, String target){
int[] searchInt = search.codePoints().toArray();
int[] targetInt = target.codePoints().toArray();
int i = 0;
while(i<search.length() && i<target.length()){
if(searchInt[i] > targetInt[i]){
return false;
}
else if(searchInt[i] < targetInt[i]) return true;
else i++;
}
if(search.length() < target.length()){
return true;
}
else return false;
}
Your while loop is faulty. It will always stop after the first iteration, no matter what.
This is what happens in order of statements. This is pseudo-code, not Java. Don't copy/paste, it won't work.
boolean bool = false;
int i = 0;
// entering the while loop:
if (!bool && i <= items.size() - 1) // returns true. We go in the while loop.
if (i == 0) // returns true, we go in that block.
if (check... ) // if this returns true, this happens:
bool = true;
else // if the previous statement returns false, this happens:
break;
So here, if the check... returns false, we're gonna get out of the loop. Let's continue in the other case:
// nothing else happens inside the loop, so go back to the loop condition.
if (!bool && i <= items.size() - 1) // Hey, wait a minute, bool is true. So "not" true is false. The condition is therefore not met, let's leave the loop.
So this is what happens, after a single execution, no matter what, your code exits the loop. In your scenario, bool = true is the near absolute equivalent to a break.
This is what you need to fix.
If I had to write your code, this is how I'd do it:
List<Item> items = ... ;
java.util.Collections.sort(items, new ItemNameComparator());
private static class ItemNameComparator implements Comparator<Item> {
#Override
public int compare(Item a, Item b) {
return a.getName().compareTo(b.getName());
}
}
If you use Java 8:
List<Item> items = ...;
items.sort((a, b) -> a.getName().compareTo(b.getName()));
All the tools exist in the Java libraries, use them instead of reimplementing them again and again.
Related
I have a piece of code that I need insight on, I don't want to know the correct solution of the problem. I just want to know why is my concept failing.
So the function is to check if a binary tree is BST or not. I need to return 1 in case it is and 0 otherwise. My code is as below
int isBST(Node root) {
if(root == null)
return 1;
if(root.left!=null) {
if(root.left.data<root.data)
isBST(root.left);
else
return 0; // line:a
}
if(root.right!=null) {
if(root.right.data<root.data)
isBST(root.right);
else
return 0;
}
return 1;
}
For this piece, when i have a binary tree as follows:
5
\
7
/
8
I expect it to reach 8 value and break at line:a but it return me 1 instead of 0. Now I know 0 gets returned to the parent calling method. But is it not terminating because I have made isBST call without capturing the return value?
Please dont point out if there are anyother bugs.
For the general case, your approach won't work. The way to test if a tree is a BST is to recursively check if the current node is greater than the maximum element of the left subtree, and smaller than the minimum element of the right subtree. Also, you're missing the returns in the recursive calls:
return isBST(root.left);
...
return isBST(root.right);
By the way, why are you returning 0 or 1 for this? use false or true instead, changing the return type to boolean.
You should check if the right data ist bigger than the current and return the value of the recursive call
if(root.right.data>root.data)
I see the following issues:
If (and only if) isBST(root.left) or isBST(root.right) is false, you need to return 0 (btw, why are you not using booleans?) immediately.
The condition root.right.data<root.data should be inverted: root.right.data>=root.data.
So here's the modified code (keeping the int return type):
int isBST(Node root) {
if(root == null)
return 1;
if(root.left!=null) {
if(root.left.data<root.data) {
if (isBST(root.left) == 0)
return 0;
} else
return 0;
}
if(root.right!=null) {
if(root.right.data>=root.data) {
if (isBST(root.right) == 0) {
return 0;
}
} else
return 0;
}
return 1;
}
I am using BlueJ IDE to write java programs.
I have a method with String return type. I have put the return statements within if-else, such that if the boolean variable "flag" has true value, then one value is returned, while if the value is false, another value is returned.
Now, the problem is that BlueJ asks for another return statement even after this, as shown below.
If I give another return after if-else, it works.
Why is this happening? I had learnt that there can be no statements after the return statement. So, why is the compiler asking for another return statement?
If someone wants the code for cut-paste purposes, here it is. This code is meant to convert binary numbers to their decimal equivalents, including fractions, but no negative numbers.
public class Conversions{
protected String Binary_Decimal(String str){
int a = str.indexOf('.');
boolean flag = false;
if (a == -1){
str += ".0";
a = str.indexOf('.');
flag = true;
}
String bd = str.substring(0, a);
String ad = str.substring(a + 1);
a = 0;
double num = 0;
for (int i = bd.length() - 1; i >= 0; i--){
num += Math.pow(2, a) * Integer.parseInt(Character.toString(str.charAt(i)));
a++;
}
if (flag == true){
return Integer.toString((int) num);
}
else if (flag == true) {
a = -1;
for (int i = 0; i < ad.length(); i++){
num += Math.pow(2, a) * Integer.parseInt(Character.toString(str.charAt(i)));
a--;
}
return String.valueOf(num);
}
return String.valueOf(num); //<-- WHY DOESN'T IT RUN WITHOUT THIS EXTRA return?
}
}
Here, str is the string that is input by the user using a different method Input().
The issue is that you wrote an if - else as an if - else if. The compiler does not understand or care that the two conditions you have are mutually exclusive and therefore cover all cases. Given how you wrote the branches, you need an explicit else or a catchall return for the compiler to be assured that the function always returns a String.
This is one example of why it is a bad idea to explicitly spell out the else when you have a set of conditions. The more important reason being that your if will often contain something much more complex and you might not negate it properly.
Delete the second ELSE IF clause and put the block directly after the first return statement, and consider that flag is a boolean. As follows:
if (flag) return Integer.toString((int) num);
a=-1;
for(....){
....
}
return String.valueOf(num);
In this way, the compiler should not notify you that error.
So, why is the compiler asking for another return statement?
Because you are missing a default return statement.
What if none of the conditions you have satisfied ? There must be something return default right ? That is what the issue is. That is why it is getting compiled when you uncomment that line.
Or even , you have an else statement, your program will have at least one satisfied return and it gets compiled too. Try it.
I had learnt that there can be no statements after the return statement.
This statement comes with some conditions. You have the return statement inside the if condition. So if your expression is not true, there is no way that the return gets execute.
I have some code that I would like to make more efficient by recursion. Trouble is I don't know where to start. The code compares two arraylists a and b to see if they are equal. Assume the sizes of both arrays are equal.
The code is
public boolean isEqual(A B) {
boolean answer = false;
if (lessThanOrEqualTo(B) == true);
for (int i = 0; i < DList.size(); i++) {
if (DList.get(i) == B.DList.get(i)) answer = true;
else answer = false;
}
return answer;
}
I have currently written
public boolean isEqualRecursion(A B) {
if DList.size() == 0;
return false();
} else {
}
I know the stopping case is 0 as when size is 0 nothing happens. I have no idea what to write next
Any help will be appreciated
Thanks
I have some code that I would like to make more efficient by recursion.
It is unlikely that you can make it more efficient by recursion. The chances are that it will be less efficient, and also fragile. This is because standard Java compilers don't implement tail-call optimization. The fragility occurs because a recursive comparison algorithm is liable to trigger a stack overflow if the input arrays are large enough.
However, if you want to continue with this as "an exercise", then my HINT is to add an index argument to the isEqualRecursion signature ...
I think that this is a pretty good start for you. This looks through all your elements, assuming they are an array, and then checks if they are equal in size.
public boolean isEqual(ArrayList<?> a, ArrayList<?> b) {
if (a.size() != b.size())
return false;
for (int i = 0; i < a.size(); i++) {
if (!isEqual((ArrayList<?>)a.get(i), (ArrayList<?>)b.get(i))) {
return false;
}
}
return true;
}
Now a couple of things to consider:
This assumes that the content of a(and b) must be an ArrayList at line (ArrayList<?>)a.get(i) what if our ArrayList actually contains something else, like an Integer?
What if our array lists contain null as an item?
What if we pass in two null ArrayLists? (or even just one?)
I'm not sure the point of your function lessThanOrEqualTo(B) is this part of the question or did you write this down wrong?
Also what is a DList?
This is a typical recursion question. You might want to try something like this:
int x = 0;
if(Dlist.get(x) != B.Dlist.get(x)) {
return false;
} else {
x+1;
}
if( x!= dList.size()) {
recursion;
}
return true;
I have several small arrayLists (800~1500) and for each one of those I must verify if it contains all items from a evaluation arrayList in the best possible time. Both the target arrayList (let's say, tSet) and the evaluation arrayList (eSet) have 1 to 5 elements.
I have tried a sequence of simple loops (current implementation), with a execution time of ~10 seonds, and containsAll(), with an inconsistent execution time ranging from 8 seconds to 16 seconds (using the same tSet). Is there a reason for this inconsistency? Is there a better way to perform this action?
Array elements are from the following class:
public class ItemBD_Temp implements Comparable<ItemBD_Temp> {
private String sTabela;
private String sValor;
private String sNome;
...
}
which also has a compareTo() method:
public int compareTo(ItemBD_Temp o) {
String concatThis;
String concatOther;
if(this.sTabela.equals("*AnyTable*") || o.sTabela.equals("*AnyTable*")){
concatThis = "";
concatOther = "";
}
else if(this.sNome.equals("*AnyAtrib*") || o.sNome.equals("*AnyAtrib*")){
concatThis = this.sTabela;
concatOther = o.sTabela;
}
else if(this.sValor.equals("*AnyValue*") || o.sValor.equals("*AnyValue*")){
concatThis = this.sTabela + this.sNome;
concatOther = o.sTabela + o.sNome;
}
else{
concatThis = this.sTabela + this.sNome + this.sValor;
concatOther = o.sTabela + o.sNome + o.sValor;
}
return concatThis.compareTo(concatOther);
}
and this is a very simplified version of what I have so far:
for(int j = 0; j < eSet.itens.size() && tSetAllowed == true; j++){
itemFound = false;
//CURRENT ITEM TO BE SEARCHED
eItem = new ItemBD_Temp(eSet.itens.get(j));
//CHECK IF CURRENT ITEM IS ON THE CURRENT tSet. IF FOUND, STOPS AND CHECKS NEXT eItem
for(int k = 0; k < tSet.size() && itemFound == false; k++){
tItem = tSet.get(k);
if(tItem.compareTo(eItem) == 0){
itemFound = true;
}
else{
itemFound = false;
}
}
//IF tItem WASN'T FOUND, THEN tSet CAN BE DISCARTED
if(itemFound==false){
tSetAllowed = false;
}
}
EDIT 1:
In order to use arrayList.containsAll() I also had to override the Equals method, as follows:
#Override
public int hashCode() {
int hash = 3;
hash = 89 * hash + (this.sTabela != null ? this.sTabela.hashCode() : 0);
hash = 89 * hash + (this.sValor != null ? this.sValor.hashCode() : 0);
hash = 89 * hash + (this.sNome != null ? this.sNome.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object obj) {
System.out.println("OVERRIDED EQUALS");
if (getClass() == obj.getClass()) {
if(this.sTabela.equals("*AnyTable*") || ((ItemBD_Temp)obj).sTabela.equals("*AnyTable*")){
return true;
}
else if(this.sNome.equals("*AnyAtrib*") || ((ItemBD_Temp)obj).sNome.equals("*AnyAtrib*")){
if(this.sTabela.equals(((ItemBD_Temp)obj).sTabela))
return true;
else
return false;
}
else if(this.sValor.equals("*AnyValue*") || ((ItemBD_Temp)obj).sValor.equals("*AnyValue*")){
if((this.sTabela+this.sNome).equals( (((ItemBD_Temp)obj).sTabela+((ItemBD_Temp)obj).sNome) ))
return true;
else
return false;
}
else{
if((this.sTabela+this.sNome+this.sValor).equals( (((ItemBD_Temp)obj).sTabela+((ItemBD_Temp)obj).sNome+((ItemBD_Temp)obj).sValor) ))
return true;
else
return false;
}
}
else{
return (this == obj);
}
}
This is needed because different objects like obj1 = {sTabela = "1", sNome = "2", sValor="3"} and obj2 = {sTabela = "AnyTable", sNome = "AnyAtrib", sValor="AnyValue"} should be considered equivalent.
You are using ArrayList as a data structure. It is an unsynchronized data structure. In your question there are only read operations, so should not be a problem. However, overall in your program with so many unsynchronized lists, think about thread safety.
For ArrayList accessing element via iterator or via index is almost the same in terms of speed. However, that is not an official benchmark. You might consider trying your code with iterators also.
I have several small arrayLists (800~1500) and for each one of those I
must verify if it contains all items from a evaluation arrayList in
the best possible time. Both the target arrayList (let's say, tSet)
and the evaluation arrayList (eSet) have 1 to 5 elements.
You have between 800 and 1500 array lists. I suppose you "are obliged" to use that datastructure.
You have 1 evaluation arrayList. Here I would consider a change maybe. I would use a Hash table/map as a data structure.
In average the search is faster. This is proven to be correct. The average time complexity for inserting/deleting/searching an element in a hash table/map is O(1). This means constant time in average. (The worst case is O(n), but in general we are interested in the average).
"If a target list contains all items of an evaluation list" is equivalent to "all evaluation list items are in target list". In your example you loop through target list and compare, but you could as well loop through evaluation list and compare.
Now assuming that you always want to test whether evaluation
list is a sub set of target list. It is better to loop through
evaluation list and do the comparison as it is expected to have less
elements.
I will go through your code later. But there is one thing that I don't feel comfortable with:
The conditions in your loop! Are you sure your algorithm works as expected?
If the die shows a 6, the player doesn't move at all on this turn and also forfeits the next turn.
To accomplish this, I have tried an integer type warning marker variable for the player and an integer type time counter variable.
If the die shows 6, I want to increment the warning marker variable by 1 during the first run(and have the while loop do nothing), then keep the value at 1 during the second run (while loop will not work), then lower it back down to 0 for the third run of the while loop (so the while loop will work). The marker will stay at zero unless the die shows a 6 again, after which the same process will repeat.
I have a while loop like this:
while the warning marker is equal to 0 {
Do Stuff
if the die shows a 6, the warning marker increases by 1.
the time counter also increases by 1.
}
How do I manipulate the variables to get the result that I need? Or is my partially complete method absolutely off in terms of logic?
Thanks.
Can u tell me if this works for you?
flag=true;
while condition{
if flag==true{
if die == 6
{
flag=false;
continue;}
}
else { Do STUFF }
} else
{
flag==true;
}
}
I think you want to reword this problem.
This is what I understood. You have a warning marker.
You have a loop that checks whether the marker is 0, if it is then you do something.
If the die is a six, you will increase the warning marker. If its new value is 3, then you will reset it to 0. Meanwhile, the time counter is always increasing.
If this is correct, I think you want something like:
int warningMarker = 0;
int timeMarker = 0;
while (true) {
if (die == 6) {
++warningMarker;
if (warningMarker == 3) {
warningMarker = 0;
}
}
if (warningMarker == 0) {
doSomething();
}
++timeMarker;
}
Java is Object-Oriented Pragramming language. Use this feature.
See following pseudocode and let me know if you have problem in undestanding it.
Create a class Player as following:
class Player
{
boolean skipChance = false;
... // Other fields
... //
}
Change your while as following:
while(isGameOn())
{
Player p = getCurrentPlayer();
if( ! p.skipChance)
{
int val = p.throwDice();
if(val == 6)
{
p.skipChance = true;
continue; // control moves to while.
}
// Do stuff
}
else
{
p.skipChance = false;
}
}