I'm writing a program in Java to solve puzzles from this game:
http://universefactory.net/0/
I've modeled the problem as follows
Node Class:
package model;
import java.util.ArrayList;
public class Node {
private final int nodeId;
private ArrayList<Edge> edges;
ArrayList<Edge> getEdges() {
return edges;
}
public int getNodeId() {
return nodeId;
}
public Node(int id) {
nodeId = id;
edges = new ArrayList<Edge>();
}
#SuppressWarnings("unused")
private Node() {
nodeId = -1;
}
private void addEdge(Edge toBeAdded) {
if (toBeAdded != null)
edges.add(toBeAdded);
}
public void addEdgeTo(Node to, Star star) {
if(this.equals(to))
return;
if (to != null) {
Edge edge = new Edge(to, star);
addEdge(edge);
}
}
public void addEdgeTo(Node to) {
if(this.equals(to))
return;
if (to != null) {
Edge edge = new Edge(to);
addEdge(edge);
}
}
public Edge getEdge(Node to)
{
Node edgeDestination;
for(Edge edgeIterator: edges)
{
edgeDestination = edgeIterator.goesTo();
if(edgeDestination.equals(to))
return edgeIterator;
}
return null;
}
public Edge popEdge(Node to)
{
Node edgeDestination;
for(Edge edgeIterator: edges)
{
edgeDestination = edgeIterator.goesTo();
if(edgeDestination.equals(to))
{
edges.remove(edgeIterator);
return edgeIterator;
}
}
return null;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Node other = (Node) obj;
if (nodeId != other.nodeId)
return false;
return true;
}
}
Edge class:
package model;
public class Edge {
private final Star star;
private final Node to;
Edge(Node nodeTo) {
star = null;
to = nodeTo;
}
Edge(Node nodeTo, Star star) {
this.star = star;
to = nodeTo;
}
public void consumeEdge() {
if (star != null) {
star.die();
}
}
public boolean consumable() {
if (star == null)
return false;
return star.isAlive();
}
public Node goesTo() {
return to;
}
}
Star Class
package model;
public class Star {
boolean dead = false;
public void die() {
dead = true;
}
public boolean isAlive()
{
return !dead;
}
}
and Graph Class:
package model;
import java.util.ArrayList;
public class Graph {
private ArrayList<Node> nodes = null;
private ArrayList<Star> stars = null;
private Node startNode = null;
private final int startNodeID = 0;
public Graph(ArrayList<Node> nodeArr, ArrayList<Star> starArr) {
// TODO Auto-generated constructor stub
nodes = nodeArr;
stars = starArr;
setStartNode();
}
private void setStartNode() {
for (Node nodeIterator : nodes) {
if (nodeIterator.getNodeId() == startNodeID) {
startNode = nodeIterator;
break;
}
}
}
public Graph(Graph other) {
nodes = new ArrayList<Node>();
stars = new ArrayList<Star>();
nodes.addAll(other.getNodes());
stars.addAll(other.getStars());
setStartNode();
}
public ArrayList<Node> solve() {
final int numberOfStars = stars.size();
ArrayList<Node> solution = new ArrayList<Node>();
solution.add(startNode);
recursiveSolver(startNode, numberOfStars, solution);
return solution;
}
private boolean recursiveSolver(Node currentNode, int numberOfStars,
ArrayList<Node> solutionPointer) {
if (numberOfStars == 0)
return true;
for(Edge edgeIterator: currentNode.getEdges())
{
Node nextNode = edgeIterator.goesTo();
Graph deepCopy = new Graph(this);
currentNode = deepCopy.getNode(currentNode);
nextNode = deepCopy.getNode(nextNode);
//deepCopy.traverse(currentNode, nextNode);
//deepCopy.recursiveSolver(.....);
//Not sure how to finish this <---------------------------PROBLEM AREA
}
}
private Node getNode(Node currentNode) {
return getNode(currentNode.getNodeId());
}
private ArrayList<Node> getNodes() {
return nodes;
}
private ArrayList<Star> getStars() {
return stars;
}
public void linkNodesWith(int fromNodeID, int toNodeID, Star star) {
final Node from = getNode(fromNodeID);
final Node to = getNode(toNodeID);
if (from != null && to != null)
linkNodesWith(from, to, star);
}
private void linkNodesWith(Node nodeFrom, Node nodeTo, Star star) {
nodeFrom.addEdgeTo(nodeTo, star);
nodeTo.addEdgeTo(nodeFrom, star);
}
public Node getNode(int nodeId) {
for (Node iteratorNode : nodes) {
if (iteratorNode.getNodeId() == nodeId)
return iteratorNode;
}
return null;
}
public void removeNode(Node nodeToRemove) {
nodes.remove(nodeToRemove);
for (Node nodeIterator : nodes) {
nodeIterator.popEdge(nodeToRemove);
}
}
public void removeNode(int nodeIdToRemove) {
Node nodeToRemove = getNode(nodeIdToRemove);
removeNode(nodeToRemove);
}
//Last three functions are used to create a specific graph to solve
public void populateEdges() {
for (Node nodeFromIterator : nodes) {
for (Node nodeToIterator : nodes) {
nodeFromIterator.addEdgeTo(nodeToIterator);
}
}
}
public void replaceEdge(int nodeFromID, int nodeToID, Star star) {
Node nodeFrom = getNode(nodeFromID);
Node nodeTo = getNode(nodeToID);
unlinkNodes(nodeFrom, nodeTo);
linkNodesWith(nodeFrom, nodeTo, star);
}
private void unlinkNodes(Node nodeFrom, Node nodeTo) {
nodeFrom.popEdge(nodeTo);
nodeTo.popEdge(nodeFrom);
}
}
I can't figure out a way to solve this without making deep copies of the graph every time a node is deleted/traversed, and even then am not sure as to how I can save the path in an array-list. Is there a better way to model the problem that would simplify the solution?
universefactory.net/0 : the game im trying to write a solution for.
You can do this with a recursive backtracking solution and an immutable graph, for example
1) Construct a graph of all nodes + all edges and a list of stars (each star containing a list of all edges it is on, OR each edge containing a list of references to stars (not copies) that are on its path. Whatever makes more sense to you)
2) Write a recursive method. Its parameters will be:
the graph + list of stars (immutable)
the list of nodes taken so far, in order
the list of edges taken so far, in order
the list of stars left to take
It should do the following:
2a) If it has possible moves to take (edges from the node it's on that aren't in the list of edges taken so far), recursively branch and try each of those next moves, by calling itself with
the graph + list of stars (immutable)
a copy of the list of edges taken so far, in order, adding the new edge taken by this mode
a copy of the list of nodes taken so far, in order, adding the new node taken by this mode
a copy of the list of stars left to take, subtracting new stars taken by this move
2b) If it has no possible modes to take, check if we have taken all stars. If we have, then this is the solution (print out the list of edges taken)
Related
I am new to the concept of Linked list, and I am having a lot of trouble building this custom linked list for the first time.
I have two classes: CellPhone and CellList.
In CellPhone, I have 4 attributes: serialNum(long), brand(String), year(int), and price(double).
In CellList, I have:
an inner class called CellNode, which has two attributes: phone(CellPhone), and next(CellNode)
and two attributes head(CellNode) and size(int)
This is from my CellList class:
private CellNode head; // point first node in this list object
private int size; // current size of the list(how many nodes in the list)
public CellList() {
head = null;
size = 0;
}
public CellList(CellList c) { // is this a correct deep copying?
head = new CellNode(c.head);
size = c.getSize();
}
public int getSize() {
return size;
}
public void addToStart(CellPhone c) {
head = new CellNode(c, null); //head.getPhone() = c, head.getNextNode() = null.
size++;
}
I am not even sure if that addToStart method is correctly done, and now I need to add methods like insertAt(/deleteFrom)Index(CellPhone c, int index). I've done till here:
public void insertAtIndex(CellPhone c, int index) { //index is invalid when it's not 0<index<size-1
if(index<0 || index>size-1) {
throw new NoSuchElementException("index is invalid! System terminated.");
}
but I can't fully understand how this Node thing works, so I am stuck.
Here is the full code:
import java.util.NoSuchElementException;
public class CellList {
class CellNode {
private CellPhone phone;
private CellNode next;
public CellNode() {
phone = null;
next = null;
}
public CellNode(CellPhone c, CellNode n) {
phone = c;
next = n;
}
public CellNode(CellNode c) {
this(c.getPhone(), c.getNextNode());
}
public CellNode clone() {
CellNode c = new CellNode(phone, next);
return c;
}
public CellPhone getPhone() {
return phone;
}
public CellNode getNextNode() {
return next;
}
public void setPhone(CellPhone c) {
phone = c;
}
public void setNextNode(CellNode n) {
next = n;
}
}
private CellNode head; // point first node in this list object
private int size; // current size of the list(how many nodes in list)
public CellList() {
head = null;
size = 0;
}
public CellList(CellList c) {
head = new CellNode(c.head);
size = c.getSize();
}
public int getSize() {
return size;
}
public void addToStart(CellPhone c) {
head = new CellNode(c, null); //head.getPhone() = c, head.getNextNode() = null.
size++;
}
public void insertAtIndex(CellPhone c, int index) { //index is invalid when it's not 0<index<size-1
if(index<0 || index>size-1) {
throw new NoSuchElementException("index is invalid! System terminated.");
}
}
public void showContents() {
while(head.getNextNode() != null) {
System.out.println(head.getPhone()+"---->");
head = head.getNextNode();
}
}
}
If you want to insert a node at an index x you have to,
go to the node at index x-1, store the next value of node x-1 in a temp variable, put the node you want to insert in next property of x-1 node, and put the value in the temp variable in the next property of the node you want to insert.
I'm trying to create a method to remove nodes from a Binary Tree but I am having a problem, it seems to be ok but I have another method for printing all of them and after "deleting" a specific node I use the print method but it prints all of them including the one I've already deleted.
public class BinaryTree
{
Node root;
Node n;
private class Node
{
public Node f; //father
public Node right;
public Node left;
public int key; // key
public String Student;
public int Mark;
public Node(int key)
{
right = null;
left = null;
f = null;
Student = null;
Mark = 0;
}
}
public void remove()
{
System.out.println("");
System.out.println("Which student do you want to delete? Write down his ID.");
int id = Genio.getInteger();
n = new Node(id);
Node temporal = root;
if(root == null)
{
System.out.println("This tree is empty");
}
else
{
while(temporal != null)
{
n.f = temporal;
if(n.key == temporal.key)
{
if(n.f.right == null && n.f.left == null)
{
n = null;
temporal = null;
}
}
else if(n.key >= temporal.key)
{
temporal = temporal.right;
}
else
{
temporal = temporal.left;
}
}
}
}
}
I have this issue, after building my problem implementation, when running Optaplanner:
java.lang.IllegalStateException: The selectionList contains 2 times the same selection (Edge to: MinMax1 from: s4,s5,) and (Edge to: Sum2 from: s3,s4,).
at org.optaplanner.core.impl.heuristic.selector.common.decorator.WeightFactorySelectionSorter.sort(WeightFactorySelectionSorter.java:58)
at org.optaplanner.core.impl.heuristic.selector.entity.decorator.SortingEntitySelector.constructCache(SortingEntitySelector.java:44)
I've read the question in here but no object is null. I've modified the Entity class, which is Edge, to implement AbstractPersistable and before that I've tried to override the equals() method with same results:
#PlanningEntity(difficultyWeightFactoryClass = EdgeDifficultyWeightFactory.class)
public class Edge extends AbstractPersistable{
/**
*
*/
private ArrayList<Node> from;
private Node to;
private double burstTime;
private BufferSize size;
public Edge(){
from = new ArrayList<Node>();
BufferSize p = new BufferSize();
p.setSize(1);
this.size = p;
//new Random().nextInt(1000)+1;
this.burstTime += this.size.getSize();
}
public void setFrom(Node from){
this.from.add(from);
this.calculateEdgeBurstTime();
}
public ArrayList<Node> getFrom(){
return from;
}
public void setTo(Node to){
this.to = to;
}
public Node getTo(){
return to;
}
#PlanningVariable(valueRangeProviderRefs = {"bufferRange"})
public BufferSize getBufferSize(){
return size;
}
public void setBufferSize(BufferSize size){
this.size = size;
System.out.println("Size has been set: "+size);
this.calculateEdgeBurstTime();
}
public void calculateEdgeBurstTime(){
for(Node node : this.from){
this.burstTime+=this.size.getSize()*node.getNodeTime();
}
}
public double getEdgeTime(){
return burstTime;
}
#Override
public String toString(){
StringBuffer sb = new StringBuffer();
sb.append("Edge to: "+to.getID()+" from: ");
for(Node node : this.from){
sb.append(node.getID()+",");
}
return sb.toString();
}
#Override
public boolean equals(Object other){
if (other == null) return false;
if (other == this) return true;
if (!(other instanceof Edge))return false;
Edge otherMyClass = (Edge)other;
boolean checkFrom = true;
if(!(otherMyClass.getTo().getID().equals(this.getTo().getID()))) return false;
for(Node node : otherMyClass.getFrom()){
for(Node nd : this.getFrom()){
if(!(node.getID().equals(nd.getID()))){
checkFrom = false;
}
}
}
System.out.println("checked "+checkFrom+this.toString());
return checkFrom;
}
#Override
public int hashCode(){
HashCodeBuilder builder = new HashCodeBuilder();
builder.append(this.to.getID());
builder.append(this.from);
return builder.toHashCode();
}
}
To better clarify the problem, my EdgeDifficultyWeight class is implemented this way:
public class EdgeDifficultyWeightFactory implements SelectionSorterWeightFactory<SmartNodeGraph,Edge>{
public Comparable createSorterWeight(SmartNodeGraph graph, Edge edge) {
int difficulty = edge.getFrom().size(); //Edges with more dependencies are more difficult to plan
if(edge.getTo() instanceof NetworkNode){
difficulty += difficulty; //Edges to NetworkNodes are more difficult to plan.
}
for(Node node : edge.getFrom()){
if(node instanceof ProcessingNode){
difficulty +=2; //If precedes form ProcessingNode is more difficult to optimise than sensors directly
}else if(node instanceof SensorNode){
difficulty +=1;
}
}
return new EdgeDifficultyWeight(edge,difficulty);
}
public class EdgeDifficultyWeight implements Comparable<EdgeDifficultyWeight> {
private final Edge edge;
private final int difficulty;
public EdgeDifficultyWeight(Edge edge, int difficulty){
this.edge = edge;
this.difficulty = difficulty;
}
public int compareTo(EdgeDifficultyWeight arg) {
return new CompareToBuilder().append(arg.difficulty, this.difficulty).toComparison();
}
}
}
The planning problem is this: I have several separated Tree structures, the Root node of each tree has a ready time, which depends on all providers nodes. I want to make all root nodes time equal, each edge of the tree have a buffer which can be modified in size to change the time of the Father node. By changing the buffers in the several edges I want to make the times at the root level of all tree's equal.
Regarding the explanation, the Edges with more nodes (among other contraints), are more difficult to assign. Using the debugger, seem's that the problem is in this line:
Comparable difficultyWeight = selectionSorterWeightFactory.createSorterWeight(solution, selection);
The Comparable object is always the same.
Can anyone help on this?
Add .append(arg.edge.getId(), this.edge.getId()) in the EdgeDifficultyWeight to distinguish 2 weights that have different edges but the same difficulty.
public class EdgeDifficultyWeight implements Comparable<EdgeDifficultyWeight> {
private final Edge edge;
private final int difficulty;
public EdgeDifficultyWeight(Edge edge, int difficulty){
this.edge = edge;
this.difficulty = difficulty;
}
public int compareTo(EdgeDifficultyWeight arg) {
return new CompareToBuilder()
.append(arg.difficulty, this.difficulty)
.append(arg.edge.getId(), this.edge.getId())
.toComparison();
}
}
I am learning Java SE and am currently at simple linked lists (page 687/1047 of Savitch's Absolute Java).
I am stuck at instantiating the LinkList in the main method of my demo class:
LinkedList1 list = new LinkedList1();
I tried using breakpoint and it indicates a ReflectiveOperationException.
This is the code:
public class Node1
{
private String item;
private int count;
private Node1 link;
public Node1()
{
link = null;
item = null;
count = 0;
}
public Node1(String newItem, int newCount, Node1 linkValue)
{
setData(newItem, newCount);
link = linkValue;
}
public void setData(String newItem, int newCount)
{
item = newItem;
count = newCount;
}
public void setLink(Node1 newLink)
{
link = newLink;
}
public String getItem()
{
return item;
}
public int getCount()
{
return count;
}
public Node1 getLink()
{
return link;
}
}
This is the LinkedList1 class:
public class LinkedList1
{
private Node1 head;
public LinkedList1()
{
head = null;
}
/**
* Adds a node at the start of the list with the specified data.
* The added node will be the first node in the list.
*/
public void add(String itemName, int itemCount)
{
head = new Node1(itemName, itemCount, head);
}
/**
* Removes the head node and returns true if the list contains at least
* one node. Returns false if the list is empty.
*/
public boolean deleteHeadNode()
{
if (head != null)
{
head = head.getLink();
return true;
}
else
return false;
}
/**
* Returns the number of nodes in the list.
*/
public int size()
{
int count = 0;
Node1 position = head;
while (position != null)
{
count++;
head = position.getLink();
}
return count;
}
public boolean contains(String item)
{
return (find(item) != null);
}
/**
* Finds the first node containing the target item, and returns a
* reference to that node. If the target is not in the list, null is returned.
*/
public Node1 find(String target)
{
Node1 position = head;
String itemAtPosition;
while(position != null)
{
itemAtPosition = position.getItem();
if(itemAtPosition.equals(target))
{
return position;
}
position = position.getLink();
}
return null; //target was not found
}
public void outputList()
{
Node1 position = head;
while (position != null)
{
System.out.println(position.getItem() + " " + position.getCount());
position = position.getLink();
}
}
}
I think that the problem has something to do with the constructor of Node1 having the member link of type Node1. I'm trying to understand how these data structures work and not just resort to using the built-in ArrayList(& APIs) for my projects. Can you guys have a look and point me in the right direction. Any help would be very much appreciated.
This is my main method.
public class LinkedListDemo
{
public static void main(String[] args)
{
try
{
LinkedList1 list = new LinkedList1();
list.add("apples", 1);
list.add("bananas", 2);
list.add("cantaloupe", 3);
System.out.println("List has "+ list.size() + " nodes.");
list.outputList();
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
}
Your size method contains an infinite loop which explain why the outputs are never reached.
while (position != null)
{
count++;
head = position.getLink();
}
You are looping until position is null, but never assign anything to position and instead assign to head. Instead, you want to do
while (position != null)
{
count++;
position = position.getLink();
}
Now you would get the output
List has 3 nodes.
cantaloupe 3
bananas 2
apples 1
How would I go about writing an iterator to iterate over each value of a binary tree in "in-order" fashion? I should be using a stack. BinaryNode is a simple node class with pointers to "left" and "right" nodes. Here is what I have so far:
class InOrderIterator implements Iterator<T> {
private Stack<BinaryNode> stack;
public InOrderIterator(BinarySearchTree<T>.BinaryNode root) {
stack = new Stack<BinaryNode>();
stack.push(root);
}
#Override
public boolean hasNext() {
while (!this.stack.isEmpty() && stack.peek() == NULL_NODE)
this.stack.pop();
return !this.stack.isEmpty();
}
#Override
public T next() {
//TODO
if (!this.hasNext())
throw new NoSuchElementException("No more nodes in tree!");
BinaryNode current = this.stack.pop();
BinaryNode output = null;
while(current != NULL_NODE){
this.stack.push(current);
current = current.left;
}
if(current == NULL_NODE){
if(!this.stack.isEmpty()){
output = this.stack.pop();
return output.data;
}
}
return null;
}
}
I have the basic algorithm down, but I can't seem to convert it to java code.
Think about invariants. You have a stack of nodes. What does it mean for a node to be on the stack?
Might I suggest: A node on the stack represents a "half-tree", a node and its entire right subtree, and the stack holds all the half-trees that together make up all the nodes that have not been returned from next() yet.
In what order should those half-trees be pushed on the stack? Answering that question gives you your invariant condition, the property that will be preserved as your code runs.
Satisfy yourself that your invariant implies that the top of the stack must be whatever next() is going to return next. When you pop it off to return it, you're going to have to somehow deal with its right subtree before returning. From your invariant, it should be obvious how to do that.
If you don't consciously and explicitly think about what your variables mean and what your invariants are, your coding efforts are going to be undirected. You're going to flail around, writing spaghetti code. Once you've done that, though, the code will write itself.
public class BinaryTreeNode {
private int element; //element stored at this node
private BinaryTreeNode left, right;
public BinaryTreeNode() { }
public BinaryTreeNode(int element) {
setElement(element);
setLeft(null);
setRight(null);
}
//returns the elements stored at this position
public int element() {
return element;
}
//sets the elements stored at this position
public void setElement(int e) {
element = e;
}
//return the left child of this position
public BinaryTreeNode getLeft() {
return left;
}
//set the left chid of this position
public void setLeft(BinaryTreeNode l) {
left = l;
}
//return the right child of this position
public BinaryTreeNode getRight() {
return right;
}
//sets the right child of this position
public void setRight(BinaryTreeNode r) {
right = r;
}
}
public class TestBTN {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
BinaryTreeNode root = null, right, left, node = null;
int arrayInt[] = {25, 20, 7, 13, 33, 50, 45, 17, 30, 55};
for (int i = 0; i < arrayInt.length; i++) {
if (root == null) {
root = node = new BinaryTreeNode(arrayInt[0]);
}//endIf
else {
node = new BinaryTreeNode(arrayInt[i]);
BinaryTreeNode s, p;
p = s = root;
while (s != null) {
p = s;
if (node.element() > s.element()) {
s = s.getRight();
} else {
s = s.getLeft();
}
}//endWhile
if (node.element() > p.element()) {
p.setRight(node);
} else {
p.setLeft(node);
}
}//emdElse
}//endFor
//printing
//Print(root);
//PostOrder(root);
//PreOrder(root);
InOrder(root);
//System.out.println("\nBinaryTreeNode");
}//endMain
private static void Print(BinaryTreeNode node) {
if (node != null) {
System.out.print(node.element() + " ");
Print(node.getLeft());
Print(node.getRight());
}//endIf
}//endPrint
static void PostOrder(BinaryTreeNode ptr) {
if(ptr != null) {
PostOrder(ptr.getLeft());
PostOrder(ptr.getRight());
System.out.print(ptr.element()+" ");
}//endIf
}//endPost
static void PreOrder(BinaryTreeNode ptr) {
if(ptr != null) {
System.out.print(ptr.element()+" ");
PreOrder(ptr.getLeft());
PreOrder(ptr.getRight());
}
}
static void InOrder(BinaryTreeNode ptr) {
if(ptr != null) {
InOrder(ptr.getLeft());
System.out.print(ptr.element()+" ");
InOrder(ptr.getRight());
}
}
}