I have two rand arrays: pointer and value. Whatever values in the pointer should also come in value with same number of times. For eg: if pointer[i] == 2, then value should have a value 2 which occur two times and should be after 1.
Expected result is shown below.
Sample code:
class ABC;
rand int unsigned pointer[$];
rand int unsigned value[20];
int count;
constraint c_mode {
pointer.size() == count;
solve pointer before value;
//======== Pointer constraints =========//
// To avoid duplicates
unique {pointer};
foreach(pointer[i]) {
// Make sure pointer is inside 1 to 4
pointer[i] inside {[1:4]};
// Make sure in increasing order
if (i>0)
pointer[i] > pointer[i-1];
}
//======== Value constraints =========//
//Make sure Pointer = 2 has to come two times in value, but this is not working as expected
foreach(pointer[i]) {
value.sum with (int'(item == pointer[i])) == pointer[i];
}
// Ensure it will be in increasing order but not making sure that pointers are not grouping together
// For eg: if pointer = 2, then 2 has to come two times together and after 1 in the array order. This is not met with the below constraint
foreach(value[i]) {
foreach(value[j]) {
((i>j) && (value[i] inside pointer) && (value[j] inside pointer)) -> value[i] >= value[j];
}
}
}
function new(int num);
count = num;
endfunction
endclass
module tb;
initial begin
int unsigned index;
ABC abc = new(4);
abc.randomize();
$display("-----------------");
$display("Pointer = %p", abc.pointer);
$display("Value = %p", abc.value);
$display("-----------------");
end
endmodule
I would implement this using a couple of helper arrays:
class pointers_and_values;
rand int unsigned pointers[];
rand int unsigned values[];
local rand int unsigned values_dictated_by_pointers[][];
local rand int unsigned filler_values[][];
// ...
endclass
The values_dictated_by_pointers array will contain the groups of values that your pointers mandate. The other array will contain the dummy values that come between these groups. So, the values array will contain filler_values[0], values_dictated_by_pointers[0], filler_values[1], values_dictated_by_pointers[1], etc.
Computing the values mandated by the pointers is easy:
constraint compute_values_dicated_by_pointers {
values_dictated_by_pointers.size() == pointers.size();
foreach (pointers[i]) {
values_dictated_by_pointers[i].size() == pointers[i];
foreach (values_dictated_by_pointers[i,j])
values_dictated_by_pointers[i][j] == pointers[i];
}
}
You need as many groups as you need pointers. In each group you have as many elements as the pointer value for that group. Also, each element of a group has the same value as the group's pointer value.
For the filler values you didn't mention what they should look like. I interpreted your problem description to say that the values in the pointers array should only come in the patters described above. This means that they are not allowed as filler values. Depending on whether you want to allow filler values before the first value, you will need either as many filler groups as you have pointers or one extra. In the following code I allowed filler values before the "real" values:
constraint compute_filler_values {
filler_values.size() == pointers.size() + 1;
foreach (filler_values[i, j])
!(filler_values[i][j] inside { pointers });
}
You'll also need to constrain the size of each of the filler value groups, otherwise the solver will leave them as 0. Here you can change the constraints to match your requirements. I chose to always insert filler values and to never insert more than 3 filler values.
constraint max_number_of_filler_values {
foreach (filler_values[i]) {
filler_values[i].size() > 0;
filler_values[i].size() <= 3;
}
}
For the real values array, you can compute its value in post_randomize() by interleaving the other two arrays:
function void post_randomize();
values = filler_values[0];
foreach (pointers[i])
values = { values, values_dictated_by_pointers[i], filler_values[i] };
endfunction
If you need to be able to constrain values as well, then you'll have to implement this interleaving operation using constraints. I'm not going to show this, as this is probably pretty complicated in itself and warrants an own question.
Be aware that the code above might not work on all EDA tools, because of spotty support for random multi-dimensional arrays. I only got this to work on Aldec Riviera Pro on EDA Playground.
Related
I am trying to copy a 2 dimensional array to another 2 dimensional array. Since the name (srcAry) is the address of the first element of the source array, I have been able to print out all the values in the source array using pointer arithmetic in a for loop. I am using the number of rows times the number of columns as the condition to stop looping. If I try to assign the values to the new array using this method I get an error message (error: assignment to expression with array type). Is this possible to do this or am I limited to using two nested for loops with indexes?
...
void copyAry(double *pAry, int numRows, int numCols)
{
double newAry[numRows][numCols];
int end = numRows * numCols;
int ctr = 0;
for( ; ctr < end; ctr++)
// printf("*(pAry + %d) = %.1f\n", ctr, *(pAry + ctr)); //this works fine
{
*(newAry + ctr) = *(pAry + ctr); //this is where I receive error
}
return;
}
...
Thanks in advance.
I would assume that the type of newAry + ctr is not double* as your code assumes, but rather double*[numCols] i.e. a pointer to an array of numCols elements. Which also means that you would advance not one element at a time, but numCols.
Usually you would use memcpy for this kind of low level data copying. Barring that, you might start with double* pNewAry = &newAry[0][0] or some such in order to test the 2d array as a linear sequence of doubles.
I've got a bit of Arduino code that is driving me nuts at the moment and I'm hoping you helpful people can help.
What I want to do is initialise a pointer to one of two arrays of unsigned ints.
A switch is read each pass and the pointer is assigned accordingly, only the compiler has a hissy fit over the assignments.
unsigned int spl_add_tbl[4096]; // arrary table no zero crossing points.
unsigned int zxd_add_tbl[4096]; // array table for zero crossing points.
unsigned int *tbl_ptr; // init table pointer
// ZXD switch D64. H = off, L = on.
if (digitalRead(64) == 1) {
// Zero Crossing off, assign Table Pointer to sample table
*tbl_ptr = &spl_add_tbl[0];
} else {
// Zero Crossing on, assign Table pointer to Zero Crossing Table and set A/D read mapping.
*tbl_ptr = &zxd_add_tbl[0];
}
The compiler gives the error: invalid conversion from 'unsigned int*' to 'unsigned int' [-fpermissive]
tbl_ptr is a pointer - you should not dereference it in order to assign an array to it:
if(digitalRead(64) == 1)
{
// Zero Crossing off, assign Table Pointer to sample table
tbl_ptr = &spl_add_tbl[0];
}
else
{
// Zero Crossing on, assign Table pointer to Zero Crossing Table and set A/D read mapping.
tbl_ptr = &zxd_add_tbl[0];
}
In one of the examination, they asked us to write a function "int similar()"
to check whether two list's data are similar or not irrespective of their order. they can also be of different sizes(in that case, they are dissimilar)
that is,. 3->2->-1 and -1>3>2 are similar
I wrote a program for that which is shown below.
that is, for list one,I am adding all the elements and storing in sum1.
I am multiplying all the elements and storing in product1.
similarly , sum2 and product2 for 2nd list.
if their sums and products are equal, then they must be containing same elements.
my question is that is this algorithm complete?
is there any case where my logic fails?
please help me
#include<stdio.h>
struct _node_
{
int data;
struct _node_ *ptr;
};
typedef struct _node_ Node;
struct _linkedlist_
{
Node *head;
Node *tail;
int count;
};
typedef struct _linkedlist_ List;
int similar(List *, List *);
int main()
{
//...code//
return 0;
}
int similar(List *one, List *two)
{
int sum1=0;
int sum2=0;
int product1=1;
int product2=1;
int i;
Node *temp;
temp=one->head;
for(i=0;i<one->count;i++)
{
sum1=sum1+(temp->data);
prodcut1=product1*(temp->data);
temp=temp->ptr;
}
temp=two->head;
for(i=0;i<two->count;i++)
{
sum2=sum2+(temp->data);
prodcut2=product2*(temp->data);
temp=temp->ptr;
}
if(sum1==sum2 && product1==product2)
return 1;
return0;
}
Your algorithm is not complete since your logic can fail. For your example 3->2->-1 there is another sequence that has the same sum and product but is not similar, namely
1 -> (3 + sqrt(33)) / 2 -> (3 - sqrt(33)) / 2
(Those values round to 1, 4.37228, and -1.37228.)
You can check and see that the sum of those values is 4 and the product is -6, just like your original list.
This happens because you put only two requirements on the values, which means you remove only two degrees of freedom. If the list has three or more values, that leaves one or more degrees of freedom, which allows for infinitely many possibilities. I showed you an example where the first value was 1--an example could be given for any value x where it is not true that -0.971168 < x <= 0 (approximately).
So you need another approach. You could sort each list then compare them. You could also put the values for each list into a multi-set (also called a bag or mset or counter) and compare those multi-sets.
As per the requirement mentioned in the question of the data being similar (i.e you are only checking for the order of data)
Consider a case where you have elements [-3,0,3] in list 1 and elements [10,-10,0] in the list 2.
In this case, the sum will be 0, and the product will also be 0
1. Sort both lists
2. Check every item of the list.
2.1 if they are not equal
-> print: lists are not equal.
3. lists are equal
Note: you either can sort the list, or make two separate lists, adding values in sorted order.
I want to append a 2D array to my 3D array. I expect it should be same as int[] arr; arr ~= 3;
void readInput()
{
char[][][] candidate;
char[] buff;
size_t counter = 0;
while ( stdin.readln(buff) )
{
char[][] line = buff.chomp().split();
writeln(line);
candidate ~= line;
writeln(candidate);
if (++counter > 1 ) break;
}
}
And I send the inputs below
201212?4 64
20121235 93
I expect a output like
[["201212?4", "64"], ["20121235", "93"]]
But instead I see
[["20121235", "93"], ["20121235", "93"]]
=~ replaces all the elements in the array with the last added. Where am I doing wrong? How can I meet my expectation?
The problem here is that byLine is reusing buf (that's actually one reason why it asks for a mutable buffer and returns mutable - as a warning that it might change on you).
So when you ~= it, it is really appending the one array multiple times all with a pointer to the same data, so when it changes, that change is seen each time.
You can fix it by adding a .dup to the array you are appending.
I'm brushing up on how hash tables work, and so I understand how the hash function calculates a unique (for the purpose of this question) hash table value to go with a stored value, so when the stored value is searched the hash function gives the computer the hash table value.
OK, so now we have the hash table value, but how is this better? Don't we still have to iterate through until we find the matching hash table value?
The hash function will be used to be mapped to an index directly in your array. So no search or iteration is done
The hash table is stored in an array. The hash value is mapped to an array index. Depending on the implementation, either the hash value is the array index or it is a number from a larger range which is taken modulo the size of the array.
Then once it looks at that spot in the array, it has to check that the value there matches, since multiple values may have the same hash value. Usually, it actually navigates a linked list of all values which have been hashed to the same spot in the hash table. This is a much, much shorter list than the full list (especially if the size of the hash table is proportional to the amount of data in it).
There are lots of different hash tables, each with differing details about the implementation, but the simplest hash table uses a hash code as index into an array:
#define TABLESIZE 1000
char **gHashTable[TABLESIZE];
void clearHashTable() {
memset(gHashTable, 0, sizeof(gHashTable));
}
int calculateHashCode(char *string) {
int val = 0;
for (int i = 0; string[i] != '\0'; ++i)
val += string[i];
return val;
}
void insertInHash(char *string) {
int hashCode = calculateHashCode(string);
gHashTable[hashCode % TABLESIZE] = string;
}
int isInHashTable(char *string) {
int hashCode = calculateHashCode(string);
return gHashTable[hashCode % TABLESIZE] != 0;
}
Now this simple hash supports fast lookup on strings. It doesn't handle collisions well, the hash function is terrible, and a number of other problems, but it will work.