C Arrays and unbroken lists - c

/edit: thanks for the help so far, however I haven't got any of the solutions to take the sample input and give the sample output. My description isn't the clearest, sorry.
I have an array composed of binary data. What I want to do is determine how long each unbroken segment of 1s or 0s is.
Say I have this data:
0111010001110
In an array binaryArray which I need to translate to:
0100110
stored in nwArray where 0 represents a narrow (less than 3 digits long) and 1 represents wide (>3 digits long). I am not concerned with the binary value but with the length of each component. I'm not sure if that explanation makes sense.
This is what I have; it doesn't work, I can see why, but I can't think of a good solution.
for(x=0;x<1000;x++){
if(binaryArray[x]==binaryArray[x+1]){
count++;
if(count>=3){
nwArray[y]=1;
y++;
count=0;
}
}else{
if(barcodeArray[x]){
nwArray[y]=0;
}
}
}

Does this do it?
int count = 0;
for (x=0; x<1000;x++)
{
if (binaryArray[x] != binaryArray[x+1])
{
if (count < 3)
nwArray[y]=0;
else
nwArray[y]=1;
y++;
count = 0;
}
else
count++;
}

One problem you have is that you compare count with 3 too early. Wait until you see a change in the bitstream. Try a while loop until the bit flips then compare the count.

Modified #MikeW's answer:
int count = 0;
int nwSize = 0;
const int ilast = SIZEOF(binaryArray) - 1;
for (int i = 0; i <= ilast; ++i)
if (i == ilast || binaryArray[i] != binaryArray[i+1]) {
nwArray[nwSize++] = (count > 1); /* true for '1110'; false for '110' */
count = 0;
}
else
++count;
assert(count == 0);

Related

How do I generate 4 random variables and only printing if it doesn't contain the int 0

this is my code, I want to make a function that when it is called will generate a number between 1111 to 9999, I don't know how to continue or if I've written this right. Could someone please help me figure this function out. It suppose to be simple.
I had to edit the question in order to clarify some things. This function is needed to get 4 random digits that is understandable from the code. And the other part is that i have to make another function which is a bool. The bool needs to first of get the numbers from the function get_random_4digits and check if there contains a 0 in the number. If that is the case then the other function, lets call it unique_4digit, should disregard of that number that contained a 0 in it and check for a new one to use. I need not help with the function get_random_4digitsbecause it is correct. I need helt constructing a bool that takes get_random_4digits as an argument to check if it contains a 0. My brain can't comprehend how I first do the get_random_4digit then pass the answer to unique_4digits in order to check if the random 4 digits contains a 0 and only make it print the results that doesn't contain a 0.
So I need help with understanding how to check the random 4 digits for the integer 0 and not let it print if it has a 0, and only let the 4 random numbers print when it does not contain a 0.
the code is not suppose to get more complicated than this.
int get_random_4digit(){
int lower = 1000, upper = 9999,answer;
answer = (rand()%(upper-lower)1)+lower;
return answer;
}
bool unique_4digits(answer){
if(answer == 0)
return true;
if(answer < 0)
answer = -answer;
while(answer > 0) {
if(answer % 10 == 0)
return true;
answer /= 10;
}
return false;
}
printf("Random answer %d\n", get_random_4digit());
printf("Random answer %d\n", get_random_4digit());
printf("Random answer %d\n", get_random_4digit());
Instead of testing each generated code for a disqualifying zero just generate a code without zero in it:
int generate_zero_free_code()
{
int n;
int result = 0;
for (n = 0; n < 4; n ++)
result = 10 * result + rand() % 9; // add a digit 0..8
result += 1111; // shift each digit from range 0..8 to 1..9
return result;
}
You can run the number, dividing it by 10 and checking the rest of it by 10:
int a = n // save the original value
while(a%10 != 0){
a = a / 10;
}
And then check the result:
if (a%10 != 0) printf("%d\n", n);
Edit: making it a stand alone function:
bool unique_4digits(int n)
{
while(n%10 != 0){
n = n / 10;
}
return n != 0;
}
Usage: if (unique_4digits(n)) printf("%d\n", n);
To test if the number doesn't contain any zero you can use a function that returns zero if it fails and the number if it passes the test :
bool FourDigitsWithoutZero() {
int n = get_random_4digit();
if (n % 1000 < 100 || n % 100 < 10 || n % 10 == 0) return 0;
else return n;
}
"I need not help with the function get_random_4digits because it is correct."
Actually the following does not compile,
int get_random_4digit(){
int lower = 1000, upper = 9999,answer;
answer = (rand()%(upper-lower)1)+lower;
return answer;
}
The following includes modifications that do compile, but still does not match your stated objectives::
int get_random_4digit(){
srand(clock());
int lower = 1000, upper = 9999,answer;
int range = upper-lower;
answer = lower + rand()%range;
return answer;
}
" I want to make a function that when it is called will generate a number between 1111 to 9999,"
This will do it using a helper function to test for zero:
int main(void)
{
printf( "Random answer %d\n", random_range(1111, 9999));
printf( "Random answer %d\n", random_range(1111, 9999));
printf( "Random answer %d\n", random_range(1111, 9999));
printf( "Random answer %d\n", random_range(1111, 9999));
return 0;
}
Function that does work follows:
int random_range(int min, int max)
{
bool zero = true;
char buf[10] = {0};
int res = 0;
srand(clock());
while(zero)
{
res = min + rand() % (max+1 - min);
sprintf(buf, "%d", res);
zero = if_zero(buf);
}
return res;
}
bool if_zero(const char *num)
{
while(*num)
{
if(*num == '0') return true;
num++;
}
return false;
}

