is there a way to use Arrays in this C problem? - arrays

I am doing this problem:
"We have a huge decimal number N. Write a program to determine the followings:
The number of digits in N.
Is N an even number?
The number of zeros in it.
Is N a multiple of 11? Note that we can determine if N is a multiple of 11 by checking the difference between the sum of the odd positioned digits and the sum of the even positioned digits. For example, 82375 is not a multiple of 11 because the sum of the even positioned digits is 2 + 7 = 9, and the sum of the odd positioned digits is 8 + 3 + 5 = 16, and the difference between 9 and 16 is 7, which is not a multiple of 11.
We will give you the number one digit per line. For example, if you get digits ‘1’, ‘2’, ‘3’, ’4’, ‘0’ in order, then the number is 12340. The number will not start with 0.
Input Format
The input has several lines. Each line has a digit. EOF indicates the end of input.
Output Format
Output the four answers above line by line. If the number is even output a 1; otherwise a 0. If the number is a multiple of 11 output a 1; otherwise output a 0.
Subtask
10 points: you can store the decimal number in an integer without overflow
10 points: the number of digits is no more than 32768, so you can store digits in an array
80 points: you will get MLE if you use array"
my code is:
#include <stdio.h>
#include <stdbool.h>
int digit(long n);
int is_even(int n);
int count_zeros(long n);
int is_multiple(long n);
int main() {
int digits = 0;
long x;
scanf("%ld", &x);
digit(x);
int even = is_even(x);
printf("%d\n", even);
printf("%ld\n",count_zeros(x));
printf("%ld\n", is_multiple(x));
}
int digit(long n)
{
int digits = 0;
while (n > 0) {
n /= 10;
digits++;
}
printf("%ld\n", digits);
}
int is_even(int n)
{
if (n % 2 == 0)
return true;
else
return false;
}
int count_zeros(long n)
{
int count = 0;
while (n > 0) {
n /= 10;
if (n %10 == 0)
count++;
}
return count;
}
int is_multiple(long n)
{
if (n % 11 == 0) {
return true;
}
else
return false;
}
Basically i dont know how to meet the problem's requirement, so I made a simpler version of the problem. Any clue on how to do this?
If you comment on this, please be nice, I am a beginner and people was rude in the past,if you have nothing important to say, do not be mean/do not comment.

Well, the first problem with your current version is it only reads one integer. However problem states that each digit is on a separate line. The first approach may be to just replace that scanf with a loop and keeping multiplying by 10 and accumulating until end of file. Then the rest of the program would work fine.
A more advanced approach will be to use an array to store the digits. An integer can hold a very limited number of digits whereas you are only bounded with the size of available memory using array.
So in the reading loop rather than storing digits in an integer, you can store digits in an array (which could be fixed size because an upper limit is given). But for the rest of the program you should change the calculation to use digits in the array instead of the regular integer arithmetic.

Related

Finding Number of pages from the total number of digits used to number the pages

