Adding element to array of array - java

I have an array of arrays with color variable
Color [] [] bin = new Color [64] [];
afterwards I want to insert colors into this array
Im looping through a list of colors and tmpColor is the particular color in the loop. I need to insert it into the specific loop it belongs.
int idx = 16* (tmpColor.getRed()/64) + 4*(tmpColor.getGreen()/64) + (tmpColor.getBlue()/64);
bin[idx].push(tmpColor);
However this doesn't seem to work. How do I add a color into the array in the specific index?

How I solve it is the following: instead of creating an array of arrays I created and array of ArrayLists
int size = 64;
ArrayList<Color>[] lists = new ArrayList[size];
for( int i = 0; i < size; i++) {
lists[i] = new ArrayList<Color>();
}
After that I pushed the elements to their particular bin ( in this case in lists)
lists[idx].add(tmpColor);
Afterwards getting the lenght and the first color in the array is s follows:
for (ArrayList<Color> p : lists){
System.out.println("size of bin" + p.size());
if (p.isEmpty())
continue;
else {
System.out.println("list" + p.get(0));
}
}

If you need a List of colors for your index you can use a Map:
private Map<Integer, List<Color>> bin = new HashMap<Integer, List<Color>>();
int idx = 16* (tmpColor.getRed()/64) + 4*(tmpColor.getGreen()/64) + (tmpColor.getBlue()/64);
if(bin.get(idx)==null) bin.put(idx, new ArrayList<Color>());
bin.get(idx).add(tmpColor); //This should be exactly what you need
You can use also different structures like List<List<Color>> or List<Color>[]. Every structure relays on a List since List can be updated and created without knowing the initial length.
What I would do is create a separate class for color bin and some useful methods within:
public class Bin{
private List<Color> colors = new ArrayList<Color>();
public void addColor(Color col){
this.colors.add(col);
}
public List<Color> getColors(){
return this.colors;
}
public boolean hasColor(Color col){
return colors.contains(col);
}
//and so on...
}
And the best structure for your goal now is a map with lazy initialization:
private Map<Integer, Bin> myBinsOfColors = new HashMap<Integer, Bin>();
int idx = 16* (tmpColor.getRed()/64) + 4*(tmpColor.getGreen()/64) + (tmpColor.getBlue()/64);
if(myBinsOfColors.get(idx)==null) myBinsOfColors.put(idx, new Bin()); //Lazy
myBinsOfColors.get(idx).addColor(tmpColor); //This should be exactly what you need
To get the avarage and the number of colors you can implement two methods in the Bin class:
public class Bin{
private List<Color> colors = new ArrayList<Color>();
//As above.
public Color calculateAverage() {
Integer red = 0;
Integer blue = 0;
Integer green = 0;
if(!colors.isEmpty()) {
for (Color col : colors) {
red+= col.getRed();
green+= col.getGreen();
blue+= col.getBlue();
}
return new Color(red/colors.size(), green/colors.size(), blue/colors.size());
}
return null;
}
public int getColorCount(){
return this.colors.size();
}
//and so on...
}

Related

Using a Method to update a 2D Array by finding a matching value and then updating with a different input variable

