I have a problem generating random numbers (C) - c

My problem is that i cant figure how to make sure the rand function doesn't give the same number to 2 different cells and if it does how can i change it without getting to a number thats already in other cell.(the if(arr[j] != -1) is because i had other function that filled some cells with (-1) )
this is one version of how i tried to do it (all the // are leftovers from different tries)
void fillArr(int arr[], int n)
{
int i,j=0;
for (i = 0; i < n; i++)
{
while (arr[j] == arr[j + 2] &&j + 2<n)
{
//srand(time(NULL));
if (arr[j] != -1)
{
if (j % 2 == 0)
{
arr[j] = rand() % (N - 1);
if (arr[j + 2] != -1)
arr[j + 2] = rand() % (N - 1);
//arr[i] = rand() % (N - 1)-rand()%(i-1);
srand(time(NULL));
}
else
{
arr[j] = rand() % (N - i);
arr[j + 2] = rand() % (N - 1);
//arr[i] = rand() % (N - 1) - rand() % (i +1);
//srand(time(NULL));
}
}
j++;
}
}
}

You are not supposed to re-seed the PRNG in every loop iteration. You should do it once at the start of your program instead.
You'll produce a duplicate sequence of numbers as soon as you have multiple calls to srand(time(NULL)) per second. Which doesn't seem to be unlikely in your code.
For reference:
https://en.cppreference.com/w/c/numeric/random/srand

Why couldn't there be two equal numbers in an array of random numbers?
Anyway, if you want to prevent it, for every new value to be added in the array, iterate from the start and check if that number is already in. If so, generate a new number and check again.
Of course there should be enough unique numbers to be fit in the array (you can check this before you start), and in theory it could take forever, but in reality this does not happen.

Related

How to find all the palindromes in a large array?

I need to find all the palindromes of π with 50 million digits 3.141592653589793238462643383279502884197169399375105820974944592307816406286... (goes on and on...)
I've stored all the digits of π in a char array. Now I need to search and count the number of 'palindromes' of length 2 to 15. For example, 535, 979, 33, 88, 14941, etc. are all valid results.
The final output I want is basically like the following.
Palindrome length Number of Palindromes of this length
-----------------------------------------------------------------
2 1234 (just an example)
3 1245
4 689
... ...
... ...
... ...
... ...
15 0
pseudocode of my logic so far - it works but takes forever
//store all digits in a char array
char *piArray = (char *)malloc(NUM_PI_DIGITS * sizeof(char));
int count = 0; //count for the number of palindromes
//because we only need to find palindroms that are 2 - 15 digits long
for(int i = 2; i <= 15; i++){
//loop through the piArray and find all the palindromes with i digits long
for(int j = 0; j < size_of_piArray; j++){
//check if the the sub array piArray[j:j+i] is parlindrom, if so, add a count
bool isPalindrome = true;
for (int k = 0; k < i / 2; k++)
{
if (piArray [j + k] != piArray [j + i - 1 - k])
{
isPalindrom = false;
break;
}
}
if(isPalindrome){
count++;
}
}
}
The problem I am facing now is that it takes too long to loop through the array of this large size (15-2)=13 times. Is there any better way to do this?
Here is a C version adapted from the approach proposed by Caius Jard:
void check_pi_palindromes(int NUM_PI_DIGITS, int max_length, int counts[]) {
// store all digits in a char array
int max_span = max_length / 2;
int start = max_span;
int end = NUM_PI_DIGITS + max_span;
char *pi = (char *)malloc(max_span + NUM_PI_DIGITS + max_span);
// read of generate the digits starting at position `max_span`
[...]
// clear an initial and trailing area to simplify boundary testing
memset(pi, ' ', start);
memset(pi + end, ' ', max_span);
// clear the result array
for (int i = 0; i <= max_length; i++) {
count[i] = 0;
}
// loop through the pi array and find all the palindromes
for (int i = start; i < end; i++) {
if (pi[i + 1] == pi[i - 1]) { //center of an odd length palindrome
count[3]++;
for (n = 2; n <= max_span && pi[i + n] == pi[i - n]; n++) {
count[n * 2 + 1]++;
}
}
if (pi[i] == pi[i - 1]) { //center of an even length palindrome
count[2]++;
for (n = 1; n <= max_span && pi[i + n] == pi[i - n]; n++) {
count[n * 2]++;
}
}
}
}
For each position in the array, it scans in both directions for palindromes of odd and even lengths with these advantages:
single pass through the array
good cache locality because all reads from the array are in a small span from the current position
fewer tests as larger palindromes are only tested as extensions of smaller ones.
A small working prefix and suffix is used to avoid the need to special case the beginning and end of the sequence.
I can't solve it for C, as I'm a C# dev but I expect the conversion will be trivial - I've tried to keep it as basic as possible
char[] pi = "3.141592653589793238462643383279502884197169399375105820974944592307816406286".ToCharArray(); //get a small piece as an array of char
int[] lenCounts = new int[16]; //make a new int array with slots 0-15
for(int i = 1; i < pi.Length-1; i++){
if(pi[i+1] == pi[i-1]){ //center of an odd length pal
int n = 2;
while(pi[i+n] == pi[i-n] && n <= 7) n++;
lenCounts[((n-1)*2+1)]++;
} else if(pi[i] == pi[i-1]){ //center of an even length pal
int n = 1;
while(pi[i+n] == pi[i-1-n] && n <= 7) n++;
lenCounts[n*2]++;
}
}
This demonstrates the "crawl the string looking for a palindrome center then crawl away from it in both directions looking for equal chars" technique..
..the only thing I'm not sure on, and it has occurred in the Pi posted, is what you want to do if palindromes overlap:
3.141592653589793238462643383279502884197169399375105820974944592307816406286
This contains 939 and overlapping with it, 3993. The algo above will find both, so if overlaps are not to be allowed then you might need to extend it to deal with eliminating earlier palindromes if they're overlapped by a longer one found later
You can play with the c# version at https://dotnetfiddle.net/tkQzBq - it has some debug print lines in too. Fiddles are limited to a 10 second execution time so I don't know if you'll be able to time the full 50 megabyte 😀 - you might have to run this algo locally for that one
Edit: fixed a bug in the answer but I haven't fixed it in the fiddle; I did have while(.. n<lenCounts.Length) i.e. allowing n to reach 15, but that would be an issue because it's in both directions.. nshould go to 7 to remain in range of the counts array. I've patched that by hard coding 7 but you might want to make it dependent on array length/2 etc
Well, I think it can't be done less than O(len*n), and that you are doing this O(len^2*n), where 2 <= len <= 15, is almost the same since the K coefficient doesn't change the O notation in this case, but if you want to avoid this extra loop, you can check these links, it shouldn't be hard to add a counter for each length since these codes are counting all of them, with maximum possible length:
source1, source2, source3.
NOTE: Mostly it's better to reach out GeekForGeeks when you are looking for algorithms or optimizations.
EDIT: one of the possible ways with O(n^2) time complexity and O(n)
Auxiliary Space. You can change unordered_map by array if you wish, anyway here the key will be the length and the value will be the count of palindromes with that length.
unordered_map<int, int> countPalindromes(string& s) {
unordered_map<int, int> m;
for (int i = 0; i < s.length(); i++) {
// check for odd length palindromes
for (int j = 0; j <= i; j++) {
if (!s[i + j])
break;
if (s[i - j] == s[i + j]) {
// check for palindromes of length
// greater than 1
if ((i + j + 1) - (i - j) > 1)
m[(i + j + 1) - (i - j)]++;
} else
break;
}
// check for even length palindromes
for (int j = 0; j <= i; j++) {
if (!s[i + j + 1])
break;
if (s[i - j] == s[i + j + 1]) {
// check for palindromes of length
// greater than 1
if ((i + j + 2) - (i - j) > 1)
m[(i + j + 2) - (i - j)]++;
} else
break;
}
}
return m;
}

c - find palindrome

I'm a newcomer to programming, and I chose C as my first language(been learning it for a month or so).
I've been trying to solve this palindrome question for hours and still couldn't come up with a satisfying solution.
The question is here (from SPOJ), and here's my code:
#include <stdio.h>
#include <string.h>
void plus_one(char *number);
int main(void)
{
char number[1000001];
int i, j, m, k, indicator;
int a;
scanf("%d", &j);
for (i = 0; i < j; i++) {
scanf("%s", number);
k = 1;
while (k != 0) {
plus_one(number);
a = strlen(number);
indicator = 1;
for (m = 0; m < a / 2; m++) {
if (number[m] != number[a - m - 1]) {
indicator = 0;
break;
}
}
if (indicator != 0) {
printf("%s\n", number);
k = 0;
}
}
}
return 0;
}
void plus_one(char *number)
{
int a = strlen(number);
int i;
number[a - 1]++;
for (i = a; i >= 0; i--){
if (number[i - 1] == ':') {
number[i - 1] = '0';
number[i - 2]++;
}
else
break;
}
if (number[0] == '0') {
number[0] = '1';
strcat(number, "0");
}
return;
}
My idea was to examine every number greater than the input until a palindrome is found, and it worked well on my computer. But SPOJ responded "time limit exceeded", so I guess I need to find the next palindrome possible myself instead of using brute force. Can someone please give me a hint about how I can make this go faster? Thanks!
Since you're asking for a hint and not for C code (which I'm notoriously bad at), here's what I would do:
Determine if the number k has an even or odd number of digits, store that in a boolean called odd.
Take the first half of the number k, including the middle digit if odd is true, and store it in a variable called half.
808 -> 80
2133 -> 21
Mirror the half variable, taking care to not duplicate the middle digit if odd is true, and store it in a variable called mirror.
80 -> 808
21 -> 2112
Check if mirror > k
If true: you found your result
If false: increment half and start over from step 3.
(After maximum one increment you're guaranteed to have found your result.)
80 -> 81 -> 818
21 -> 22 -> 2222
Here's a JavaScript implementation for your reference:
const palin = (k) => {
const mirror = (half, odd) => half + Array.from(half).reverse().join('').substring(odd);
const s = k.toString();
const odd = s.length % 2;
const half = s.substring(0, Math.floor(s.length / 2) + odd);
let mirrored = mirror(half, odd);
if (+mirrored <= k) {
mirrored = mirror((+half + 1).toString(), odd);
}
return mirrored;
}
console.log(palin(5));
console.log(palin(808));
console.log(palin(2133));
Welcome to the site. What you have posted is commendable for someone who has only been using C for a month! Anyway ... I think your suspicion is correct. Using 'brute force' to find the next palindrome is probably the not to way go.
This question is as much about algorithm design as about C. Nonetheless, how you handle char[] representations of integers in C is interesting and relevant. FWIW, my attempt is pasted below.
It accepts a char[] representation of the number (n) and the number of digits (k) as arguments, and returns 1 on success or 0 on failure (another pass needed).
static int next_palindrome(char *n, size_t k) {
unsigned i = 0, carry = 0;
char tmp = 0;
int finished = 1;
for (i = 0; i < k; i++) {
if (carry) {
finished = 0;
*(n + k - i - 1) = *(n + k - i - 1) + 1;
if (*(n + k - i - 1) == 10) {
*(n + k - i - 1) = 0;
carry = 1;
} else
carry = 0;
continue;
}
if (i >= k / 2) continue;
if (*(n + k - i - 1) == *(n + i)) continue;
tmp = *(n + k - i - 1);
*(n + k - i - 1) = *(n + i);
if (tmp > *(n + i)) {
carry = 1;
}
}
return finished;
}
I have only tested it on numbers with < 64 digits so far, but have no reason to believe it will fail for larger numbers of digits.
Sample usage: http://codepad.org/3yyI9wEl

Sphere Online Judge Issues (Prime Number Generator)

Ok, so I enjoy using SPOJ to practice programming and developing algorithms. I always have issues with the questions though. A lot of times, I will get a "wrong answer" message when clearly my code answers the questions properly. If someone could tell me if there is anything wrong or why SPOJ would be telling me my answer was wrong that would be awesome! Here is the problem word-for-word:
Prime Number Generator
Peter wants to generate some prime numbers for his cryptosystem. Help him! Your task is to generate all prime numbers between two given numbers!
Input
The input begins with the number t of test cases in a single line (t<=10). In each of the next t lines there are two numbers m and n (1 <= m <= n <= 1000000000, n-m<=100000) separated by a space.
Output
For every test case print all prime numbers p such that m <= p <= n, one number per line, test cases separated by an empty line.
My code:
int n;
scanf("%d", &n);
if(n > 10){ return 0; }
n = n*2;
int arr[n];
for(int i = 0; i < n; i++){ scanf("%d", &arr[i]); }
for(int i = 0; i < n; i += 2){
if(arr[i] >= 1 && arr[i] <= arr[i+1] && arr[i+1] <= 1000000000 && arr[i+1]-arr[i] <= 100000){
for(int j = arr[i]; j <= arr[i+1]; j++){
if(j % 2 == 1 || j == 2){
printf("%d\n", j);
}
}
printf("\n");
}
}
return 0;
INPUT:
2
7 11
2 9
OUTPUT:
7
9
11
2
3
5
7
9
A lot of times, I will get a "wrong answer" message when clearly my code answers the questions properly.
This is not one of those cases as evidenced by the fact that, despite the contrary, your code seems to think that 9 is a prime. The line:
if(j % 2 == 1 || j == 2)
combined with the fact that you appear to be printing all odd numbers (and two), is an indication that your prime check is incorrect.
Where you should probably start is with a simple prime check function such as:
int isPrime(int num) {
int chk = 2;
while (chk * chk <= num)
if ((num % chk) == 0)
return 0;
++chk;
}
return 1;
}
Once you have it working, then worry about performance (two of my favourite mantras are "Wrong is the least optimised state" and "Get it working first, then get it working fast").
The things you can look into for optimisations include, but are not limited to:
Eratosthenes sieve where, provided the range of primes isn't too large, it can greatly improve speed by not having to do a lot of calculations for each prime test; and
Using the fact that all primes other than two and three are of the form 6n±1, effectively tripling the speed of the isPrime function (see here for an explanation).
For that second bullet point, you can use:
int isPrime(unsigned int num) {
// Special cases for 0-3.
if (num < 2) return 0;
if (num < 4) return 1;
int chk = 5, add = 2; // prime generator, 6n +/- 1.
while (chk * chk <= num) // check every candidate.
if ((num % chk) == 0) // check if composite.
return 0;
chk += add; // next candidate.
add = 6 - add; // alternate +2, +4.
}
return 1; // no factors, must be prime.
}