How to properly make a counting algorithm to count from file?

This is a program to find the largest even number and its times of occurring from an input file and output it to an output file. I'm having a problem with the output, there seems to be an extra iteration that messes things up.
int main(int argc, char const *argv[])
{
int n, num, i, even, count;
FILE * fptr;
FILE * fptro;
fptr =fopen("maximpar.in", "r");
fptro=fopen("maximpar.out", "w");
/*scanning the first line from the file to get n for for()*/
fscanf(fptr, "%d", &n);
count = 0;
even = INT_MIN;
for(i = 0; i < n; i++)
{
fscanf(fptr, "%d", &num);
if( (num % 2 == 0 && num > even) || (even == num) )
/*checking for largest even number,
not sure about the ..||(even == num) part of the condition*/
{
even = num;
count++;
}
}
fprintf(fptro, "%d %d", even, count);
fclose(fptr);
fclose(fptro);
return 0;
}
Input file
6
9 6 9 8 9 8
Output file
8 3
Why isn't the output file like this? I don't understand
8 2
You need to reset your count whenever you get a new larger number.
I didn't test this, but it should work:
cate = 0;
par = INT_MIN;
for (i = 0; i < n; i++) {
fscanf(fptr, "%d", &b);
// skip odd numbers
if ((b % 2) != 0)
continue;
// get new larger number
if (b > par) {
par = b;
cate = 1;
continue;
}
// increment count on existing largest number
if (b == par)
++cate;
}
UPDATE:
I dont understand why skip iterations explicitly instead of only picking out the iterations that matter? Is there some sort of advantage?
Yes, it's better style. It allows simple single level indented if statements that can have their own comments.
It avoids a messy compound if or a triple level if/else ladder.
IMO, it's a common misconception [particularly among beginning C programmers] that a complex if will execute faster [or is somehow "better"] than several simple ones.
The first if could be thought of a "skip this iteration" test. Here, there's only one. But, for more complex code, there might be several.
The multiple condtion escapes could be handled in a single if with if (c1 || c2 || c2 || ... || c10) continue; but that gets messy fast.
Herein, for properly indented if/else ladder logic, we'd need:
if (cond1)
do_stuff1;
else
if (cond2)
do_stuff2;
else
if (cond3)
do_stuff3;
If we're not in a loop, here's a "trick" to avoid if/else ladder logic, by using do { ... } while (0);:
do {
if (cond1) {
do_stuff1;
break;
}
if (cond2) {
do_stuff2;
break;
}
if (cond3) {
do_stuff3;
break;
}
} while (0);
enclose the condition
if( ( ...&&...) ||(....) )
The answer is because count was incremented from 0 to 1 when b = 6. 2 iterations later, b = 8 and now count = 2, and 2 iterations after that, b = 8 and count = 3.
I also recommend you nest your if statement in parentheses for readability. Commenting would help too :) I'm a stats guy, and I have no idea what you are doing based on your variables' names.
You need to reset your counter inside the if block if b > par.
Like:
if( num % 2 == 0 && num >= even) {
if (num > even){
even = num;
count = 1;
} else {
count++;
}
}
Thanks.
JK

Need some suggestions on how to print a histogram more neatly

