I'm making a 3 dimensional tic tac toe game. The game is complete and works fine, however, the assignment demands that (for testing game situations) the program take in a file of integers that places pieces on the game board. It takes in the file from the Unix command line.
However, the game is supposed to run from start if no file is entered in command line. I'm getting an out of bounds exception and don't know why for the life of me. Any help would be greatly appreciated.
Portion of code for getting file and storing the integers:
public class Test {
static int board[][][] = new int[4][4][4];
static boolean ComputerMoved = false;
static int[] sums = new int[76];
static int n = 0;
public static void main(String[] args) throws FileNotFoundException {
//Method purpose is to look and see if there is a startup file given to
//initally setup the board. If not, plays an empty board and prompts the
//user for the first move.
Scanner scan = new Scanner(new FileInputStream(args[0]));
if (args.length > 0) {
int size = scan.nextInt();
for (int i = 0; i < size; i++) {
int level = scan.nextInt();
int row = scan.nextInt();
int column = scan.nextInt();
int value = scan.nextInt();
level = level % 4;
row = row % 4;
column = column % 4;
board[level][row][column] = value;
}
}
Hint: It appears that the out of bounds exception is coming not from your array, but rather your scanner. Could it be possible you don't have "enough" numbers to scan?
Related
Problem: https://www.educative.io/m/connect-all-siblings
I'm attempting to connect all sibling nodes by creating a dummy node and set it's next to the node that we're currently visiting by using a next pointer, but after executing the code:
public static void populate_sibling_pointers(BinaryTreeNode root) {
if(root == null) return;
Queue<BinaryTreeNode> q = new LinkedList<>();
q.offer(root);
while(!q.isEmpty()){
int size = q.size();
BinaryTreeNode dummy = new BinaryTreeNode(0);
for(int i = 0; i < size; i++){
BinaryTreeNode cur = q.poll();
dummy.next = cur;
dummy = dummy.next;
if(cur.left!=null){
q.offer(cur.left);
}
if(cur.right!=null){
q.offer(cur.right);
}
}
}
}
I still failed to pass some test but I'm not sure what I did wrong here.
Any help is appreciated!
Two issues:
You should create a new dummy node only once. By creating a new one at every iteration of the while loop, you break the chain of next references. So the creation of that node should happen before the while loop.
The last node in the next chain should have its next set to null.
Here is the corrected code:
class connectSiblings{
public static void populate_sibling_pointers(BinaryTreeNode root) {
if(root == null) return;
Queue<BinaryTreeNode> q = new LinkedList<>();
q.offer(root);
BinaryTreeNode dummy = new BinaryTreeNode(0);
while(!q.isEmpty()){
int size = q.size();
for(int i = 0; i < size; i++){
BinaryTreeNode cur = q.poll();
dummy.next = cur;
dummy = dummy.next;
if(cur.left!=null){
q.offer(cur.left);
}
if(cur.right!=null){
q.offer(cur.right);
}
}
}
dummy.next = null;
}
}
You can further optimise this code by replacing the use of the LinkedList with the actual linked list you are building with the next references: when a layer of the tree has been correctly wired with next references, you can iterate that section of that linked list to find and wire the nodes of the next layer, which then can serve as linked list for the next layer, ...etc.
Have tried debugging by using System.out to check whether a method is run or not. The run method executes fine and the radar begins spinning with the robot console displaying Hello. onScannedRobot seems to be never called. Completely out of a clue of how to resolve. In the battle, the robot compiles fine into the game and it definitely is spinning its radar across other bots.
package ke_shen;
import robocode.util.*;
import robocode.*;
import java.util.*;
import java.awt.Color;
import java.awt.geom.Point2D;
//Oldest Scanned Radar
//Functions by spinning until all robots have been scanned
//then begins to scan in the opposite direction until
//all robots have been scanned again
//this minimizes the time in between all robots in the battlefield
//can be scanned, maximizing speed of scanning
public class shen_robot extends AdvancedRobot {
// the use of a linked hash map is deal here to store the enemy
// robot's names (the key)and their respective absolute bearings (thevalue)
static double scanDirection;
static Object sought;
static Object mostDanger = null;
static double distance = 50000;
static int tempindex = 0;
static int mostDangerIndex;
ArrayList<String> names = new ArrayList<String>();
ArrayList<Double> distanceArray = new ArrayList<Double>();
ArrayList<Double> velocityArray = new ArrayList<Double>();
ArrayList<Double> headingArray = new ArrayList<Double>();
public void run() {
setAdjustRadarForRobotTurn(true);
setAdjustGunForRobotTurn(true);
setAdjustRadarForGunTurn(true);
setAllColors(Color.BLUE);
System.out.println("Hello.");
scanDirection = 1;
// below, scanDirection will be become either negative or positive
// this changes the direction of the scan from initially
// clockwise to counterclockwise and vice versa;
setTurnRadarRightRadians(scanDirection * Double.POSITIVE_INFINITY);
scan();
// linearTargeting();
// execute();
}
// removes the robot from the hash map when it dies
public void onRobotDeathEvent(RobotDeathEvent e) {
int index = names.indexOf(e.getName());
names.remove(e.getName());
distanceArray.remove(index);
velocityArray.remove(index);
headingArray.remove(index);
}
public void onScannedRobot(ScannedRobotEvent e) {
System.out.println("Helo.");
// RADAR
// the radar will spin in a full circle once in the beginning of the
// battle
// and add all the robots to the hash map
// the second rotation, once it reaches the last robot in the hash map,
// because the radar heading is now greater than the normalRelative
// angle
// scanDirection will become negative, resulting in the radar spinning
// in the other
// direction due to the code above in line 31
// UPDATES PROPERTIES AFTER THE INITIAL 360 degree SCAN
String name = e.getName();
if (names.contains(name) == true) {
tempindex = names.indexOf(name);
headingArray.remove(tempindex);
headingArray.add(tempindex, e.getHeadingRadians());
velocityArray.remove(tempindex);
velocityArray.add(tempindex, e.getVelocity());
distanceArray.remove(tempindex);
distanceArray.add(tempindex, e.getDistance());
}
// HEADING
else {
int index = names.size()-1;
headingArray.add(e.getHeadingRadians());
if (names.size() == getOthers()) {
scanDirection = Utils.normalRelativeAngle(headingArray.get(index) - getRadarHeadingRadians());
}
// VELOCITY
velocityArray.add(e.getVelocity());
// DISTANCE & MOSTDANGEROUS
distanceArray.add(e.getDistance());
}
while (distanceArray.iterator().hasNext()) {
if (distanceArray.iterator().next() < distance) {
distance = distanceArray.iterator().next();
}
}
mostDangerIndex = distanceArray.indexOf(distance);
}
public void addInfo(String name, int number) {
}
}
Trivial Test
Changing OnScannedRobot to this allows it to execute normally. So the robot is catching the on scan events:
public void onScannedRobot(ScannedRobotEvent e) {
System.out.println("Helo.");
}
Diagnose the Problem
The issue is that if a robot fails to complete his turn in the time allotted, the turn will be skipped. Now the question is, what piece of the OnScannedRobot method is time inefficient?
Resolution
As it turns out, the mostDangerIndex calculation (that includes the while loop) is the culprit. So to fix the OnScannedRobot method, I replaced the mostDangerIndex calculation (that includes the while loop) with:
mostDangerIndex = distanceArray.indexOf(Collections.min(distanceArray));
Now it works!
QUESTION:
I'm having trouble finding the minimum amount of coins needed to reach a specific sum. I'm pretty sure this is done easiest recursively and using the dynamic programming methodology, I should basically get Math.min("takeACoin","leaveACoin");
Unfortunately, My code doesn't terminate though I do have if statements that terminate under the condition that the sum is met, the array of coins is depleted, or if the sum is over. Please look at my code below and let me know what I'm doing wrong and especially why my code continues executing until it receives a stackoverflow error though I have the appropriate terminating conditions.
CODE:
private static final int S = 3;
public static int arr[] = {1,2};
public static void main(String[] args) {
Interview i = new Interview();
i.sumCoins(arr, 0);
}
public int sumCoins(int[] ar, int sum) {
//if the sum is met, dont add any coins, just return 0
if(sum == S){
return 0;
}
//if the sum is greater, then return max value as it is impossible to get less sum
if(sum > S){
return Integer.MAX_VALUE;
}
//if the array is out of coins return max value
if(ar.length == 0){
return Integer.MAX_VALUE;
}
//if the sum is less than S and there is still more coins to use, keep checking
//add the first coin
int tmpSum = sum + ar[0];
//delete the first coin from the list
int[] tmp = Arrays.copyOfRange(ar, 1, ar.length);
//add one coin to the solution
int one = 1+sumCoins(tmp, tmpSum);
//don't add one coin to the solution
int two = sumCoins(ar,sum);
//see which is more minimized
return Math.min(one,two);
}
Requested Stack Trace:
Exception in thread "main" java.lang.StackOverflowError
at java.lang.Math.min(Math.java:879)
at java.util.Arrays.copyOfRange(Arrays.java:2623)
at Interview.sumCoins(Interview.java:28)
at Interview.sumCoins(Interview.java:32)
at Interview.sumCoins(Interview.java:32)
The answer to this question is in regards to how I was implementing my dynamic programming. I was using the original array in the case where you left the coin. this is incorrect. In more detail:
If you take the coin: get rid of the first (coin) index of the array, add the sum, add +1 for the number of coins.
If you don't take the coin: get rid of the first (coin) index of the array since you're leaving that coin to not be considered.
In my solution, I received a stackoverflow because I was going through the "leaving the coin" scenario infinite times as the array never decreased and I wasn't actually "leaving the coin".
Correct Code here:
private static final int S = 5;
public static int arr[] = {1,1,1,1,1};
public static void main(String[] args) {
Interview i = new Interview();
System.out.println(i.sumCoins(arr, 0));
}
public int sumCoins(int[] ar, int sum) {
//if the sum is met, dont add any coins, just return 0
if(sum == S){
return 0;
}
//if the sum is greater, then return global array (not local)
//length +1 as it's impossible to get more coins than indices
if(sum > S){
return arr.length+1;
}
//if the array is out of coins return max value
if(ar.length == 0){
return arr.length+1;
}
//if the sum is less than S and there is still more coins to use, keep checking
//add the first coin
int tmpSum = sum + ar[0];
//delete the first coin from the list
int[] tmp = Arrays.copyOfRange(ar, 1, ar.length);
//add one coin to the solution
int one = 1+sumCoins(tmp, tmpSum);
//don't add one coin to the solution
int two = sumCoins(tmp,sum);
//see which is more minimized
return Math.min(one,two);
}
Right now I cant even compile this program. Im trying to write a program that takes a inputted string and then encrypts the letters by swapping them out with another letter predetermined in a array and then shows you again the original text. any help would be appreciated.
import java.util.Scanner;
public class Array {
private char [] alphabet = new char [25];
private char [] crypt = new char [25];
String oldMessage;
public Array()
{ char[] alphabet = "abcdefghijklmnoptqrstuvwxyz".toCharArray();
char[] crypt = "qwertyuiopasdfghjklzxcvbnm|".toCharArray();
}
public static void run(){
Scanner scan = new Scanner(System.in);
System.out.println("Enter a message that you would like to encrypt\n");
oldMessage = scan.nextLine();
String newMessage = "";
for (int i=0; i<oldMessage.length(); ++i) {
int index = alphabet.indexOf(old.charAt(i));
if (index == -1)
newMessage +="?";
else
newMessage += crypt.charAt(index);
/**
* #param args the command line arguments
*/
public static void main(String[] args) {Array myApplication = new Array(); myApplication.run();}
First off, when encountering errors, it's always best to include the error in your question--often it will point you right to the source of the error. What does your compiler say when the build fails?
Next, I'm on my phone right now and can't verify that I've found all the problems, but remember that strings in Java are immutable, meaning that they can't be changed after creation. This means that you can't append to them in the way you're doing. Try using the StringBuilder class to accomplish what you're looking for here, or filling a new array as you go and converting to String at the end.
Also, it looks like you're missing two end braces (the for loop and the run method).
From static method run() you are referring to non-static variables like alphabet, crypt, oldMessage.
This is first that comes into mind
As far as I know, DP is either you start with bigger problem and recursively come down, and keep saving the value each time for future use or you do it iteratively and keep saving values bottom up. But what if I am doing it bottom up but recursively going up?
Say for example the following question, Longest Common Subsequence
Here's my solution
public class LongestCommonSubseq {
/**
* #param args
*/
public static List<Character> list = new ArrayList<Character>();
public static int[][] M = new int[7][7];
public static void main(String[] args) {
String s1 = "ABCDGH";
String s2 = "AEDFHR";
for(int i=0;i<=6;i++)
for(int j=0;j<=6;j++)
M[i][j] = -1;
int max = getMax(s1,s2,0,0);
System.out.println(max);
Collections.sort(list);
for(int i = 0;i < max;i++)
System.out.println(list.get(i));
}
public static int getMax(String s1, String s2,int i ,int j){
if(i >= s1.length() || j>= s2.length()){
M[i][j] = 0;
return M[i][j];
}
if(M[i][j] != -1)
return M[i][j];
if(s1.charAt(i) == s2.charAt(j)){
M[i][j] = 1 + getMax(s1,s2,i+1,j+1);
list.add(s1.charAt(i));
}
else
M[i][j] = max(getMax(s1,s2,i+1,j) , getMax(s1, s2, i, j+1));
return M[i][j];
}
public static int max(int a,int b){
return a > b ? a : b;
}
}
So you see,I am going from M[0][0] in the other direction but I am not doing it iteratively.
But I guess it should be fine. Just needed to confirm.
Thanks
The direction does not matter. What is more important is that you go from more general(complex) problem to simpler ones. What you have done is dynamic programming.
For dynamic programming it doesn't matter if you follow the bottom-up or top-down-paradigm. The basic thesis (like you have correctly mentioned) of dynamic programming is known as Bellman's Principle of Optimality which is the following:
Principle of Optimality: An optimal policy has the property that
whatever the initial state and initial decision are, the remaining
decisions must constitute an optimal policy with regard to the state
resulting from the first decision.
Resource: Wikipedia (http://en.wikipedia.org/wiki/Bellman_equation#Bellman.27s_Principle_of_Optimality)
An great approach to cut of some of these optimal sub-solutions from the recursive-call-tree is to use Caching (like in your code).