keystroke generation - c

I have a scenario where i need to generate all possible keystrokes using numbers 2 to 9. The possible keystrokes should generate 2-git, 3-digit etc upto 32-digit numbers. can anybody tell me what is the best way to solve this problem.
Thanks,
Pdit

Start with some simple analysis to consider feasibility. One digit has 8 possible values. Two digits have 8 x 8. Etc. Now grab your calculator and compute 8 ^ 32.

You're looking at quite a bit of computation towards the higher end of that.
One possible way to do it would be to have an array as a place-holder for your digit sequence, increment either the highest or lowest index, check if it overflows and then "carry" it to the next index and do that until you overflow the poistion "at the other end". Start with the array filled with 2.

I'd take a simple recursive approach, here with characters, but you could build your numbers using other means as well..
in C:
#include <stdio.h>
void keystrokes(int x, int lo, int hi, char array[]) {
int i;
if (x > hi)
return;
if (x >= lo) {
array[x] = 0;
printf ("%s\n", array);
}
for (i = 2; i < 10; i++) {
array[x] = i+'0';
keystrokes (x+1, lo, hi, array);
}
}
int main(void)
{
char array[33];
keystrokes(0, 2, 32, array);
return 0;
}
It can be optimized a bit (for example, for all 32-digit numbers, it'll still make 10 extra recursive calls), but it'll still take forever to compute all possible combinations.

Related

Performing a sum between two arrays of digis

Had an interview today and I was asked the following question - given two arrays arr1 and arr2 of chars where they contain only numbers and one dot and also given a value m, sum them into one array of chars where they contain m digits after the dot. The program should be written in C. The algorithm was not important for them, they just gave me a compiler and 20 minutes to pass their tests.
First of all I though to find the maximum length and iterate through the array from the end and sum the values while keeping the carry:
int length = (firstLength < secondLength) ? secondLength : firstLength;
char[length] result;
for (int i = length - 1; i >= 0; i--) {
// TODO: add code
}
The problem is that for some reason I'm not sure what is the right way to perform that sum while keeping with the dot. This loop should just perform the look and not counter to k. I mean that at this point I thought just adding the values and at the end i'll insert another loop which will print k values after the dot.
My question is how should look the first loop I mentioned (the one that actually sums), I'm really got stuck on it.
The algorithm was not important
Ok, I'll let libc do it for me in that case (obviously error handling is missing):
void sum(char *as, char *bs, char *out, int precision)
{
float a, b;
sscanf(as, "%f", &a);
sscanf(bs, "%f", &b);
a += b;
sprintf(out, "%.*f", precision, a);
}
It actually took me a lot longer than 20 mins to do this. The code is fairly long too so I don't plan on posting it here. In a nutshell, the code does:
normalize the 2 numbers into 2 new strings so they have the same number of decimal digits
allocate a new string with length of longer of the 2 strings above + 1
add the 2 strings together, 2 digits at a time, with carrier
it is not clear if the final answer needs to be rounded. If not, just expand/truncate the decimals to m digits. Remove any leading zero if needed.
I am not sure whether this is the best solution or not but here's a solution and I hope it helps.
#include<stdio.h>
#include<math.h>
double convertNumber(char *arr){
int i;
int flag_d=0; //To check whether we are reading digits before or after decimal
double a=0;
int j=1;
for(i=0;i<arr[i]!='\0';i++){
if(arr[i] !='.'){
if(flag_d==0)
a = a*10 + arr[i]-48;
else{
a = a + (arr[i]-48.0)/pow(10, j);
j++;
}
}else{
flag_d=1;
}
}
return a;
}
int main() {
char num1[] = "23.20";
char num2[] = "20.2";
printf("%.6lf", convertNumber(num1) + convertNumber(num2));
}

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;
}

why < is much faster than !=?

