RLE - my code produced more instead less? - java
Im trying to solve a task where I need to implement two methods for the RLE function.
I wrote this code for the compress method:
List<Character> compressRLE(List<Character> text) {
List<Character> ergebnis = new ArrayList<>();
int count = 48;
for (int i = 0; i < text.size(); i++) {
if (i == 0) {
ergebnis.add(text.get(0));
count++;
}
if (i != 0 && text.get(i) == text.get(i-1)) {
count++;
}else if(i != 0 && text.get(i) != text.get(i-1)) {
ergebnis.add((char)count);
ergebnis.add(text.get(i));
count = 49;
}
if (i == text.size()-1) {
ergebnis.add((char)count);
}
}
return ergebnis;
}
that arrayList below I want to compress:
[a, a, a, c, a, a, a, e, e, a, d, e, f, a, d, a, c, d, c, e, a, c, a, f, a, a, a, b, e, a, c, b, c, e, b, d, e, a, e, d, a, e, c, f, b, a, a, a, e, a, d, d, a, d, a, f, e, a, a, a, a, e, c, c, d, f, e, d, e, e, a, e, a, a, b, e, e, a, a, d, a, b, b, a, a, a, d, e, a, e, e, b, a, e, a, e, c, a, e, f, a, a, a, b, e, d, a, c, a, d, f, a, c, b, a, e, a, a, d, d, a, e, a, f, b, d, d, d, a, c, b, d, d, e, f, b, e, d, c, e, c, d, a, a, a, a, a, d, d, a, e, c, a, d, c, e, a, b, a, a, b, a, a, f, b, a, a, d, a, e, d, b, a, b, e, a, a, d, d, d, a, e, a, a, b, e, a, a, a, e, e, e, a, c, d, e, d, c, a, a, e, a, e, e, e, e, a, e, e, e, a, a, a, a, d, a, b, a, a, e, e, c, c, a, e, d, a, d, e, c, a, d, f, c, a, e, a, a, e, e, e, e, a, d, e, a, e, a, c, e, a, d, a, b, a, a, e, a, b, b, e, b, d, a, e, e, e, e, c, a, d, b, e, e, a, b, b, c, a, b, a, a, a, d, a, a, c, e, e, e, a, c, f, a, d, a, d, b, e, a, a, e, b, a, a, a, e, a, a, e, a, d, f, c, a, e, c, d, b, e, a, a, e, d, b, a, a, e, e, b, a, e, e, c, b, a, a, a, a, d, a, a, a, d, e, b, c, e, a, a, a, e, b, a, e, a, a, e, a, a, e, c, a, a, e, c, a, b, c, e, e, c, d, b, a, e, e, d, e, a, c, f, e, a, e, b, e, e, a, e, a, b, a, a, d, e, a, e, e, d, c, b, a, a, e, f, a, a, a, d, f, e, c, a, a, e, e, a, d, a, d, a, a, f, a, a, a, e, a, a, b, a, e, e, a, c, a, f, a, c, e, a, e, a, c, a, c, a, a, a, a, a, c, d, a, a, e, a, a, c, a, b, a, a, a, e, a, c, e, a, a, a, d, c, e, a, e, a, a, d, a, a, d, c, c, a, a, b, d, a, a, e, c, e, e, e, f, a, c, c, c, d, a, a, d, a, b, a, c, b, a, b, e, e, a, e, a, c, d, a, a, a, c, a, a, a, a, a, e, e, c, c, a, a, a, e, d, a, c, e, c, a, a, c, d, b, a, e, a, e, c, d, c, e, a, f, e, a, e, a, a, e, e, a, c, a, c, a, a, e, a, a, a, e, e, a, c, d, a, a, d, a, a, d, e, b, b, f, a, a, b, d, e, a, a, d, c, d, b, c, a, a, c, d, c, a, a, d, d, d, a, d, a, c, a, a, a, a, a, a, e, e, a, f, e, f, f, b, e, b, c, a, a, a, b, a, e, e, f, e, d, b, b, a, a, a, a, e, e, a, b, d, a, a, b, a, a, e, a, d, d, d, f, a, a, f, e, d, a, a, a, d, d, a, d, b, a, e, a, e, c, e, d, e, b, a, a, a, e, c, a, b, e, e, c, e, e, c, a, a, e, a, a, d, b, a, b, e, a, a, a, d, d, e, a, e, a, a, b, d, a, d, a, c, b, f, a, c, a, a, a, d, a, f, a, a, a, d, c, e, a, d, a, a, a, c, d, a, b, e, c, d, d, b, a, b, b, a, a, e, f, a, d, b, a, a, c, a, d, b, a, e, e, a, a, c, a, c, a, a, e, c, b, c, a, e, a, a, b, a, d, b, b, e, a, d, c, e, c, d, c, d, d, c, a, a, e, c, b, a, a, a, a, d, f, f, a, d, d, d, a, a, a, f, e, e, e, c, a, a, f, a, b, d, d, b, a, b, b, d, a, a, d, b, a, a, d, a, d, c, c, a, d, b, e, e, b, a, d, d, f, b, e, a, a, e, d, a, c, d, a, d, a, e, b, b, a, a, e, a, a, c, e, a, a, d, d, d, a, e, a, e, a, a, c, b, c, d, a, b, d, d, f, f, a, a, a, a, a, e, a, f, b, b, c, c, b, d, d, e, a, c, e, f, b, e, a, a, a, a, d, a, d, a, e, c, e, d, d, b, c, a, d, c, a, b, c, e, d, d, d, c, d, c, a, d, e, a, a, d, a, a, a, a, c, b, e, b, e, d, a, a, d, e, b, c, d, b, a, a, e, a, a, e, f, a, c, d, d, e, a, b, d, a, a, d, d, a, d, e]
But somehow Im doing it right and wrong at the same time. I did the compress but the size of the list has been increased almost 3 times:
[a, 3, c, 1, a, 3, e, 2, a, 1, d, 1, e, 1, f, 1, a, 1, d, 1, a, 1, c, 1, d, 1, c, 1, e, 1, a, 1, c, 1, a, 1, f, 1, a, 3, b, 1, e, 1, a, 1, c, 1, b, 1, c, 1, e, 1, b, 1, d, 1, e, 1, a, 1, e, 1, d, 1, a, 1, e, 1, c, 1, f, 1, b, 1, a, 3, e, 1, a, 1, d, 2, a, 1, d, 1, a, 1, f, 1, e, 1, a, 4, e, 1, c, 2, d, 1, f, 1, e, 1, d, 1, e, 2, a, 1, e, 1, a, 2, b, 1, e, 2, a, 2, d, 1, a, 1, b, 2, a, 3, d, 1, e, 1, a, 1, e, 2, b, 1, a, 1, e, 1, a, 1, e, 1, c, 1, a, 1, e, 1, f, 1, a, 3, b, 1, e, 1, d, 1, a, 1, c, 1, a, 1, d, 1, f, 1, a, 1, c, 1, b, 1, a, 1, e, 1, a, 2, d, 2, a, 1, e, 1, a, 1, f, 1, b, 1, d, 3, a, 1, c, 1, b, 1, d, 2, e, 1, f, 1, b, 1, e, 1, d, 1, c, 1, e, 1, c, 1, d, 1, a, 5, d, 2, a, 1, e, 1, c, 1, a, 1, d, 1, c, 1, e, 1, a, 1, b, 1, a, 2, b, 1, a, 2, f, 1, b, 1, a, 2, d, 1, a, 1, e, 1, d, 1, b, 1, a, 1, b, 1, e, 1, a, 2, d, 3, a, 1, e, 1, a, 2, b, 1, e, 1, a, 3, e, 3, a, 1, c, 1, d, 1, e, 1, d, 1, c, 1, a, 2, e, 1, a, 1, e, 4, a, 1, e, 3, a, 4, d, 1, a, 1, b, 1, a, 2, e, 2, c, 2, a, 1, e, 1, d, 1, a, 1, d, 1, e, 1, c, 1, a, 1, d, 1, f, 1, c, 1, a, 1, e, 1, a, 2, e, 4, a, 1, d, 1, e, 1, a, 1, e, 1, a, 1, c, 1, e, 1, a, 1, d, 1, a, 1, b, 1, a, 2, e, 1, a, 1, b, 2, e, 1, b, 1, d, 1, a, 1, e, 4, c, 1, a, 1, d, 1, b, 1, e, 2, a, 1, b, 2, c, 1, a, 1, b, 1, a, 3, d, 1, a, 2, c, 1, e, 3, a, 1, c, 1, f, 1, a, 1, d, 1, a, 1, d, 1, b, 1, e, 1, a, 2, e, 1, b, 1, a, 3, e, 1, a, 2, e, 1, a, 1, d, 1, f, 1, c, 1, a, 1, e, 1, c, 1, d, 1, b, 1, e, 1, a, 2, e, 1, d, 1, b, 1, a, 2, e, 2, b, 1, a, 1, e, 2, c, 1, b, 1, a, 4, d, 1, a, 3, d, 1, e, 1, b, 1, c, 1, e, 1, a, 3, e, 1, b, 1, a, 1, e, 1, a, 2, e, 1, a, 2, e, 1, c, 1, a, 2, e, 1, c, 1, a, 1, b, 1, c, 1, e, 2, c, 1, d, 1, b, 1, a, 1, e, 2, d, 1, e, 1, a, 1, c, 1, f, 1, e, 1, a, 1, e, 1, b, 1, e, 2, a, 1, e, 1, a, 1, b, 1, a, 2, d, 1, e, 1, a, 1, e, 2, d, 1, c, 1, b, 1, a, 2, e, 1, f, 1, a, 3, d, 1, f, 1, e, 1, c, 1, a, 2, e, 2, a, 1, d, 1, a, 1, d, 1, a, 2, f, 1, a, 3, e, 1, a, 2, b, 1, a, 1, e, 2, a, 1, c, 1, a, 1, f, 1, a, 1, c, 1, e, 1, a, 1, e, 1, a, 1, c, 1, a, 1, c, 1, a, 5, c, 1, d, 1, a, 2, e, 1, a, 2, c, 1, a, 1, b, 1, a, 3, e, 1, a, 1, c, 1, e, 1, a, 3, d, 1, c, 1, e, 1, a, 1, e, 1, a, 2, d, 1, a, 2, d, 1, c, 2, a, 2, b, 1, d, 1, a, 2, e, 1, c, 1, e, 3, f, 1, a, 1, c, 3, d, 1, a, 2, d, 1, a, 1, b, 1, a, 1, c, 1, b, 1, a, 1, b, 1, e, 2, a, 1, e, 1, a, 1, c, 1, d, 1, a, 3, c, 1, a, 5, e, 2, c, 2, a, 3, e, 1, d, 1, a, 1, c, 1, e, 1, c, 1, a, 2, c, 1, d, 1, b, 1, a, 1, e, 1, a, 1, e, 1, c, 1, d, 1, c, 1, e, 1, a, 1, f, 1, e, 1, a, 1, e, 1, a, 2, e, 2, a, 1, c, 1, a, 1, c, 1, a, 2, e, 1, a, 3, e, 2, a, 1, c, 1, d, 1, a, 2, d, 1, a, 2, d, 1, e, 1, b, 2, f, 1, a, 2, b, 1, d, 1, e, 1, a, 2, d, 1, c, 1, d, 1, b, 1, c, 1, a, 2, c, 1, d, 1, c, 1, a, 2, d, 3, a, 1, d, 1, a, 1, c, 1, a, 6, e, 2, a, 1, f, 1, e, 1, f, 2, b, 1, e, 1, b, 1, c, 1, a, 3, b, 1, a, 1, e, 2, f, 1, e, 1, d, 1, b, 2, a, 4, e, 2, a, 1, b, 1, d, 1, a, 2, b, 1, a, 2, e, 1, a, 1, d, 3, f, 1, a, 2, f, 1, e, 1, d, 1, a, 3, d, 2, a, 1, d, 1, b, 1, a, 1, e, 1, a, 1, e, 1, c, 1, e, 1, d, 1, e, 1, b, 1, a, 3, e, 1, c, 1, a, 1, b, 1, e, 2, c, 1, e, 2, c, 1, a, 2, e, 1, a, 2, d, 1, b, 1, a, 1, b, 1, e, 1, a, 3, d, 2, e, 1, a, 1, e, 1, a, 2, b, 1, d, 1, a, 1, d, 1, a, 1, c, 1, b, 1, f, 1, a, 1, c, 1, a, 3, d, 1, a, 1, f, 1, a, 3, d, 1, c, 1, e, 1, a, 1, d, 1, a, 3, c, 1, d, 1, a, 1, b, 1, e, 1, c, 1, d, 2, b, 1, a, 1, b, 2, a, 2, e, 1, f, 1, a, 1, d, 1, b, 1, a, 2, c, 1, a, 1, d, 1, b, 1, a, 1, e, 2, a, 2, c, 1, a, 1, c, 1, a, 2, e, 1, c, 1, b, 1, c, 1, a, 1, e, 1, a, 2, b, 1, a, 1, d, 1, b, 2, e, 1, a, 1, d, 1, c, 1, e, 1, c, 1, d, 1, c, 1, d, 2, c, 1, a, 2, e, 1, c, 1, b, 1, a, 4, d, 1, f, 2, a, 1, d, 3, a, 3, f, 1, e, 3, c, 1, a, 2, f, 1, a, 1, b, 1, d, 2, b, 1, a, 1, b, 2, d, 1, a, 2, d, 1, b, 1, a, 2, d, 1, a, 1, d, 1, c, 2, a, 1, d, 1, b, 1, e, 2, b, 1, a, 1, d, 2, f, 1, b, 1, e, 1, a, 2, e, 1, d, 1, a, 1, c, 1, d, 1, a, 1, d, 1, a, 1, e, 1, b, 2, a, 2, e, 1, a, 2, c, 1, e, 1, a, 2, d, 3, a, 1, e, 1, a, 1, e, 1, a, 2, c, 1, b, 1, c, 1, d, 1, a, 1, b, 1, d, 2, f, 2, a, 5, e, 1, a, 1, f, 1, b, 2, c, 2, b, 1, d, 2, e, 1, a, 1, c, 1, e, 1, f, 1, b, 1, e, 1, a, 4, d, 1, a, 1, d, 1, a, 1, e, 1, c, 1, e, 1, d, 2, b, 1, c, 1, a, 1, d, 1, c, 1, a, 1, b, 1, c, 1, e, 1, d, 3, c, 1, d, 1, c, 1, a, 1, d, 1, e, 1, a, 2, d, 1, a, 4, c, 1, b, 1, e, 1, b, 1, e, 1, d, 1, a, 2, d, 1, e, 1, b, 1, c, 1, d, 1, b, 1, a, 2, e, 1, a, 2, e, 1, f, 1, a, 1, c, 1, d, 2, e, 1, a, 1, b, 1, d, 1, a, 2, d, 2, a, 1, d, 1, e, 1]
ergebnis.size() give me this: 2996 (from 1000 to 2996)
I cant figure what went wrong here so Im kindly ask for a little help here.
First of all: do not throw an acronym on stackoverflow and expect people to know what it means. Maybe your whole world is about RLE right now, so you know perfectly well what it means, but not everyone does. So, for the benefit of other readers (and search engines):
RLE stands for Run Length Encoding.
RLE is the most primitive lossless compression algorithm imaginable. (There exist even more primitive compression algorithms, but they are lossy, for example compress( String s ) => return "";)
Secondly: you don't really know whether you "did the compress" unless you also "do the decompress". But let us assume that your algorithm is correct, based on a visual examination of the input data and the result. (I highly doubt that it is correct, because it contains some magic numbers like 48 and 49, which make me not want to read the code.)
Finally: Yes, what you observe is perfectly normal with RLE. If your data to compress has lots of single-value sequences and not many repeated-value sequences, then the result of the RLE algorithm will be longer than the original data to compress, because for every single-value sequence it will produce two values in the output.
Related
Breadth First Search from scratch in Java
I wrote a java-code to find the path in an 2d array. The array is filled with 0=valid node and 1=obstacle. The code runs perfetcly with small 2d arrays for example with the size of int [][] obstacleMap=new int[10][11]; When I increase the size of the array (e.g. int[][] obstacleMap =[600][300];) now the code doesn't work anymore, I get not an Error. I have tested a lot of times my code, I think the problem is the while loop within the findpath function (code below) My code has following functions: main: to test the other functions 2.findPath: find path with given map from start position to target position 3.addNeighbour: add neighbour Following classes: Node : x and y coordinates and distance to start pathCoordinates: x and y values for path The Code is here: package strategyRobot; //import java.awt.datatransfer.SystemFlavorMap; import java.util.ArrayDeque; import java.util.HashSet; import java.util.Queue; import java.util.Set; import java.util.LinkedList; import java.util.List; public class strategyRobotClass { static Set<String> visitedNodes = new HashSet<>(); public static void main(String[] args) { int[][] randomMap={ { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 0, 1, 1, 1, 1, 0, 1, 1, 1 }, { 1, 0, 0, 0, 1, 1, 0 ,1, 1, 1 }, { 1, 1, 1, 0, 1, 1, 0, 1, 1, 1 }, { 1, 1, 1, 0, 1, 1, 0, 1, 1, 1 }, { 1, 1, 1, 0, 0, 0, 0, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, }; int value = randomMap[2][6]; System.out.printf("value = %d", value); System.out.println(" "); LinkedList<pathCoordinates> pathMap= findPath(randomMap,0,0,3,6); for(int i = 0; i<pathMap.size();i++) { System.out.printf("(%d,%d) %n",pathMap.get(i).x,pathMap.get(i).y); } } static public LinkedList<pathCoordinates> findPath(int map[][], int xStartPos, int yStartPos, int xTargetPos, int yTargetPos) { LinkedList<pathCoordinates> pathMap = new LinkedList<pathCoordinates>(); Node source = new Node(xStartPos, yStartPos,0); Queue<Node> queue= new LinkedList<Node>(); queue.add(source); while(!queue.isEmpty()) { // IS THE BUG HERE ???? Node poped = queue.poll(); if(poped.x == xTargetPos && poped.y ==yTargetPos) { return pathMap; } else { map[poped.x][poped.y] = 1 ; pathCoordinates coordinates = new pathCoordinates(poped.x,poped.y); pathMap.add(coordinates); List<Node> neighbourList = addNeighbours(poped,map); queue.addAll(neighbourList); } } return null; } static public List addNeighbours(Node poped, int[][] map) { List<Node> list=new LinkedList<Node>(); if((poped.x-1 >0 && poped.x-1<map.length) && (map[poped.x-1][poped.y]== 0)) { list.add(new Node(poped.x-1, poped.y, poped.distanceFromStart+1)); } if((poped.x+1 >0 && poped.x+1<map.length) && (map[poped.x+1][poped.y]== 0)) { list.add(new Node(poped.x+1, poped.y, poped.distanceFromStart+1)); } if((poped.y-1 >0 && poped.y-1<map.length) && (map[poped.x][poped.y-1]== 0)) { list.add(new Node(poped.x-1, poped.y, poped.distanceFromStart+1)); } if((poped.y+1 >0 && poped.y+1<map.length) && (map[poped.x][poped.y+1]== 0)) { list.add(new Node(poped.x, poped.y+1, poped.distanceFromStart+1)); } return list; } static public class Node{ int x, y; //coordinates in a cell int distanceFromStart; Node parent; Node(int x, int y, int distanceFromStart){ this.x=x; this.y=y; this.distanceFromStart=distanceFromStart; } } static public class pathCoordinates { int x,y; pathCoordinates(int x, int y){ this.x=x; this.y=y; } }
How to program a "get field" function in Java for our game board in Peg-Solitaire
public class SolitaireBoard { private static final int empty = 0; private static final int occupied = 1; private static final int invalid = 2; public int col; public int row; public SolitaireBoard(){ int [] [] board = { {2, 2, 2, 1, 1, 1, 2, 2, 2}, {2, 2, 2, 1, 1, 1, 2, 2, 2}, {2, 2, 2, 1, 1, 1, 2, 2, 2}, {1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 0, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1}, {2, 2, 2, 1, 1, 1, 2, 2, 2}, {2, 2, 2, 1, 1, 1, 2, 2, 2}, {2, 2, 2, 1, 1, 1, 2, 2, 2}, }; } } I need to programm a get field function that has row and col (column) as an input and returns the state of the specific field. I was not able to find any solution online.
You have to make board a property, so you can get a specific field from another method. If you want to access a field you have to count from zero. For example if you want to access a field from the first row, you have to type in the index 0 for the row. public class SolitaireBoard { private static final int empty = 0; private static final int occupied = 1; private static final int invalid = 2; public int[][] board; public int col; public int row; public SolitaireBoard(){ board = new int[][]{ {2, 2, 2, 1, 1, 1, 2, 2, 2}, {2, 2, 2, 1, 1, 1, 2, 2, 2}, {2, 2, 2, 1, 1, 1, 2, 2, 2}, {1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 0, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1}, {2, 2, 2, 1, 1, 1, 2, 2, 2}, {2, 2, 2, 1, 1, 1, 2, 2, 2}, {2, 2, 2, 1, 1, 1, 2, 2, 2}, }; } public int getField(int row, int column) { return board[row][column]; } }
It seems your class should not have row,col attributs, but a board one, like public class SolitaireBoard { private static final int empty = 0; private static final int occupied = 1; private static final int invalid = 2; private int[][] board; public SolitaireBoard(){ this.board = new int[][]{ {2, 2, 2, 1, 1, 1, 2, 2, 2}, // Should be {invalid, invalid, invalid, occupied, ...} {2, 2, 2, 1, 1, 1, 2, 2, 2}, ... }; } } Then build a method to access a box public int getField(int row, int col){ return this.board[row][col]; } To manipulate more easily your constants, you could reduce their name, like EM, OC, IN and build the array with them new int[][]{ {IN, IN, IN, OC, OC, OC, IN, IN, IN}, {IN, IN, IN, OC, OC, OC, IN, IN, IN}, {IN, IN, IN, OC, OC, OC, IN, IN, IN}, {OC, OC, OC, OC, OC, OC, OC, OC, OC}, {OC, OC, OC, OC, EM, OC, OC, OC, OC}, {OC, OC, OC, OC, OC, OC, OC, OC, OC}, {IN, IN, IN, OC, OC, OC, IN, IN, IN}, {IN, IN, IN, OC, OC, OC, IN, IN, IN}, {IN, IN, IN, OC, OC, OC, IN, IN, IN}, };
Equivalent of for x, y in z in java
In python, you can use the structure for x in [a, b, c, d] for loops. This can be replicated using a foreach loop in java. What about if I wanted to replicate a for x, y in z loop, such as the one below, in java? for x_off, y_off in ( (1, 2), (-1, 2), (1, -2), (-1, -2), (2, 1), (-2, 1), (2, -1), (-2, -1) ): #do something
I ended up just using variables for each index. But this won't be useful for 2d arrays with large counts for each inner array. int[][] offsets = new int[][] { {0, 1}, {0, -1}, {1, 0}, {-1, 0}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1} }; for(int[] offset: offsets) { int x = offset[0], y = offset[1]; // do something with x and y
You should create a class for storing the three values: final class Point3D { private final int x, y, z; // constructor, getters, and equals/hashCode/toString here } Then you can use an array initializer with an enhanced for loop: for (Point3D point : new Point3D[] { new Point3D(1, 1, 1), new Point3D(-1, 1, 1), new Point3D(-1, -1, 1), new Point3D(1, -1, 1) }) { // code here } It reads better if you create the array separately, especially if there are many points: Point3D[] points = { new Point3D( 1, 1, 1), new Point3D(-1, 1, 1), new Point3D(-1, -1, 1), new Point3D( 1, -1, 1), new Point3D( 1, 1, -1), new Point3D(-1, 1, -1), new Point3D(-1, -1, -1), new Point3D( 1, -1, -1) }; for (Point3D point : points) { // code here }
Collection.shuffle with seeded Random - anomaly with List of size 16
When using a Random seed that increments by 1 (e.g. epochDay) to generate a deterministic shuffling for a List, I'm observing that for some sequence of the seed a certain entry will always be on the last position of the result. This only happens for Collections of size 16. I've narrowed it down to this piece of code: import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Random; public class Main { public static void main(String[] args) { for (int i = 0; i < 50; i++) { List<String> values = Arrays.asList( "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F" ); Random r = new Random(i); Collections.shuffle(values, r); System.out.println(values); } } } which produces the following output: [0, 7, C, 9, 6, 5, A, 4, 3, 1, 2, E, 8, F, D, B] [A, 5, 0, C, 3, 8, 6, 7, E, 4, F, 2, 9, 1, D, B] [D, 5, 7, E, A, 2, 3, F, 0, 6, 1, 9, 8, 4, C, B] [4, F, 8, E, A, 3, D, 1, C, 9, 2, 0, 7, 6, 5, B] [E, 6, A, 5, F, 2, 8, 0, C, D, 4, 3, 9, 1, 7, B] [2, 9, 0, 1, C, F, 5, 3, 8, D, E, 6, A, 4, 7, B] [5, F, 0, D, 3, A, 8, 2, C, 7, 4, 1, 9, E, 6, B] [3, C, 1, 6, 2, 0, 7, 9, 5, 8, D, 4, A, F, E, B] [3, 9, 2, A, 5, 6, F, D, 8, E, 7, 0, C, 4, 1, B] [0, D, 4, 5, E, 2, A, 7, 6, 3, 9, C, F, 8, 1, B] [2, 5, E, 3, 8, D, 1, 6, 4, C, 7, A, F, 9, 0, B] [C, 3, 5, A, 6, E, 4, 1, 2, 0, 7, 9, F, D, 8, B] [F, 7, 3, D, 8, E, C, 9, 5, 0, A, 4, 1, 6, 2, B] [8, 0, 5, D, E, 6, 4, 9, 2, 3, C, 7, 1, F, A, B] [5, 4, 7, A, 1, 3, 0, 8, F, 6, E, 2, C, D, 9, B] [8, C, 6, 4, D, F, 3, 5, 7, 9, A, 1, 0, E, 2, B] [9, F, A, 4, 0, 6, E, 8, 5, 3, 2, C, 1, D, 7, B] [8, 5, 9, A, 7, 6, 1, E, 3, F, C, D, 2, 4, 0, B] [9, D, 5, 6, C, A, 3, 7, 2, 8, 0, F, 1, 4, E, B] [D, 3, 1, 6, 5, 4, 7, F, 9, C, 2, A, 0, 8, E, B] [6, 8, 0, 7, A, C, 4, D, 9, 3, F, 5, 2, E, 1, B] [2, 7, 1, D, C, A, 0, E, F, 4, 5, 8, 3, 6, 9, B] [D, A, 9, 5, 1, 6, 4, F, E, 7, C, 3, 2, 8, 0, B] [E, 7, A, C, 2, 9, 1, D, 5, 0, 4, 6, 3, F, 8, B] [9, E, 8, D, 4, 0, 3, C, 1, F, 7, 2, 5, 6, A, B] [D, A, C, F, E, 2, 8, 0, 6, 5, 7, 1, 4, 9, 3, B] [A, 0, C, 2, D, 1, 3, E, 6, 7, 5, 8, 4, F, 9, B] [D, 5, A, 9, C, 3, 6, 8, E, 0, 7, F, 4, 1, 2, B] [F, 5, 1, E, D, 3, 9, 0, C, 2, A, 6, 7, 8, 4, B] [C, 9, 1, 2, 6, 8, 0, 3, E, F, A, 5, 7, D, 4, B] [1, 0, 9, C, 8, 7, 2, E, F, 6, A, 4, 5, D, 3, B] [E, 2, 8, C, D, 1, 7, 5, 0, 9, A, 3, 6, 4, F, B] [4, 2, 6, F, C, 8, 5, A, E, 0, 3, 7, D, 9, 1, B] [0, 5, E, 7, 4, 2, 1, 6, 8, F, 3, C, A, D, 9, B] [0, 9, 3, 2, 4, A, E, F, C, 6, 1, 5, 7, D, 8, B] [D, F, 2, 6, 9, A, 1, 0, 5, 7, 3, C, E, 4, 8, B] [2, 5, 4, 0, 1, C, D, 7, 8, 9, 6, 3, E, F, A, B] [7, A, 8, E, 1, 5, 0, 9, 4, C, 6, D, F, 2, 3, B] [7, 3, D, 0, C, 9, A, F, 5, 6, 4, 1, 8, E, 2, B] [5, 3, 7, E, C, 8, F, 4, 1, A, D, 0, 9, 6, 2, B] [C, 5, 1, 2, 7, 0, E, 3, 6, A, 9, 8, F, D, 4, B] [7, 8, 5, 0, D, 3, 1, 6, A, 2, 9, F, E, 4, C, B] [F, 4, 0, 1, 7, A, E, 9, 2, 5, 8, D, C, 6, 3, B] [1, C, 7, 3, 2, 4, 6, 0, 9, A, 8, 5, D, E, F, B] [1, A, 2, 5, 6, E, 9, 7, 3, 8, F, C, 0, 4, D, B] [7, F, 5, D, 4, 8, E, 2, A, 1, C, 3, 0, 9, 6, B] [7, 3, 8, 2, 6, D, 4, 1, F, 5, E, A, 0, 9, C, B] [2, 9, 7, F, 3, 6, A, 4, E, 8, 0, C, 1, D, 5, B] [7, 6, 1, D, 8, 5, 0, 4, A, C, 3, 9, 2, E, F, B] [5, A, 1, F, 6, 2, 9, 7, 8, C, 4, 0, E, D, 3, B] (Tested on Oracle JRE 1.8, 10 and 12) As you can see, the entry B always ends up in the last position of the list. When I let the seed run to values in other ranges, a different element will be placed last, but always the same one for an interval 100-300 incremental seed values. I can work around the issue by placing a call to r.nextInt() before the shuffle, however I'm still baffled by this behaviour and would like to know if there is an explanation or documentation for it.
the source codeshuffle(List<?> list, Random rnd) public static void shuffle(List<?> list, Random rnd) { int size = list.size(); if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) { for (int i=size; i>1; i--) swap(list, i-1, rnd.nextInt(i)); } else { ... so the problem is random.nextInt(16) always return 11 and Random.java private static final long multiplier = 0x5DEECE66DL; private static final long addend = 0xBL; private static final long mask = (1L << 48) - 1; public Random(long seed) { if (getClass() == Random.class) this.seed = new AtomicLong(initialScramble(seed)); else { // subclass might have overriden setSeed this.seed = new AtomicLong(); setSeed(seed); } } private static long initialScramble(long seed) { return (seed ^ multiplier) & mask; } protected int next(int bits) { long oldseed, nextseed; AtomicLong seed = this.seed; do { oldseed = seed.get(); nextseed = (oldseed * multiplier + addend) & mask; } while (!seed.compareAndSet(oldseed, nextseed)); return (int)(nextseed >>> (48 - bits)); } public int nextInt(int bound) { if (bound <= 0) throw new IllegalArgumentException(BadBound); int r = next(31); int m = bound - 1; if ((bound & m) == 0) // i.e., bound is a power of 2 r = (int)((bound * (long)r) >> 31); else { for (int u = r; u - (r = u % bound) + m < 0; u = next(31)) ; } return r; } the first call of random.nextInt(16) int bound = 16; long seed = (i ^ multiplier) & mask; long r = (seed * multiplier + addend) & mask; r = (r >>> (48 - 31)); r = (bound * r) >> 31; after simplify //j is in [-64, 64] r = (((multiplier + j) * multiplier + addend) >>> 44) & 0xF and multiplier < (1 << 35), so r = ((multiplier * multiplier) >> 44) & 0xF that is 11
How to multiply 2 matrices in java and then use the result as transformation matrix for Imgproc.warpPerspective function
I want to create 3 matrices: A of 3x4 and B of 4x4 and C of 4x3 . Then I want to multiply them D = A * (B * C) to receive a 3x3 matrix And then call warpPerspective with D. All of the above is needed to be done with Java. In c++ it is 'extremely' easy opposed to Java, I could not find any real example for Java implementation.
package test; import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.core.Size; import org.opencv.imgproc.Imgproc; public class MatrixMul { static { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); } public static void main(String[] args) { Mat A = new Mat(3, 4, CvType.CV_32FC1); Mat B = new Mat(4, 4, CvType.CV_32FC1); Mat C = new Mat(4, 3, CvType.CV_32FC1); Mat tmp = new Mat(); Mat D = new Mat(); A.put(0, 0, new float[] { 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3 }); B.put(0, 0, new float[] { 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4 }); C.put(0, 0, new float[] { 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3 }); Core.gemm(B, C, 1, new Mat(), 0, tmp); Core.gemm(A, tmp, 1, new Mat(), 0, D); // Mat src = ... // Mat dst = new Mat(); // Imgproc.warpPerspective(src, dst, D, new Size(3,3)); System.out.println("A =\n" + A.dump()); System.out.println("B =\n" + B.dump()); System.out.println("C =\n" + C.dump()); System.out.println("B * C =\n" + tmp.dump()); System.out.println("D = A * (B * C) =\n" + D.dump()); } }