I am stuck in a problem where the user inputs the total number of digits used in numbering the pages and the program gives the total number of pages in the book.
(i.e. a book of 10 pages needs 11 digits to number because the numbers 1-9 are written with one digit and the number 10 is written with two digits; an 11 pages book requires 13 digits ...).
I tried it by using a while loop but it does not run as it exceeds the execution time.
My C code looks like this:
#include <stdio.h>
int main() {
int n, pages = 9;
scanf("%d", &n);
if (n <= 9) {
printf("%d",n);
}
else if (n % 2 == 0) {
printf("Invalid input");
}
else {
while (n < 9) {
pages++;
n -= 2;
}
}
return 0;
}
Can anyone please help me with this problem?
Consider using successive tests like this:
if the number <= 9, the number of pages is number, else set pages = 9 and subtract 9 from number.
if the number <= 90 * 2, the number of pages is pages + number / 2, else set pages += 90 and subtract 90 * 2 from number.
if the number <= 900 * 3, the number of pages is pages + number / 3, else set pages += 900 and subtract 900 * 3 from number.
etc.
You can write a loop to solve the problem without making an assumption on the range of the type used to store number and pages.
int number_of_pages(int number_of_digits) {
int n1 = 9, n2 = 1, pages = 0;
while (number / n2 > n1) {
pages += n1;
number -= n1 * n2;
n1 *= 10;
n2 += 1;
}
return pages + number / n2;
}
else if(n%2==0)
{
printf("Invalid input");
}
Please note that there are books with more than 100 pages:
A book with 102 pages has 198 digits!
while(n!=0)
{
pages++;
n-=2;
}
This loop will run forever:
Because n is initially an odd number, n-2 is also odd. So n will always be odd (maybe negative) if n-=2 is the only instruction that modifies n. n cannot become 0, so the loop will run forever.
You also have to consider that books with more than 100 pages or with more than 1000 pages may exist.
I would do it the other way round and count pages up from 1 to N. I would sum up the digits required for the given number of pages and stop when the number of digits is exceeded:
int n, pages=0, digits=0;
int realdigits=0, neededdigits, tooLarge;
/* "realdigits" is the number of digits required
* by "pages" pages; loop until
* "realdigits" >= "digits" */
while(realdigits < digits)
{
pages++;
/*
* Add some code that calculates:
* neededdigits = Number of digits required by
* the number "pages"
*/
realdigits += neededdigits;
}
/* Case: "(pages-1)" pages need less digits
* than "digits" but "pages" pages need more
* digits... */
if(realdigits > digits)
{
printf("Invalid number\n");
}
else
{
printf("%d pages\n", pages);
}
I would use a loop based on a condition to calculate the number of digits required by the number pages:
neededdigits = 1;
tooLarge = 10; /* Number that is too large for digits */
while(pages >= tooLarge)
{
neededdigits++;
tooLarge *= 10;
}
Note that in "C-like" programming languages (C, C++, Java, C#, PHP ...) you may use the for keyword for "condition-based" loops ...
In your posts body you do not ask a question (apart from "Can somebody help me?", which is not considered a question here). In your comments you ask for the main() function, or the logic, or the pseudo code. Sorry, that is not how StackOverflow is meant to be used.
But finally you ask how to arrive at the needed formula.
With How do I ask and answer homework questions? in mind I will help you with that.
make a table of the simplest case (1,2,3,4,5,6,7,8,9) pages and digits, the same
find the formula for that
check the next complex case (10,11,12,13,14,...99) pages and digits, there is a very simple relation
consider which influence the pages 1...9 have on the formula, think offset
consider the next complex case (100, 101, .... 999)
and proceed to the mentioned limit of 2 billion pages
No loops! Uses log10() and pow() from math library.
Based on formula found on OEIS A058183: "Number of digits in concatenation of first n positive integers."
#include <math.h>
int digits_for_pages(unsigned n) {
// oeis A058183
return (n+1)*floor(log10(10*n)) - (pow(10, floor(log10(10*n)))-1)/(10-1);
}
https://ideone.com/7GJYXq

why my answer is only partially accepted in a hackerearth practice problem

Problem:
You are provided an array A of size N that contains non-negative integers. Your task is to determine whether the number that is formed by selecting the last digit of all the N numbers is divisible by 10.
Note: View the sample explanation section for more clarification.
Input format
First line: A single integer N denoting the size of array Ai.
Second line: N space-separated integers.
Output format:
If the number is divisible by 10 , then print Yes . Otherwise, print No.
Constraints:
1<=N<=100000
0<=A[i]<=100000
i have used int, long int ,long long int as well for declaring N and 'm'.But the answer was again partially accepted.
#include <stdio.h>
int main() {
long long int N,m,i;
scanf("%ld", &N);
long data[N];
for(auto i=0; i<N; i++) {
scanf("%ld", &data[i]);
}
// write your code here
// ans =
m=(data[0]%10);
for(i=1; i<N; i++) {
m=m*10;
m=(data[i]%10)+m;
}
if(m%10!=0 && m==0) {
printf("Yes");}
else{
printf("No");
}
return 0;
}
Try making a test suite, that is, several tests for which you know the answer. Run your program on each of the tests; compare the result with the correct answer.
When making your tests, try to hit also corner cases. What do I mean by corner cases? You have them in your problem statement:
1<=N<=100000
0<=A[i]<=100000
You should have at least one test with minimal and maximal N - you should test whether your program works for these extremes.
You should also have at least one test with minimal and maximal A[i].
Since each of them can be different, try varying them - make sure your program works on the case where some of the A[i] are large and some are small.
For each category, include tests for which the answer is Yes and No - to exclude the case where your algorithm always outputs e.g. Yes by mistake.
In general, you should try to make tests which challenge your program - try to prove that it has a bug, even if you believe it's correct.
This code overflows:
m=(data[0]%10);
for(i=1; i<N; i++) {
m=m*10;
m=(data[i]%10)+m;
}
For example, when N is 1000, and each of the input items A[i] (scanned into data[i]) ends in 9, this attempts to compute m = 99999…99999, which grossly overflows the capability of the long long m.
To determine whether the numeral formed by concatenating a sequence of digits is divisible by ten, you merely need to know whether the last digit is zero. The number is divisible by ten iff data[N-1] % 10 == 0. You do not even need to store these numbers in an array; simply use scanf to read but ignore N−1 numerals (e.g., scanf("%*d")), then read the last one and examine its last digit.
Also scanf("%ld", &N); wrongly uses %ld for the long long int N. It should be %lld, or N should be long int.
An integer number given in decimal is divisible by ten if, and only if, its least significant digit is zero.
If this expression from your problem:
the number that is formed by selecting the last digit of all the N numbers
means:
a number, whose decimal representation comes from concatenating the least significant digits of all input numbers
then the last (the least significant) digit of your number is the last digit of the last input number. And that digit being zero is equivalent to that last number being divisible by 10.
So all you need to do is read and ignore all input data except the last number, then test the last number for divisibility by 10:
#include <stdio.h>
int main() {
long N, i, data;
scanf("%ld", &N);
for(i=0; i<N; i++)
scanf("%ld", &data); // scan all input data
// the last input number remains in data
if(data % 10 == 0) // test the last number
printf("Yes");
else
printf("No");
return 0;
}

How do I write a program to find the number of binary strings of length n containing exactly three 1s, all consecutive

I've followed a dynamic programming approach here.
dp(i,x) :denotes number of strings of length i with x consecutive 1s in position i + 1 to i + x.
n here is the length of the bit string taken as input from the user
However, I think I'm counting strings that have more than 3 consecutive ones as well maybe?
EDIT: Just to clarify
I am looking for strings with exactly 3 1s. For eg: 111000 is a valid string whereas 1110101111 and 10101000 are not.
#include<stdio.h>
#include<stdlib.h>
int solve(int i,int x,int **arr)
{
if(i<0)
return x==3;
if(arr[i][x]!=-1)
return arr[i][x];
arr[i][x] = solve(i-1,0,arr);
arr[i][x]+=solve(i-1,x+1,arr);
return arr[i][x];
}
int main()
{
int n;
scanf("%d",&n);
int **arr = (int**)malloc(n*sizeof(int*));
for(int i=0;i<n;i++)
arr[i] = (int*)malloc(4*sizeof(int));
for(int i=0;i<n;i++)
for(int j=0;j<4;j++)
arr[i][j]=-1;
for(int i=0;i<n;i++)
arr[i][3] = (1<<(i+1));
printf("%d",solve(n-1,0,arr));
return 0;
}
Your DP state [i][x] means - number of binary strings of length i that have x bits in ending, so you're also counting strings like 11110111.
You need to take into account groups of 3 that are not suffixes, for that you can update dp state as follows: [i][x][y] - number of binary strings of length i that have x bits in ending and a maximum y consecutive bits.
Code modification is quite minimal:
int solve(int i,int x, int y, int ***arr)
{
if(y > 3) return 0;
if(i<0) return y==3;
if(arr[i][x][y]!=-1) return arr[i][x][y];
arr[i][x][y] = solve(i-1,0,y,arr);
arr[i][x][y]+=solve(i-1,x+1,max(x+1,y),arr);
return arr[i][x][y];
}
I'm not sure if I have well understood your question:
The question is not : "What are all the binary numbers, containing exactly three consecutive ones?", but just: "What's the number of the binary numbers, containing exactly three consecutive ones?".
If you are just interested in the number, you might just calculate it by heart:
1110xxxxx (total length : N) : amount of such numbers : 2^(N-4) [(N-4) digits with 2 possibilities)]
xx01110xx (total length : N) : amount of such numbers : 2^(N-5)*(N-5)
[(N-5) digits with 2 possibilities]
[(N-5) places to put the '01110']
xxxxx0111 (total length : N) : amount of such numbers : 2^(N-4) [(N-4) digits with 2 possibilities]
Solution : 2*2^(N-4) + 2^(N-5)*(N-5)
(I didn't check completely, forgive me if this contains errors)
If you're not sure that you really need to generate all of them, then doing the calculation might actually be a better (and much faster) solution.

how to iterate over a number to get every other digit

For a homework program we are asked to check if credit card numbers are valid.
While I am fairly sure about how I want to solve this problem I am stuck with iterating over a creditcard number and getting every second digit.
I already know that I need to use modulo and division and I do get the second to last number, but I am lost at how to iterate over the rest of the numbers.
In the code is the code I used to check that I did indeed get the second to last number, and after that some code I tried to use to iterate over the complete number. Hope somebody could show me in the right direction!
long number = 378282246310005;
int digit;
int cc_number;
cc_number = number % 10;
digit = cc_number / 10;
printf("%i\n", digit);
while (number > 0)
{
digit += number % 10;
number /= 10;
printf("%li", number);
}
printf("\n");
Before your while loop you reversed the last digit and the remaining number.
number % 10 is the last digit, number / 10 is the remaining number.
Adding to digit doesn't make sense if the variable is intended to contain a single digit. (You may need to add the digits for a validity check.)
Example code to extract all digits and their positions:
#include <stdio.h>
int main(void)
{
long number = 378282246310005;
int digit;
int position = 0;
printf("%li\n", number);
while (number > 0)
{
digit = number % 10;
number /= 10;
printf("(%i) %i ", position, digit);
position++;
}
printf("\n");
return 0;
}
This prints
378282246310005
(0) 5 (1) 0 (2) 0 (3) 0 (4) 1 (5) 3 (6) 6 (7) 4 (8) 2 (9) 2 (10) 8 (11) 2 (12) 8 (13) 7 (14) 3
To select every other digit you could check position % 2 or toggle a variable between 0 and 1 in every loop cycle.
Edit:
Explanation as requested in ron_g's comment: "Why's it printing out the digits in reverse?"
The loop separates the last digit from the remaining part of the number, so it prints the last digit first. Then it repeats the same with the remaining part as long as the remaining number is not 0.
The answer keeps the original implementation from the question which is based on storing the number as a long int. In this case it is easier to start with the last digit. When the number would be stored as a string it would be easier to start with the first digit.
/* number is initially the whole number or the remaining part */
while (number > 0)
{
/* remainder of division by 10 is the last digit */
digit = number % 10;
/* division by 10 is the remaining part after cutting off the last digit */
number /= 10;
printf("(%i) %i ", position, digit);
position++;
}

Display number in vertical format [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I'm new to C. I have a class assignment to display a number in a vertical format. If the user enters 5678, the instructor want it to display vertically to the screen in a single column as:
8
7
6
5
Second part of assignment is to find the largest divisor of the same number.
I'm totally lost. I'm getting the NUM value from another function. formula seems to work on even numbers, but on odd.
int divisor (int NUM)
{
int index, count=0;
for(index=2;index<=(NUM/2);index=index+1)
{
if(NUM%index==0)
count++;
}
printf("\n\nThe largest divisor of %d is %d\n",NUM, index-1);
return(index);
}
To display the number vertically:
1. get least significant digit,
2. print it and print new line,
3. shift number to the right by one digit
4. goto 1
Algorithm terminates when the number is zero. Call the input number n; getting the least significant (rightmost) digit can be done with n % 10. Right shift can be done with n = n / 10.
For the second part, observe that the largest divisor cannot be more than n/2 (because n = 2 * n/2). So try all number from n/2 down to 1 and break once you find a divisor. You will find the largest divisor because you are considering numbers in decreasing order. To check that x divides y use y % x == 0.
A second way it to check numbers from sqrt(n) down to 1. If m divides n, we can write n = m * k for some k. Now you take max(m, n/m) and continue.
Hope this helps :)
For the first part, there are many ways to approach this. But, without using too many of the standard library functions which seems to be a level appropriate for the question, I think the easiest way would be to take the numbers as a character array. Then access each value through it's index in the character array. This requires only the stdio.h header file. Some quick notes: simply use printf to print the value contained at each index, and throw the newline \n character at the end. If you wanted convert the string to an integer, you can do that very easily using the function atoi() which can be found in stdlib.h. If you want to print out backward, you can simply traverse the array backward.
void displayvert(char str[])
{
int i;
for (i = 0; str[i] != '\0'; ++i) {
printf("%c\n", str[i]);
}
}
Also many ways to approach the second, but in this case for the second question I think I'd use the modulus operator and track the highest value where the result is zero. In order for this to work with the single user provided input, I actually needed atoi() which is in the stdlib.h header. Basically, starting from the value one you'll increase the value up the integer just below the value of 'num' itself. And, if the remainder is zero when you when you divide by it (the purpose of using the modulus operator) then you know it's divisible. Because we're ascending from 1 to the number itself, the last value to return a remainder of zero is the greatest common divisor.
void getgcd(int num)
{
int i, gcd;
// remember, you can't do x % 0!
for (i = 1; i < num; i++) {
if ((num % i) == 0 ) {
gcd = i;
}
}
printf("The greatest common divisor is: %d\n", gcd);
}
Main function and prototypes here so you can see how it all tied together. A couple of quick notes (1) 11 digits was arbitrary; but it's important to note that we used 10 digits for the total input value (you can add checks to this to enforce) and reserved the 11th (at index 10) to allow space for the null terminating character \0. (2) Use scanf to grab input; note that because character arrays do not require the address operator & because it defaults to that.
#include <stdio.h>
#include <stdlib.h>
void displayvert(char str[]);
void getgcd(int num);
int main()
{
char input[11]; // additional character added for \0
printf("Please enter a value up to 10 digits: ");
scanf("%s", input);
displayvert(input);
getgcd(atoi(input));
return 0;
}

Resources