Lets say I have a public class called GameBoard that will be a two dimensional array with 4 rows and 5 columns. The spaces in the array are filed with String values from 1 to 20. A card will be drawn that has a name (King of Spades for example) . If the user inputs 15 I will store it in a String variable called userLocation. What would be the most efficient way to create a method that takes the input location and updates the array with the name of the Card? Would a for loop be most efficient?
public GameBoard() {
square = new String[4][5];
square[0][0] = new String("1");
square[0][1] = new String("2");
square[0][2] = new String("3");
square[0][3] = new String("4");
square[0][4] = new String("5");
square[1][0] = new String("6");
square[1][1] = new String("7");
square[1][2] = new String("8");
square[1][3] = new String("9");
square[1][4] = new String("10");
square[2][1] = new String("11");
square[2][2] = new String("12");
square[2][3] = new String("13");
square[3][1] = new String("14");
square[3][2] = new String("15");
square[3][3] = new String("16");
square[2][0] = new String(17);
square[3][0] = new String(18);
square[2][4] = new String(19);
square[3][4] = new String(20);
}
My preferred method as of now would look something like this but it gives me the error code "type mismatch:cannot convert string to boolean" under userLocation = board[i][j]
public String[][] updateBoard(String userLocation, Card card, String[][] board) {
for (int i = 0; i <4; i++)
{
for (int j = 0; j < 5; j++)
{
if(userLocation = board[i][j]) {
board[i][j] = card.name;
}
}
}
return board;
}
So the reason it will not compile is your = does not return a boolean expression. == would, but it's still not what you want, since you want to check if the String contents are the same, not if they're the same object, so use .equals.
But, no, I think you don't want to depend on strings to identify locations. What if you want to replace a card? And why look through everything when you need not?
Rather if i is some number between 1 and 20, identify the corresponding spot in the array by square[(i-1)/5][(i-1)%5]
That should bypass the issue you are having with matching strings.
So for example, your constructor becomes:
public GameBoard() {
square = new String[4][5];
for (int i=1; i<=20;i++){
square[(i-1)/5][(i-1)%5]=""+i;//initialize with 1 to 20 if you like
}
and userLocation is an int.

Copy Three Dimensional ArrayList as Pass-By-Value

Java Version 8
IntelliJ IDEA 2016.1.4
Build #IC-145.2070, built on August 2, 2016
JRE: 1.8.0_77-b03 x86
JVM: Java HotSpot(TM) Server VM by Oracle Corporation
I need to be able to copy this ArrayList for when changes are made to values in the ArrayList (added, removed, edited)... And these changes made, must only be made in the copied ArrayList without Affecting the original ArrayList.
Example Code Provided Below:
Line 61: is where the copy of pass-by-value should happen.
Lines 19-23: is where I was thinking of creating the copy pass-by-value method, and then just using the method call on line#61.
package Main;
import java.util.ArrayList;
public class QuickTest {
private static void printHpMpLvlsValues(ArrayList<ArrayList<ArrayList<Integer>>> hpMpLvlsValues, int hpValuesIndex, int mpValuesIndex){
int currentLvl = 1;
for (int lvlIndex = 0; lvlIndex < hpMpLvlsValues.get(hpValuesIndex).size(); lvlIndex++, currentLvl++){
System.out.println("****************** LVL(" + currentLvl + ") Possible Values ******************");
System.out.println("HP Values = " + hpMpLvlsValues.get(hpValuesIndex).get(lvlIndex));
System.out.println("MP Values = " + hpMpLvlsValues.get(mpValuesIndex).get(lvlIndex));
System.out.println();
}
System.out.println("*************************************************************");
System.out.println("*************************************************************");
System.out.println("*************************************************************");
System.out.println();
}
private static ArrayList<ArrayList<ArrayList<Integer>>> getCopyThreeDimArrListPassByValue(ArrayList<ArrayList<ArrayList<Integer>>> origThreeDimArrList){
ArrayList<ArrayList<ArrayList<Integer>>> copiedThreeDimArrList = new ArrayList<>();
//ToDo: fill in code to copy the Three Dimensional ArrayList as pass-by-value.
return copiedThreeDimArrList;
}
public static void main(String[] args) {
int hpValuesIndex = 0;
int mpValuesIndex = 1;
// Setup originalHpMpLvlsValues ArrayList...
ArrayList<ArrayList<ArrayList<Integer>>> originalHpMpLvlsValues = new ArrayList<>();
ArrayList<ArrayList<ArrayList<Integer>>> copiedHpMpLvlsValues = new ArrayList<>();
ArrayList<ArrayList<Integer>> hpLvlsValues = new ArrayList<>();
ArrayList<ArrayList<Integer>> mpLvlsValues = new ArrayList<>();
int maxLvl = 10;
int lvlTotalNumOfValuesPerLvl = 5;
int currentHpValue = 50;
int IncreaseHpValue = 50;
int currentMpValue = 10;
int IncreaseMpValue = 10;
for (int lvlIndex = 0; lvlIndex < maxLvl; lvlIndex++){
hpLvlsValues.add(new ArrayList<>());
mpLvlsValues.add(new ArrayList<>());
for (int valueNum = 1; valueNum <= lvlTotalNumOfValuesPerLvl; valueNum++){
hpLvlsValues.get(lvlIndex).add(currentHpValue);
mpLvlsValues.get(lvlIndex).add(currentMpValue);
currentHpValue += IncreaseHpValue;
currentMpValue += IncreaseMpValue;
}
}
originalHpMpLvlsValues.add(hpLvlsValues);
originalHpMpLvlsValues.add(mpLvlsValues);
// End Setup originalHpMpLvlsValues ArrayList...
// Print multiple hp/mp possible level results to system output
System.out.println("************************************************************");
System.out.println("Original HP/MP Levels Results:");
printHpMpLvlsValues(originalHpMpLvlsValues, hpValuesIndex, mpValuesIndex);
// Attempt to copy originalHpMpLvlsValues ArrayList as pass-by-value
copiedHpMpLvlsValues = originalHpMpLvlsValues; // <--------- Insert how to copy pass-by-value here
// Change hpValue for 5th level from 1150 to 1175
// ... this change should only affect "copiedHpMpLvlsValues" ArrayList and NOT the "originalHpMpLvlsValues" ArrayList
int lvlFiveIndex = 4;
copiedHpMpLvlsValues.get(hpValuesIndex).get(lvlFiveIndex).set(2, 1175);
// Print change made to copiedHpMpLvlsValues ArrayList
System.out.println("************************************************************");
System.out.println("Copied HP/MP Levels Results with change(s):");
printHpMpLvlsValues(copiedHpMpLvlsValues, hpValuesIndex, mpValuesIndex);
// Print originalHpMpLvlsValues ArrayList to ensure NO changes were made to this ArrayList
System.out.println("************************************************************");
System.out.println("Original HP/MP Levels Results without change(s):");
printHpMpLvlsValues(originalHpMpLvlsValues, hpValuesIndex, mpValuesIndex);
}
}
As a side-note, I got help with how to copy two dimensional ArrayLists as pass-by-value here -> Copy Two Dimensional ArrayList as new (read sweepers answer at the bottom done with 1 line of code)
Filled in the copy method on lines 19-23 in original post...
private static ArrayList<ArrayList<ArrayList<Integer>>> getCopyThreeDimArrListPassByValue(ArrayList<ArrayList<ArrayList<Integer>>> origThreeDimArrList){
ArrayList<ArrayList<ArrayList<Integer>>> copiedThreeDimArrList = new ArrayList<>();
ArrayList<ArrayList<Integer>> copiedArr;
for (ArrayList<ArrayList<Integer>> origArr: origThreeDimArrList){
copiedArr = new ArrayList<>(origArr.stream().map(x -> new ArrayList<>(x)).collect(Collectors.toList()));
copiedThreeDimArrList.add(copiedArr);
}
return copiedThreeDimArrList;
}
Then I just use this method call on line#61(now 67)...
copiedHpMpLvlsValues = getCopyThreeDimArrListPassByValue(originalHpMpLvlsValues);
However... I was wondering if there was a better way to do this or a built-in library I could use for this??

algorithm to find the largest area

................................
.XXXXXXXXXXXXXXX.....XXXXXXXXXX.
.X.....X.......X.....X........X.
.X.....X.......XXXXXXX........X.
.XXXXXXXXXXXX.................X.
.X....X.....X.................X.
.X....X.....XXXX..............X.
.XXXXXX........X..............X.
......X........X..............X.
......X........X..............X.
......X........X..............X.
......XXXXXXXXXXXXXXXXXXXXXXXXX.
................................
Looking for an algorithm to find the largest area. Here, "area" is defined as a number of dots (.) bounded by Xs.
private static void readFile(File inputFile) throws IOException {
Scanner fileScanner = new Scanner(inputFile);
Point previousPoint = null;
int rowCount = 0;
while(fileScanner.hasNext()){
String line = fileScanner.next();
String[] points = line.split(" ");
for(int columnCount=0;columnCount<points.length;columnCount++){
if(points[columnCount].equalsIgnoreCase("x")){
Point currentPoint = new Point();
currentPoint.setxValue(columnCount);
currentPoint.setyValue(rowCount);
}
}
rowCount++;
}
}
This is my first and struggling to move further.
This algorithm should work. You just need to implement it in Java.
Load the file into a char[][]. (1 char[] per line)
Loop through the char[][] (2 dimensionally)
upon finding a '.', perform flood fill, changing all '.' to ',', also incrementing a counter on every change.
At the end of flood fill, compare this counter with a globally set maximum. If it's higher, then set it as the new highest. (If the edges are not a proper boundary, then do not set this counter if you reached an edge during flood fill by setting a flag during 3)
Return the highest you set.
If you have any specific problems with the Java implementation, then let me know
Geobits:
Note: If you want to exclude the area "outside" any boxes, flood as
usual, but discard any area that hits the edge during the fill(skip
step 2.2 for that flood).
When doing the flood fill, you have 2 types of boundaries. A wall ('X'), and the edge of the array(which you need to explicitly check for to avoid OutOfBounds exceptions). If you hit an out of bounds, keep doing the fill, but set a flag so you know later to not consider the number you counted for the biggest box.
I was given this as assignment in an interview process and this is the compile and running code
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class FindArea {
public static void main(String[] args)
{
String fileName="C:\\map.txt";
FindArea area = new FindArea();
try{
FileReader inputFile = new FileReader(fileName);
BufferedReader bufferReader = new BufferedReader(inputFile);
char[][] twoArray= new char[100][100];
String line;
int i=0;
while ((line = bufferReader.readLine()) != null) {
twoArray[i] = line.toCharArray();
System.out.println(line);
i++;
}
bufferReader.close();
System.out.println("file read");
System.out.println("Max area: " + area.getMaxArea(twoArray));
} catch(Exception e) {
System.out.println("error : " + e.getMessage());
}
}
/**
* Get the maximum area from the given map
*
* #param charArray
* #return
*/
private int getMaxArea(char[][] charArray) {
HashMap<Integer, ArrayList<String>> numberOfBoxes = convertToBoxes(charArray);
numberOfBoxes = mergeOverlapAreas(numberOfBoxes);
int largeSize = 0;
for (Integer key : numberOfBoxes.keySet()) {
ArrayList<String> list = numberOfBoxes.get(key);
System.out.println("Key : " + key + " Size : " + list.size());
if (largeSize < list.size()) {
largeSize = list.size();
}
}
return largeSize;
}
/**
* Convert the 2d Array to HashMap
* Key being the count of boxes and
* Value being the list of indexes associations
*
* #param charArray
* #return
*/
private HashMap<Integer, ArrayList<String>> convertToBoxes(char[][] charArray) {
HashMap<Integer, ArrayList<String>> numberOfBoxes = new HashMap<Integer, ArrayList<String>>();
int boxes = 0;
for(int i=1; i<charArray.length; i++) {
for (int j=0; j<charArray[i].length; j++) {
if (charArray[i][j] == '.') {
boolean isExists = false;
for(Integer key : numberOfBoxes.keySet()) {
ArrayList<String> arrList = numberOfBoxes.get(key);
if(arrList != null) {
if(arrList.contains((i-1) + "-" + j) ||
arrList.contains(i + "-" + (j-1))) {
isExists = true;
arrList.add(i + "-" + j);
numberOfBoxes.put(key, arrList);
}
}
}
if (!isExists) {
ArrayList<String> list = new ArrayList<String>();
list.add(i + "-" + j);
numberOfBoxes.put(boxes, list);
boxes++;
}
}
}
}
return numberOfBoxes;
}
/**
* Check for the points exists in more than one area
* #param numberOfBoxes
* #return
*/
private HashMap<Integer, ArrayList<String>> mergeOverlapAreas( HashMap<Integer, ArrayList<String>> numberOfBoxes) {
for(Integer key : numberOfBoxes.keySet()) {
ArrayList<String> list1 = numberOfBoxes.get(key);
for (Integer key2 : numberOfBoxes.keySet()) {
if (key < key2) {
ArrayList<String> list2 = numberOfBoxes.get(key2);
Iterator<String> listIter = list2.iterator();
while(listIter.hasNext()) {
if (list1.contains(listIter.next())) {
list1.addAll(list2);
Set<String> noDuplicates = new HashSet<String>(list1);
numberOfBoxes.put(key, new ArrayList<String>(noDuplicates));
break;
}
}
}
}
}
return numberOfBoxes;
}
}
Here's an algorithm that's an alternative to flood fill. This method sweeps through the 2d array and whenever you encounter a node(pixel) that's outside to the left (right, top, bottom), it flags the current node as outside, ie if your neighbour is 'outside', you're marked 'outside' too.
The algorithm continues like this until there're no more updates. That means that all the nodes that are reachable from the 'outside' have been flagged. BTW, this is a very similar problem to level sets functions and updating them (where flood fill is also used). The nice this about this method is that it is ideal for parallelization.
1. Load 2D Symbol Array from File
2. hasupdates = false
3. Create 'isinside' bool array -> {
if(symbolarray[row][col] == '.' and row or col is at boundary)
isinside[row][col] = false
else
isinside[row][col] = true
}
4. do{
Do a sweep from left to right (for all rows) -> //This loop can be run parallely on all rows.
If (!isinside[row][col-1] and symbolarray[row][col] == '.'){
isinside[row][col] = false //mark current value as 'outside'
hasupdates = true
}
Do similar sweeps from right to left, top to bottom(all columns) and bottom to top.
}while(hasupdates)
5. Go through 'isinside' array and count the number of falses.
If you have huge files where you have to do this area calculation, you can have the sweeps along the rows and columns run parallely, because each row update (column update) is independent of the other updates.

Check if color is already in array in Java

I am working on a Java program that is making an array of colors that have been used in another array to draw a picture. I am stumbling on writing code that creates this new array, while also excluding colors that have been added to this array already.
I would appreciate any help into where I am going wrong with my code.
Thanks. My code is below:
public ArrayList<Color> getColorList()
{
ArrayList<Color> getColorList;
getColorList = new ArrayList<Color>();
int index = 0;
boolean colorAdded = false;
for(Stroke stroke : drawing){
while(index <= getColorList.size() && colorAdded == false) {
if(getColorList.get(index) == stroke.getColor()){
colorAdded = true;
}
else{
index = index + 1;
}
}
if(colorAdded == false){
getColorList.add(stroke.getColor());
}
index = 0;
colorAdded = false;
}
return getColorList();
}
Store the colors in a Set and you dont need to worry about duplication:
Set<Color> distinctColors = new HashSet<Color>();
distinctColors .add(stroke.getColor());
return new ArrayList<Color>(distinctColors );
Above code will return an arraylist of distinct colors.
EDIT[After comments]:
Color class should implement hashcode and equals methods such that if 2 objects are equal then they have same hashcode and if 2 objects have same hashcode then they may or may not be equal.

Java "2D-array" issues

I have a table on a mySQL server that has data stored like this
Name Goal New Used Total Pace
Jill 5 6 1 7 0
Bob 5 2 3 5 0
Ann 5 1 2 3 0
It can have many more than that in it. What I need to do is read in the data from the mySQL server and load it into a 2D String array. I already know how to load sql data...the issue is I can not, for the life of me, figure out how to load it into the array.
After the data is loaded into the array, it will be sent off to a table to be loaded for viewing.
So basically the output of the array would need to be:
Jill 5 6 1 7 0
Bob 5 2 3 5 0
Ann 5 1 2 3 0
here is the code I have:
public String[][] fillInTableForStoreFromArchive(String Person, String DateTable) throws SQLException{
stmt = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
rs = stmt.executeQuery("SELECT * FROM `" +DateTable+ "` WHERE name = '" +Person+"'");
int rows = 0; //column number
int columns = 6; //row number
rows = getAmountOfSalesPeople(DateTable).length;
String[][] data = new String[rows][columns];
String name = null;
int goal = 0, New = 0, used = 0,total = 0,pace = 0;
while(rs.next()){
name = rs.getString("Name");
goal = rs.getInt("Goal");
New = rs.getInt("New");
used = rs.getInt("Used");
// total = rs.getInt("total");
// pace = rs.getInt("pace");
String[] mData = { name, new Integer(goal).toString(),
new Integer(New).toString(), new Integer(used).toString(),
new Integer(New + used).toString(),new Integer(pace).toString() };
for(int row = 0; row >data.length; row ++){
data[row] = mData;
}
}
for(int row = 0; row < data.length; row++){
for(int col = 0; col <data[row].length; col++){
System.out.print(data[row][col] + " ");
}
System.out.println();
}
return data;
}
Looking at your example I'll make the assumption that name is unique. Since you've got mixed types, Strings and ints, you can't put them all into one array unless you store the ints as Strings. One solution would be to make an Object that holds a name and its associated data...that is, after all, something one does in object oriented programming.
Barring that I would store the data in a Map, where name is the key and an int array is the value:
HashMap<String, int[]> myMap = new HashMap<String, int[]>();
String name;
int[] myData;
while(rs.next())
{
myData = new int[5];
name = rs.getString("Name");
myData[0] = rs.getInt("Goal");
myData[1] = rs.getInt("New");
myData[2] = rs.getInt("Used");
myData[3] = rs.getInt("total");
myData[4] = rs.getInt("pace");
myMap.put(name, myData);
}
It is then trivial to iterate over the map when needed (hint: use a Map.Entry<String, int[]>), such as in toString(). Arrays don't have "output" so you'll either need to use an object or a separate method to get the data formatted as needed.
Also, avoid variable names like New...no good can come of names that are the same as keywords yet capitalized differently.
Your problem is that youre trying to deal with array rows as independent entities, by setting a row ton other array...
... 2D arrays cannot be set at the "row" level - because they are not managed using row level pointers --- in order to set an 2D array row, you have to explicitly set and define the row and column 'for' each column in the row, in a proper "for" loop.
Once you have the mdata array you want to use it as one of the rows in data. Instead you are using a cycle and assigning to several positions.
You should use a counter to keep track of how many rows have you added and then use that counter to put mdata in the right position.
As a corolary to #Paul's solution you can describe your table in a class and access it through normal OO principle. That would completely eliminate the need for arrays.
Say for example :
public class Player {
private String name;
private int goal;
private int _new; //As #Paul pointed out you should not use reserved keywords
private int used;
private int total;
private int pace;
public Player(String name, int goal, int _new, int used, int total, int pace) {
this.name = name;
this.goal = goal;
this._new = _new;
this.used = used;
this.total = total;
this.pace = pace;
}
public String getName() {
return name;
}
public int getGoal() {
return goal;
}
public int get_new() {
return _new;
}
public int getUsed() {
return used;
}
public int getTotal() {
return total;
}
public int getPace() {
return pace;
}
}
your initialization loop then becomes a much more readable :
List<Player> players = new ArrayList<Player>();
while (rs.next()) {
players.add(new Player(rs.getString("Name"),
rs.getInt("Goal"),
rs.getInt("New"),
rs.getInt("Used"),
rs.getInt("total"),
rs.getInt("pace")));
}
If you want to print information from your data good approach here would be to overload the toString of Player or to add a new method, say dumpToString().
public String dumpTostring() {
StringBuilder sb = new StringBuilder();
sb.append("Player ");
sb.append(name);
sb.append(" Goal=");
sb.append(goal);
sb.append(" New=");
sb.append(_new);
sb.append(" Used=");
sb.append(used);
sb.append(" Total=");
sb.append(total);
sb.append(" Pace=");
sb.append(pace);
return sb.toString();
}
and then just call in as part of a for each loop iterating through the list.

Categories

Resources