I'm writing a program that will read input and then give back a histogram of the character count from K & R - Ex. 1.13
Any suggestions on how I can improve my code? Does it matter whether or not if I test for status in condition or out first? I have noticed in my examples people test to see if c is a blank or tab first.
I think I need to revisit my histogram. It doesn't really scale the results. It just draws a hyphen based on the length.
Revised to make a little bit more readable I think.
// Print a histogram of the length of words in it's input.
#include <stdio.h>
#define IN 1
#define OUT 2
#define MAX 99
int main(){
int c; // the character
int countOfLetters = 0;
int insideWord = OUT;
int frequencyOfLengths[MAX];
int longestWordCount = 0;
int i, j; // Counters
for (i = 0; i < MAX; i++){
frequencyOfLengths[i] = 0;
}
while ((c = getchar()) != EOF){
if (c == ' ' || c == '\n' || c == '\t'){
if (insideWord == IN){
if (countOfLetters > MAX){
return 1;
}
++frequencyOfLengths[countOfLetters];
if (countOfLetters >= longestWordCount) longestWordCount = countOfLetters;
}
countOfLetters = 0;
}
else {
countOfLetters++;
insideWord = IN;
}
}
for (i = 1; i <= longestWordCount; i++){
printf("%3i : %3i ", i, frequencyOfLengths[i]);
for (j = 0; j < frequencyOfLengths[i]; j++){
printf("*");
}
printf("\n");
}
return 0;
}
Definitely scale results, check out my Character Histogram that does a horizontal scaling histogram.
Also, you could benefit a y-axis label. It's hard to tell which bar is for which kind of word length. I have no idea which bar is for what word length.
I added this code right before you display the histogram, it basically halves every value, which does throw off your bar number labels. You can figure it out!
// Iterates and tells us the most frequent word length
int mostFrequent = 0;
for (i = 1; i < MAXWORD; i++)
if (charCount[i] > mostFrequent)
mostFrequent = charCount[i];
// If the bar will be too big, cut every value in half
while (mostFrequent > 60) {
for (i = 1; i < MAXWORD; i++)
if (charCount[i] > 0) {
charCount[i] /= 2;
charCount[i] |= 1;
}
// Check again to find the most frequent word length category
mostFrequent = 0;
for (i = 1; i < MAXWORD; i++)
if (charCount[i] > mostFrequent)
mostFrequent = charCount[i];
}
Honestly the bars are hard to read, maybe just use a single row of characters such as █ !
Great book so far, we're practically reading it together and are on the same page!
Cheers

Counting number of strings in hash table

So, I am trying to count the number of strings present in my hash table. For some reason, this function always returns 0. I have tried re-writing it a couple of times in slightly different ways to find an error in the logic, but, as far as I know, this function should output the number of entries in the table. I would really appreciate some help, as this has become very frustrating! Thanks!
/* htbl_n_entries : htbl* -> unsigned int */
/* return the number of entries in all buckets */
unsigned int htbl_n_entries(htbl *t){
int i;
int nbucks = t->n_buckets;
sll**bucks= t->buckets;
unsigned int sum = 0;
for (i = 0; i < nbucks; ++i)
{
while(bucks[i] != NULL){
sum++;
bucks[i] = bucks[i]->next;
}
}
return sum;
}
The while in your code will set to NULL each bucks[i]. Try:
sll**bucks= t->buckets;
unsigned int sum = 0;
for (i = 0; i < nbucks; ++i)
{
sll*bucks_= bucks[i];
while(bucks_ != NULL){
sum++;
bucks_ = bucks_->next;
}
}
This is just one error, but do not explain why return 0. It correctly count the first time, but any other time will be 0. My gess is that you have simmilar error in other functions and at this point your table is allready broken.

Optimizing I/O(Output) in C code + a loop

