I'm writing a code that should theoretically take a text file representation of a graph with a number of vertices, edges, and a list of edges, and use depth-first-search to determine if it's bipartite. However I'm using an Arraylist of lists to store the adjacency lists, and I keep getting java.lang.IndexOutOfBoundsException: Index: 1, Size: 0 error at the for loop in the childColor method
import java.io.File;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.*;
import static java.lang.System.*;
import java.util.*;
public class detect_bipartite {
public static void main(String[] args){
int bipartCheck = 1;
List<Integer> numList = new ArrayList<Integer>();
File inFile = null;
//separate white space
if (0 < args.length) {
inFile = new File(args[0]);
}
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(inFile));
String text = null;
while ((text = reader.readLine()) != null) {
String[] tmp = text.split(" ");
for(String str: tmp)
if(!str.equals("")){
numList.add(Integer.parseInt(str));}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
}
}
int n = numList.get(0);
int m = numList.get(1);
List<Integer> edgeA = new ArrayList<Integer>();
List<Integer> edgeB = new ArrayList<Integer>();
for(int i=2; i<numList.size(); i++){
if(i%2==0){edgeA.add(numList.get(i));}
else if(i%2==1){edgeB.add(numList.get(i));}
}
List<List<Integer>> adjLists = new ArrayList<List<Integer>>(n);
for(int j = 1; j <= adjLists.size(); j++){ //get adjacency lists
for(int a=1; a <=edgeA.size(); a++){
if(edgeA.get(a)==j){ (adjLists.get(j)).add(edgeB.get(a));}
if(edgeB.get(a)==j){ (adjLists.get(j)).add(edgeA.get(a));}
}
}
int[] color = new int[n];
Arrays.fill(color, 0);
//0 = uncolored
//1 = red
//2 = blue
int bipart = childColor(n, 1, adjLists, color, 1);
if (bipart==0){bipartCheck = 0;}
for(int d = 0; d < n; d++) //for any disconnected graphs
{
if(color[d] == 0){
bipart = childColor(n, d, adjLists, color, 1);}
if (bipart==0){bipartCheck = 0;}
}
if(bipartCheck == 1){
System.out.println("Bipartite");
} else{
System.out.println("Not a Bipartite");
}
}
public static int childColor(int n, int node, List<List<Integer>> adjLists, int[] color, int nodeColor){
if(color[node] == nodeColor){
return 1;}
int bipart = 1;
int newColor;
if(nodeColor == 1){newColor = 2;}
else{newColor = 1;}
if(color[node] == newColor)
{return 0;}
color[node] = nodeColor;
for(int k = 0; k < adjLists.get(node).size(); k++){ **//This is the error line**
bipart = childColor(n, adjLists.get(node).get(k), adjLists, color, newColor);
if(bipart == 0)
{return 0;}
}
return bipart;
}
}
When you do:
List<List<Integer>> adjLists = new ArrayList<List<Integer>>(n);
You create an ArrayList with initial capacity n. This does not mean the list has size n though. In fact, since the list has no elements, its size is 0. Given that, 1 <= 0 is false and this loop is never executed:
for(int j = 1; j <= adjLists.size(); j++){ //get adjacency lists
for(int a=1; a <=edgeA.size(); a++){
if(edgeA.get(a)==j){ (adjLists.get(j)).add(edgeB.get(a));}
if(edgeB.get(a)==j){ (adjLists.get(j)).add(edgeA.get(a));}
}
}
So, when you call childColor(n, 1, adjLists, color, 1), adjLists is empty. When you try to access an element at index 1, by doing adjLists.get(node), there is no element, thus the IndexOutOfBoundsException.
Also note that Java lists and arrays indices start at 0, not 1.
To solve the problem, you could initialize all the lists before trying to use them:
List<List<Integer>> adjLists = new ArrayList<List<Integer>>(n);
for (int i = 0; i < n; i++) {
adjLists.add(new ArrayList<>());
}
Related
Question to find Bfs path ,, i am able to code bfs path if the graph have vertices marked as 0,1,2,3,4,,like this
But can't able to apply adjacency matrix how to solve bfs for graph like 5,10,15,20
attached images what i have coded
solution
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Bfs {
public static void bfsTraversal(int[][] adjMatrix) {
Queue<Integer> pendingVertices = new LinkedList<>();
boolean[] visited = new boolean[adjMatrix.length];
visited[0] = true;
pendingVertices.add(0);
while (!pendingVertices.isEmpty()) {
int currentVertex = pendingVertices.poll();
System.out.print(currentVertex + " ");
for (int i = 0; i < adjMatrix.length; i++) {
if (adjMatrix[currentVertex][i] == 1 && !visited[i]) {
pendingVertices.add(i);
visited[i] = true;
}
}
}
}
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int v = s.nextInt();
int e = s.nextInt();
int[][] adjMatrix = new int[v][v];
for (int i = 0; i < e; i++) {
int v1 = s.nextInt();
int v2 = s.nextInt();
adjMatrix[v1][v2] = 1;
adjMatrix[v2][v1] = 1;
}
bfsTraversal(adjMatrix);
}
}
Click here for Question for bfs like vertices 0,1,2,3,4...
Click here for ,How i want to solve this for bfs like vertices 5,10,15,20...
And i want to do the same for graph like this ,,can't get logic
Solved by mapping the input with 0,1,2,3.... and maintained a reverseMap
Click here to view the Solution
If you know the range of the numbers, you can let the numbers 5, 10, 15 and 20 be the IDs of the nodes and store the indices of the nodes in a seperate array. Suppose the name of the array is IndexLookupArray, if you want to lookup the index of a node with ID x you can find it in IndexLookupArray[x]. And the rest of the code should be the same. If the range of the numbers is unknown or if it's too big to fit in an array, you can store the indices in a hash map for example and do the same thing.
You can write something like this:
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Bfs {
public static void bfsTraversal(int[][] adjMatrix) {
Queue<Integer> pendingVertices = new LinkedList<>();
boolean[] visited = new boolean[adjMatrix.length];
visited[0] = true;
pendingVertices.add(0);
while (!pendingVertices.isEmpty()) {
int currentVertex = pendingVertices.poll();
System.out.print(currentVertex + " ");
for (int i = 0; i < adjMatrix.length; i++) {
if (adjMatrix[currentVertex][i] == 1 && !visited[i]) {
pendingVertices.add(i);
visited[i] = true;
}
}
}
}
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int idx = 0;
int range = s.nextInt();
int v = s.nextInt();
int e = s.nextInt();
int[] IndexLookupArray = new int[range + 1]; // range + 1 since IndexLookupArray[range] should be accessible.
int[][] adjMatrix = new int[v][v];
Arrays.fill(IndexLookupArray, 0, range + 1, -1);
for (int i = 0; i < e; i++) {
int v1 = s.nextInt();
if (IndexLookupArray[v1] == -1)
{
IndexLookupArray[v1] = idx;
idx++;
}
v1 = IndexLookupArray[v1];
int v2 = s.nextInt();
if (IndexLookupArray[v2] == -1)
{
IndexLookupArray[v2] = idx;
idx++;
}
v2 = IndexLookupArray[v2];
adjMatrix[v1][v2] = 1;
adjMatrix[v2][v1] = 1;
}
bfsTraversal(adjMatrix);
}
}
I am working on this magical sub-string problem.
Magical binary strings are non-empty binary strings if the following two conditions are true:
The number of 0's is equal to the number of 1's.
For every prefix of the binary string, the number of 1's should not be less than the number of 0's.
I got stuck on how to proceed further in my Java program.
Here is my program:
static String findLargest(String str) {
String[] splits = str.split("");
Set<String> set = new LinkedHashSet<String>();
for (int i = 0; i < splits.length; i++) {
if (splits[i].equals("0")) {
continue;
}
int zeros = 0;
int ones = 0;
StringBuilder sb = new StringBuilder("");
for (int j = i; j < splits.length; j++) {
if (splits[j].equals("0")) {
zeros++;
} else {
ones++;
}
sb.append(splits[j]);
if (zeros == ones && ones >= zeros) {
set.add(sb.toString());
}
}
}
set.remove(str);
List<String> list = new ArrayList<String>(set);
System.out.println(list);
return null;
}
Using this program I am able to get the magical sub-strings for the given input String 11011000 as [10, 101100, 1100] in my list variable.
Now from here I am struggling how to remove the invalid entry of 101100 from my list and then use the elements 10, 1100 to swap from my input 11011000 to get the final result as 11100100
Also please guide me if there is any other alternate approach.
If your question is about only eliminating the unwanted "101100" from the result, here is the answer
import java.util.ArrayList;
import java.util.HashMap;
import java.lang.*;
import java.util.Set;
import java.util.*;
public class HelloWorld{
public static void main(String []args){
findLargest("11011000");
}
public static String findLargest(String str) {
String[] splits = str.split("");
Set<String> set = new LinkedHashSet<String>();
for (int i = 0; i < splits.length; i++) {
if (splits[i].equals("0")) {
continue;
}
int zeros = 0;
int ones = 0;
StringBuilder sb = new StringBuilder("");
for (int j = i; j < splits.length; j++) {
if (splits[j].equals("0")) {
zeros++;
} else {
ones++;
}
sb.append(splits[j]);
if (zeros == ones && ones >= zeros) {
set.add(sb.toString());
j = i +1; // RESET THE INDEX ELEMENT TO SKIP THE SUBSTRING FROM CONSIDERATION
break; // BREAK FROM THE LOOP
}
}
}
set.remove(str);
List<String> list = new ArrayList<String>(set);
System.out.println(list);
return null;
}
}
I can provide some points.
First, get all the magical substrings and store them as a pair of start and end index(l, r) in a list;
Second, sort the list based on index l;
Those who can be potentially swapped substring can get from the same index l. look at the example given "11011000"
the list will have (0,7),(1,2),(1,6),(3,6),(4,5)
obviously only potential swap is among (1,2)(1,6)
deal these substrings have same index l will help find potential swapping substrings, sort them to find the maximum order.
class Pair{
int start;
int end;
}
public List<Pair> findmagicalPairs(String binString){
List<Pair> magicPairs = new ArrayList<Pair>();
for(int start=0;start<binString.length()-1;start++){
int ones=0;
int zeros=0;
for(int i=start; i<binString.length();i++){
if(binString.charAt(i) == '1'){
ones++;
} else if(binString.charAt(i)=='0'){
zeros++;
}
if(ones == zeros){ //check if magical
Pair temp=new Pair();
temp.start=start;
temp.end =i;
magicPairs.add(temp);
}
}
}
return magicPairs;
}
public String largestMagical(String binString) {
// Write your code here
List<Pair> allPairs = findmagicalPairs(binString);
String largest=binString;
//check by swapping each pairs
for(int i=0;i<allPairs.size()-1;i++){
for(int j=i+1;j<allPairs.size()-1;j++){
if(allPairs.get(i).end+1 == allPairs.get(j).start){
//consecutive Pair so swap and see largest
int index = allPairs.get(j).start;
String swapped = binString.substring(0,allPairs.get(i).start)+binString.substring(allPairs.get(j).start,allPairs.get(j).end+1)+binString.substring(allPairs.get(i).start,allPairs.get(i).end+1)+binString.substring(allPairs.get(j).end+1);
largest = LargestString(largest, swapped);
} else {
//else ignore
}
}
}
return largest;
}
public String LargestString(String first, String second){
if(first.compareTo(second)>0){
return first;
} else {
return second;
}
}
JavaScript Code!
const largestMagical = (binString) => {
//console.log({ binString });
const len = binString.length;
const height = Array(len + 1).fill(0),
num = { 1: 1, 0: -1 },
marked = Array(len + 1).fill(false),
sameHeights = {};
let i,
j,
result = "";
for (i = 1; i <= len; ++i) {
height[i] = height[i - 1] + num[binString[i - 1]];
}
//console.log({ height });
for (i = 0; i <= len; ++i) {
if (marked[i]) continue;
marked[i] = true;
sameHeights[i] = [i];
for (j = i + 1; j <= len; ++j) {
if (height[j] < height[i]) break;
if (height[j] === height[i]) {
sameHeights[i].push(j);
marked[j] = true;
}
}
}
//console.log({ sameHeights });
for (let k in sameHeights) {
const leng = sameHeights[k].length;
let startId, midId, endId;
for (startId = 0; startId < leng - 2; ++startId) {
for (midId = startId + 1; midId < leng - 1; ++midId) {
for (endId = midId + 1; endId < leng; ++endId) {
const start = sameHeights[k][startId],
mid = sameHeights[k][midId],
end = sameHeights[k][endId];
//console.log({start, mid, end});
const swapped =
binString.substring(0, start) +
binString.substring(mid, end) +
binString.substring(start, mid) +
binString.substring(end, len);
//console.log({swapped});
if (swapped > result) result = swapped;
}
}
}
}
return result;
};
console.log(largestMagical("1010111000"));
console.log(largestMagical("11011000"));
I am working on a Merge-sort algorithm, and I am currently trying to test if it works.
It should be controlled through stdin with the input format:
array length
element values (separated by " ")
However, when typing in:
3
17 10 3
Nothing happens, and hitting enter, just get me to the next line in the console.
I get no error message (unless I type in wrong input), and so I have a hard time figuring out why the script is not prompted to run with the input given.
(Code is copied below)
package merge;
import java.io.*;
import java.util.*;
public class MergeSort
{
// This method takes two sorted arrays of integers as input parameters
// and it should return one sorted array of integers.
public int[] merge(int[] A1, int[] A2) {
int[] C = new int[A1.length + A2.length];
int i = 0, j = 0, k = 0;
while (i < A1.length && j < A2.length)
C[k++] = A1[i] < A2[j] ? A1[i++] : A2[j++];
while (i < A1.length)
C[k++] = A1[i++];
while (j < A2.length)
C[k++] = A2[j++];
return C;
}
// This method takes an array of integers as input parameter,
// and it should then return the integers sorted
// in ascending order using the MergeSort algorithm.
private int[] sort(int[] numbers) {
//pointers
int i = 0, j = 0, k = 0;
// reference values
int half = numbers.length / 2;
int[] sorted = new int[numbers.length];
if (numbers.length <= 1){
return numbers;
}
//left part of 'numbers'
int[] left = new int[half];
int[] right;
//right part of 'numbers'
if (numbers.length % 2 != 0){
right = new int[half+1];
j = half + 1;
}
else{
right = new int[half];
j = half;
}
//fills out left half of array with values from input array
while (i < half)
left[i] = numbers[i];
i++;
//fills out right half of array with values from input array
while (j < numbers.length)
right[j] = numbers[k];
j++; k++;
left = sort(left);
right = sort(right);
merge(left,right);
return sorted;
}
// ##################################################
// # Stdin part. #
// ##################################################
public static void main(String[] args) throws IOException {
new MergeSort().run();
}
private void run() throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
int[] numbers = readIntArray(in);
numbers = sort(numbers);
for (int i = 0; i < numbers.length; i++) {
System.out.print(numbers[i] + " ");
}
}
private int[] readIntArray(BufferedReader in) throws IOException {
int length = Integer.parseInt(in.readLine());
int[] array = new int[length];
StringTokenizer st = new StringTokenizer(in.readLine());
for (int i = 0; i < length; i++) {
array[i] = Integer.parseInt(st.nextToken());
}
return array;
}
}
You call readLine() two times, resulting in an attempt to read two lines on the standard input.
I got this class :
import java.util.*;
public class MatrixArrayList extends AbstractMatrix {
private ArrayList<ArrayList<Integer>> values;
public MatrixArrayList(int nbl, int nbc) {
super(nbl, nbc);
values=new ArrayList<ArrayList<Integer>>();
}
#Override
public int getValue(int x, int y) {
return values.get(x).get(y) ;
}
#Override
public void setValue(int x, int y, int value) {
values.get(x).set(y, value);
}
}
and I got
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
I want to make a matrix with an ArrayList
i have w problem with this :
valeurs.get(x).set(y, valeur);
It's not clear from your code which call causes the exception, however it is clear that you are not initializing your inner array-list, nor are you adding any objects to it.
When you initialize it in the constructor:
values=new ArrayList<ArrayList<Integer>>();
What you're basically doing is instantiating the values object to be an ArrayList of size 0 (no items have been added to it yet).
Then, if say, you're doing setValue at index 0, you get the exception because when you do get(x), you're basically doing get(0) on a collection of size 0 - there is nothing to get, you exceed the bounds of the your array.
What you might want to do is initialize all arrays in the constructor:
public MatrixArrayList(int nbl, int nbc) {
super(nbl, nbc);
values=new ArrayList<ArrayList<Integer>>(nbl);
for (int i = 0; i < nbl; i++) {
values.add(new ArrayList<Integer>(nbc));
}
}
And then you can access them without a problem in getValue or setValue (you'll get this exception if you actually do exceed the bounds or if you haven't set any value at the specific index yet. See comment below:).
Notice, though, that since you're using the ArrayList object, rather than a primitive int[] array, you still don't have values inside your array. Simply doing new ArrayList<Integer>() or even new ArrayList<Integer>(num) still leaves you with a list of size 0. If you want to cover all your bases, you might want to either initailize your ArrayList, or perform bounds checks before each get you make in either getValue or setValue.
new ArrayList<ArrayList<Integer>>() creates an empty list. To fill that list with values, you need to call add().
Assuming you want to fill matrix with nbl lists of nbc null values:
this.values = new ArrayList<>(nbl);
for (int i = 0; i < nbl; i++) {
ArrayList<Integer> row = new ArrayList<>(nbc);
for (int j = 0; j < nbc; j++)
row.add(null);
this.values.add(row);
}
You could also fill it with 0 values if you want.
Of course, if the matrix cannot change size, it would likely be much better to create a simple array version, instead of the ArrayList version you're trying to create.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class Shell {
static List<ArrayList<ArrayList<Double>>> read(String filename) {
ArrayList<ArrayList<Double>> A = new ArrayList<ArrayList<Double>>();
ArrayList<ArrayList<Double>> B = new ArrayList<ArrayList<Double>>();
String thisLine;
try {
BufferedReader br = new BufferedReader(new FileReader(filename));
// Begin reading A
while ((thisLine = br.readLine()) != null) {
if (thisLine.trim().equals("")) {
break;
} else {
ArrayList<Double> line = new ArrayList<Double>();
String[] lineArray = thisLine.split("\t");
for (String number : lineArray) {
line.add((double) Integer.parseInt(number));
}
A.add(line);
}
}
// Begin reading B
while ((thisLine = br.readLine()) != null) {
ArrayList<Double> line = new ArrayList<Double>();
String[] lineArray = thisLine.split("\t");
for (String number : lineArray) {
line.add((double) Integer.parseInt(number));
}
B.add(line);
}
} catch (IOException e) {
System.err.println("Error: " + e);
}
List<ArrayList<ArrayList<Double>>> res = new LinkedList<ArrayList<ArrayList<Double>>>();
res.add(A);
res.add(B);
return res;
}
static int[][] ijkAlgorithm(ArrayList<ArrayList<Integer>> A,
ArrayList<ArrayList<Integer>> B) {
int n = A.size();
// initialise C
int[][] C = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < n; k++) {
C[i][j] += A.get(i).get(k) * B.get(k).get(j);
}
}
}
return C;
}
static void printMatrix(Matrix matrix, int n) {
for (int i = 0; i < n; i++) {
StringBuilder sb = new StringBuilder(matrix.length);
for (int j = 0; j < n; j++) {
if (j != 0) {
sb.append("\t");
}
String formattedString = String.format("%.0f", matrix.get(i, j))
sb.append(formattedString);
}
System.out.println(sb.toString());
}
}
public static void main(String[] args) {
String filename;
if (args.length < 2) {
filename = "2000.in";
} else {
filename = args[1];
}
List<ArrayList<ArrayList<Double>>> matrices = read(filename);
ArrayList<ArrayList<Double>> A = matrices.get(0);
ArrayList<ArrayList<Double>> B = matrices.get(1);
int n = A.size();
double[][] Aarray = new double[n][n];
double[][] Barray = new double[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
Aarray[i][j] = A.get(i).get(j);
Barray[i][j] = B.get(i).get(j);
}
}
Matrix AM = new Matrix(Aarray);
Matrix BM = new Matrix(Aarray);
Matrix CM = AM.times(BM);
printMatrix(CM, n);
}
}
input file that have matrices you want to do this operation
Hope this code helps happy coding.
import java.util.ArrayList;
import java.util.Random;
public class Merge {
private static ArrayList<Integer> newArrayList;
public static ArrayList<Integer> generateArray(int n){
newArrayList = new ArrayList<Integer>(n);
Random rand = new Random();
for (int i = 0; i<n; i++){
newArrayList.add(rand.nextInt(n + 1));
}
return newArrayList;
}
public static ArrayList<Integer> mergeSort(ArrayList<Integer> x){
if (x.size()>1){
ArrayList<Integer> ArrayList1 = new ArrayList<Integer>(x.size()/2);
ArrayList<Integer> ArrayList2 = new ArrayList<Integer>(x.size()-(x.size()/2));
for (int i = 0; i<newArrayList.size()/2; i++){
ArrayList1.set(i, newArrayList.get(i));
}
for (int i = (newArrayList.size()/2); i<((newArrayList.size()/2)+(newArrayList.size()-newArrayList.size()/2)); i++){
ArrayList2.set(i-(newArrayList.size()/2), newArrayList.get(i));
}
//ArrayList1 = mergeSort(ArrayList1);
//ArrayList2 = mergeSort(ArrayList2);
int j = 0;
int k = 0;
int a = 0;
while(ArrayList1.size() != j && ArrayList2.size() != k){
if (ArrayList1.get(j) < ArrayList2.get(k)){
x.set(a, ArrayList1.get(j));
a++;
j++;
} else {
x.set(a, ArrayList2.get(k));
a++;
k++;
}
}
while (ArrayList1.size()!=j){
x.set(a, ArrayList1.get(j));
a++;
j++;
}
while (ArrayList2.size()!=k){
x.set(a, ArrayList2.get(k));
a++;
k++;
}
}
return x;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList<Integer> new1;
//ArrayList<Integer> new2;
//ArrayList<Integer> new3;
new1 = generateArray(10);
//new2 = generateArray(100);
//new3 = generateArray(1000);
System.out.println(new1);
mergeSort(new1);
System.out.println(new1);
}
}
I am attempting to implement a mergeSort method but I keep getting the following error:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.RangeCheck(ArrayList.java:547)
at java.util.ArrayList.set(ArrayList.java:337)
at Merge.mergeSort(Merge.java:23)
at Merge.main(Merge.java:73)
Any ideas?
You are attempting to set a position that doesn't exist yet in your ArrayList called ArrayList1. You've set the initial capacity to x.size() / 2, but there's nothing in it yet.
It looks like you are attempting to set each position, starting with position 0, so just add the elements instead. Replace
for (int i = 0; i<newArrayList.size()/2; i++){
ArrayList1.set(i, newArrayList.get(i));
}
with
for (int i = 0; i<newArrayList.size()/2; i++){
ArrayList1.add(newArrayList.get(i));
}
And you'll need to make similar changes to the for loop after that, which populates ArrayList2.