GridWorld Custom UnboundedGrid<Actor>(2, infinite) - java

For creating a UnboundedGrid and show it:
ActorWorld world = new ActorWorld(new UnboundedGrid<Actor>());
world.show();
For creating a BoundedGrid (let's say 10x10) and show it:
ActorWorld world = new ActorWorld(new BoundedGrid<Actor>(10, 10));
world.show();
There is any way to create a Custom UnboundedGrid?
By custom, I mean one of the parameters (cols or rows) is not unbounded.
I've checked UnboundedGrid's GridWorld source code and it extends AbstactGrid which implements Grid but I don't imagine any way of doing this.

The best idea is to implement it yourself by extending AbstractGrid. I suggest using an array of Maps that map integers representing the columns with the actors and the length of the array represents the number of rows. (Remember, you can't have generic arrays, so you have to use raw types.) Like this:
public class CustomUnboundedGrid<E> extends AbstractGrid<E>
{
private Map[] data;
private int cols;
public CustomUnboundedGrid(int rows, int cols)
{
if(cols <= 0)
throw new IllegalArgumentException();
try
{
data = new Map[rows];
for(int i = 0; i < rows; ++i)
{
data[i] = new HashMap();
}
}
catch(NegativeArraySizeException e)
{
throw new IllegalArgumentException();
}
}
//override methods from AbstractGrid
}

Related

Initializing 2D ArrayList for for-loop summation (Java)

I am trying to sum N pairs of ints--an Nx2 ArrayList--and return the N summations as an ArrayList. While I understand it is not necessary to set up a class to accomplish this, I would like to do so as practice for future projects.
import java.util.ArrayList;
public class SumsInLoop {
public SumsInLoop(int numberOfPairs, ArrayList<ArrayList<Integer>> numbersList) {}
public ArrayList<Integer> getSums(int numberOfPairs, ArrayList<ArrayList<Integer>> numbersList) {
ArrayList<Integer> pairsOfSums = new ArrayList<Integer>();
for (ArrayList<Integer> Pair : numbersList) {
int x = Pair.get(0);
int y = Pair.get(1);
int sum = x + y;
pairsOfSums.add(sum);
}
System.out.println(pairsOfSums);
return pairsOfSums;
}
The data that I am given is a random assortment of N pairs (numbersOfPairs) of integers, e.g. 612673 108695. I would like to add these pairs of integers to a 2D ArrayList (numbersList) that will be called by getSums.
However, I am having difficulties initializing numbersList. My main function is as follows:
public static void main(String[] args) {
int myNumberOfPairs = 13;
ArrayList[][] myNumbersList = new ArrayList[13][2];
myNumbersList[0][0] = new ArrayList<>();
myNumbersList[0][0].add(612673);
myNumbersList[0][1].add(108695);
myNumbersList[1][0] = new ArrayList<>();
myNumbersList[1][0].add(756875);
myNumbersList[1][1].add(496058);
SumsInLoop mySum = new SumsInLoop(myNumberOfPairs,myNumbersList);
mySum.getSums(myNumberOfPairs, myNumbersList);
The last two lines of code throw errors, asking me to change myNumbersList to type ArrayList<List<Integer>> which throws even more errors, even after changing all 2D ArrayLists to type ArrayList<List<Integer>>.
So, my two questions are as follows:
How can I initialize an NxM ArrayList and populate it correctly?
Is there a faster way of accomplishing this task while still using a class method?
P.S. I'm used to coding in Python and am self-teaching myself Java, so any other information or resources you can provide me with are much appreciated.
You may want to simplify your input by using 2D array of int : int[][] myNumbersList = new int[13][2];
The expected output in that case is a 1D array of int[13] that can be obtained as follows (demonstrated with 2 pairs. See mcve ) :
public class SumsInLoop {
//pairsOfInts should be an [n][2] array
private static int[] sumOfPairs(int[][] pairsOfInts) {
int[] sums = new int[pairsOfInts.length];
for(int pairIndex = 0; pairIndex < pairsOfInts.length; pairIndex++) {
sums[pairIndex]= pairsOfInts[pairIndex][0]+pairsOfInts[pairIndex][1];
}
return sums;
}
public static void main(String[] args) {
int numberOfPairs = 2;
int[][] pairsOfInts = new int[numberOfPairs][2];
pairsOfInts[0] = new int[] {612673,108695 };
pairsOfInts[1] = new int[] {756875,496058 };
int[] sumOfPairs = sumOfPairs(pairsOfInts);
System.out.println(Arrays.toString(sumOfPairs));
}
}
If you want a solution implemented with List you can make use of javafx Pair (or make your own pair class.
The input can be defined as List<Pair<Integer,Integer>> pairsOfInts = new ArrayList<>();
The out put can be an array as above, or a List<Integer>:
import java.util.ArrayList;
import java.util.List;
import javafx.util.Pair;
public class SumsInLoop {
private static List<Integer> sumOfPairs(List<Pair<Integer, Integer>> pairsOfInts) {
List<Integer> sums = new ArrayList<>();
for(Pair<Integer,Integer> pair : pairsOfInts) {
sums.add(pair.getKey()+ pair.getValue());
}
return sums;
}
public static void main(String[] args) {
List<Pair<Integer,Integer>> pairsOfInts = new ArrayList<>();
pairsOfInts.add (new Pair<>(612673,108695 ));
pairsOfInts.add (new Pair<>(756875,496058));
List<Integer> sumOfPairs = sumOfPairs(pairsOfInts);
System.out.println(sumOfPairs);
}
}
The (compile) exception you are getting is due to the fact that you expect a ArrayList<ArrayList<Integer>>, but pass an ArrayList[][]. (which is not the same in Java)
In your case you'd need (in the main method):
ArrayList<ArrayList<Integer>> myNumbersList = new ArrayList</* when java > 6 ;)*/>(13);
this only sets the capacity of the (parent) list (..and the underlying/internal backing array)
to initialize the child lists, you'd not come around looping (somehow...even not in python :):
for (int i = 0; i < 13; i++) {
myNumbersList.add(new ArrayList<Integer>(2));
}
Depends on what means "correctly" ...but I assume with "random data", ideally you would again inner loop:
java.util.Random rnd = new Random(/*seed default current timestamp*/);
//...
for (int i = 0; i < 13; i++) {
ArrayList<Integer> innerList = new ArrayList<>(2);
for (int j = 0; j < 2; j++) {
innerList.add(rnd.netxInt(/*bound default Integer.MAX_VALUE*/) /*+/-/% offset*/);
}
myNumberList.add(innerList);
}
Sorry I am not aware of one (faster way), but much depends on the "input format".
Since you already know the amount of values in a pair, an ArrayList is unnecessary. You can create your own, simpler implementation of a pair.
class Pair {
public final int left;
public final int right;
public Pair(int left, int right){
this.left = left;
this.right = right;
}
}
You can then access the values by creating a pair object and accessing its fields.
Pair p = new Pair(10, 7);
System.out.println(p.left); // 10
System.out.println(p.right); // 7
You can then more easily redefine your getSums method.
public static List<Integer> getSums(List<Pair> pairs){
List<Integer> pairsOfSums = new ArrayList<>();
for(Pair pair : pairs){
int sum = pair.left + pair.right;
pairsOfSums.add(sum);
}
return pairsOfSums;
}
Please also notice the function can be static and you don't need to pass the number of pairs. The for-each loop will cycle through all of them regardless.
Initializing the array is then easier than the method you have described in the question.
List<Pair> pairs = new ArrayList<>();
pairs.add(new Pair(7, 10));
pairs.add(new Pair(18, 3));
pairs.add(new Pair(-6, 0));
pairs.add(new Pair(4, 2));
System.out.println(SumsInLoop.getSums(pairs));

Individually/separately instantiated objects using the same data structure

Note: This is a troubling problem, possibly a bug, although I might be incorrect and missing something small
Problem:
Issue is the separately instantiated objects are referring to the same data structure.
Calling a.add() adds an object to data[NEXT], where is instantiated to NEXT = 0, followed by NEXT++ for increment purposes.
Thereafter, b.add() is called, and following the logic of the add() method, the array is extended,
BUT no initial value has been inserted into b i.e. b.data[0] = null
TL;DR
a.add() adds value to a.
b.add() extends a's array. This should not happen as a and b are 2 separate objects of the same type
main class code:
//...
SimpleSet<Integer> a = new SimpleSet<>();
SimpleSet<Integer> b = new SimpleSet<>();
// add a maximum of 20 unique random numbers from 0..99
Random rand = new Random();
for (int i = 0; i < 20; i++) {
a.add(rand.nextInt(100)); //i=0 - adds to data[0] with no issue
b.add(rand.nextInt(100)); //i=0 - extends a's array? why?
}
//...
class SimpleSet
public class SimpleSet<E> {
private static int MIN_SIZE = 1;
private static int NEXT = 0;
private Object[] data;
/**
* constructor of SimpleSet
*/
public SimpleSet() {
data = new Object[MIN_SIZE];
}
public void add(E e) {
if(NEXT > 0.75*MIN_SIZE){
extendArray();
}
if (data != null) {
data[NEXT] = e;
NEXT++;
}
}
private void extendArray() {
MIN_SIZE = MIN_SIZE*2;
Object[] newData = new Object[MIN_SIZE];
for (int i = 0; i < data.length; i++) {
newData[i] = data[i];
}
data = newData;
return;
}
//...
}
Am I missing something small or is this a bug?
IDE = IntelliJ 2016.3

Collections is private

I keep getting a "collections is private" error. I wanted to create an ArrayList. How do you properly extend the Collections class?
import java.util.Collections;
public class lists extends Collections {
public static void main(String[] args) {
Arraylist <Integer> x = new Arraylist<>();
int[] y = new int[100];
for(int i = 0; i<100-1; i++) {
y[i] = i;
}
for(int j = 0; j<100-1; j++) {
Integer z = new Integer(y[j]);
x.set( j , z );
System.out.println(x.get(j));
}
}
}
Perhaps if you are only trying to use ArrayList then you don't need to extend that.
It's ArrayList (not Arraylist)
Use y.length on your first loop rather than 100-1.
You can just use x.add() to add your integer value in without setting index it should be added into since there you are strictly specifying a pattern.
Try this solution:
import java.util.ArrayList;
public static void main (String[] args) throws java.lang.Exception
{
ArrayList <Integer> x = new ArrayList<Integer>();
int[] y = new int[100];
for(int i = 0; i<y.length; i++){
y[i] = i;
}
for(int j = 0; j<100-1; j++){
x.add(new Integer(y[j]));
System.out.println(x.get(j));
}
}
But, here is better solution, same achievement with one loop:
public static void main (String[] args) throws java.lang.Exception
{
ArrayList <Integer> x = new ArrayList<>();
for(int j = 0; j<100-1; j++){
x.add(new Integer(j));
System.out.println(x.get(j));
}
}
First off, if all you want to do is create an instance of ArrayList, there's no reason to extend anything. In your example code there's no need for it.
If you really do want your own collection class, then Collections is the wrong class. You need to implement Collection<E>, singular, or List<E>.
Implementing those interfaces is a lot of work. You can save a lot of time by sub-classing AbstractList<E>. When you do that you only have to implement get(int) and size(); the rest is done for you. If the list is modifiable then you'll also want to override set(int, E), add(int, E), and remove(int).
From the source of Collections class. Collections class is non-instantiable since it has a private constructor. If you have a Subclass which calls the Collections class, the subclass will invoke the super class constructor since the super class does not define any other constructor to invoke. You cannot instantiate the Collections super class and its sub-classes.
// Suppresses default constructor, ensuring non-instantiability.
private Collections() {
}
From your question, if you want to just instantiate an ArrayList class. The line ArrayList <Integer> x = new ArrayList<>(); will suffice with an import of java.util.ArrayList.
Check your code and add variables where needed and you can improve further on the logic.
final int RANGEVAL = 100;
for(int i = 0; i < RANGEVAL -1 ; i++) {
x.set( i , i ); //You can also use x.add(i);
System.out.println(x.get(i));
}

Fill array bidimensional without columns

how Can I fill an array bidimensional without a specific number of columns?
private Animals[] animals;
private Animals[][] matrizAnimal;
private final int MAX_ANIMALS = 20;
private int numAnimals;
CatalogueAnimals()
{
animals = new Animals[MAX_ANIMALS];
numAnimals = 4;
matrizAnimal = new Animals [2][];
animals[0] = new Dog("Pipi", 10);
animals[1] = new Cat("mimi", 4);
animals[2] = new Cat("jerry", 5);
animals[3] = new Cat("josh", 9);
}
public void fillArrayBi()
{
int i=0;
do{
for (int col=0; col<matrizAnimal.length; col++)
{
if (animals[i] instanceof Dog)
{
matrizAnimal[0][col] = animals[i];
}
else if (animals[i] instanceof Cat)
{
matrizAnimal[1][col] = animals[i];
}
i++;
}
}while(i<numAnimals);
}
I'm trying to fill the array. The first row contains 'Dogs' and the second row contains 'Cats'.
Thanks
for (int col=0; col<matrizAnimal.length; col++)
{
if (animals[i] instanceof Dog)
{
matrizAnimal[0][col] = animals[i];
}
...
}
This won't work due to a number of reasons:
col is bounded by the first dimension of matrizAnimal which is 2, thus it is somewhat risky to apply the value to the second dimension
you created matrizAnimal but I can't see any code where you initialize the elements, hence matrizAnimal[0][col] will result in a NullPointerException because the element at index 0 doesn't exist yet
If I understand your question correctly you want to create the 2nd dimension of matrizAnimal with a length calculated at runtime.
For that you'd have two options:
If you know the length when creating the second dimension, you can pass that directly to the construction call:
int lengthOfRow = 4;
matrizAnimal[0] = new Animals[lengthOfRow];
If the length depends on the elements in that second dimension array you could use a list, fill that and finally convert it to an array:
List<Animals> list = ...;
//fill list
matrizAnimal[0] = list.toArray(new Animals[list.size()]);
Edit:
To clarify on multi-dimensional arrays: arrays can only be one-dimensional but can contain other arrays. Hence a "multi-dimensional" array is actually an array containing arrays etc. In contrast to other languages like C++ the entire array is not laid out in contiguous memory.
In Java arrays need size to be declared, so you must know the number of columns when creating the array. I would make this approach in a different way using Collections
You can use 2 ArrayList, or if you want only one object, a Map:
Create and initialize Map
Map<String, List<Animals>> animalsMap = new HashMap<String, List<Animals>>();
Then,
if (animals[i] instanceof Dog)
{
if (animalsMap.get("Dog") != null)
{
animalsMap.put("Dog", animalsMap.get("Dog").add(animals[i]));
} else {
List<Animal> a = new ArrayList<Animal>();
a.add(animals[i]);
animalsMap.put("Dog", a);
}
}
else if (animals[i] instanceof Cat)
{
if (animalsMap.get("Dog") != null)
{
animalsMap.put("Cat", animalsMap.get("Dog").add(animals[i]));
} else {
List<Animal> a = new ArrayList<Animal>();
a.add(animals[i]);
animalsMap.put("Cat", a);
}

How does one access an ArrayList of ArrayLists? (Generics?)

I'm trying to create a table class, who's rows and columns may expand or shrink, to store ints and strings as a first Java project. The data structure I'm trying to use to represent the table is an ArrayList of ArrayLists, where the initial array's elements all point to a new array list - so the initial array kind of serves as an entrance into rows. This would be a picture of how I have it in my mind, for reference:
The problem I'm having is accessing the inner ArrayLists. I've been reading a bit of documentation, and I can't seem to understand the big issue with why I'm not able to access the inner lists. Some code here:
import java.util.ArrayList;
public class Table {
private int length, width;
private ArrayList newTable;
public Table() {
this.length = this.width = 0;
}
/**
* Testing a few functions
*/
public static void main(String[] args) {
// Just testing a few functions.
Table list1 = new Table();
list1.createTable(4, 4);
list1.displayRow(1);
list1.displayColumn(1);
System.out.println("displayColumn done!");
list1.displayEntireTable();
}
public void createTable(int tableLength, int tableWidth) {
length = tableLength;
width = tableWidth;
this.newTable = new ArrayList();
for (int i = 0; i < tableWidth; i++) {
this.newTable.add(new ArrayList(tableLength));
}
}
public void displayRow(int row) {
System.out.println(this.newTable.get(row));
}
/**
* This function displays the column of the table. Still work which
* needs to be done here.
* #param column
*/
public void displayColumn(int column) {
if (this.newTable.size() >= column) {
for (int i = 0; i < this.newTable.size(); i++) {
// This doesn't work.
System.out.println(this.newTable.get(i).get(column));
}
}
}
public void displayEntireTable() {
for (int i = 0; i < this.newTable.size(); i++) {
System.out.println(this.newTable.get(i));
}
}
}
I'm suspicious that the problem may rely the lack of use in generics, which I'm not quite as familiar with yet as I would like to be. So my question to you, stackoverflow, is whether this data structure - an ArrayList of ArrayLists - is even possible, and if so, where lays my problem?
I think the problem is that you misunderstood the semantics of the new ArrayList(tableLength) call: it does not create an array list of tableLength elements; rather, it creates an ArrayList with the initial capacity enough to hold at least tableLength elements.
I am not sure what kind of elements you are planning to add to your ArrayList of ArrayLists, but here is one way to test your code that creates a two-dimensional ArrayList:
for (int i = 0; i < tableWidth; i++) {
ArrayList toAdd = new ArrayList(tableLength);
for (int j = 0; j != tableLength ; j++) {
toAdd.add(new Integer(i*tableLength +j));
}
this.newTable.add(toAdd);
}
Using Java 1.7 generics improvements:
import java.util.ArrayList;
import java.util.List;
public class Table {
private int length, width;
private List<List<String>> newTable;
public Table() {
this.length = this.width = 0;
}
/**
* Testing a few functions
*/
public static void main(String[] args) {
// Just testing a few functions.
Table list1 = new Table();
list1.createTable(4, 4);
list1.displayRow(1);
System.out.println("displayRow done!");
list1.displayColumn(1);
System.out.println("displayColumn done!");
list1.displayEntireTable();
System.out.println("displayEntireTable done!");
}
public void createTable(int tableLength, int tableWidth) {
length = tableLength;
width = tableWidth;
//by java 1.7 diamond feature, some generics can be hidden
this.newTable = new ArrayList<>();
for (int i = 0; i < tableWidth; i++) {
List<String> columns = new ArrayList<>();
for (int j = 0; j < tableLength; j++) {
columns.add(new String("test"));
} //added here
this.newTable.add(columns);
}
}
public void displayRow(int row) {
System.out.println(this.newTable.get(row));
}
/**
* This function displays the column of the table. Still work which
* needs to be done here.
* #param column
*/
public void displayColumn(int column) {
for (int i = 0; i < this.newTable.size(); i++) {
System.out.println("[" + this.newTable.get(i).get(column) + "]");
}
}
public void displayEntireTable() {
for (int i = 0; i < this.newTable.size(); i++) {
System.out.println(this.newTable.get(i));
}
}
}
Sure it's possible, and I suspect your issues are related to generics, actually -- if you don't use generics, you'll have to do a bunch of casts, which may appear to you as if it just doesn't work.
I'd write this as something like
List<List<Object>> table;
and then I'd add rows by doing table.add(new ArrayList<Object>()), and access elements with table.get(i).get(j).
First of all, what is your real problem? You don't add any data into the inner ArrayLists, so they are empty.
On the other hand, it is better if you create an object for a row, and store these objects in an arraylist.
Change your code that doesn't work to:
System.out.println(((ArrayList) this.newTable.get(i)).get(column));
ArrayList in ArrayList is certainly possibly.
And it is certainly not generics that prohibits you.
Generics is only a compile time check for mistakes and has nothing to do with it. You can complete leave it out, not advised as the probability for class cast exceptions due too mistakes is far larger.
Explanation. The compiler don't knows your ArrayList contains an ArrayList so it doesn't recognize the get method as it trys to invoke it on Object and not ArrayList. So the solution is to cast it if you wan't to use it without generics. However I would recomend to use generics and define your List like this.
private List<List<String> newTable;
Notice how I used List and not ArrayList. Typically your left hand assignment contains an Interface and the right hand an concrete class like ArrayList.

Categories