I'm taking a computer science class at my high school, and we learned a lesson on selection sort today. I wrote a program (it's probably clumsy, but please bear with me, I'm learning) and it works in that it sorts, but sometimes it throws an ArrayIndexOutOfBoundsException. Only sometimes. I don't know how this is possible, because I deal with the same array throughout the entire program and arrays have a fixed length. If anyone has some insight it would be extremely helpful.
I think the error has something to do with int first = y[movedVariable];. However, I don't understand how movedVariable can be out of bounds, because I'm pretty sure I wrote my program so that it would be < the length of the array.
public class selectionSort
{
public static int[] array;
public static int movedVariable = 0;
public static void main()
{
array = new int[10];
int x;
for (int count = 0; count < array.length; count++)
{
if (count == 0)
{
x = (int)(Math.random()*100+2);
array[count] = x;
}
else
{
x = (int)(Math.random()*100+2);
for (int y = 0; y < count; y++)
{
while(x == array[y])
{
x = (int)(Math.random()*100+2);
}
}
array[count] = x;
}
}
sort(array);
}
public static void sort(int[] x)
{
int thing = 0;
for(int hello = 0; hello < x.length; hello++)
{
int part = x[thing];
for ( int count = thing; count < x.length-1; count++)
{
if( part > x[count+1] )
{
part = x[count+1];
}
}
thing++;
swap( x, part);
}
int f = 0;
String output = "";
for( int val : x )
{
if (f%10 == 0)
{output += "\n";}
output += val + " ";
f++;
}
System.out.print(output);
}
public static int[] swap(int [] y, int num)
{
int count = 0;
int index = 0;
for ( count = 0; count < y.length; count++)
{
if (y[count] == num)
{index = count;}
}
int first = y[movedVariable];
y[movedVariable] = y[index];
y[index] = first;
movedVariable++;
return y;
}
}
For fun, I ran your code for 1,000,000 iterations and no out of bounds exception, unless I did not clear the static movedVariable to 0 before each iteration.
Since movedVariable is static after the first 10 calls to swap() it will be 10 and if another call is made to swap you'll get the index out of bounds. However, this can only happen if you call sort() more than once per run. Only use static for values that need to be preserved between instances of your class. Non statics that are part of the your instance state. Local variables for everything else. Otherwise your are creating a mine field of bugs just waiting to happen.
I refactored your class to remove variables that have the same functionality. For example your thing and your movedVariable and your hello variable in sort() can be just one variable. Try to eliminate multiple variables that do the same thing, like the plague. It is a source of non obvious bugs.
Also, you are passing the value in the array to swap then looking for it in the array to get the index, this is a waste of time. Just pass in the index to swap. It also creates a problem for your sort function when you have the same value at two different places. Swap will use the last one it finds. sort() should handle duplicate values in the array. That explains why you initialized your array with unique values. You should not have to do that. Actually you should test your code with duplicates explicitly added to make sure your function works.
I moved printing of the array out of sort into its own method. It is useful for debugging at intermediate steps not just when the sort is done.
I tried to leave variable names the same and the logic unchanged so you can follow the changes.
public class Main
{
public static void sort(int[] x)
{
for (int movedVariable = 0; movedVariable < x.length; movedVariable++)
{
int part = x[movedVariable];
int index = movedVariable;
for (int count = movedVariable; count < x.length - 1; count++)
{
if (part > x[count + 1])
{
part = x[count + 1];
index = count + 1;
}
}
swap(x, index, movedVariable);
}
printArray(x);
}
private static void printArray(int[] x)
{
int f = 0;
String output = "";
for (int val : x)
{
if (f % 10 == 0)
{
output += "\n";
}
output += val + " ";
f++;
}
System.out.print(output);
}
public static int[] swap(int[] y, int index, int movedVariable)
{
int first = y[movedVariable];
y[movedVariable] = y[index];
y[index] = first;
return y;
}
public static void main(String[] args)
{
int[] array = new int[10];
int x = 0;
for (int count = 0; count < array.length; count++)
{
for (int y = count; --y >= 0; )
{
do
{
x = (int) (Math.random() * 100 + 2);
}
while (x == array[y]);
}
array[count] = x;
}
printArray(array);
sort(array);
}
}
Related
I am writing a function to increase the values of all elements in an array until they all reach a specified value, this value can be different for each item. This is what I have so far.
Edit: I forgot to mention that the reason not to set it directly as in arr[i].value = arr[i].setpoint (as pointed out by kaylum) it is because there is a limitation where, while incrementing, the values in the array can only differ by the same unit of increment, in this case 1. So abs(arr[i].value - arr[i+1].value) <= 1. Once an element reaches the setpoint it is free of this limitation (so that the other elements can reach its setpoint)
#include <stdio.h>
typedef struct
{
unsigned value;
unsigned setpoint;
} ValSet;
void set_all(ValSet arr[static 1], size_t arr_size)
{
for (size_t cnt = arr_size; cnt;)
{
cnt = arr_size;
for (size_t i = 0; i < arr_size; i++)
{
if (arr[i].value != arr[i].setpoint)
{
arr[i].value++;
}
else
{
cnt--;
}
}
}
}
int main()
{
ValSet arr[2] = {{0, 2}, {0, 4}};
set_all(arr, 2);
return 0;
}
This generates the desired output so, after the call to set_all(arr, 2), arr[0].value = 2 and arr[1].value = 4, but I am not sure this is the best idea. Is there a better way to achieve this?
You were a bit unspecific about what you want exactly, so here are some solutions:
typedef struct {
unsigned value;
unsigned setpoint;
} ValSet;
/**
* for each element:
* increases value by one, until value is not smaller than setpoint
* will never decrease value
*/
void increase_all_slow(ValSet* arr, int len) {
for (int i = 0; i < len; i++) {
while (arr[i].value < arr[i].setpoint) {
arr[i].value++;
}
}
}
/**
* for each element:
* sets value to setpoint, if value is smaller than setpoint
* will never decrease value
*/
void increase_all(ValSet* arr, int len) {
for (int i = 0; i < len; i++) {
if (arr[i].value < arr[i].setpoint) {
arr[i].value = arr[i].setpoint;
}
}
}
/**
* for each element:
* sets value to setpoint
* decreases value if less than setpoint
*/
void set_all(ValSet* arr, int len) {
for (int i = 0; i < len; i++) {
arr[i].value = arr[i].setpoint;
}
}
Your implementation has a lot of redundant checks, every element will be compared if (arr.value[i] != arr.setpoint[i]) as long as any element is not set correctly. This will make it very slow.
I hope my code is self explanatory (I even added comments where usually you don't need them). If not, feel free to ask
Edit:
Now I know what you want. Next time tell us before:
typedef struct {
unsigned value;
unsigned setpoint;
} ValSet;
/**
* Until every element is equal (or bigger) to its corresponding setpoint.
* Every elements value that is not, will be increased.
*/
void increase_all(ValSet* arr, int len) {
int max_allowed = INT_MAX;
for (int i = 0; i < len; i++) {
if (arr[i].value < max_allowed) {
max_allowed = arr[i].value;
}
}
bool done = false;
while (!done) {
max_allowed++;
done = true;
for (int i = 0; i < len; i++) {
if (arr[i].value < arr[i].setpoint && arr[i].value < max_allowed) {
arr[i].value++;
done = false;
}
}
}
}
I was made this program
This program makes array which each digit is different
but it takes so much time
void generateArr() {
int randomNum;
int sameNum = 0;
for (int i = 0; i < arrScale; i++) {
while (true)
{
sameNum = 0;
srand((unsigned int)time(NULL));
randomNum = rand() % 10;
for (int j = 0; j < arrScale; j++) {
if (numArr[j] == randomNum) {
sameNum = 1;
}
}
if (sameNum == 0) {
break;
}
}
numArr[i] = randomNum;
}
}
numArr and arrScale is made in front
First: Don't call srand more than once per program run. Here's why
In order to speed up generating the numbers, you could make sure that you never pick a number that's been picked before.
Example:
void swap(int *a, int *b) {
int tmp = *a;
*a = *b;
*b = tmp;
}
void generateArr() {
for (int i = arrScale; i > 1; --i) {
// pick a number never picked before and swap with the last number
swap(numArr + (rand() % i), numArr + (i-1));
}
}
Not only is it pretty fast - every possible permutation will have an equal chance of appearing (with the little detail that rand() % i is not uniformly distributed).
You can have a separate buffer t of size 10 and whenever you draw x, set t[x] to 1. So you can evaluate t[x] == 1 to check if x is already in your array and don't have to loop over it.
Note that your program won't work if your array has size greater than 10.
/I tried to write a code to see if the sum of any 2 numbers in an array equals sum, but I cannot fix a bug that is if I input only one 4 it is still true/
import java.util.*;
public class Main {
public static void main(String[] args) {
Vector vec = new Vector();
int sum = 8;
int[] a = {1, 2, 4};
int i;
int k = a.length;
for(i = 0; i < a.length; i++) {
vec.add(sum - a[i]);
}
for(int value : a) {
if (vec.contains(value)) {
System.out.println("true");
break;
}
}
}
}
You can use the debugger to see the values of the variables during the calculation to see if they are doing the expected operations.
I am trying to populate a 2D array vertically or horizontally from a given coordinate, if the indexes are in range.
Below is the program I can think about as of now.
I just want to know if there is any other optimized way to perform this logical operation.
public static void Main()
{
var arr = new string[10,10];
int x = 0;
int y = 1;
int len = 5;
string somevalue = "x";
string align = "vertical";
int i = x;
int j = y;
try
{
while(len > 0)
{
arr[i,j] = somevalue;
if(align == "vertical")
j++;
else
i++;
len--;
}
}
catch(IndexOutOfRangeException ex)
{
Console.WriteLine(ex);
}
}
I need an idea how to effectively find areas below marked with 0 in two-dimensional array. It should be noted that there are other areas, such as this picture shows one of two who owns coordinate (0.0) and the other owns coordinate (21.3).
00000000000111110000111
00000000001111110000111
00000000011111100000111
00000000000111000001101
00000000011100000011101
00000001111100001111001
00000111111111011111001
00000001111100001111001
00000000010000000011001
00000000000000000001111
Of course a real array will be much larger.
Recursive version that goes to all sides and stops at mark 1 or array side isn't fast enough.
It looks like you're looking for a flood-fill algorithm. The wikipedia page I linked lists a few algorithms which may be faster than the obvious recursive method.
Flood-fill will be a good match if the areas you're looking for are small compared to the entire array, and you don't need to search for all of them. If you need to know about most or all of them, then computing them all in a single shot using a union-merge based connected component labeling algorithm may be a better choice. Here's some code that implements such an algorithm (note that I've altered it to run in a single pass):
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <map>
const char *data[] = {
"00000000000111110000111",
"00000000001111110000111",
"00000000011111100000111",
"00000000000111000001101",
"00000000011100000011101",
"00000001111100001111001",
"00000111111111111111001",
"00000001111100001111001",
"00000000010000000011001",
"00000000000000000001111",
NULL
};
struct label {
private:
int index;
int rank;
label *parent;
public:
label ()
: index(-1), rank(0), parent(this)
{ }
int getIndex(int &maxIndex) {
if (parent != this)
return find()->getIndex(maxIndex);
if (index < 0)
index = maxIndex++;
return index;
}
label *find() {
if (parent == this)
return this;
parent = parent->find();
return parent;
}
label *merge(label *other)
{
label *xRoot = find();
label *yRoot = other->find();
if (xRoot == yRoot)
return xRoot;
if (xRoot->rank > yRoot->rank) {
yRoot->parent = xRoot;
return xRoot;
} else {
xRoot->parent = yRoot;
if (xRoot->rank == yRoot->rank)
yRoot->rank++;
return yRoot;
}
}
};
int width, height;
int main() {
for (int i = 0; data[0][i]; i++)
width = i + 1;
for (int i = 0; data[i]; i++) {
height = i + 1;
}
std::vector<std::vector<unsigned short> > lblinfo;
lblinfo.resize(height, std::vector<unsigned short>(width, 0));
std::vector<label *> labels;
labels.push_back(NULL); // 0 is used as an unassigned flag
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (data[y][x] == '1')
continue;
// Try to find a neighboring label
unsigned short lblid = 0;
if (x != 0 && lblinfo[y][x-1] != 0)
lblid = lblinfo[y][x-1];
// merge with cells above
if (y != 0) {
for (int x2 = x - 1; x2 <= x + 1; x2++) {
if (x2 < 0)
continue;
if (x2 >= width)
continue;
unsigned short otherid = lblinfo[y - 1][x2];
if (!otherid)
continue;
if (!lblid)
lblid = otherid;
else {
labels[lblid]->merge(labels[otherid]);
}
}
}
if (!lblid) {
// assign a new label
lblid = labels.size();
labels.push_back(new label);
}
lblinfo[y][x] = lblid;
}
}
// Assign indices to the labels by set and print the resulting sets
int maxindex = 0;
static const char chars[] = "abcefghijklmnopqrstuvwxyz";
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
unsigned short labelid = lblinfo[y][x];
if (labelid == 0) {
putchar(data[y][x]);
continue;
}
label *label = labels[labelid];
int idx = label->getIndex(maxindex);
if (idx >= sizeof(chars) - 1) {
printf("\n\n Too many labels to print!\n");
exit(1);
}
putchar(chars[idx]);
}
printf("\n");
}
return 0;
}