Breadth-First Search Algorithm JAVA 8-puzzle - java

Im trying to implement the Breadth-First algorithm for 8 puzzle game. I know that it is not a new case and theres a bunch of solutions on web, but I want to make it on my way of thinking.
This code already finds the node result, which is
123
456
780
But it takes 350,000 steps to do it!
Any thoughts would be appreciated!
=)
//This method receives a Collection of `Nodo` objects, each one will be checked and compare with the finalGoal
public void percorreNodos(Collection<Nodo> nodosBase)
{
//In this class a have an array that has all the IDs os nodes that already has been checked
//The ID of a Node, is the representation: 123456780, 354126870 , etc..
System.out.println("idsPercorrido.size() = " + idsPercorridos.size());
//Check if the collection nodosBase contains the finalGoal
Iterator<Nodo> iterator = nodosBase.iterator();
while( iterator.hasNext() )
{
Nodo nodoBase = (Nodo) iterator.next();
//If this current node has already been checked, we dont have to check it again
idsPercorridos.add( nodoBase.getId() );
//Just print the node (sysout)
nodoBase.print();
contPassos++;
System.out.println( "\n" + contPassos + " STEPS(number of nodes checked)..." );
//Check if this node is the final goal
if( nodoBase.isObjetivoFinal() )
{
//set the variable indicating that the result has been found
encontrouObjetivo = true;
System.out.println( "Resultado alcancado EM " + contPassos + " PASSOS..." );
nodoBase.print();
break;
}
}
// Now that we know that no one Node of nosoBase collection is the final goal, we are going to generate the next children to be checked, and call this function recursively
//Just confirm that we didnt find the goal
if(encontrouObjetivo == false)
{
//Creates the next frontier
Collection<Nodo> novaFronteira = new HashSet<Nodo>();
for(Nodo nodoPai : nodosBase)
{
//Generate each Node its childrens and add to a collection called "novaFronteira"
Collection<Nodo> filhos = nodoPai.gerarFilhos();
for(Nodo filho : filhos)
{
//idsPercorridos is a collection<String> which contains all the nodes ids that we checked, we dont want to check a node more than one time !
if( idsPercorridos.contains( filho.getId() ) == false )
{
novaFronteira.add( filho );
}
}
}
this.percorreNodos( novaFronteira );
}
}

You could make sure you don't add duplicate elements to novaFronteira.
There's nothing preventing this code:
for(Nodo nodoPai : nodosBase)
{
Collection<Nodo> filhos = nodoPai.gerarFilhos();
for(Nodo filho : filhos)
{
if( idsPercorridos.contains( filho.getId() ) == false )
{
novaFronteira.add( filho );
}
}
}
From adding many duplicate nodes to novaFronteira.
If you were to add to idsPercorridos inside the if-statement, that would prevent this from happening, and result in less steps, although, depending on exactly what your data and data structures looks like, the added running time of this call may actually make it take longer than it did originally.
If the problem is running time, you should make sure that idsPercorridos is a TreeSet or HashSet, as these allow for efficient contains calls, as opposed to ArrayList or LinkedList, which don't.
If this doesn't help, you could try using the A* algorithm instead, which involves adding a heuristic function to each node, which is the distance to the target - this allows us to explore the nodes closer to the target first, often resulting in less steps to get there.
A good heuristic function might be the sum of Manhattan distances between each tile and its target location.
Note that this would involve quite a few changes to your current code.