Generating a Sparse Matrix in C

Is there a simpler way of generating sparse matrix other than this?
for (i = 0; i < 1000; i++)
{
if (rand() % 3 == 0)
{
array[i] = rand() % 3;
}
else
{
array[i] = ((rand() % 3) - 1);
}
}
Thanks.
I used array for presentational purposes
With a determine how sparse you want it to be.
for (i = 0; i < 1000; i++)
{
if (rand() % a == 0)
{
array[i] = rand() % 100;
}
else
{
array[i] = 0;
}
}
Let t be the target number of non-zero elements in the array, which should be much less than the length of the array for sparseness. I'm assuming your array is of length length. I'm also generating the random indices without the modulus operator to avoid modulo bias.
for (i = 0; i < t; ++i) {
int index = (int) (length * ((double) rand() / (RAND_MAX + 1.0)));
array[index] = i % 2 ? -1 : 1;
}
Note that this may give a few less than t non-zero elements because random numbers can produce duplicates, but that should be rare if it really is sparse, e.g., t < square root of the array length. If you're worried about duplicate randoms making things sparser than you want, you can modify accordingly:
for (i = 0; i < t;) {
int index = (int) (length * ((double) rand() / (RAND_MAX + 1.0)));
if (array[index]) { /* something already at this index */
continue; /* skip incrementing and try again */
}
array[index] = i % 2 ? -1 : 1;
++i;
}
In both cases I'm alternating +/- ones for the non-zero values, but if you want it more random that would be easy to replace the right-hand side of the assignment of array[index].
Finally, I ask your indulgence if I fluffed something on C syntax. My C is about 15 years rusty, but the intent should be clear.

