Search for an element in array with threads [closed] - java

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I have following homework to do:
Implement parallel searching for specified element in array. Use number of threads as a function parameter. Eeach thread checks own array piece size of (ArraySize/NumberOfThreads).
class MyThread extends Thread {
final int[] SEARCH_TAB;
final int RANGE_TAB[][];
final int SEARCH_VALUE;
static int searchIndex = -1;
static boolean isWorking = true;
int whichThread;
MyThread(int[] searchTab, int[][] rangeTab, int searchValue, int whichThread) {
SEARCH_TAB = searchTab;
RANGE_TAB = rangeTab;
SEARCH_VALUE = searchValue;
this.whichThread = whichThread;
}
#Override
public void run() {
for (int i = RANGE_TAB[whichThread][0]; i < RANGE_TAB[whichThread][1] && isWorking; ++i) {
synchronized(this) {
if (SEARCH_TAB[i] == SEARCH_VALUE) {
isWorking = false;
searchIndex = i;
}
}
}
}
}
class Main {
private static int[][] range(int n, int p) {
int[] quantities = new int[p];
int remainder = n % p;
int quotient = n/p;
int i;
for (i = 0; i < p; ++i) quantities[i] = quotient;
i = 0;
while (remainder != 0) {
--remainder;
++quantities[i];
++i;
}
int[][] tab = new int[p][2];
tab[0][0] = 0;
tab[0][1] = quantities[0];
for (i = 1; i < p; ++i) {
tab[i][0] = tab[i-1][1];
tab[i][1] = tab[i][0] + quantities[i];
}
return tab;
}
private static int search(int[] searchTab, int numberOfThreads, int searchValue) {
int[][] rangeTab = range(searchTab.length, numberOfThreads);
Thread[] threads = new Thread[numberOfThreads];
for ( int i = 0; i < numberOfThreads; ++i) threads[i] = new MyThread(searchTab, rangeTab, searchValue, i);
for ( int i = 0; i < numberOfThreads; ++i) threads[i].start();
return MyThread.searchIndex;
}
public static void main(String[] args) {
int[] tab = {0, 1, 2, 3, 4, 5, 6, 7 , 8, 9, 10};
int value = 5;
int valueIndex = search(tab, 1, value);
if (valueIndex == -1) System.out.println("Not found.");
else System.out.println(valueIndex);
}
}
This code generally works but cant't find index when one thread is implemented. By the way my teacher said that my code is too long and complicated any suggestions with that?
I will be grateful for any kind of help.

How about the following code:
public class Searcher implements Runnable {
private int intToFind;
private int startIndex;
private int endIndex;
private int[] arrayToSearchIn;
public Searcher(int x, int s, int e, int[] a) {
intToFind = x;
startIndex = s;
endIndex = e;
arrayToSearchIn = a;
}
public void run() {
for (int i = startIndex; i <= endIndex; i++) {
if (arrayToSearchIn[i] == intToFind) System.out.println("Found x at index: " + i);
}
}
}
public class Starter {
public static void main(String[] args) {
int[] a = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
int numberOfThreads = 5;
int x = 20;
findElement(numberOfThreads, x, a);
}
private static void findElement(int numberOfThreads, int x, int[] a) {
int sizeOfa = a.length;
int range = sizeOfa/numberOfThreads;
for (int i = 0; i <= numberOfThreads-1; i++) {
Thread searcher;
if (i == numberOfThreads-1) {
searcher = new Thread(new Searcher(x, i*range, sizeOfa-1, a));
} else {
searcher = new Thread(new Searcher(x, i*range, i*range+range-1, a));
}
searcher.start();
}
}
}
You can still optimize the code e.g. by splitting the rest of the array on all threads instead of just pushing it into the last one (like in my code) but the idea is still the same.
EDIT: I think that there is a problem with your code. It will only show one appearance of x in the array. If you are looking for x = 5 in [5,5,5,5,5] using five threads you can neven know which index will be returned because it depends on how your threads are scheduled. The outcome will be between 0 and 5.

Related

Find all connected components and their sizes in a graph