I have a code which reads around (10^5) int(s) from stdin and then after performing ## i output them on stdout. I have taken care of the INPUT part by using "setvbuf" & reading lines using "fgets_unlocked()" and then parsing them to get the required int(s).
I have 2 issues which i am not able to come over with:
1.) As i am printing int(s) 5 million on stdout its taking lot of time : IS THERE ANY WAY TO REDUCE THIS( i tried using fwrite() but the o/p prints unprintable characters due to the reason using fread to read into int buffer)
2.) After parsing the input for the int(s) say 'x' i actually find the no of divisors by doing %(mod) for the no in a loop.(See in the code below): Maybe this is also a reason for my code being times out:
Any suggestions on this to improved.
Many thanks
This is actually a problem from http://www.codechef.com/problems/PD13
# include <stdio.h>
# define SIZE 32*1024
char buf[SIZE];
main(void)
{
int i=0,chk =0;
unsigned int j =0 ,div =0;
int a =0,num =0;
char ch;
setvbuf(stdin,(char*)NULL,_IOFBF,0);
scanf("%d",&chk);
while(getchar_unlocked() != '\n');
while((a = fread_unlocked(buf,1,SIZE,stdin)) >0)
{
for(i=0;i<a;i++)
{
if(buf[i] != '\n')
{
num = (buf[i] - '0')+(10*num);
}
else
if(buf[i] == '\n')
{
div = 1;
for(j=2;j<=(num/2);j++)
{
if((num%j) == 0) // Prob 2
{
div +=j;
}
}
num = 0;
printf("%d\n",div); // problem 1
}
}
}
return 0;
}
You can print far faster than printf.
Look into itoa(), or write your own simple function that converts integers to ascii very quickly.
Here's a quick-n-dirty version of itoa that should work fast for your purposes:
char* custom_itoa(int i)
{
static char output[24]; // 64-bit MAX_INT is 20 digits
char* p = &output[23];
for(*p--=0;i/=10;*p--=i%10+0x30);
return ++p;
}
note that this function has some serious built in limits, including:
it doesn't handle negative numbers
it doesn't currently handle numbers greater than 23-characters in decimal form.
it is inherently thread-dangerous. Do not attempt in a multi-threaded environment.
the return value will be corrupted as soon as the function is called again.
I wrote this purely for speed, not for safety or convenience.
Version 2 based on suggestion by #UmNyobe and #wildplasser(see above comments)
The code execution took 0.12 seconds and 3.2 MB of memory on the online judge.
I myself checked with 2*10^5 int(input) in the range from 1 to 5*10^5 and the execution took:
real 0m0.443s
user 0m0.408s
sys 0m0.024s
**Please see if some more optimization can be done.
enter code here
/** Solution for the sum of the proper divisor problem from codechef **/
/** # author dZONE **/
# include <stdio.h>
# include <math.h>
# include <stdlib.h>
# include <error.h>
# define SIZE 200000
inline int readnum(void);
void count(int num);
int pft[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709};
unsigned long long int sum[SIZE];
int k = 0;
inline int readnum(void)
{
int num = 0;
char ch;
while((ch = getchar_unlocked()) != '\n')
{
if(ch >=48 && ch <=57)
{
num = ch -'0' + 10*num;
}
}
if(num ==0)
{
return -1;
}
return num;
}
void count(int num)
{
unsigned int i = 0;
unsigned long long tmp =0,pfac =1;
int flag = 0;
tmp = num;
sum[k] = 1;
for(i=0;i<127;i++)
{
if((tmp % pft[i]) == 0)
{
flag =1; // For Prime numbers not in pft table
pfac =1;
while(tmp % pft[i] == 0)
{
tmp =tmp /pft[i];
pfac *= pft[i];
}
pfac *= pft[i];
sum[k] *= (pfac-1)/(pft[i]-1);
}
}
if(flag ==0)
{
sum[k] = 1;
++k;
return;
}
if(tmp != 1) // For numbers with some prime factors in the pft table+some prime > 705
{
sum[k] *=((tmp*tmp) -1)/(tmp -1);
}
sum[k] -=num;
++k;
return;
}
int main(void)
{
int i=0,terms =0,num = 0;
setvbuf(stdin,(char*)NULL,_IOFBF,0);
scanf("%d",&terms);
while(getchar_unlocked() != '\n');
while(terms--)
{
num = readnum();
if(num ==1)
{
continue;
}
if(num == -1)
{
perror("\n ERROR\n");
return 0;
}
count(num);
}
i =0;
while(i<k)
{
printf("%lld\n",sum[i]);
++i;
}
return 0;
}
//Prob 2 Is your biggesr issue right now.... You just want to find the number of divisors?
My first suggestion will be to cache your result to some degree... but this requires potentially twice the amount of storage you have at the beginning :/.
What you can do is generate a list of prime numbers before hand (using the sieve algorithm). It will be ideal to know the biggest number N in your list and generate all primes till his square root. Now for each number in your list, you want to find his representation as product of factors, ie
n = a1^p1 * a1^p2 *... *an^pn
Then the sum of divisors will be.
((a1^(p1+1) - 1)/(a1 - 1))*((a2^(p2+1) - 1)/(a2-1))*...*((an^(pn+1) - 1)/(an-1))
To understand you have (for n = 8) 1+ 2 + 4 + 8 = 15 = (16 - 1)/(2 - 1)
It will drastically improve the speed but integer factorization (what you are really doing) is really costly...
Edit:
In your link the maximum is 5000000 so you have at most 700 primes
Simple decomposition algorithm
void primedecomp(int number, const int* primetable, int* primecount,
int pos,int tablelen){
while(pos < tablelen && number % primetable[pos] !=0 )
pos++;
if(pos == tablelen)
return
while(number % primetable[pos] ==0 ){
number = number / primetable[pos];
primecount[pos]++;
}
//number has been modified
//too lazy to write a loop, so recursive call
primedecomp(number,primetable,primecount, pos+1,tablelen);
}
EDIT : rather than counting, compute a^(n+1) using primepow = a; primepow = a*primepow;
It will be much cleaner in C++ or java where you have hashmap. At the end
primecount contains the pi values I was talking about above.
Even if it looks scary, you will create the primetable only once. Now this algorithm
run in worst case in O(tablelen) which is O(square root(Nmax)). your initial
loop ran in O(Nmax).

Resources