Cannot figure out Kata Direction Reduction problem error - java

I am working on a direction reduction problem from codewars and I can't figure out the error it is giving me. I know there have been similar cases as this but when I test my code on Visual Studio Code it works flawlessly so I'm not sure why codewars is giving me this error. The error I am getting is: "NORTH","SOUTH","SOUTH","EAST","WEST","NORTH": array lengths differed, expected.length=0 actual.length=6
Here is my code. Keep in mind that codewars tests it for you so my main method is not actually needed:
import java.lang.*;
public class DirReduction {
public static String[] dirReduc(String[] arr) {
int directionNS = 0;
int directionEW = 0;
for(int i = 0; i < arr.length; i++){
if(arr[i] == "NORTH"){
directionNS++;
} else if(arr[i] == "SOUTH"){
directionNS--;
} else if(arr[i] == "EAST"){
directionEW++;
} else if(arr[i] == "WEST"){
directionEW--;
} else {
System.out.println("Invalid Direction.");
}
}
String[] reducArray;
if(directionNS == 0 && directionEW == 0){
reducArray = new String[arr.length];
System.arraycopy(arr, 0, reducArray, 0, arr.length);
} else {
reducArray = new String[Math.abs(directionNS + directionEW)];
if(directionNS > 0){
for(int i = 0; i < directionNS; i++){
reducArray[i] = "NORTH";
}
} else if(directionNS < 0){
for(int i = 0; i > directionNS; i--){
reducArray[i] = "SOUTH";
}
}
if(directionEW > 0){
for(int i = 0; i < directionEW; i++){
reducArray[i] = "EAST";
}
} else if(directionEW < 0){
for(int i = 0; i > directionEW; i--){
reducArray[i] = "WEST";
}
}
}
return reducArray;
}
public static void main(String[] args){
String[] a = {"NORTH", "SOUTH", "SOUTH", "EAST", "WEST", "NORTH","WEST"};
String[] result = dirReduc(a);
for(int i = 0; i < result.length; i++){
System.out.println(result[i]);
}
}
}