I'm trying to find all connected components and their sizes in a graph. I don't know why, but the size is always 0. Maybe something is wrong in the method.
This is the problem that I am trying to solve. https://www.codechef.com/LRNDSA08/problems/FIRESC
public class B {
static void dfs(int s, int v, boolean[] visited, ArrayList<ArrayList<Integer>> adj) {
s++;
visited[v] = true;
for (int u : adj.get(v)) {
if (!visited[u]) {
dfs(s, u, visited, adj);
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
StringBuilder str = new StringBuilder();
int t = sc.nextInt();
for (int xx = 0; xx < t; xx++) {
int n = sc.nextInt();
int m = sc.nextInt();
ArrayList<ArrayList<Integer>> arr = new ArrayList<>();
for (int i = 0; i < n; i++) {
arr.add(new ArrayList<Integer>());
}
boolean[] visited = new boolean[n];
Arrays.fill(visited, false);
for (int i = 0; i < m; i++) {
int a = sc.nextInt();
int b = sc.nextInt();
a--;
b--;
arr.get(a).add(b);
arr.get(b).add(a);
}
long ways = 1;
int groups = 0;
for (int i = 0; i < n; i++) {
if (visited[i])
continue;
int size = 0;
dfs(size, i, visited, arr);
groups++;
ways *= size;
ways %= 1000000007;
}
System.out.println(groups + " " + ways);
}
}
}
You know size is passed as value and not as reference. So it won't get updated after you return from the call. One thing you could do is define a single element array like
int[] size = new int[1];
and modify your dfs like:
static void dfs(int[] s, int v, boolean[] visited, ArrayList<ArrayList<Integer>> adj) {
s[0]++;
visited[v] = true;
for (int u : adj.get(v)) {
if (!visited[u]) {
dfs(s, u, visited, adj);
}
}
}
Then your result will be in size[0] which you can use to update ways like ways *= size[0]
Or you could modify dfs to return size which is a cleaner way to get the size like below:
static int dfs(int v, boolean[] visited, ArrayList<ArrayList<Integer>> adj) {
visited[v] = true;
int sz = 1;
for (int u : adj.get(v)) {
if (!visited[u]) {
sz += dfs(u, visited, adj);
}
}
return sz;
}
And it seems like you have a misconception on how variables in Java work (see). Incrementing an int variable that resides on one lair of the stack would not affect a variable on another stack lair. That's why the size is always 0.
The following solution passes base test on CodeChef:
public class CountComponents {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int testCases = sc.nextInt();
for (int i = 0; i < testCases; i++) {
EmployeeGraph graph = parseGraph(sc);
graph.countComponentsAndComponentSizes();
}
}
public static EmployeeGraph parseGraph(Scanner sc) {
int employeeCount = sc.nextInt();
int connectionsCount = sc.nextInt();
boolean[][] adjacencyMatrix = new boolean[employeeCount][employeeCount];
for (int i = 0; i < connectionsCount; i++) {
int row = sc.nextInt() - 1;
int col = sc.nextInt() - 1;
adjacencyMatrix[row][col] = true;
adjacencyMatrix[col][row] = true;
}
return new EmployeeGraph(adjacencyMatrix);
}
}
class EmployeeGraph {
public static final int BILLION_SEVEN = 1_000_000_007;
private boolean[][] adjacencyMatrix;
public EmployeeGraph(boolean[][] adjacencyMatrix) {
this.adjacencyMatrix = adjacencyMatrix;
}
public void countComponentsAndComponentSizes() {
boolean[] visited = new boolean[adjacencyMatrix.length];
int componentCount = 0;
int waysToChooseCaptain = 1;
for (int row = 0; row < adjacencyMatrix.length; row++) {
if (!visited[row]) {
componentCount++;
waysToChooseCaptain = (waysToChooseCaptain % BILLION_SEVEN) * dfs(visited, row);
}
}
System.out.println(componentCount + " " + waysToChooseCaptain % BILLION_SEVEN);
}
public int dfs(boolean[] visited, int row) {
visited[row] = true; // marking the current employee as visited
int size = 1; // this component consists at least from 1 employee
for (int col = 0; col < adjacencyMatrix.length; col++) {
if (adjacencyMatrix[row][col] && !visited[col]) {
size += dfs(visited, col);
}
}
return size;
}
}

Using Depth-First Search in JAVA program instead of Breadth-First Search

I have a JAVA program where I am creating graphs and I have a Breadth-First Search but I would like to change it to Depth First Search. What changes should I make in a code? Thanks for help in advance.
public class ConnectedComponents
{
static final int MAXV = 100;
static boolean processed[] = new boolean[MAXV];
static boolean discovered[] = new boolean[MAXV];
static int parent[] = new int[MAXV];
static void bfs(CCGraph g, int start)
{
Queue<Integer> q = new LinkedList<Integer>();
int i, v;
q.offer(start);
discovered[start] = true;
while (!q.isEmpty())
{
v = q.remove();
process_vertex(v);
processed[v] = true;
for (i = g.degree[v] - 1; i >= 0; i--)
{
if (!discovered[g.edges[v][i]])
{
q.offer(g.edges[v][i]);
discovered[g.edges[v][i]] = true;
parent[g.edges[v][i]] = v;
}
}
}
}
I think you should understand the difference between depth first search and breadth first search. The code for depth first search goes as follows:
public class ConnectedComponents
{
static final int MAXV = 100;
static boolean processed[] = new boolean[MAXV];
static boolean discovered[] = new boolean[MAXV];
static int parent[] = new int[MAXV];
static void dfs(CCGraph g, int vertex)
{
discovered[vertex] = true;
for (i = g.degree[vertex] - 1; i >= 0; i--)
{
if (!discovered[g.edges[vertex][i]])
{
parent[g.edges[v][i]]=vertex;
dfs(g.edges[v][i]]);
}
}
}
}
The basic difference is the order by which vertexes are tested. While BFS uses queue (FIFO: First In First Out), DFS use stack (LIFO: Last In First Out).
You could implement stack using LinkedList:
LinkedList<Integer> stack = new LinkedList<Integer>();
stack.pop(); //returns the top of the stack
For more information please post mcve including test data.
Full code of the program. The goal is to change bfs to dfs.
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
class CCGraph
{
static final int MAXV = 100;
static final int MAXDEGREE = 50;
public int edges[][] = new int[MAXV + 1][MAXDEGREE];
public int degree[] = new int[MAXV + 1];
public int nvertices;
public int nedges;
CCGraph()
{
nvertices = nedges = 0;
for (int i = 1; i <= MAXV; i++)
degree[i] = 0;
}
void read_CCGraph(boolean directed)
{
int x, y;
Scanner sc = new Scanner(System.in);
System.out.println("Enter the number of vertices: ");
nvertices = sc.nextInt();
System.out.println("Enter the number of edges: ");
int m = sc.nextInt();
System.out.println("Enter the edges: <from> <to>");
for (int i = 1; i <= m; i++)
{
x = sc.nextInt();
y = sc.nextInt();
insert_edge(x, y, directed);
}
sc.close();
}
void insert_edge(int x, int y, boolean directed)
{
if (degree[x] > MAXDEGREE)
System.out.printf(
"Warning: insertion (%d, %d) exceeds max degree\n", x, y);
edges[x][degree[x]] = y;
degree[x]++;
if (!directed)
insert_edge(y, x, true);
else
nedges++;
}
void print_CCGraph()
{
for (int i = 1; i <= nvertices; i++)
{
System.out.printf("%d: ", i);
for (int j = degree[i] - 1; j >= 0; j--)
System.out.printf(" %d", edges[i][j]);
System.out.printf("\n");
}
}
}
public class ConnectedComponents
{
static final int MAXV = 100;
static boolean processed[] = new boolean[MAXV];
static boolean discovered[] = new boolean[MAXV];
static int parent[] = new int[MAXV];
static void bfs(CCGraph g, int start)
{
LinkedList<Integer> q = new LinkedList<Integer>();
int i, v;
q.offer(start);
discovered[start] = true;
while (!q.isEmpty())
{
v = q.remove();
process_vertex(v);
processed[v] = true;
for (i = g.degree[v] - 1; i >= 0; i--)
{
if (!discovered[g.edges[v][i]])
{
q.offer(g.edges[v][i]);
discovered[g.edges[v][i]] = true;
parent[g.edges[v][i]] = v;
}
}
}
}
static void initialize_search(CCGraph g)
{
for (int i = 1; i <= g.nvertices; i++)
{
processed[i] = discovered[i] = false;
parent[i] = -1;
}
}
static void process_vertex(int v)
{
System.out.printf(" %d", v);
}
static void connected_components(CCGraph g)
{
int c;
initialize_search(g);
c = 0;
for (int i = 1; i <= g.nvertices; i++)
{
if (!discovered[i])
{
c++;
System.out.printf("Component %d:", c);
bfs(g, i);
System.out.printf("\n");
}
}
}
static public void main(String[] args)
{
CCGraph g = new CCGraph();
g.read_CCGraph(false);
g.print_CCGraph();
connected_components(g);
}
}

Java Array Index out of Bounds Error

I'm working on a brute force approach to the traveling salesman problem. I have a certain line that produces the ArrayIndexOutOfBounds exception, however all the arrays used there have more than enough space. The particular line of code:
testCity[0][a] = cities[0][(int) cityList[a]];
This is where I initialize testCity:
int[][] testCity = new int[2][CITIES+10];
cities:
public static int[][] cities = new int[2][CITIES+10];
And, finally, cityList:
Object[] cityList = new Integer[CITIES+10];
This is the entire error message:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4
at BruteF.permute(BruteF.java:39)
at BruteF.permute(BruteF.java:30)
at BruteF.permute(BruteF.java:30)
at BruteF.permute(BruteF.java:30)
at BruteF.main(BruteF.java:11)
And here is the code:
public class BruteF {
public static final int CITIES = 5;
public static int[][] cities = new int[2][CITIES+10];
public static int[][] bestCity = new int[2][CITIES+10];
public static double bestDistance = 1000;
public static int[][] testCity = new int[2][CITIES+10];
public static Object[] cityList = new Integer[CITIES+10];
public static void main(String[] args)
{
permute(java.util.Arrays.asList(1,2,3,4), 0);
for (int i = 0;i < CITIES;i++)
{
System.out.println(bestCity[0][i] + "," + bestCity[1][i]);
}
}
static void permute(java.util.List<Integer> arr, int k){
cities[0][0] = 1;
cities[1][0] = 1;
cities[0][1] = 2;
cities[1][1] = 5;
cities[0][2] = 3;
cities[1][2] = 2;
cities[0][3] = 4;
cities[1][3] = 3;
int originalX = cities[0][0];
int originalY = cities[1][0];
for(int i = k; i < arr.size(); i++){
java.util.Collections.swap(arr, i, k);
permute(arr, k+1);
java.util.Collections.swap(arr, k, i);
}
if (k == arr.size() -1){
for (int i = 0;i < CITIES;i++)
{
cityList = arr.toArray();
for (int a = 0;a < CITIES;a++)
{
testCity[0][a] = cities[0][(int) cityList[a]];
}
if (distance(testCity,CITIES,originalX, originalY) < bestDistance)
{
bestCity = testCity;
bestDistance = distance(testCity,CITIES, originalX, originalY);
}
}
}
}
static double distance (int[][] cities, int CITIES, int originalX, int originalY)
{
int[][] taken = new int[2][CITIES+1];
int takenCounter = 0;
double distance = 0;
cities[0][CITIES] = cities[0][0];
cities[1][CITIES] = cities[1][0];
for (int i = 0;i <= CITIES;i++)
{
for (int z = 0;z <= CITIES;z++)
{
if (cities[0][i] == taken[0][z] && cities[1][i] == taken[1][z])
{
return CITIES*1000; //possible error here
}
else {
taken[0][takenCounter] = cities[0][i];
taken[1][takenCounter] = cities[1][i];
}
}
if (cities[0][0] != originalX && cities[1][0] != originalY)
{
return CITIES*1000; //POSSIBLE BUG HERE
}
distance = distance + Math.sqrt(Math.pow(cities[0][i+1]-cities[0][i],2) + Math.pow(cities[1][i+1]-cities[1][i],2));
}
return distance;
}
}
Why is this happenening? What can I do to fix it?
It is giving out of bound exception : 4
when you are initializing cityList i.e. cityList = arr.toArray(); your array cityList[] = {1,2,3,4} , i.e of size 4 from 0 to 3.
And you are running a for loop i.e
for (int a = 0;a < CITIES;a++)
from a=0 to CITIES , so as the moment arrive when a=4, it gives out of bound error.

Java--Making 10-integer ordering program recursive

I have a simple problem - I need to order 10 numbers. I had an idea how to do this recursively: Make an array of the 10 numbers, take the maximum of the ten numbers, take it out of the array, and repeat the same function with the nine numbers left. The problem was that I did not know how to implement that. I wrote the program, and it works, only it has a part that repeats all the time but with new arrays, because you cannot change the size of the array.
/* package whatever; // don't place package name! */
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone {
public static void main (String[] args) throws java.lang.Exception {
int[] sortedArray = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
Scanner input = new Scanner(System.in);
int in0 = input.nextInt();
int in1 = input.nextInt();
int in2 = input.nextInt();
int in3 = input.nextInt();
int in4 = input.nextInt();
int in5 = input.nextInt();
int in6 = input.nextInt();
int in7 = input.nextInt();
int in8 = input.nextInt();
int in9 = input.nextInt();
int[] numArray = new int[]{in0, in1, in2, in3, in4, in5, in6, in7, in8, in9};
int numArrayLength = numArray.length;
recursiveSort(numArray);
for (int i=0;i<numArrayLength;i++) {
System.out.print(numArray[i]+",");
}
sortedArray[0] = numArray[0];
System.out.println(" ");
int[] numArray2 = Arrays.copyOfRange(numArray, 1, numArrayLength);
int numArray2Length = numArray2.length;
recursiveSort(numArray2);
for (int j=0;j<numArray2Length;j++) {
System.out.print(numArray2[j]+",");
}
sortedArray[1] = numArray2[0];
System.out.println(" ");
int[] numArray3 = Arrays.copyOfRange(numArray2, 1, numArray2Length);
int numArray3Length = numArray3.length;
recursiveSort(numArray3);
for (int k=0;k<numArray3Length;k++) {
System.out.print(numArray3[k]+",");
}
sortedArray[2] = numArray3[0];
System.out.println(" ");
int[] numArray4 = Arrays.copyOfRange(numArray3, 1, numArray3Length);
int numArray4Length = numArray4.length;
recursiveSort(numArray4);
for (int k=0;k<numArray4Length;k++) {
System.out.print(numArray4[k]+",");
}
sortedArray[3] = numArray4[0];
System.out.println(" ");
int[] numArray5 = Arrays.copyOfRange(numArray4, 1, numArray4Length);
int numArray5Length = numArray5.length;
recursiveSort(numArray5);
for (int k=0;k<numArray5Length;k++) {
System.out.print(numArray5[k]+",");
}
sortedArray[4] = numArray5[0];
System.out.println(" ");
int[] numArray6 = Arrays.copyOfRange(numArray5, 1, numArray5Length);
int numArray6Length = numArray6.length;
recursiveSort(numArray6);
for (int k=0;k<numArray6Length;k++) {
System.out.print(numArray6[k]+",");
}
sortedArray[5] = numArray6[0];
System.out.println(" ");
int[] numArray7 = Arrays.copyOfRange(numArray6, 1, numArray6Length);
int numArray7Length = numArray7.length;
recursiveSort(numArray7);
for (int k=0;k<numArray7Length;k++) {
System.out.print(numArray7[k]+",");
}
sortedArray[6] = numArray7[0];
System.out.println(" ");
int[] numArray8 = Arrays.copyOfRange(numArray7, 1, numArray7Length);
int numArray8Length = numArray8.length;
recursiveSort(numArray8);
for (int k=0;k<numArray8Length;k++) {
System.out.print(numArray8[k]+",");
}
sortedArray[7] = numArray8[0];
System.out.println(" ");
int[] numArray9 = Arrays.copyOfRange(numArray8, 1, numArray8Length);
int numArray9Length = numArray9.length;
recursiveSort(numArray9);
for (int k=0;k<numArray9Length;k++) {
System.out.print(numArray9[k]+",");
}
sortedArray[8] = numArray9[0];
System.out.println(" ");
int[] numArray10 = Arrays.copyOfRange(numArray9, 1, numArray9Length);
int numArray10Length = numArray10.length;
recursiveSort(numArray10);
for (int k=0;k<numArray10Length;k++) {
System.out.print(numArray10[k]+",");
}
sortedArray[9] = numArray10[0];
System.out.println(" ");
sortedArray[2] = numArray3[0];
for (int dasdasd=0;dasdasd<sortedArray.length;dasdasd++) {
System.out.print(sortedArray[dasdasd]+",");
}
}
private static int[] recursiveSort(int numArray[]) {
int numArrayLength = numArray.length;
int maximum = 0;
for (int i=0;i<numArrayLength;i++) {
if (numArray[i] > maximum) {
maximum = numArray[i];
}
}
int indexOfMaximum = -1;
for (int j=0;j<numArrayLength;j++) {
if (numArray[j] == maximum) {
indexOfMaximum = j;
break;
}
}
int temporary = numArray[0];
numArray[0] = numArray[indexOfMaximum];
numArray[indexOfMaximum] = temporary;
return numArray;
}
}
As you can see, the
int[] numArray(n) = Arrays.copyOfRange(numArray(n-1), 1, numArray(n-1)Length);
int numArray(n)Length = numArray(n).length;
recursiveSort(numArray(n));
for (int k=0;k<numArray(n)Length;k++) {
System.out.print(numArray(n)[k]+",");
}
sortedArray[(n-1)] = numArray(n)[0];
System.out.println(" ");
constantly repeats, so there is probably a recursive solution that will work nicely. Maybe I can do something using ArrayLists because their size can change...
Any help will be appreciated!
Thank you!
I suggest a recursive routine that uses an explicit start index for the part that remains to be sorted:
private static void recursiveSort(int[] array, int start) {
if (start < array.length - 1) {
int maximum = array[start];
int maximumIndex = start;
for (int i = start + 1; i < array.length; ++i) {
if (array[i] > maximum) {
maximum = array[i];
maximumIndex = i;
}
}
if (maximumIndex != start) {
int tmp = array[start];
array[start] = array[maximumIndex];
array[maximumIndex] = tmp;
}
recursiveSort(array, start + 1);
}
}
This actually does recursion (unlike your code, which iterates calling a routine named "recursiveSort" but isn't recursive at all). The whole process would be started by calling:
recursiveSort(numArray, 0);
When it returns, the array will be sorted in descending order.
As a general heuristic, when you are struggling with how to make a method recursive, you should consider adding arguments to the method to help with the bookkeeping.
Is this homework or you just need to have the numbers ordered? Java has an easy way to do this if you use ArrayList() instead of array[]. You would just need to call Collections.sort(yourArrayList);
I suggest not trying to make your own sorting algorithm. Many smart people have already done that hard work for you.
The "recursive" sort that you were trying to implement (aka bubble sort which Ted has shown you how to truly make recursive) will work, but it is grossly inefficient. See a comparison of sorting algorithms here.
Below is a demo of the algorithm you were trying to implement compared to a shell sort, one of the fastest sorting algorithms available. The implementation I used was taken from here. Run it and you will see that shell sort is on average 7 to 8 times faster than bubble sort.
public class SortingDemo {
// Methods required for Shell sort
public static void shellSort(Comparable[] a) {
int N = a.length;
int h = 1;
while (h < N/3) h = 3*h + 1;
while (h >= 1) {
for (int i = h; i < N; i++) {
for (int j = i; j >= h && less(a[j], a[j-h]); j -= h) {
exch(a, j, j-h);
}
}
assert isHsorted(a, h);
h /= 3;
}
assert isSorted(a);
}
private static boolean less(Comparable v, Comparable w) {
return (v.compareTo(w) < 0);
}
private static void exch(Object[] a, int i, int j) {
Object swap = a[i];
a[i] = a[j];
a[j] = swap;
}
private static boolean isSorted(Comparable[] a) {
for (int i = 1; i < a.length; i++)
if (less(a[i], a[i-1])) return false;
return true;
}
private static boolean isHsorted(Comparable[] a, int h) {
for (int i = h; i < a.length; i++)
if (less(a[i], a[i-h])) return false;
return true;
}
// Method required for "recursive" sort
private static void recursiveSort(Integer[] array, int start) {
if (start < array.length - 1) {
int maximum = array[start];
int maximumIndex = start;
for (int i = start + 1; i < array.length; ++i) {
if (array[i] > maximum) {
maximum = array[i];
maximumIndex = i;
}
}
if (maximumIndex != start) {
int tmp = array[start];
array[start] = array[maximumIndex];
array[maximumIndex] = tmp;
}
recursiveSort(array, start + 1);
}
}
public static void main(String[] args) {
int desiredArraySize = 1000;
int minSizeOfNumberInArray = 0;
int maxSizeOfNumberInArray = 100;
Integer[] array = new Integer[desiredArraySize]; // Used Integer instead of int to utilize Comparable interface
for(int i = 0; i < array.length; i++) {
int randomInt = (int) Math.random() * (maxSizeOfNumberInArray - minSizeOfNumberInArray);
array[i] = randomInt;
}
long startTime = System.nanoTime();
recursiveSort(array, 0);
long endTime = System.nanoTime();
long recursiveSortTime = endTime - startTime;
System.out.println(String.format("\"Recursive\" sort completed in %d ns", recursiveSortTime));
startTime = System.nanoTime();
shellSort(array);
endTime = System.nanoTime();
long shellSortTime = endTime - startTime;
System.out.println(String.format("Shell sort completed in %d ns", shellSortTime));
System.out.println(String.format("\"Recursive\" sort took %f times longer", (float)recursiveSortTime / (float)shellSortTime));
}
}
When learning programming, both writing your own sorting algorithms and your own recursive algorithms are great exercises for solidifying your understanding of how things work. It's time well invested, even if someone's already done it better.
You noticed a pattern that repeats, and associated that with recursion. When evaluating whether recursion is a good fit, I would encourage you to tweak that thought process with the notion of "divide-and-conquer". If you're solving only one element with each recursion, then your stack will grow very deep, which should be avoided. If you can split your problem into roughly even chunks and process each chunk recursively, then recursion will be a good fit. Otherwise, a loop is already an excellent fit for repeating patterns.

getting error StringIndexOutOfBoundsException: String index out of range [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I am trying to build a matrix with row and column having values such as "aaa" for aligning purposes. but when I run it I get an error. below is my code
public class compute_matrix {
static String seq1="aaa";
static String seq2="aaa";
static int[][] matrix;
static int max_row;
static int max_col;
private static int match_reward=1;
private static int mismatch_penalty= -1;
private static int gap_cost= -1;
private static boolean case_sensitive;
private static boolean isCaseSensitive() {
return case_sensitive;
}
private static int max(int ins, int sub, int del, int i) {
if (ins > sub) {
if (ins > del) {
return ins > i? ins : i;
} else {
return del > i ?del : i;
}
} else if (sub > del) {
return sub> i ? sub : i;
} else {
return del > i ? del : i;
}
}
protected char sequence[];
public static void main(String args[]){
int r, c, rows, cols, ins, sub, del, max_score;
rows = seq1.length()+1;
cols = seq2.length()+1;
matrix = new int [rows][cols];
// initiate first row
for (c = 0; c < cols; c++)
matrix[0][c] = 0;
// keep track of the maximum score
max_row = max_col = max_score = 0;
// calculates the similarity matrix (row-wise)
for (r = 1; r < rows; r++)
{
// initiate first column
matrix[r][0] = 0;
for (c = 1; c < cols; c++)
{
sub = matrix[r-1][c-1] + scoreSubstitution(seq1.charAt(r),seq2.charAt(c));
ins = matrix[r][c-1] + scoreInsertion(seq2.charAt(c));
del = matrix[r-1][c] + scoreDeletion(seq1.charAt(r));
// choose the greatest
matrix[r][c] = max (ins, sub, del, 0);
if (matrix[r][c] > max_score)
{
// keep track of the maximum score
max_score = matrix[r][c];
max_row = r; max_col = c;
}
}
}
}
private static int scoreSubstitution(char a, char b) {
if (isCaseSensitive())
if (a == b)
return match_reward;
else
return mismatch_penalty;
else
if (Character.toLowerCase(a) == Character.toLowerCase(b))
return match_reward;
else
return mismatch_penalty;
}
private static int scoreInsertion(char a) {
return gap_cost;
}
private static int scoreDeletion(char a) {
return gap_cost;
}
public char charAt (int pos)
{
// convert from one-based to zero-based index
return sequence[pos-1];
}
}
and my error is displaying this
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 3
at java.lang.String.charAt(String.java:695)
at compute_matrix.main(compute_matrix.java:67)
Java Result: 1
rows = seq1.length()+1;
cols = seq2.length()+1;
matrix = new int [rows][cols];
and then later:
for (c = 1; c < cols; c++)
{
//when c == cols-1, it is also `seq2.length()`
//the access to seq2.charAt(c) will cause this exception then.
sub = matrix[r-1][c-1] + scoreSubstitution(seq1.charAt(r),seq2.charAt(c));
ins = matrix[r][c-1] + scoreInsertion(seq2.charAt(c));
del = matrix[r-1][c] + scoreDeletion(seq1.charAt(r));
In the above loop, when c == cols-1, it is also seq2.length(), the access to seq2.charAt(c) will cause this exception then.
You initialize the number of rows and cols to length() + 1, while you later iterate from 0 to length (inclusive), while the string contain only length() chars - from 0 to n exclusive.
If you are a C programmer in your past - I assume you are expecting a \0 terminator at the end of the string. In java you don't have those - since String is an object - you can hold a field to indicate its exact length. Meaning the last char in the string, is actually the last character there.
in line 60 of your code
sub = matrix[r-1][c-1] + scoreSubstitution(seq1.charAt(r),seq2.charAt(c));
max value for r is 4 so when you look up for seq.charAt(3) there is nothingso it shows index out of bound
I refactored your code into more canonical java.
The things I've changed:
The class is now called SimilarityMatrix, a more appropriate, self documenting name
variable declarations now happen where they get used as opposed to at the top of main
The work is now done in an instance of the class rather than the main method
I used the built in Math.max(int, int) instead of rolling my own
I removed a lot of unnecessary nested if statements. Java's short circuit evaluation helps here
Since both r and c as well as r+1 and c+1 are used frequently in your calculation loop, I track both
I removed many of the dependencies on static state (made many things instance variables)
Static state that remains is all final now (I made them constants)
Used more java-y variable names (java people really like their camel case)
public class SimilarityMatrix
{
public static final int matchReward = 1;
public static final int mismatchPenalty = -1;
public static final int gapCost = -1;
private int[][] matrix;
private int maxRow = 0;
private int maxCol = 0;
private boolean caseSensitive = false;
SimilarityMatrix(String s1, String s2, boolean dontIgnoreCase)
{
this(s1, s2);
caseSensitive = dontIgnoreCase;
}
SimilarityMatrix(String s1, String s2)
{
int rows = s1.length() + 1;
int cols = s2.length() + 1;
matrix = new int[rows][cols];
int max_score = 0;
for (int x = 0; x < cols; x++)
{
matrix[0][x] = 0;
matrix[x][0] = 0;
}
for (int r = 0, rp1 = 1; rp1 < rows; ++r, ++rp1)
{
for (int c = 0, cp1 = 1; cp1 < rows; ++c, ++cp1)
{
int sub = matrix[r][c] + scoreSubstitution(s1.charAt(r), s2.charAt(c));
int ins = matrix[rp1][c] + scoreInsertion(s2.charAt(c));
int del = matrix[r][cp1] + scoreDeletion(s1.charAt(r));
// choose the greatest
matrix[rp1][cp1] = Math.max(Math.max(ins, sub), Math.max(del, 0));
if (matrix[rp1][cp1] > max_score)
{
// keep track of the maximum score
max_score = matrix[rp1][cp1];
maxRow = rp1;
maxCol = cp1;
}
}
}
}
public static void main(String args[])
{
SimilarityMatrix me = new SimilarityMatrix("aaa", "aaa");
System.out.println(me.getMaxRow() + " " + me.getMaxCol());
}
private int scoreSubstitution(char a, char b)
{
if ((a == b && caseSensitive) || Character.toLowerCase(a) != Character.toLowerCase(b))
return matchReward;
else
return mismatchPenalty;
}
public int getMaxRow()
{
return maxRow;
}
public int getMaxCol()
{
return maxCol;
}
private int scoreInsertion(char a)
{
return gapCost;
}
private int scoreDeletion(char a)
{
return gapCost;
}
}

Categories