Running weighted quick union - arrays

So I have to take an ID array
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
And perform weighted quick union on it. I have to perform the operations 9-0, 3-4, 5-8, 7-2, 2-1, 5-7, 0-3, and 4-2. Here's what I did to the array for these operations:
9-0
0 1 2 3 4 5 6 7 8 9
9 1 2 3 4 5 6 7 8 9
3-4
0 1 2 3 4 5 6 7 8 9
9 1 2 3 3 5 6 7 8 9
5-8
0 1 2 3 4 5 6 7 8 9
9 1 2 3 3 5 6 7 5 9
7-2
0 1 2 3 4 5 6 7 8 9
9 1 7 3 3 5 6 7 5 9
2-1
0 1 2 3 4 5 6 7 8 9
9 7 7 3 3 5 6 7 5 9
5-7
0 1 2 3 4 5 6 7 8 9
9 7 7 3 3 7 6 7 5 9
0-3
0 1 2 3 4 5 6 7 8 9
9 7 7 3 3 7 6 7 5 3
4-2
0 1 2 3 4 5 6 7 8 9
9 7 7 3 3 7 6 3 5 9
The problem is that the ID array operations are different depending on if you're using quick find or quick union or weighted quick union. So would this be right for weighted quick union? Here's the code I'm using for weighted quick union:
public class WeightedQuickUnionUF
{
private int[] id; // parent link (site indexed)
private int[] sz; // size of component for roots (site indexed)
private int count; // number of components
public WeightedQuickUnionUF(int N)
{
count = N;
id = new int[N];
for (int i = 0; i < N; i++) id[i] = i;
sz = new int[N];
for (int i = 0; i < N; i++) sz[i] = 1;
}
public int count()
{ return count; }
public boolean connected(int p, int q)
{ return find(p) == find(q); }
private int find(int p)
{ // Follow links to find a root.
while (p != id[p]) p = id[p];
return p;
}
public void union(int p, int q)
{
int i = find(p);
int j = find(q);
if (i == j) return;
// Make smaller root point to larger one.
if (sz[i] < sz[j]) { id[i] = j; sz[j] += sz[i]; }
else { id[j] = i; sz[i] += sz[j]; }
count--;
}
}
The code for weighted quick union shows you how it works but basically it's a type of Union-find where you connect two trees together. With weighted quick union you always connected the smaller tree to the larger one. The ID array is a representation of a tree where there's numbers on the top row and bottom row. If the number on top matches the bottom then that number is a root in the forest but for example if the top number is a 9 and the bottom number is 0 then it means 9 is a child of 0. The ID array starts out with 9 single node trees and operations like 9-0 connects two trees together.

Related

Equalize to zero a different element of a matrix for each row without loop