According to Wikipedia there are 9!/2 = 181440 possible solvable combinations to this puzzle. If you check each node for each of these combinations (which you don't, but it makes the calculation easier), it makes about (9!/2) * 9 = 1,632,960 steps. Therefore, there I don't see an issue if it takes your algorithm 350,000 steps because a computer can do those steps really fast.

Related

How do I select a specific element from a set with similar XPath paths?

There are 2 drop-down lists. Each has a similar meaning, for example, "Jorge". Lists in different modules. When I need to fill in, for example, a list that is lower in the tree, then the first match is taken along the XPath path, on an undisclosed list.
Not lists, but values in drop-down lists!
There are 2 drop-down lists. Each has a similar meaning, for example, "Jorge". Lists in different modules. When I need to fill in, for example, a list that is lower in the tree, then the first match is taken along the XPath path, on an undisclosed list.
Not lists, but values in drop-down lists!
I wanted to implement it in Java this way:
Example:
if (findElement(By.xpath("(//example//example)")).isDisplayed()) {
findElement(By.xpath("(//example//example)")).click();
}
But in this case, the element is not displayed.
How to implement a search of all values similar to the XPath path in order to get the one that is displayed?
I tried to do something like this: (//example//example)1 (//example//example)[2] (//example//example)[3]
In my case, we have that 1 - the element does not exist [2] - exists, but is not displayed (isDisplayed = false) [3] - exists, is displayed (isDisplayed = true)
iterating through the values in the loop for [n] cannot be implemented, because, for example, the value 1 is not.
Described as difficult as possible :D. Excuse me.
If someone understands my nonsense, please help me. How to implement my requirement?
enter image description here
UPD:
The problem was solved (for me) by substituting the first value into the expression ()"{1}" immediately.
Now I'm interested in why I get an exception after the first iteration:
Method threw 'org.openqa.selenium.ElementNotInteractableException' exception.
Code:
int number = 1;
String option = "(//ul[contains(#style, 'display: block')]//li//span[contains(text(),'" + valueField + "') or strong[contains(text(),'" + valueField.toUpperCase() + "')]])";
findElement(By.xpath(option+"["+number+"]"));
String[] words = valueField.split(" ");
StringBuilder builder = new StringBuilder();
for (int i = 0; i < words.length; i++) {
builder.append(words[i]);
setFieldByLabel(nameModule, nameLabel, builder.toString());
fastWaitLoading();
for (int y = 0; y < 10; y++) {
if (findElement(By.xpath(option+"["+number+"]")).isDisplayed()) {
new Actions(browser.getWebDriver())
.moveToElement(findElement(option))
.click()
.build()
.perform();
break;
}
number++;
}
}
So I am trying to fully understand your question, and I don't. What I would recommend for a situation like this is, iterate through all elements by creating a list with: findElements(By.xpath ... )
This way you will get a list of webelements and you can iterate through them. Then apply a foreach, assert if element is displayed (it exists as it has been found with findElements) and you should be able to interact with it.
Yeah, everything is in a prominent place)
Missed it
new actions(browser.getWebDriver()) .moveToElement(findElement(**option**)) .click() .build() .perform(); break;
Here
new actions(browser.getWebDriver())
.moveToElement(findElement(**option + "[" + number+"]"**))
.click()
.build()
.perform();
break;

How to quickly insert an element into array with duplicates after all of the equal elements?

I have an ArrayList, which contains game objects sorted by their 'Z' (float) position from lower to higher. I'm not sure if ArrayList is the best choice for it but I have come up with such a solution to find an index of insertion in a complexity faster than linear (worst case):
GameObject go = new GameObject();
int index = 0;
int start = 0, end = displayList.size(); // displayList is the ArrayList
while(end - start > 0)
{
index = (start + end) / 2;
if(go.depthZ >= displayList.get(index).depthZ)
start = index + 1;
else if(go.depthZ < displayList.get(index).depthZ)
end = index - 1;
}
while(index > 0 && go.depthZ < displayList.get(index).depthZ)
index--;
while(index < displayList.size() && go.depthZ >= displayList.get(index).depthZ)
index++;
The catch is that the element has to be inserted in a specific place in the chain of elements with equal value of depthZ - at the end of this chain. That's why I need 2 additional while loops after the binary search which I assume aren't too expensive becouse binary search gives me some approximation of this place.
Still I'm wondering if there's some better solution or some known algorithms for such problem which I haven't heard of? Maybe using different data structure than ArrayList? At the moment I ignore the worst case insertion O(n) (inserting at the begining or middle) becouse using a normal List I wouldn't be able to find an index to insert using method above.
You should try to use balanced search tree (red-black tree for example) instead of array. First you can try to use TreeMap witch uses a red-black tree inside to see if it's satisfy your requirements. Possible implementation:
Map<Float, List<Object>> map = new TreeMap<Float, List<Object>>(){
#Override
public List<Object> get(Object key) {
List<Object> list = super.get(key);
if (list == null) {
list = new ArrayList<Object>();
put((Float) key, list);
}
return list;
}
};
Example of usage:
map.get(0.5f).add("hello");
map.get(0.5f).add("world");
map.get(0.6f).add("!");
System.out.println(map);
One way to do it would to do a halving search, where the first search is half way thru your list (list.size()/2), then for the next one you can do half of that, and so on. With this exponential method, instead of having to do 4096 searches when you have 4096 objects, you only need 12 searches
sorry for the complete disregard for technical terms, I am not the best at terms :P
Unless I overlook something, your approach is essentially correct (but there's an error, see below), in the sense that your first while tries to compute the insert-index such that it will be placed after all lower OR EQUAL Z: there's correctly an equal sign in your first test (updating "start" if it yields TRUE).
Then, of course, there's no need to worry anymore about its position among equals. However, your follow-up while destroys this nice situation: the test in the first follow-up while yields always TRUE (one time) and so you move back; and then you need the second follow-up while to undo that. So, you should remove BOTH follow-up whiles and you're done...
However, there's a little problem with your first while, such that it doesn't always exactly do what the purpose is. I guess that the faulty outcomes triggered you to implement the follow-up whiles to "repair" that.
Here's the issue in your while. Suppose you have a try-index (start+end)/2 that points to a larger Z, but the one just before it has value Z. You then get into your second test (elseif) and set "end" to the position where that Z-value resides. Finally you wind up with precisely that position.
The remedy is simple: in your elseif assignment, put "end = index" (without the -1). Final remark: the test in the elseif is unnecessary, just else is sufficient.
So, all in all you get
GameObject go = new GameObject();
int index = 0;
int start = 0, end = displayList.size(); // displayList is the ArrayList
while(end - start > 0)
{
index = (start + end) / 2;
if(go.depthZ >= displayList.get(index).depthZ)
start = index + 1;
else
end = index;
}
(I hope I haven't overlooked something trivial...)
Add 1 to the least significant byte of the key (with carry); binary search for that insert position; and insert it there.
Your binary search has to be so constructed as to end at the leftmost of a sequence of duplicates, but this is trivial given an understanding of the various Binary search algorithms.

Finding middle element of linked list with 1 pass, is this a creative "useless answer"?

Suppose you want to find the middle node of a linked list in as efficient a way possible. The most typical "best" answer given is to maintain 2 pointers, a middle, and current. And to increment the middle pointer when the # of elements encountered is divisible by 2. Hence, we can find the middle in 1 pass. Efficient, right? Better than brute force, which involves 1 pass to the end, then 1 more pass until we reach size/2.
BUT... not so fast, why is the first method faster than the "brute force" way? In the first method, we're incrementing the middle pointer approximately size/2 times. But in the brute force way, in our 2nd pass, we're traversing the list until we reached the size/2th node. So aren't these 2 methods the same? Why is the first better than the 2nd?
//finding middle element of LinkedList in single pass
LinkedList.Node current = head;
int length = 0;
LinkedList.Node middle = head;
while(current.next() != null){
length++;
if(length%2 ==0){
middle = middle.next();
}
current = current.next();
}
if(length%2 == 1){
middle = middle.next();
}
If we modify the code to be:
while(current.next() != null){
current = current.next();
middle = middle.next();
if(current.next() != null){
current = current.next();
}
}
Now there are fewer assignments since length does not have to be incremented and I do believe this will give an identical result.
At the end of the day both solutions are O(N) so it is a micro-optimization.
As #Oleg Mikheev suggested, why can't we use Floyd's cycle-finding algorithm to find the middle element, as follows:
private int findMiddleElement() {
if (head == null)
return -1; // return -1 for empty linked list
Node temp = head;
Node oneHop, twoHop;
oneHop = twoHop = temp;
while (twoHop != null && twoHop.next != null) {
oneHop = oneHop.next;
twoHop = twoHop.next.next;
}
return oneHop.data;
}
The first answer has multiple advantages:
Since the two methods are of the same complexity O(N), any analysis on the efficiency needs to be careful, maybe involving the specific implementation and cost model. However, for the most naive implementation, the first method can save some loop variable increments.
It save you one variable's space - the two pointers v.s. the length, the counter and one pointer. Also, what if it is a huge list, and the length overflowed?
However, if you consider some specific model, then the second method might be much better. If the elements are all adjacent in memory, and the list is large enough , the cache can only hold one place of continuous memory, the first method might incur some memory access cost. At the end of the day, these two methods are mostly equivalent. Of course, the technique used in the first method is more flashy, and the thought process might be useful in other contexts.
public void middle(){
node slow=start.next;
node fast=start.next;
while(fast.next!=null)
{
slow=slow.next;
fast=fast.next.next;
}
System.out.println(slow.data);
}
10->9->8->7->6->5->4->3->2->1->
5
This is classic job interview question.
They don't want you to come with algorithm O(n), because both of them has O(n) complexity. Common person will say, there's no way to know where is middle if i don't traverse once (so traversing once to find length, and traversing 2nd time to find middle is two passes for those who interview you). They want you to think outside of box, and figure out way you mentioned which include two pointers.
So the complexity is same, but the way of thinking is different, and people who interview you want to see that.

Attempting to remove an Element at specific location in user-defined Doubly Linked List

This is from an old homework problem, that I already turned in, but I wasn't able to figure it out. I'm trying to remove an element from my LinkedList at a specific index using my user-defined class. Below is the pseudo code I'm working off of, but it doesn't have the same parameters as mine so I tried modifying it, but had an issue. I'm a programming noob (roughly 6 months of experience), just FYI. I understand ArrayLists just fine, but LinkedLists have been giving me trouble.
/*
* Remove the nth element in the list. The first element is element 1.
* Return the removed element to the caller.
function remove(List list, Node node)
if node.prev == null
list.firstNode := node.next
else
node.prev.next := node.next
if node.next == null
list.lastNode := node.prev
else
node.next.prev := node.prev
destroy node
*/
My method asks the user to enter an index position to delete. Because an int and LinkEntry are different types, naturally I'm having issues. I don't know how to incorporate the int that is passed through the parameter.
public void remove(int n)
{
LinkEntry<E> remove_this = new LinkEntry<E>();
remove_this.element = n;
for (remove_this = head; remove_this != null; remove_this = remove_this.next)
{
//removes the head if list is only 1 item long
if (head.next == null)
head = remove_this.next;
else
//sets previous element to the next element
remove_this.previous.next = remove_this.next;
//if nothing comes after remove_this, then remove the tail element
if (remove_this.next == null)
tail = remove_this.previous;
else
//sets next previous element to current previous element
remove_this.next.previous = remove_this.previous;
}
}
If you know of anywhere that gives another example that is more similar to what I'm trying to solve I would really appreciate it. I've looked through my text and online, but no luck.
You should set a counter to zero, browse your linked list from its first element (apparently named "head"), and increment the counter until its equal to n (or you reached the end of the list).
When counter equals to n, you must connect previous entry to next, and next to previous (so it deconnects the Nth). You also have to take care of special cases, when n=1 (you're supposed to delete "head" entry, that is to say set head to head.next), when next is null (n = list length), and when n negative or greater than list length.
When I learned this in galaxy far, far away ... it helped me to paint it on paper. Something like this:
You have
A B C
next *------>*------>*---->NULL
prev NULL<---*<------*-------*
and you want
A C
next *------>*---->NULL
prev NULL<---*<------*
So if you find B, you know what to do. But how to find B? B is the second element in our example above, so we'll be given a "1" in zero-based lists or a "2" in one-based lists.
A typical scenario would be to hold a reference to the first element of the list. This is often referred to as the "head". Now you would start with that head and follow its next-pointer. What do you get? The second element in the list. In our example that would already be our "B". Notice, that we followed next 1 time ... now assume we were to delete C. We got index 2 ( or one-based: 3) , we startet with head, followed next 1 time and got B. 1<2 so follow next again. Notice that we have to follow B's next instead of "head"'s So if using a loop, we'll have to use some sort of local var. Now we have the 2nd Element, which is C and remove it. Notice that C's "next" is null. So we are done in that direction.

issues with iterative code in java

I want to convert the recursive function given below:
LinkedList i=a; //a contains the nodes which are adjacent to the last element of g
for(String i1: i )
{
if(g.contains(i1) || i1.equals("o"))
{ continue; }
g.addLast(i1);
func(g);
g.removeLast();
}
I want to convert the above program to an iterative one. Can someone help
LinkedList i=a; //a contains the nodes which are adjacent to the last element of g
for(String i1: i )
{
if(g.contains(i1) || i1.equals("o"))
{ continue; }
g.addLast(i1);
func(g);
g.removeLast();
}
So walking through this it appears as though the steps are as follows:
1) Check for existence of current String or if it equals "o"
2a) If yes continue
2b) else put current string at end of list.
3) repeat steps 1->2
4) remove the last element of the list
If I were to make the code as simple as possible given those steps it would look like so:
func(LinkedList ll)
{
Set set = new HashSet(ll); //removes all duplicates
if(set.contains("o") { set.remove("o") ;} //these are strings so that works
LinkedList newLL = new LinkedList(set); //order still retained
newLL.poll(); //remove last element
}
If I understand correctly your code, it finds all the available paths, right ?
The main 2 issues I see in your 2nd code are :
In the recursive version, you handle the path with currentNode by calling func, then remove currentNode. In the iterative version, you put visitedNodes in the stack "to be handled", and then alter visitedNodes before it was handled !
Related issue : you're always stacking over and over the same visitedNodes
So some solutions would be to put in the stack a copy of visitedNodes + the element currentNode.
visitedNodes will not be altered this way
I can do a bit of code if needed

Categories