Related
I want to construct two big number by array in c programming and make them add.
The following is my code:
void add(unsigned char* a, unsigned char* b, unsigned int len)
{
int i;
unsigned short T;
unsigned char carry = 0;
for (i = len - 1; i >= 0; --i)
{
T = (unsigned short)(a[i]) + (unsigned short)(b[i]) + (unsigned short)carry;
//T = a[i] + b[i] + carry;
if (T > 0xFF)
carry = 1;
else
carry = 0;
a[i] = (unsigned char)T;
}
}
The max value in array a and b for every element is 255.
EDIT1: The highest carry is discarded. The result is save in array a.
EDIT2: replace "Byte" with "carry".
The original code is :
Integer B1(B, SM3_BLOCK_SIZE);
++B1;
for (i = 0; i < ILen; i += v)
(Integer(I + i, v) + B1).Encode(I + i, v);
I write two new function. One is as the Above add(), The other is as following:
void add_one(unsigned char *arr, unsigned int len)
{
int i;
for (i = len-1; i >= 0; --i)
{
arr[len] += 1;
if (arr[len] != 0)
return;
}
}
If my code is rigth, the original code is as following:
add_one(B, SM3_BLOCK_SIZE);
for (i = 0; i < ILen; i += v)
add(I + i, B, SM3_BLOCK_SIZE);
There is (at least) one bug. Look at this code:
void add_one(unsigned char *arr, unsigned int len)
{
int i;
for (i = len-1; i >= 0; --i)
{
arr[len] += 1; // Indexing using len is wrong
if (arr[len] != 0) // Indexing using len is wrong
return;
}
}
You probably want to use i as index.
I assumed you know that you are implementing the add function for a bigendian positive integer.
Avoid using for (i = len-1; i >= 0; --i). You can catch a runtime error when i is unsigned and len is 0. Instead, use for (i = len; i-- > 0;).
If you need a little-endian integer than use for (int i = 0; i < len; ++i)
char add(unsigned char* a, unsigned char* b, unsigned int len)
{
unsigned short carry = 0;
//for (int i = 0; i < len; ++i) // for little-endian
for (int i = len; i-- > 0;) // for big-endian
{
carry += a[i] + b[i];
a[i] = carry & 0xFF;
carry >>= 8;
}
return carry;
}
Tests
unsigned char a[5] = {255,2,3,4,5};
unsigned char b[5] = {255,256-2,256-3,4,5};
char overflow = add(a,b,5);
printf("%d %d %d %d %d / %d",a[0],a[1],a[2],a[3],a[4] , overflow);
Output
255 1 0 8 10 / 1
I have to implement the Rabin-Karp string searching algorithm.
I think there is something wrong with my rkhash_next function. My professor told us to compute the next hash value in the string using this equation:
yi+1 = 256^m-1*Y[i+1] + 256^m-2*Y[i+2] + ... + Y[i+m]
= 256 * ( 256^m-2*Y[i+1] + ... Y[i+m-1]) + Y[i+m]
= 256 * ((256^m-1*Y[i] + 256^m-2*Y[i+1] + ... Y[i+m-1]) - 256^m-1*Y[i]) + Y[i+m]
= 256 * ( yi - 256^m-1 * Y[i]) + Y[i+m]
= 256 * yi - 256^m * Y[i] + Y[i+m]
I did this, but my program keeps giving me surprising hash values as it "rolls" through the string. Here is my general code for my rkhash_substring_match:
int rk_substring_match(const char *pattern, const char *doc, int *first_match_ind)
{
int plength = strlen(pattern);
int dlength = strlen(doc);
int i,j,x;
int counter = 0;
int first_match = 0;
first_match_ind = &first_match;
long long hash = 256;
long long *h;
long long phash = 0;
long long dhash = 0;
for (x = 0; x <= plength-1; x++)
hash *= 256;
phash = rkhash_init(pattern, plength,h);
dhash = rkhash_init(doc, plength,h);
for(i = 0; i <= dlength - plength; i++) {
if (phash == dhash) {
for (j = 0; j < plength; j++)
if (doc[i+j] != pattern[j])
break;
if (j == plength && counter == 0)
first_match = i;
if (j == plength)
counter++;
}
printf("%lld\n", dhash);
dhash = rkhash_next(dhash,hash,doc[i + 1], doc[i+plength]);
}
return counter;
}
In my class, long long variables are used to store hash values and 256^m for later usage in the program. Below is rkhash_init which generates the hash value and stores 256^m in the value of h:
long long rkhash_init(const char *charbuf, int m, long long *h)
{
int i,j;
long long value = 1;
long long hash = 0;
for (j = 0; j < m; j++)
value *= 256;
h = &value;
long long val = value;
for (i = 0; i < m -1 ; i++) {
value = value/256;
hash += mmul(value, charbuf[i]);
}
hash += charbuf[m-1];
return hash;
}
And here is the problem child, rkhash_next:
long long rkhash_next(long long curr_hash, long long h, char leftmost, char rightmost)
{
return madd(msub(mmul(curr_hash, 256), mmul(leftmost, h)), rightmost);
}
madd, msub, and mmul are functions given to us by the professor. They perform modulus arithmetic after completing either addition, subtraction or multiplication. For example, here is the madd function:
long long madd(long long a, long long b)
{
return (a + b) % PRIME;
}
Can anyone please help me find out why my program is not working!?
I have spent more 10hr+ on trying to sort the following(hexadecimals) in LSD radix sort, but no avail. There is very little material on this subject on web.
0 4c7f cd80 41fc 782c 8b74 7eb1 9a03 aa01 73f1
I know I have to mask and perform bitwise operations to process each hex digit (4 bits), but have no idea on how and where.
I'm using the code (I understand) from GeeksforGeeks
void rsort(int a[], int n) {
int max = getMax(a, n);
for (int exp = 1; max / exp > 0; exp *= 10) {
ccsort(a, n, exp);
}
}
int getMax(int a[], int n) {
int max = a[0];
int i = 0;
for (i = 0; i < n; i++) {
if (a[i] > max) {
max = a[i];
}
}
return max;
}
void ccsort(int a[], int n, int exp) {
int count[n];
int output[n];
int i = 0;
for (i = 0; i < n; i++) {
count[i] = 0;
output[i] = 0;
}
for (i = 0; i < n; i++) {
++count[(a[i] / exp) % 10];
}
for (i = 1; i <= n; i++) {
count[i] += count[i - 1];
}
for (i = n - 1; i >= 0; i--) {
output[count[(a[i] / exp) % 10] - 1] = a[i];
--count[(a[i] / exp) % 10];
}
for (i = 0; i < n; i++) {
a[i] = output[i];
}
}
I have also checked all of StackOverFlow on this matter, but none of them covers the details.
Your implementation of radix sort is slightly incorrect:
it cannot handle negative numbers
the array count[] in function ccsort() should have a size of 10 instead of n. If n is smaller than 10, the function does not work.
the loop for cumulating counts goes one step too far: for (i = 1; i <= n; i++). Once again the <= operator causes a bug.
you say you sort by hex digits but the code uses decimal digits.
Here is a (slightly) improved version with explanations:
void ccsort(int a[], int n, int exp) {
int count[10] = { 0 };
int output[n];
int i, last;
for (i = 0; i < n; i++) {
// compute the number of entries with any given digit at level exp
++count[(a[i] / exp) % 10];
}
for (i = last = 0; i < 10; i++) {
// update the counts to have the index of the place to dispatch the next
// number with a given digit at level exp
last += count[i];
count[i] = last - count[i];
}
for (i = 0; i < n; i++) {
// dispatch entries at the right index for its digit at level exp
output[count[(a[i] / exp) % 10]++] = a[i];
}
for (i = 0; i < n; i++) {
// copy entries batch to original array
a[i] = output[i];
}
}
int getMax(int a[], int n) {
// find the largest number in the array
int max = a[0];
for (int i = 1; i < n; i++) {
if (a[i] > max) {
max = a[i];
}
}
return max;
}
void rsort(int a[], int n) {
int max = getMax(a, n);
// for all digits required to express the maximum value
for (int exp = 1; max / exp > 0; exp *= 10) {
// sort the array on one digit at a time
ccsort(a, n, exp);
}
}
The above version is quite inefficient because of all the divisions and modulo operations. Performing on hex digits can be done with shifts and masks:
void ccsort16(int a[], int n, int shift) {
int count[16] = { 0 };
int output[n];
int i, last;
for (i = 0; i < n; i++) {
++count[(a[i] >> shift) & 15];
}
for (i = last = 0; i < 16; i++) {
last += count[i];
count[i] = last - count[i];
}
for (i = 0; i < n; i++) {
output[count[(a[i] >> shift) & 15]++] = a[i];
}
for (i = 0; i < n; i++) {
a[i] = output[i];
}
}
void rsort16(int a[], int n) {
int max = a[0];
for (int i = 1; i < n; i++) {
if (a[i] > max) {
max = a[i];
}
}
for (int shift = 0; (max >> shift) > 0; shift += 4) {
ccsort16(a, n, shift);
}
}
It would be approximately twice as fast to sort one byte at a time with a count array of 256 entries. It would also be faster to compute the counts for all digits in one pass, as shown in rcgldr's answer.
Note that this implementation still cannot handle negative numbers.
There's a simpler way to implement a radix sort. After checking for max, find the lowest power of 16 >= max value. This can be done with max >>= 4 in a loop, incrementing x so that when max goes to zero, then 16 to the power x is >= the original max value. For example a max of 0xffff would need 4 radix sort passes, while a max of 0xffffffff would take 8 radix sort passes.
If the range of values is most likely to take the full range available for an integer, there's no need to bother determining max value, just base the radix sort on integer size.
The example code you have shows a radix sort that scans an array backwards due to the way the counts are converted into indices. This can be avoided by using an alternate method to convert counts into indices. Here is an example of a base 256 radix sort for 32 bit unsigned integers. It uses a matrix of counts / indices so that all 4 rows of counts are generated with just one read pass of the array, followed by 4 radix sort passes (so the sorted data ends up back in the original array). std::swap is a C++ function to swap the pointers, for a C program, this can be replaced by swapping the pointers inline. t = a; a = b; b = t, where t is of type uint32_t * (ptr to unsigned 32 bit integer). For a base 16 radix sort, the matrix size would be [8][16].
// a is input array, b is working array
uint32_t * RadixSort(uint32_t * a, uint32_t *b, size_t count)
{
size_t mIndex[4][256] = {0}; // count / index matrix
size_t i,j,m,n;
uint32_t u;
for(i = 0; i < count; i++){ // generate histograms
u = a[i];
for(j = 0; j < 4; j++){
mIndex[j][(size_t)(u & 0xff)]++;
u >>= 8;
}
}
for(j = 0; j < 4; j++){ // convert to indices
m = 0;
for(i = 0; i < 256; i++){
n = mIndex[j][i];
mIndex[j][i] = m;
m += n;
}
}
for(j = 0; j < 4; j++){ // radix sort
for(i = 0; i < count; i++){ // sort by current lsb
u = a[i];
m = (size_t)(u>>(j<<3))&0xff;
b[mIndex[j][m]++] = u;
}
std::swap(a, b); // swap ptrs
}
return(a);
}
void int_radix_sort(void) {
int group; //because extracting 8 bits
int buckets = 1 << 8; //using size 256
int map[buckets];
int mask = buckets - 1;
int i;
int cnt[buckets];
int flag = NULL;
int partition;
int *src, *dst;
for (group = 0; group < 32; group += 8) {
// group = 8, number of bits we want per round, we want 4 rounds
// cnt
for (int i = 0; i < buckets; i++) {
cnt[i] = 0;
}
for (int j = 0; j < n; j++) {
i = (lst[j] >> group) & mask;
cnt[i]++;
tmp[j] = lst[j];
}
//map
map[0] = 0;
for (int i = 1; i < buckets; i++) {
map[i] = map[i - 1] + cnt[i - 1];
}
//move
for (int j = 0; j < n; j++) {
i = (tmp[j] >> group) & mask;
lst[map[i]] = tmp[j];
map[i]++;
}
}
}
After hours of researching I came across the answer. I'm still do not understand what is going on in this code/answer. I cannot get my head wrapped around the concept. Hopefully, someone can explain.
I see your points. I think negative numbers are easy to sort after the list has been sorted with something like loop, flag, and swap. wb unsigned float points? – itproxti Nov 1 '16 at 16:02
As for handling floating points there might be a way, for example 345.768 is the number, it needs to be converted to an integer, i.e. make it 345768, I multiplied 1000 with it. Just like the offset moves the -ve numbers to +ve domain, so will multiplying by 1000, 10000 etc will turn the floats to numbers with their decimal part as all zeros. Then they can be typecasted to int or long. However with large values, the whole reformed number may not be accomodated within the entire int or long range.
The number that is to be multiplied has to be constant, just like the offset so that the relationship among the magnitudes is preserved. Its better to use powers of 2 such as 8 or 16, as then bitshifting operator can be used. However just like the calculation of offset takes some time, so will calculation of the multiplier will take some time. The whole array is to be searched to calculate the least number that when multiplied will turn all the numbers with zeros in decimal parts.
This may not compute fast but still can do the job if required.
I found this Hash function written in Java and with some help from stackoverflow converted it to C. The problem is it gives a different hash value each time it runs on the same word.
Here's the original function:
long sfold(String s, int M)
{
int intLength = s.length() / 4;
long sum = 0;
for (int j = 0; j < intLength; j++)
{
char c[] = s.substring(j * 4, (j * 4) + 4).toCharArray();
long mult = 1;
for (int k = 0; k < c.length; k++)
{
sum += c[k] * mult;
mult *= 256;
}
}
char c[] = s.substring(intLength * 4).toCharArray();
long mult = 1;
for (int k = 0; k < c.length; k++)
{
sum += c[k] * mult;
mult *= 256;
}
return(Math.abs(sum) % M);
}
And here's how we rewrote it:
include <stdlib.h>
include <stdio.h>
include <math.h>
include <string.h>
long sfold(char * s, int M);
int main(void)
{
char * s = "test";
int M;
long x;
M = 525;
x = sfold(s,M);
printf("%ld\n",x);
}
long sfold(char * s, int M)
{
int intLength = strlen(s) / 4;
long sum = 0;
for (int j = 0; j < intLength; j++)
{
char c[4];
memcpy(c, s + 4 * j, 4);
//char c[] = s.substring(j * 4, (j * 4) + 4).toCharArray();
long mult = 1;
for (int k = 0; k < strlen(c); k++)
{
sum += c[k] * mult;
mult *= 256;
}
}
char c[intLength];
memcpy(c,s,intLength);
//char c[] = s.substring(intLength * 4).toCharArray();
long mult = 1;
for (int k = 0; k < strlen(c); k++)
{
sum += c[k] * mult;
mult *= 256;
}
return(abs(sum) % M);
}
Shouldn't this give the same value each time we run the program? Anyone see what's wrong?
All that string copying is really silly. What's the point of copying if all you need is the character value?
Here's how it might look in C:
long sfold(char* s, unsigned long M) {
unsigned long mult = 1, sum = 0;
while (*s) {
sum += (uint8_t)(*s++) * mult;
mult *= 256;
if (!mult) mult = 1;
}
return sum % M;
}
But it's a terrible hash algorithm. You'd be better off with a simple modular hash (which is also not great, but it's not as bad):
/* This could be any small prime */
static const unsigned long mult = 31;
long sfold(char* s, unsigned long M) {
/* Avoid having the hash of the empty string be 0 */
unsigned long sum = 0xBEA00D1FUL;
while (*s)
sum += (uint8_t)(*s++) * mult;
return sum % M;
}
I think I took care of most of the bugs for you. I made it C99 compliant, mainly out of habit. The major problem was using strlen(c): c is a character array, not a string (which is a character array terminated with the null '\0' character). You'll need to rewrite your function so that if calloc()/malloc() fails, the function terminates with an error. Or you can go back to variable length arrays like you were using before if your compiler supports it. There are likely better hash functions in other posts on StackOverflow, but this at least helps you getting yours working in a deterministic manner without invoking undefined behavior.
Code Listing
/******************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#define BUF_SIZE (4)
/******************************************************************************/
long sfold(const char* s, int M);
/******************************************************************************/
int main(void) {
const char* s = "test string";
int M;
long x;
M = 525;
x = sfold(s,M);
printf("String:%s - Hash:%ld\n", s, x);
}
/******************************************************************************/
long sfold(const char* s, int M) {
int intLength = strlen(s) / 4;
char* c = calloc(intLength, sizeof(char)); /* Warning, test if c==NULL, this
* call can fail.
*/
long sum = 0;
int j, k;
for (j=0; j<intLength; j++) {
char c[BUF_SIZE];
memcpy(c, s + BUF_SIZE * j, BUF_SIZE);
//char c[] = s.substring(j * 4, (j * 4) + 4).toCharArray();
long mult = 1;
for (k=0; k<BUF_SIZE; k++) {
sum += c[k] * mult;
mult *= 256;
}
}
memcpy(c, s, intLength);
//char c[] = s.substring(intLength * 4).toCharArray();
long mult = 1;
for (k=0; k<BUF_SIZE; k++) {
sum += c[k] * mult;
mult *= 256;
}
free(c);
return(abs(sum) % M);
}
Sample Output
for i in $(seq 1 5); do echo $i; ./a.out; done
1
String:test string - Hash:384
2
String:test string - Hash:384
3
String:test string - Hash:384
4
String:test string - Hash:384
5
String:test string - Hash:384
Is there a more efficient way to achieve this:
Given an array A of size n and two positive integers a and b, find the sum floor(abs(A[i]-A[j])*a/b) taken over all pairs (i, j) where 0 <= i < j < n.
int A[n];
int a, b; // assigned some positive integer values
...
int total = 0;
for (int i = 0; i < n; i++) {
for (int j = i+1; j < n; j++) {
total += abs(A[i]-A[j])*a/b; // want integer division here
}
}
To optimize this a little bit, I sorted the array (O(nlogn)) and then didn't use an abs function. Also, I cached the value a[i] before the inner for loop, so I could just read stuff from A sequentially. I was considering precomputing a/b and storing that in a float, but the extra casting just makes it slower (especially since I want to take the floor of the result).
I couldn't come up with a solution that was better than O(n^2).
Yes, there is a more efficient algorithm. It can be done it in O(n*log n). I don't expect there to be an asymptotically faster way, but I'm far from any idea of a proof.
Algorithm
First sort the array in O(n*log n) time.
Now, let us look at the terms
floor((A[j]-A[i])*a/b) = floor ((A[j]*a - A[i]*a)/b)
for 0 <= i < j < n. For each 0 <= k < n, write A[k]*a = q[k]*b + r[k] with 0 <= r[k] < b.
For A[k] >= 0, we have q[k] = (A[k]*a)/b and r[k] = (A[k]*a)%b with integer division, for A[k] < 0, we have q[k] = (A[k]*a)/b - 1 and r[k] = b + (A[k]*a)%b unless b divides A[k]*a, in which case we have q[k] = (A[k]*a)/b and r[k] = 0.
Now we rewrite the terms:
floor((A[j]*a - A[i]*a)/b) = floor(q[j] - q[i] + (r[j] - r[i])/b)
= q[j] - q[i] + floor((r[j] - r[i])/b)
Each q[k] appears k times with positive sign (for i = 0, 1, .. , k-1) and n-1-k times with negative sign (for j = k+1, k+2, ..., n-1), so its total contribution to the sum is
(k - (n-1-k))*q[k] = (2*k+1-n)*q[k]
The remainders still have to be accounted for. Now, since 0 <= r[k] < b, we have
-b < r[j] - r[i] < b
and floor((r[j]-r[i])/b) is 0 when r[j] >= r[i] and -1 when r[j] < r[i]. So
n-1
∑ floor((A[j]-A[i])*a/b) = ∑ (2*k+1-n)*q[k] - inversions(r)
i<j k=0
where an inversion is a pair (i,j) of indices with 0 <= i < j < n and r[j] < r[i].
Calculating the q[k] and r[k] and summing the (2*k+1-n)*q[k] is done in O(n) time.
It remains to efficiently count the inversions of the r[k] array.
For each index 0 <= k < n, let c(k) be the number of i < k such that r[k] < r[i], i.e. the number of inversions in which k appears as the larger index.
Then obviously the number of inversions is ∑ c(k).
On the other hand, c(k) is the number of elements that are moved behind r[k] in a stable sort (stability is important here).
Counting these moves, and hence the inversions of an array is easy to do while merge-sorting it.
Thus the inversions can be counted in O(n*log n) too, giving an overall complexity of O(n*log n).
Code
A sample implementation with a simple unscientific benchmark (but the difference between the naive quadratic algorithm and the above is so large that an unscientific benchmark is conclusive enough).
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
long long mergesort(int *arr, unsigned elems);
long long merge(int *arr, unsigned elems, int *scratch);
long long nosort(int *arr, unsigned elems, long long a, long long b);
long long withsort(int *arr, unsigned elems, long long a, long long b);
int main(int argc, char *argv[]) {
unsigned count = (argc > 1) ? strtoul(argv[1],NULL,0) : 1000;
srand(time(NULL)+count);
long long a, b;
b = 1000 + 9000.0*rand()/(RAND_MAX+1.0);
a = b/3 + (b-b/3)*1.0*rand()/(RAND_MAX + 1.0);
int *arr1, *arr2;
arr1 = malloc(count*sizeof *arr1);
arr2 = malloc(count*sizeof *arr2);
if (!arr1 || !arr2) {
fprintf(stderr,"Allocation failed\n");
exit(EXIT_FAILURE);
}
unsigned i;
for(i = 0; i < count; ++i) {
arr1[i] = 20000.0*rand()/(RAND_MAX + 1.0) - 2000;
}
for(i = 0; i < count; ++i) {
arr2[i] = arr1[i];
}
long long res1, res2;
double start = clock();
res1 = nosort(arr1,count,a,b);
double stop = clock();
printf("Naive: %lld in %.3fs\n",res1,(stop-start)/CLOCKS_PER_SEC);
start = clock();
res2 = withsort(arr2,count,a,b);
stop = clock();
printf("Sorting: %lld in %.3fs\n",res2,(stop-start)/CLOCKS_PER_SEC);
return EXIT_SUCCESS;
}
long long nosort(int *arr, unsigned elems, long long a, long long b) {
long long total = 0;
unsigned i, j;
long long m;
for(i = 0; i < elems-1; ++i) {
m = arr[i];
for(j = i+1; j < elems; ++j) {
long long d = (arr[j] < m) ? (m-arr[j]) : (arr[j]-m);
total += (d*a)/b;
}
}
return total;
}
long long withsort(int *arr, unsigned elems, long long a, long long b) {
long long total = 0;
unsigned i;
mergesort(arr,elems);
for(i = 0; i < elems; ++i) {
long long q, r;
q = (arr[i]*a)/b;
r = (arr[i]*a)%b;
if (r < 0) {
r += b;
q -= 1;
}
total += (2*i+1LL-elems)*q;
arr[i] = (int)r;
}
total -= mergesort(arr,elems);
return total;
}
long long mergesort(int *arr, unsigned elems) {
if (elems < 2) return 0;
int *scratch = malloc((elems + 1)/2*sizeof *scratch);
if (!scratch) {
fprintf(stderr,"Alloc failure\n");
exit(EXIT_FAILURE);
}
return merge(arr, elems, scratch);
}
long long merge(int *arr, unsigned elems, int *scratch) {
if (elems < 2) return 0;
unsigned left = (elems + 1)/2, right = elems-left, i, j, k;
long long inversions = 0;
inversions += merge(arr, left, scratch);
inversions += merge(arr+left,right,scratch);
if (arr[left] < arr[left-1]) {
for(i = 0; i < left; ++i) {
scratch[i] = arr[i];
}
i = 0; j = 0; k = 0;
int *lptr = scratch, *rptr = arr+left;
while(i < left && j < right) {
if (rptr[j] < lptr[i]) {
arr[k++] = rptr[j++];
inversions += (left-i);
} else {
arr[k++] = lptr[i++];
}
}
while(i < left) arr[k++] = lptr[i++];
}
return inversions;
}