I have an IxS matrix called numerateur and I would like to set one element per row to zero. However, the column to which this element belongs changes for each row. I can do it with a loop but would like to use a more efficient method.
You can find my loop below:
choice is an Ix1 vector containing, for each row, the column number of the element I want to set to zero in numerateur.
for i = 1:I
rank1 = choice(i);
numerateur(i,rank1) = 0;
end
You need to convert the column indices to linear indices:
ind = (1:size(numerateur,1)) + (choice(:).'-1)*size(numerateur,1);
numerateur(ind) = 0;
Example:
>> numerateur = randi(9,5,7)
numerateur =
8 7 8 3 2 8 4
7 8 6 3 6 1 3
8 9 5 5 5 9 5
4 4 2 7 4 9 9
1 6 7 3 8 7 9
>> choice = [2; 3; 6; 5; 1];
>> ind = (1:size(numerateur,1)) + (choice(:).'-1)*size(numerateur,1);
>> numerateur(ind) = 0;
>> numerateur
numerateur =
8 0 8 3 2 8 4
7 8 0 3 6 1 3
8 9 5 5 5 0 5
4 4 2 7 0 9 9
0 6 7 3 8 7 9
Use implicit expansion to find logical indices:
numerateur(choice == 1:size(numerator,2)) = 0;
Alternatively you can use sparse matrix to generate logical indices:
numerateur(sparse(1:I,choice,true,I,S)) = 0;

How to access adjacent elements from a current starting position?

I have a matrix:
E = [ 3 6 3 7 2 ; 3 8 3 7 2; 1 9 5 4 1; 7 5 1 6 9; 10 8 4 3 10 ]
If I started at E(3,3) = 5, how do I access the adjacent numbers to the east (or west). For example, I wanted to access the 3 elements to the east of E(3,3), which are 7, 4 and 6.
% define matrix and point
E = [ 3 6 3 7 2 ; 3 8 3 7 2; 1 9 5 4 1; 7 5 1 6 9; 10 8 4 3 10 ];
Raw=3;
Col=3;
% find the value of the point, 3 east values and 3 west values
Point=E(Raw,Col)
EastVal=E(max(1,Raw-1):min(size(E,1),Raw+1),Col+1)
WestVal=E(max(1,Raw-1):min(size(E,1),Raw+1),Col-1)
Produce:
Point =
5
EastVal =
7
4
6
WestVal =
8
9
5

Trick the randomizer in C

I want to get random numbers between 1 to 10.
It actually works, but when it's in a loop, I don't really get random numbers.
int randomNum;
srand ( (unsigned int)time(NULL) );
randomNum = rand() % 10;
I've been spending hours here and in google looking for a solution, but it looks like no one really solved it (or maybe I didn't search good enough).
The value we get from the randomizer depends on the seconds (not miliseconds or something else, like in other programming language) and that's why the numbers are not random.
In addition, I don't want to download a package for C because I run my code in the university labs, and they won't allow it.
Is there anyone with a creative solution for this problem? maybe some mathematic functions?
To illustrate Sidoh's answer.
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int main(int argc, char** argv)
{
int i;
srand ( (unsigned int)time(NULL) );
for (i = 0; i < 100; i++)
{
printf("%d ", 1 + (rand() % 10));
}
putchar('\n');
return 0;
}
This produced the following results for my one time seed using time( ).
7 10 2 4 4 4 2 1 7 7 10 4 3 10 2 9 6 9 2 9 7 10 4 1 1 8 2 4 8 1 2
4 2 3 9 5 8 1 7 4 9 8 10 1 8 1 1 5 1 4 5 7 3 9 10 3 6 1 9 3 4 10
8 5 2 7 2 2 9 10 5 9 8 4 1 7 7 2 3 7 5 8 6 10 8 5 4 3 7 2 8 2 1 7
7 5 5 10 6 5
Do not seed the random number generator more than once. Since your code probably runs all within the same second, every query to rand uses the same seed, so you'll get the same number every time.
Dave Newman provides a very good answer.
Alternatively, you could also try a pseudo random generator, for example
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main()
{
int a0; // this value will be our requirement
int mod = 11; //this is the limit (0 - mod-1), here 10
int a; // this stores the previous value of a0;
int i; // loop variable
int mul=25; //multiplicative factor
int add=3; // additive factor
int limit=100; // our limit
srand ( (unsigned int)time(NULL) ); // initialize the seed
a0 = rand() % mod;
for(i=0;i<limit;i++)
{
printf("%d\t",a0);
a = a0;
a0 = (a * mul + add) % mod;
}
putchar('\n');
return 0;
}
The output::
1st run::
2 10 4 3 1 8 0 6 7 9 2 10 4 3 1 8 0 6
7 9 2 10 4 3 1 8 0 6 7 9 2 10 4 3 1 8
0 6 7 9 2 10 4 3 1 8 0 6 7 9 2 10 4 3
1 8 0 6 7 9 2 10 4 3 1 8 0 6 7 9 2 10
4 3 1 8 0 6 7 9 2 10 4 3 1 8 0 6 7 9
2 10 4 3 1 8 0 6 7 9
2nd output::
9 2 10 4 3 1 8 0 6 7 9 2 10 4 3 1 8 0
6 7 9 2 10 4 3 1 8 0 6 7 9 2 10 4 3 1
8 0 6 7 9 2 10 4 3 1 8 0 6 7 9 2 10 4
3 1 8 0 6 7 9 2 10 4 3 1 8 0 6 7 9 2
10 4 3 1 8 0 6 7 9 2 10 4 3 1 8 0 6 7
9 2 10 4 3 1 8 0 6 7

Index manipulation of array in C

Begining with an ordered array
[1, 2, 3, 4, 5, 6, 8, 9, 10]
How would be the way to get every iteration the following results?
1 2 3 4 5 6 7 8 9 10
1 3 4 5 6 7 8 9 10 2
1 4 5 6 7 8 9 10 2 3
1 5 6 7 8 9 10 2 3 4
1 6 7 8 9 10 2 3 4 5
1 7 8 9 10 2 3 4 5 6
1 8 9 10 2 3 4 5 6 7
1 9 10 2 3 4 5 6 7 8
1 10 2 3 4 5 6 7 8 9
#include <stdio.h>
#define MAX 10
int a[MAX], i,j,cnt=2;
main (){
for (i=0; i<MAX; i++){
a[i]= i+1;
}
for (i=0; i<MAX; i++) {
printf ("%d ", a[i]);
}
printf ("\n");
for (j=0; j < MAX-2;j++){
a[0]=1;
for (i=1; i < MAX-1; i++){
if (a[i]%MAX != 0){
a[i]= a[i] + 1;
}else{
if (a[i]==10) {
//printf ("a[%d]: %d \t ** %d\n", i , a[i] ,cnt);
//a[i-1]= i;
a[i] = cnt;
}
}
}
for (i=0; i<MAX; i++) {
printf ("%d ", a[i]);
}
printf ("\n");
}
}
Now I almost get it but the last column is not right, What should I do?
1 2 3 4 5 6 7 8 9 10
1 3 4 5 6 7 8 9 10 10
1 4 5 6 7 8 9 10 2 10
1 5 6 7 8 9 10 2 3 10
1 6 7 8 9 10 2 3 4 10
1 7 8 9 10 2 3 4 5 10
1 8 9 10 2 3 4 5 6 10
1 9 10 2 3 4 5 6 7 10
1 10 2 3 4 5 6 7 8 10
C arrays are indexed from 0. So when you access elements from 1 to MAX, you are running off the end of the array.
Have your loops go from 0 to MAX-1. Customary way to write it is
for (i=0 ; i < MAX ; ++i)
...so anybody reading your code can immediately prove that the array index never equals MAX.
Well, at a minimum, arrays in C are zero based so you are writing past the end of the array. For an array declared int foo[MAX] valid elements are from foo[0]…foo[MAX-1]
Specifically a[MAX] might well reference the memory location that the variable i uses, causing the loop to reset when it attempt to overwrite a[MAX].
Either shift everything down by one, or declare your array MAX+1 and ignore the zero bit.
Oh, and you should not need to set a[1]=1; every time.

Need help with logic (C)

I need to swap first n elements from two non repeating sequences(arrays), where n is a random integer.
Seq1: 1 4 5 6 9 8 2 3 7
Seq2: 3 9 1 2 8 7 4 5 6
If n = 4
Seq1: 3 9 1 2 | 9 8 2 3 7
Seq2: 1 4 5 6 | 8 7 4 5 6
Now i need to repair the sequence by replacing the repeated numbers after '|'.
How to do this?
This is my effort..
for(left1 = 0; left1<pivot; left1++)
{
for(right1 = pivot; right1 < no_jobs; right1++)
{
if(S1->sequence[left1] == S1->sequence[right1])
{
for(left2 = 0; left2<pivot; left2++)
{
for(right2 = pivot; right2<no_jobs; right2++)
{
if(S2->sequence[left2] == S2->sequence[right2])
{
swap_temp = S1->sequence[right1];
S1->sequence[right1] = S2->sequence[right2];
S2->sequence[right2] = swap_temp;
break;
}
}
}
}
}
}
Swapping the first n elements is straightforward using a single for loop.
for(int i = 0; i < n; i++){
int tmp = array1[i];
array1[i] = array2[i];
array2[i] = tmp;
}
Now you need to find what has changed in the arrays. You can do this by comparing the parts you swapped.
int m1 = 0, m2 = 0;
int missing_array1[n];
int missing_array2[n];
for(int i = 0; i < n; i++){
bool found = false;
for(int j = 0; j < n; j++){
if(array1[i] == array2[j]){
found = true;
break;
}
}
if(!found){
missing_array2[m2++] = array1[i];
}
}
for(int i = 0; i < n; i++){
bool found = false;
for(int j = 0; j < n; j++){
if(array2[i] == array1[j]){
found = true;
break;
}
}
if(!found){
missing_array1[m1++] = array2[i];
}
}
missing_array2 now contains the numbers that are missing from array2. These are all the numbers that will be duplicated in array1. The same goes for missing_array1. Next you need to scan both arrays and replace the duplicates with the missing numbers.
while(m1 >= 0){
int z = 0;
while(missing_array1[m1] != array2[n + z]){
z++;
}
array2[n + z] = missing_array2[m1--];
}
while(m2 >= 0){
int z = 0;
while(missing_array2[m2] != array1[n + z]){
z++;
}
array1[n + z] = missing_array1[m2--];
}
In summary, you compare the parts you swapped to find the values that will be missing from each array. These value are also the values that will be duplicated in the opposite array. Then you scan each of the arrays and replace the duplicate values with one of the missing values (I assume you don't care which of the missing values, as long as all the values are unique.
If the swapped portions of the sequences contain the same values, then there would be no repeats - performing the swap would just shuffle the first n elements. So the values you need to repair are the values which occur in one of the swapped sequences
Firstly, I'd create a histogram of the n swapped elements, with those from sequence 1 counting as bit 0, and those from sequence 2 as bit 1. If any members of the histogram are non-zero, then they occur in one or the other sequence only.
If there are values requiring repair, then you can construct a look-up table of the values which require rewriting. This should map i to i unless i is one of the asymmetric values in the histogram, in which case it needs to map to the another asymmetric value.
Seq1: 1 4 5 6 9 8 2 3 7
Seq2: 3 9 1 2 8 7 4 5 6
If n = 4
Seq1: 3 9 1 2 | 9 8 2 3 7
Seq2: 1 4 5 6 | 8 7 4 5 6
histogram
value 1 2 3 4 5 6 7 8 9
count 3 1 1 2 2 2 0 0 1
mapping for sequence 1 ( while histogram [S1[i]] & 1, replace[S1[i]] with S2[i] )
value 1 2 3 4 5 6 7 8 9
replace 1 6 5 4 5 6 7 8 4
apply mapping to sequence 1 for i > n
Seq1: 3 9 1 2 | 9 8 2 3 7
replace - - - - | 4 8 6 5 7
result 3 9 1 2 | 4 8 6 5 7
mapping for sequence 2 ( while histogram [S2[i]] & 2, replace[S2[i]] with S1[i] )
value 1 2 3 4 5 6 7 8 9
replace 1 2 3 9 3 2 7 8 9
apply mapping to sequence 1 for i > n
Seq2: 1 4 5 6 | 8 7 4 5 6
replace - - - - | 8 7 9 3 2
result 1 4 5 6 | 8 7 9 3 2
Alternatively, replace with the next value with the other bit set in the histogram (the iterated replace will also need to check for replacing a value with itself); I'm assuming it doesn't really matter what value is used as the replacement as long as the values in the result are unique.

Resources