Problem : Consider the following algorithm to generate a sequence of
numbers. Start with an integer n. If n is even, divide by 2. If n is
odd, multiply by 3 and add 1. Repeat this process with the new value
of n, terminating when n = 1. The input will consist of a series of
pairs of integers i and j, one pair of integers perline. All integers
will be less than 1,000,000 and greater than 0.
For each pair of
input integers i and j, output i, j in the same order in which they
appeared in the input and then the maximum cycle length for integers
between and including i and j. These three numbers should be separated
by one space, with all three numbers on one line and with one line of
output for each line of input.
sample input :
1 10
sample output:
1 10 20
so i wrote this :
#include <stdio.h>
#include <string.h>
struct line{int in1;int in2;int result;};
int cycle(int in);
int main(int argc, char *argv[]) {
int cycle(int in);
char c;
int firstIn=0;
struct line l[500] ;
int pointer=0;
while(2<3){
l[pointer].in1=0;
l[pointer].in2=0;
scanf("%u %u",&l[pointer].in1,&l[pointer].in2);
if(l[pointer].in1<1||l[pointer].in2<1){
break;
}
int maxCyc=0;
int j,m;
int min,max;
if(l[pointer].in1>l[pointer].in2){
max=l[pointer].in1;
min=l[pointer].in2;
}
else{
max=l[pointer].in2;
min=l[pointer].in1;
}
for(j=min;j<=max;j++){
m = cycle(j);
if(m>maxCyc)
maxCyc=m;
}
l[pointer].result=maxCyc;
printf("%d %d %d\n",l[pointer].in1,l[pointer].in2,l[pointer].result);
pointer++;
}
}
int cycle(int in){
int cyc = 1;
while(in>1){
if(in%2==0){
cyc++;
in=in/2;
}
else{
cyc++;
in=in*3+1;
}
}
return cyc;
}
Its completly ok but when you change while(in>1) in cycle method to while(in!=1) it gets much more slower. my question is why?!
Time when its while(in>1) : 0.683 sec
and when its while(in!=1) : I waited more than 5 min nothing
happened yet :)
for input : 1 1000000
there is no infinite loop or something because in cant get below 1 at all(for that it must be already 1) .
Best regards
When you call cycle with the input value 113383, the process eventually sets n to
827370449, and 3*827370449+1 is 2482111348, which is greater than the maximum signed int and is interpreted as -1812855948. So there's your first negative number where there should be no negative number.
If this process then eventually sets n to -2, it will loop infinitely between -2 and -1 from then on. There may be other loops I haven't considered.
If you were to use an unsigned int, there is a possibility (I haven't checked) that this too will overflow eventually, which will not result in a negative value but will result in an incorrect value, invalidating your results.
No matter what integer representation you use, it would probably be a good idea to compare n with (maximum-1)/3 at the top of each loop, where maximum is the largest possible positive value of your integer type, just to be sure you do not overflow.
As you told me it was a simple overflow problem thx everyone.
max int value is 2,147,483,647; So when i changed int cycle(int in) to int cycle(long long int in) my problem was solved.
i also figured it out that my first answer with while(in>1) was wrong.
When an integer overflow occurs,the value will go below 0 .That was the reason while(in!=1) was an infinte loop.
I was really tired that i didn't figure it out by myself. sorry for that :)

why runtime error on online judge?

I am unable to understand why i am getting runtime error with this code. Problem is every number >=6 can be represented as sum of two prime numbers.
My code is ...... Thanks in advance problem link is http://poj.org/problem?id=2262
#include "stdio.h"
#include "stdlib.h"
#define N 1000000
int main()
{
long int i,j,k;
long int *cp = malloc(1000000*sizeof(long int));
long int *isprime = malloc(1000000*sizeof(long int));
//long int *isprime;
long int num,flag;
//isprime = malloc(2*sizeof(long int));
for(i=0;i<N;i++)
{
isprime[i]=1;
}
j=0;
for(i=2;i<N;i++)
{
if(isprime[i])
{
cp[j] = i;
j++;
for(k=i*i;k<N;k+=i)
{
isprime[k] = 0;
}
}
}
//for(i=0;i<j;i++)
//{
// printf("%d ",cp[i]);
//}
//printf("\n");
while(1)
{
scanf("%ld",&num);
if(num==0) break;
flag = 0;
for(i=0;i<j&&num>cp[i];i++)
{
//printf("%d ",cp[i]);
if(isprime[num-cp[i]])
{
printf("%ld = %ld + %ld\n",num,cp[i],num-cp[i]);
flag = 1;
break;
}
}
if(flag==0)
{
printf("Goldbach's conjecture is wrong.\n");
}
}
free(cp);
free(isprime);
return 0;
}
Two possibilities immediately spring to mind. The first is that the user input may be failing if whatever test harness is being used does not provide any input. Without knowing more detail on the harness, this is a guess at best.
You could check that by hard-coding a value rather than accepting one from standard input.
The other possibility is the rather large memory allocations being done. It may be that you're in a constrained environment which doesn't allow that.
A simple test for that is to drop the value of N (and, by the way, use it rather than the multiple hardcoded 1000000 figures in your malloc calls). A better way would be to check the return value from malloc to ensure it's not NULL. That should be done anyway.
And, aside from that, you may want to check your Eratosthenes Sieve code. The first item that should be marked non-prime for the prime i is i + i rather than i * i as you have. I think it should be:
for (k = i + i; k < N; k += i)
The mathematical algorithm is actually okay since any multiple of N less than N * N will already have been marked non-prime by virtue of the fact it's a multiple of one of the primes previously checked.
Your problem lies with integer overflow. At the point where N becomes 46_349, N * N is 2_148_229_801 which, if you have a 32-bit two's complement integer (maximum value of 2_147_483_647), will wrap around to -2_146_737_495.
When that happens, the loop keeps going since that negative number is still less than your limit, but using it as an array index is, shall we say, inadvisable :-)
The reason it works with i + i is because your limit is well short of INT_MAX / 2 so no overflow happens there.
If you want to make sure that this won't be a problem if you get up near INT_MAX / 2, you can use something like:
for (k = i + i; (k < N) && (k > i); k += i)
That extra check on k should catch the wraparound event, provided your wrapping follows the "normal" behaviour - technically, I think it's undefined behaviour to wrap but most implementations simply wrap two positives back to a negative due to the two's complement nature. Be aware then that this is actually non-portable, but what that means in practice is that it will only work on 99.999% of machines out there :-)
But, if you're a stickler for portability, there are better ways to prevent overflow in the first place. I won't go into them here but to say they involve subtracting one of the terms being summed from MAX_INT and comparing it to the other term being summed.
The only way I can get this to give an error is if I enter a value greater than 1000000 or less than 1 to the scanf().
Like this:
ubuntu#amrith:/tmp$ ./x
183475666
Segmentation fault (core dumped)
ubuntu#amrith:/tmp$
But the reason for that should be obvious. Other than that, this code looks good.
Just trying to find what went wrong!
If the sizeof(long int) is 4 bytes for the OS that you are using, then it makes this problem.
In the code:
for(k=i*i;k<N;k+=i)
{
isprime[k] = 0;
}
Here, when you do k = i*i, for large values if i, the value of k goes beyond 4 bytesand get truncated which may result in negative numbers and so, the condition k<N is satisfied but with a negative number :). So you get a segmentation fault there.
It's good that you need only i+i, but if you need to increase the limit, take care of this problem.