Combinations based on 2 variables

What I'm trying to accomplish is making a function to the following:
Imagine that I have between 1-9 squares. Those squares have a number assigned to them globally, not individually. They are like a set, and that set has this number.
E.g.: | _ | _ | _ | 19
What I'm trying to do is a function that gives me the possible combinations depending on number of squares and the number associated with them. For the example above: 9, 8, 2 is one of the possible combinations. However I just want the numbers that are in those combinations, not the combinations themselves. Plus they have to be unique (shouldn't be 9, 9, 1). Oh and those numbers range from 1-9 only.
How can I achieve this in C? If you are wondering this is for a puzzle game.
Thanks in advance!
Looks like you are trying to find a restricted Partition of the integer on the right. The link should give you a good starting place, and you should be able to find some algorithms that generate partitions of an integer into an arbitrary number of parts.
For future reference, in combinatorics we say "order doesn't matter" to mean "I only want the set of numbers, not a specific ordering"
//Sets the given digit array to contain the "first" set of numbers which sum to sum
void firstCombination(int digits[], int numDigits, int sum) {
reset(digits, 0, 1, numDigits, sum);
}
//Modifies the digit array to contain the "next" set of numbers with the same sum.
//Returns false when no more combinations left
int nextCombination(int digits[], int numDigits) {
int i;
int foundDiffering = 0;
int remaining = 0;
for (i = numDigits - 1; i > 0; i--) {
remaining += digits[i];
if (digits[i] - digits[i - 1] > 1) {
if (foundDiffering || digits[i] - digits[i - 1] > 2) {
digits[i - 1]++;
remaining--;
break;
} else
foundDiffering = 1;
}
}
if (i == 0)
return 0;
else {
reset(digits, i, digits[i - 1] + 1, numDigits - i, remaining);
return 1;
}
}
//Helper method for firstCombination and nextCombination
void reset(int digits[], int off, int lowestValue, int numDigits, int sum) {
int i;
int remaining = sum;
for (i = 0; i < numDigits; i++) {
digits[i + off] = lowestValue;
remaining -= lowestValue;
lowestValue++;
}
int currentDigit = 9;
for (i = numDigits + off - 1; i >= off; i--) {
if (remaining >= currentDigit - digits[i]) {
remaining -= currentDigit - digits[i];
digits[i] = currentDigit;
currentDigit--;
} else {
digits[i] += remaining;
break;
}
}
}
It sounds like what you're working on is very similar to kakuro, also know as Cross Sums: http://en.wikipedia.org/wiki/Cross_Sums
There are generators out there for these kinds of puzzles, for example: http://www.perlmonks.org/?node_id=550884
I suspect that most kakuro generators would have to solve your exact problem, so you might look at some for inspiration.

Resources