There were four errors I found.
1) The case "NORTH","SOUTH","SOUTH","EAST","WEST","NORTH" should end up back where you started, so the array length should be 0, as requested by Codewars. To get that to work, I got rid of your special case for both direction counts being 0 and let what had been your else case deal with it by adding 0 and 0 to get the array size. [This error is the one mentioned in your question]
2) Your calculation of the array size was a little off. For example for "SOUTH" "EAST" it was calculating a size of 0 because they canceled out. Instead you need to sum the absolute values, not take the absolute value of the sum.
3) Your EAST/WEST in the reduced array were starting at position 0, and so overwriting NORTH/SOUTH. I made sure to offset into the array before doing those.
4) Your strategy of going negative on the for loop will try to write to a negative index if you have like SOUTH, EAST, SOUTH. I kept it positive using Math.abs
Here is the resulting method.
public static String[] dirReduc(String[] arr) {
int directionNS = 0;
int directionEW = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] == "NORTH") {
directionNS++;
} else if (arr[i] == "SOUTH") {
directionNS--;
} else if (arr[i] == "EAST") {
directionEW++;
} else if (arr[i] == "WEST") {
directionEW--;
} else {
System.out.println("Invalid Direction.");
}
}
String[] reducArray;
//removed special case for ending up back where one started, that will be made a 0 length array as it should be
reducArray = new String[Math.abs(directionNS) + Math.abs(directionEW)]; //note have to take abs of each so one does not cancel out the other
if (directionNS > 0) {
for (int i = 0; i < directionNS; i++) {
reducArray[i] = "NORTH";
}
} else if (directionNS < 0) {
for(int i = 0; i < Math.abs(directionNS); i++){//keep the i's positive so they work in the array easily
reducArray[i] = "SOUTH";
}
}
if (directionEW > 0) {
for (int i = 0; i < directionEW; i++) {
reducArray[i + Math.abs(directionNS)] = "EAST"; //note have to start where north south left off
}
} else if (directionEW < 0) {
for(int i = 0; i < Math.abs(directionEW); i++){
reducArray[i + Math.abs(directionNS)] = "WEST";
}
}
return reducArray;
}`

Related

Keep getting IndexOutOfBounds exception when trying to merge arraylist

I'm doing a school assignment (so still a noob) but cannot seem to figure out why i keep getting IndexOutOfBoundsException. any help is appreciation. It's most likely some stupid mistake but i've gotten very good at not noticing those. It's supposed to separate slice objects in to 3 ArrayLists, scramble those lists, then put them back in the correct order based on color.
public void scramble()
{
ArrayList<Slice> temp = new ArrayList<>();
ArrayList<Slice> red = new ArrayList<>();
ArrayList<Slice> black = new ArrayList<>();
ArrayList<Slice> blue = new ArrayList<>();
int blackListCount = 0;
int redListCount = 0;
int blueListCount = 0;
for (Slice s : slices) {
if (s.getColor().equals("red")) {
red.add(s);
} else if (s.getColor().equals("black")) {
black.add(s);
} else if (s.getColor().equals("blue")) {
blue.add(s);
}
}
blueScram(blue);
blackScram(black);
redScram(red);
for (int i = 0; i < slices.size() - 1; i++) {
if (i % 5 == 0) {
temp.add(i, black.get(blackListCount));
blackListCount++;
}
if (i % 2 == 0) {
temp.add(i, blue.get(blueListCount));
blueListCount++;
}
if (i % 2 == 1) {
temp.add(i, red.get(redListCount));
redListCount++;
}
}
slices.clear();
slices = temp;
}
private void blueScram(ArrayList<Slice> blue) {
for (int i = 0; i < blue.size(); i++) {
switchSlice(blue, i, (int) (Math.random() * (blue.size())));
}
}
private void redScram(ArrayList<Slice> red) {
for (int i = 0; i < red.size(); i++) {
switchSlice(red, i, (int) (Math.random() * (red.size())));
}
}
private void blackScram(ArrayList<Slice> black) {
for (int i = 0; i < black.size(); i++) {
switchSlice(black, i, (int) (Math.random() * (black.size())));
}
}
private void switchSlice(ArrayList<Slice> list, int firstIndex, int lastIndex) {
try {
Slice temp = list.get(firstIndex);
list.set(firstIndex, list.get(lastIndex));
list.set(lastIndex, temp);
} catch (IndexOutOfBoundsException e) {
System.out.println("IndexOutBounds while trying to randomize/switch elements of a slice list");
e.printStackTrace();
}
}
Here's the initial (given) slice creation / sorting code
private static int[] getStandardPrizes()
{
int[] arr = new int[20];
for (int i=0; i < 20; i++)
{
if (i%5 == 0)
arr[i] = i*1000;
else if (i%2 == 1)
arr[i] = i*100;
else
arr[i] = i*200;
}
return arr;
}
I get errors at if(i % 5 == 0) and the other if statements within the scope of the surrounding for loop

Some test cases not running but some are in terms of probability

I have a program in which it rolls five dice and assigns a hand to the rolls. i.e. nothing, a pair, two pair, three of a kind, full house, four of a kind, five of a kind. The code runs 1000000 times and gives percentage chances for each roll. Below I have attached general percentages my code should output near:
Case 1, None alike, is 0.092533
Case 2, One pair, is 0.462799
Case 3, Two pair, is 0.231789
Case 4, Three of a kind, is 0.154192
Case 5, Full house, is 0.038595
Case 6, Four of a kind, is 0.019316
Case 7, Five of a kind, is 0.000776
However my code gives the following output:
Case 1, None alike is 0.093099
Case 2, One pair is 0.384768
Case 3, Two pair is 0.076921
Case 4, Three of a kind is 0.15485
Case 5, Full House is 0.270349
Case 6, Four of a kind is 0.019281
Case 7, Five of a kind is7.33E-4
I don't understand why my programs percentages are off for one pair, two pairs, and full house. I have gone through and tested my logic but it is sound from what I have seen. Originally, my one pair was correct but my two pair was 0.0. Below is my original logic which causes the two pair to be 0 and my pair to be correct.
I, however, changed it to the current logic to get the current output. I would appreciate another set of eyes to take a look and let me know if they could catch something. Below is my code:
Change 1 :
if (hand < 6) {
int counter3 = 0;
int counter2 = 0;
for (int j = 0; j < length; j++) {
if (counts[j] == 3) {
counter3++;
}
if (counts [j] == 2) {
counter2++;
}
}
if (counter3 == 1 && counter2 == 1) {
hand = 5;
}
}
Change 2:
if (hand < 4) {
int newcounter = 0;
for (int j = 0; j < length; j++) {
if (counts[j] == 2) {
newcounter++;
}
}
if (newcounter==2) {
hand = 3;
}
if (newcounter == 1) { hand = 2; }
}
Change 3 :
Please remove if( hand < 3) part of code.
Updated my answer. In your code the counter variable (when you're trying to check "full house") was becoming 2 due to two pairs (ex : counts = 020200) not due to full house (ex: counts = 300200). Hence, it wasn't counting the two pairs in the following code where it was supposed to because hand was already becoming 5, so it didn't go inside any other if parts below although it was supposed to go inside if(hand<3). Hope it will fix the issue.
See comment in code
if (hand < 4) {
int newcounter = 0;
boolean firstp = false;
boolean secondp = false;
for (int j = 0; j < length; j++) {
firstp = false;
secondp = false;
if (counts[j] == 2) {
firstp = true; <---- THIS
}
if (counts[j] == 2) {
secondp = true; <---- AND THIS will always hit together as j never changes from the first if to second if
// break;
}
}
if (firstp && secondp) {
hand = 3; <---- firstp always equal to secondp, I would be surprised to see hand ever = 2
}
}
I modified your code. The original logic is a little bit messy. I made some slight improvement but hopefully better. Not perfect though.
import java.util.*;
public class PokerDice {
public static void main(String[] args) {
double none = 0;
double pair = 0;
double twop = 0;
double threep = 0;
double full = 0;
double fourp = 0;
double fivep = 0;
for (int i = 0; i<=1000000; i++) {
int [] rolls = new int[5];
for (int j = 0; j < 5; j++) {
rolls[j] = (int)(1 + (Math.random()*(6)));
}
int[] counts = Counts(rolls);
boolean has_two = false;
boolean has_three = false;
none++;
for (int j = 0; j < counts.length; j++) {
if (counts[j] == 4) {
fourp++;
none--;
break;
}
if (counts[j] == 5) {
fivep++;
none--;
break;
}
if (counts[j] == 3) {
has_three = true;
if (has_two) {
full++;
pair--;
break;
} else {
none--;
threep++;
}
}
if (counts[j] == 2) {
if (has_two) {
twop++;
pair--;
break;
}
else if (has_three) {
full++;
threep--;
break;
} else {
has_two = true;
pair++;
none--;
}
}
}
}
fivep/=1000000;
fourp/=1000000;
full/=1000000;
threep/=1000000;
twop/=1000000;
pair/=1000000;
none/=1000000;
System.out.println("Poker Dice Probability Calculator");
System.out.println("Running 1,000,000 trials");
System.out.println();
System.out.println("Case 1, None alike is "+none);
System.out.println("Case 2, One pair is "+pair);
System.out.println("Case 3, Two pair is "+twop);
System.out.println("Case 4, Three of a kind is "+threep);
System.out.println("Case 5, Full House is "+full);
System.out.println("Case 6, Four of a kind is "+fourp);
System.out.println("Case 7, Five of a kind is"+fivep);
}
public static int[] Counts (int [] rolled) {
int one = 0;
int two = 0;
int three = 0;
int four = 0;
int five = 0;
int six = 0;
int len = rolled.length;
int [] rolltimes = new int[6];
for (int i = 0; i<len; i++) {
if (rolled [i] == 1) {
one++;
}
else if (rolled [i] == 2) {
two++;
}
else if (rolled [i] == 3) {
three++;
}
else if (rolled [i] == 4) {
four++;
}
else if (rolled [i] == 5) {
five++;
}
else if (rolled [i] == 6) {
six++;
}
}
rolltimes[0] = one;
rolltimes[1] = two;
rolltimes[2] = three;
rolltimes[3] = four;
rolltimes[4] = five;
rolltimes[5] = six;
return rolltimes;
}
}

an alternative to all and any from python to Java?

I'm tryin' to code how to find out a determinant in a matrix with Java 8. There are some particular cases for that work. For instance, when a matrix is an upper triangular. I coded this work with Python 3.6 using this code:
def is_upper_triangular(a, order):
for i in range(1, order):
if all(a[i][j] == 0 for j in range(order)):
return True
return False
This is very easy and clean code, so I've thought to code with Java, but I don't find any "all" method with Java to use it. I've found some information about that in this web page with negative solution. Is there any alternative to solve my problem.
Here's my java code for now:
public static double detMatrix(double[][] matriz) {
if(matriz.length == 1)
return matriz[0][0];
if(matriz.length == 2)
return matriz[0][0] * matriz[1][1] - matriz[1][0] * matriz[0][1];
double det = 0;
for(int i=0; i<matriz.length; i++){
double[][] nm = new double[matriz.length-1][matriz.length-1];
for(int j=0; j<matriz.length; j++){
if(j != i){
for(int k=1; k<matriz.length; k++){
int indice = -1;
if(j<i)
indice = j;
else if(j>i)
indice = j - 1;
nm[indice][k-1] = matriz[j][k];
}
}
}
if(i % 2 == 0)
det += matriz[i][0] * detMatrix(nm);
else
det -= matriz[i][0] * detMatrix(nm);
}
return det;
}
Thanks
I know you are asking for a specific keyword feature in Java, but different programming languages afford different approaches.
For example, instead of an all operator, why not simply use Arrays.fill(...)? The python that looks like
for i in range(1, order):
if all(a[i][j] == 0 for j in range(order))
would look like
for (int i = 0; i < a.length, i++) {
Arrays.fill(a[i], i+1, a[i].length, 0);
}
Likewise, the any operation in Python might look like it is doing more with less, but really it collapses down to
for (Element element : allElements() {
if (element satisifies condition) {
... statements ...
}
}
With Java, the above loop can work, but it makes the inefficiency apparent. If you really don't like to see what your code is doing, you can hide this in a method.
public List<int> findFives(int[][] a) {
...
}
Well, it seems java works with Streams, but Streams is a hard option beause, it seems, it converts any matrix in an Array 1D, and this is very difficult when i want to search all 0's under main diagonal matrix. I suppose some people know to solve it but i don't know about that.
Other problem with that is we have to load some java packages. So i've found another solution without to load extra java packages. Here is:
public static double [][] transMatrix(double [][] mat) {
double[][] matrizT = new double[mat[0].length][mat.length];
for(int i=0; i<mat.length; i++)
for (int j = 0; j<mat[i].length; j++)
matrizT[j][i] = mat[i][j];
return matrizT;
}
public static boolean isUpper(double[][] mat) {
int p = 0;
for(int i=0;i<mat.length;i++)
{
for(int j=0;j<i;j++)
{
if(mat[i][j]!=0)
p = 1; break;
}
}
return p == 0;
}
public static double productDiag(double[][] mat) {
double prod;
prod = 1.;
for(int i=0;i<mat.length;i++)
for(int j=0; j<mat[0].length;j++)
if(i==j)
prod *= mat[i][j];
return prod;
}
public static double detMatrix(double[][] matrix) {
if(matrix.length == 1)
return matrix[0][0];
if(matrix.length == 2)
return matrix[0][0] * matrix[1][1] - matrix[1][0] * matrix[0][1];
if(isUpper(matrix) || isUpper(transMatrix(matrix))
|| (isUpper(matrix) && isUpper(transMatrix(matrix)))){
return productDiag(matrix);
}
double det = 0;
for(int i=0; i<matrix.length; i++){
double[][] minor = new double[matrix.length-1][matrix.length-1];
for(int j=0; j<matrix.length; j++){
if(j != i){
for(int k=1; k<matrix.length; k++){
int index = -1;
if(j<i)
index = j;
else if(j>i)
index = j - 1;
minor[index][k-1] = matrix[j][k];
}
}
}
if(i % 2 == 0)
det += matrix[i][0] * detMatrix(minor);
else
det -= matrix[i][0] * detMatrix(minor);
}
return det;
}
Thanks everybody for your help.

For-loop is executed only once?

I'm implementing Insertionsort for university. My code works in theory, but my for-loop is executed only once instead of books.size() (which is 5, I've tested that). I tried it using the number 5, but it won't work and I'm kind of desperate because I can't seem to find the error.
Here is my code:
static void sort(LinkedList<Book> books)
{
int i;
for ( i = 0; i < books.size(); i++)
{
Book temp = books.get(i);
books.remove(i);
for (int j = 0; j < books.size(); j++) {
if (books.get(j).compareTo(temp) > 0) {
books.add(j, temp);
return;
}
}
books.add(temp);
}
}
The compareTo function of the Book-Class looks like the following:
public int compareTo(Book other)
{
int iAutor = autor.compareTo(other.getAutor());
if (iAutor != 0)
return iAutor;
else
{
int iTitel = titel.compareTo(other.getTitel());
if (iTitel != 0)
return iTitel;
else
{
if (this.auflage < other.getAuflage())
return -1;
else if (this.auflage > other.getAuflage())
return 1;
else
return 0;
}
}
}
Am I simply blind?
You need to swap return for break and fix the logic to avoid adding the book twice. There may be more elegant ways than this, but it should work:
int i;
for ( i = 0; i < books.size(); i++)
{
Book temp = books.get(i);
books.remove(i);
bool added = false;
for (int j = 0; j < books.size(); j++) {
if (books.get(j).compareTo(temp) > 0) {
books.add(j, temp);
added = true;
break;
}
}
if (!added) {
books.add(temp);
}
}
Well, I found out how to solve it, just if someone has the same problem (don't think that will happen, but it's a good habit I hope).
As #Klitos Kyriacou pointed out right, I had a twist in my thoughts about the process of Insertionsorting.
The solution is changing the loops in the following:
static void sort(LinkedList<Book> books) {
Book temp;
for (int counter = 0; counter < books.size(); counter++) {
temp = books.get(counter);
for (int position = 0; position < counter; position++)
{
if (temp.compareTo(books.get(position)) < 0)
{
books.remove(counter);
books.add(position, temp);
break;
}
}
}
}

Stuck In For Loop?

Okay so, I added saving into my game (through serialization), which works completely fine, but these items have things like sprites and stuff that I logically wouldn't save, how I got around that was pretty simple.
I made a method in my Item class (every item extends it) that assigns everything it needs to (called basicInitialization()). This works great!
However, I noticed that any code placed after the loading of items wouldn't run. I investigated and realized I was stuck in an infinite for-loop:
public void loadItems(Player p) {
Item[] temp = SaveGame.loadItems();
for (int i = 0; i < items.length; i++) {
this.removeByIndex(i);
}
for (int j = 0; j < temp.length; j++) {
items[j] = temp[j];
}
for (int t = 0; t < items.length; t++) {
if (items[t] == null) {
t += 1;
}
items[t].basicInitialization();
if (items[t] instanceof EquipableItem) {
items[t].basicInitialization(((EquipableItem)items[t]).slot);
}
}
}
When I removed the:
items[t].basicInitialization();
if (items[t] instanceof EquipableItem) {
items[t].basicInitialization(((EquipableItem)temp[t]).slot);
}
portion and the problem went away.
Am I missing something really obvious here?
Thanks for any help you can give, if anymore code is needed I will happily give it!
Edit:
- Re-structured some code
Here is an example of basicInitialization:
public void basicInitialization() {
this.sprite = Sprite.HealthPotion;
this.name = "Health Potion";
this.value = "25";
this.desc = "Heals Up to 5 HP";
level = Game.getGame().getLevel();
}
You should have the code inside first for loop as :
int j = 0;
if (temp[i] == null) { //If there is no item then continue to the next one
i+= 1
}
else{
items[j] = temp[i];
j++;
}
If the next item is null, then it would get assigned without the else block.
I think I've finally fixed it, thanks for all the help! It was definitely a tough nut to crack!
public void loadItems(Player p) {
Item[] temp = SaveGame.loadItems();
for (int i = 0; i < items.length; i++) {
this.removeByIndex(i); // Remove all current items
}
if (this.lastItemInList(temp) == -1) { // If the loaded item list has no items
return;
}
for (int j = 0; j < temp.length; j++) {
items[j] = temp[j];items
}
for (int t = 0; t < items.length; t++) {
if (items[t] == null) {
if (t != items.length) {
for (int i = t; i < items.length; i++) {
if (items[i] != null) {
t = i; //Gets the next time there is an item that isn't null
break;
}
}
}
}
items[t].basicInitialization();
if (items[t] instanceof EquipableItem) {
items[t].basicInitialization(((EquipableItem)items[t]).slot);
}
if (t == this.lastItemInList(items)) { //Once it hits the last item, then return
System.out.println(":::FULLY LOADED ITEMS >> RETURNING:::");
return;
}
}
}

Categories

Resources