storing known sequences in c

I'm working on Project Euler #14 in C and have figured out the basic algorithm; however, it runs insufferably slow for large numbers, e.g. 2,000,000 as wanted; I presume because it has to generate the sequence over and over again, even though there should be a way to store known sequences (e.g., once we get to a 16, we know from previous experience that the next numbers are 8, 4, 2, then 1).
I'm not exactly sure how to do this with C's fixed-length array, but there must be a good way (that's amazingly efficient, I'm sure). Thanks in advance.
Here's what I currently have, if it helps.
#include <stdio.h>
#define UPTO 2000000
int collatzlen(int n);
int main(){
int i, l=-1, li=-1, c=0;
for(i=1; i<=UPTO; i++){
if( (c=collatzlen(i)) > l) l=c, li=i;
}
printf("Greatest length:\t\t%7d\nGreatest starting point:\t%7d\n", l, li);
return 1;
}
/* n != 0 */
int collatzlen(int n){
int len = 0;
while(n>1) n = (n%2==0 ? n/2 : 3*n+1), len+=1;
return len;
}
Your original program needs 3.5 seconds on my machine. Is it insufferably slow for you?
My dirty and ugly version needs 0.3 seconds. It uses a global array to store the values already calculated. And use them in future calculations.
int collatzlen2(unsigned long n);
static unsigned long array[2000000 + 1];//to store those already calculated
int main()
{
int i, l=-1, li=-1, c=0;
int x;
for(x = 0; x < 2000000 + 1; x++) {
array[x] = -1;//use -1 to denote not-calculated yet
}
for(i=1; i<=UPTO; i++){
if( (c=collatzlen2(i)) > l) l=c, li=i;
}
printf("Greatest length:\t\t%7d\nGreatest starting point:\t%7d\n", l, li);
return 1;
}
int collatzlen2(unsigned long n){
unsigned long len = 0;
unsigned long m = n;
while(n > 1){
if(n > 2000000 || array[n] == -1){ // outside range or not-calculated yet
n = (n%2 == 0 ? n/2 : 3*n+1);
len+=1;
}
else{ // if already calculated, use the value
len += array[n];
n = 1; // to get out of the while-loop
}
}
array[m] = len;
return len;
}
Given that this is essentially a throw-away program (i.e. once you've run it and got the answer, you're not going to be supporting it for years :), I would suggest having a global variable to hold the lengths of sequences already calculated:
int lengthfrom[UPTO] = {};
If your maximum size is a few million, then we're talking megabytes of memory, which should easily fit in RAM at once.
The above will initialise the array to zeros at startup. In your program - for each iteration, check whether the array contains zero. If it does - you'll have to keep going with the computation. If not - then you know that carrying on would go on for that many more iterations, so just add that to the number you've done so far and you're done. And then store the new result in the array, of course.
Don't be tempted to use a local variable for an array of this size: that will try to allocate it on the stack, which won't be big enough and will likely crash.
Also - remember that with this sequence the values go up as well as down, so you'll need to cope with that in your program (probably by having the array longer than UPTO values, and using an assert() to guard against indices greater than the size of the array).
If I recall correctly, your problem isn't a slow algorithm: the algorithm you have now is fast enough for what PE asks you to do. The problem is overflow: you sometimes end up multiplying your number by 3 so many times that it will eventually exceed the maximum value that can be stored in a signed int. Use unsigned ints, and if that still doesn't work (but I'm pretty sure it does), use 64 bit ints (long long).
This should run very fast, but if you want to do it even faster, the other answers already addressed that.

Resources