why is my 3n+1 problem solution wrong - c

I have recently started reading "Programming Challenges" book by S. Skiena and believe or not I am kind of stuck in the very first problem.
Here's a link to the problem: 3n+1 problem
Here's my code:
#include <stdio.h>
long get_cycle(long input){
if (input == 1){
return 1;
}
else{
if (input & 1){
return 2 + get_cycle((3*input+1)>>1);
}
else{
return 1 + get_cycle(input >> 1);
}
}
}
long get_range_cycle(int k, int j){
int i;
int max = 0;
int current_cycle;
int to = k > j ? k : j;
int from = k < j ? k : j;
for (i=from; i<=to; ++i){
current_cycle = get_cycle(i);
if (current_cycle > max){
max = current_cycle;
}
}
return max;
}
int main(){
long p, q;
long re[100][3];
int i = 0;
while (scanf("%ld %ld",&p,&q) == 2){
re[i][0] = p;
re[i][1] = q;
re[i][2] = get_range_cycle(p,q);
++i;
}
int j;
for (j=0; j<i; ++j){
printf("%ld %ld %ld\n",re[j][0],re[j][1],re[j][2]);
}
}
what is wrong with my code? the input and out is exactly the same with sample.But the submission result is always run time error!

You're code seems to assume maximum 100 lines in the input file - the sample data they are testing on might be bigger? They make no explicit claim wrt the maximum set size of the input data.

I believe that the problem you seek answer for is in the answer #Elemental . If you fix that, however, your solution will time out.
What you should do is to build up a list of all answers between 0 and 1000000. This can be done in linear time (I will not give you the full answer).

Related

Why can't I return the last value of the recursive fuction in C?

I've been trying to build a recursive function which calculates the max value, but even I can see the total value when I print in the function, I can't return the value to the main function. Can you tell me where do I do wrong? Thanks for help!
note : more explanation about what I ve been trying to build is : user defines an object and as long as user doesn't give the price, I keep asking what the object is..
small example :
Define the object:
Car
What is Car?:
4*Wheel+1*Frame
What is Wheel?:
2*Rim
What is Rim?
5.0
What is Frame?:
10.0
Total is : 50.0
Current code:
#include <stdio.h>
#include <stdlib.h>
#define INPUT_SIZE 101
void delete_space(char arr[])
{
int a, i, j, len;
for(a = 0; a < INPUT_SIZE; a++)
{
for(i = 0; i < INPUT_SIZE; i++)
{
if(arr[i] == ' ')
{
for(j = i; j < INPUT_SIZE; j++)
{
arr[j] = arr[j + 1];
}
}
}
}
}
double result(char input[], double coeff, double total)
{
/* if the input is number, num_of_obj is 0, if the input is object, num_or_obj is more than 0.
*/
int i, k = 1, num_of_obj = 0;
char temp_input[INPUT_SIZE];
char temp_input_1[INPUT_SIZE];
char x;
int* p;
double value;
p = (int*)calloc(1, sizeof(int));
p[0] = 0;
printf("What is %s:?\n", input);
scanf("%[^\n]s", temp_input);
getchar();
delete_space(temp_input);
for(i = 0; i < INPUT_SIZE; i++)
{
if(temp_input[i] == '*')
{
num_of_obj++;
}
}
if(num_of_obj == 0) // if the input is number.
{
sscanf(temp_input, "%lf", &value);
total = total + coeff * value;
printf("total : %lf", total);
return total;
}
if(num_of_obj > 0)
{
for(i = 0; i < INPUT_SIZE; i++)
{
if(temp_input[i] == '+')
{
p = (int*)realloc(p, (k + 1) * sizeof(int));
p[k] = i + 1;
k++;
}
}
for(i = 0; i < k; i++)
{
sscanf(&temp_input[p[i]], "%lf%c%[^+]s", &coeff, &x, temp_input_1);
result(temp_input_1, coeff, total);
}
}
printf("test");
return total;
}
int main()
{
double total = 0;
char input[INPUT_SIZE];
printf("Define the object :\n");
scanf("%[^\n]s", input);
getchar();
delete_space(input);
printf("total : %.2lf", result(input, 0, 0));
return 0;
}
I believe that the main issue is the recursive call: result(temp_input_1, coeff, total);, which is ignoring the returned result.
Two possible solutions: (1) do the aggregation in result OR (2) tail recursion. I'm not sure that this case fit into tail recursion (or that there are any benefits here). Consider removing the 'total' from result prototype, and doing the aggregation (over the 'components') in the loop.
double result(char input[], double coeff) {
double total ;
...
for(i = 0; i < k; i++)
{
sscanf(&temp_input[p[i]], "%lf%c%[^+]s", &coeff, &x, temp_input_1);
total += result(temp_input_1, coeff, total);
}
Side comment: Consider also removing the 'delete_space' function. I believe it does not property fix the string. Much easier to skip over the spaces in the scanf call.
Welcome to stackoverflow! I too am new here, but if you word your questions right, you'll get better answers. If this is a homework assignment, I highly recommend including that, it can be hard to follow descriptions.
So as a general rule of thumb, when writing C functions its best to use as few return statements as possible. But I too have difficulty with this.
It looks like your are checking for
is first condition met?
if not check next condition
should you be using if, if else, and else?
Also you have if statements with no else, generally needed, especially in a recursive function (you might be skipping over the next step after the last recursive call)
Hope this helps! Swamped with the end of the semester myself or else I would have attempted a solution!
You need three things to write a recursive method successfully:
A terminating condition, so that the method doesn't call itself forever,
Some work to do, and
A recursive call.
Consider the following code:
typedef struct node{
void* item;
struct node* next;
} Node;
int CountNodes(Node* list)
{
if (list == null) return 0;
return 1 + CountNodes(list.next);
}
This code works because it counts the current node plus all remaining nodes. The recursive call counts the next node and all remaining nodes. And so on.

Dynamic Programming - Minimum number of coins in C

I have looked through various questions on the site and I haven't managed to find anything which implements this by the following reasoning (so I hope this isn't a duplicate).
The problem I'm trying to solve via a C program is the following:
As the programmer of a vending machine controller your are required to compute the minimum number of coins that make up the required change to give back to customers. An efficient solution to this problem takes a dynamic programming approach, starting off computing the number of coins required for a 1 cent change, then for 2 cents, then for 3 cents, until reaching the required change and each time making use of the prior computed number of coins. Write a program containing the function ComputeChange(), that takes a list of valid coins and the required change. This program should repeatedly ask for the required change from the console and call ComputeChange() accordingly. It should also make use of “caching”, where any previously computed intermediate values are retained for subsequent look-up.
After looking around online to find how others have solved it, I found the following example applied with pennies, nickels and dimes:
Which I tried to base my code upon. But first of all, my code isn't halting, and secondly, I'm not sure if I'm incorporating the caching element mentioned in the rubric above. (I'm not really sure how I need to go about that part).
Can anyone help find the flaws in my code?
#include <stdio.h>
#include <limits.h>
int computeChange(int[],int,int);
int min(int[],int);
int main(){
int cur[]={1,2,5,10,20,50,100,200};
int n = sizeof(cur)/sizeof(int);
int v;
printf("Enter a value in euro cents: ");
scanf("%d", &v);
printf("The minimum number of euro coins required is %d", computeChange(cur, v, n));
return 0;
}
int computeChange(int cur[], int v, int n){
if(v < 0)
return -1;
else if(v == 0)
return 0;
else{
int possible_mins[n], i;
for(i = 0; i < n; i++){
possible_mins[i]=computeChange(cur, v-cur[i], n);
}
return 1+min(possible_mins, n);
};
}
int min(int a[], int n){
int min = INT_MAX, i;
for(i = 0; i < n; i++){
if((i>=0) && (a[i]< min))
min = a[i];
}
return min;
}
Any assistance will be greatly appreciated.
OP's supplied Change() algorithm incurs lots of recursion, even with the if(v < 0) return INT_MAX; correction. So much recursion that even small-ish values take millions of recursive calls.
A simple improvement is to "cache" the best solution found so far. Then when an intermediate solution is already worse than the best, no need to continue that path.
int computeChange(int cur[], int v, int n, int count_now, int *bestcount) {
if (count_now >= *bestcount) {
return INT_MAX;
}
if (v < 0) {
return INT_MAX;
}
if (v == 0) {
*bestcount = count_now;
return 0;
}
int min_count = INT_MAX;
for (int i = 0; i < n; i++) {
int count = computeChange(cur, v - cur[i], n, count_now+1, bestcount);
if (count < min_count) {
min_count = count + 1;
}
}
return min_count;
}
int bc = INT_MAX;
computeChange(cur, v, n, 0, &bc));
A secondary improvement is to attempt using large coins first
// int count = computeChange(cur, v - cur[i], n, count_now+1, bestcount);
int count = computeChange(cur, v - cur[n-i-1], n, count_now+1, bestcount);
So the below is the code snippet for your problem using memoization and dynamic programming. The complexity is O(Val*numTypesofCoins).
In the end, change[val] will give you the min number of coins for val.
int change [MAX];
int cur[]={1,2,5,10,20,50,100,200};
int n = sizeof(a)/sizeof(int);
int val= //whatever user enters to get the num of coins required.
for (i=0; i <= val; i++) {
change[i] = INT_MAX;
}
for (i=0; i < n; i++) { // change for the currency coins should be 1.
change[cur[i]] = 1;
}
for (i=1; i <= val; i++) {
int min = INT_MAX;
int coins = 0;
if (change[i] != INT_MAX) { // Already got in 2nd loop
continue;
}
for (j=0; j < n; j++) {
if (cur[j] > i) { // coin value greater than i, so break.
break;
}
coins = 1 + change[i - cur[j]];
if (coins < min) {
min = coins;
}
}
change[i] = min;
}
if you have the sum of say x and the coins of denominations say a1, a2, a3, a4..(in decreasing order)
then the answer is simply->
x/a1+(x%a2)/a3+((x%a2)%a3)/a4+...
This should hopefully give the answer

C : Runtime Error Verdict (Help debugging)

I am working on a problem on an Online Judge ( link here ), and I keep getting a runtime error verdict each time I submit my solution. I have been looking at it for a while now, I still can't figure out what's wrong with it. I have also looked up the typical reasons behind a runtime error (arrays out of bonds, memory limit exceeded, logical errors ... ect). I can't find any of them in the code posted below :
#include<stdio.h>
int Hall[110][110];
int isValid(int x, int y){
int i,j,cnt=0;
for(i=x-1; i<=x+1; i++)
for(j=y-1; j<=y+1; j++)
if(Hall[x][y]==Hall[i][j])
cnt++;
if(cnt>1)
return 0;
else
return 1;
}
int notChecked(int N,int* checked,int size){
int i;
for(i=0; i<size; i++)
if(checked[i] == N)
return 0;
return 1;
}
int main (void){
int T,R,C,checked[110],i,j,k,size;
scanf("%d",&T);
for(i=0; i<T; i++){
scanf("%d %d",&R,&C);
//initialize
size=0;
for(j=0; j<R*C; j++) checked[j] = -1;
for(j=0; j<=C+1; j++){
Hall[0][j] = -1;
Hall[R+1][j] = -1;
}
for(j=0; j<=R+1; j++){
Hall[j][0] = -1;
Hall[j][C+1] = -1;
}
//read input
for(j=1; j<=R; j++)
for(k=1; k<=C; k++)
scanf("%d",&Hall[j][k]);
//algo:
for(j=1; j<=R; j++)
for(k=1; k<=C; k++)
if(Hall[j][k]>=0){
if(notChecked(Hall[j][k],checked,size)){
if(isValid(j,k)==0){
checked[size] = Hall[j][k];
size++;
}
}
}
printf("%d\n",size);
}
return 0;}
Any help is much appreciated !
You need to do bounds checking on your input.
According to the site T needs to be between 1 and 100 inclusive, so you need to check for that. Then for each R and C (N and M on the site), they also need to be between 1 and 100 inclusive.
For each set of R by C entries, you need to make sure you actually read in R rows and C columns. You also need to ensure that you read in T total sets of entries.
Problem Solved !
The code contained an array out of bonds problem, in the following line:
for(j=0; j<R*C; j++) checked[j] = -1;
Knowing that checked had a size of 110 and R and C a max size of 100 each. I changed the size of checked to 10100 and it worked.
Thanks #chux for the help !

C Code running fine on ideone, but getting WA in spoj

http://www.spoj.com/problems/MORENA/
Getting WA in spoj, running fine otherwise on ideone, for the test cases. any idea?
Earlier i wrote this in java, was getting NZEC. Wrote this in C then.
#include<stdio.h>
int main(){
int n,i;
scanf("%d",&n);
long num[n];
for(i=0;i<n;i++){
scanf("%ld",&num[i]);
}
int flag;
int l;
for(l=0;l<n;l++){
if(num[l+1] > num[l]){
flag = 1;
break;
}
else if(num[l+1] < num[l]){
flag = 0;
break;
}
}
int count = 1,k;
for(k =0; k<n-1; k++){
if(flag){
if (num[k+1] > num[k]){
count++;
flag = 0;
}
else if(num[k+1]==num[k]){
flag = 1;
}
else if(num[k+1]<num[k]){
//count++;
flag=1;
}
}
else{
if(num[k+1] < num[k]){
count++;
flag = 1;
}
else if(num[k+1]==num[k]){
flag = 0;
}
else if(num[k+1]>num[k]){
//count++;
flag = 0;
}
}
}
printf("%d",count);
return 0;
}
Wait what, MANY problems here.
Here are few, first:
int n,i;
scanf("%d",&n);
long num[n];
isn't possible (or isn't supposed to be possible at least) to declare an array in the size of a certain variable, use malloc() for that by doing so:
long* num = malloc(sizeof(long)*n);
Another problem, is that you cross the boundary of the array in the first loop, which is weird because you took care of it in the second one :P
Just change: for(l = 0 ; l < n ; l++) to for(l = 0 ; l < n-1 ; l++) as in your IF statement you use the array l+1 element, and when l is n-1 you actually test n-1 element compared to the Nth one - which isn't in the boundary of your array.
Other than that the code seems okay.
The question has strong bonds with competitive programming. Usually there is a problem displayed and user is expected to submit code which gives expected output for tested input for online judge, and SPOJ being one of them. And actually there is sample input and sample output displayed an almost all problems. So your code would give same output as shown in sample output for problem's sample input in ideone, but your code is tested to huge amount of data in online judge and that would result in NZEC.

Changing code to make it parallel [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 8 years ago.
Improve this question
#include <conf.h>
#include <kernel.h>
#include <stdio.h>
#define MAX_ITEMS 50
typedef long double LD;
int run_solve_equ();
void xmain(){
int pid;
pid = create(run_solve_equ, 20*INITSTK, INITPRIO, "B", 0);
resume(pid);
}
int solve_equ(LD b, int n, LD a[], int choosen[] ){
if ( n == 1 )
if (a[0] == b) {
choosen[0] = 1;
return 1;
} /* if */
else if (b == 0) {
choosen[0] = 0;
return 1;
} /* else if*/
else {
choosen[0] = 0;
return 0;
}
else /* n > 1 */
if (solve_equ(b, n-1, a, choosen)) {
choosen[n-1] = 0;
return 1;
} /* if */
else if (solve_equ(b - a[n-1],n-1, a, choosen)) {
choosen[n-1] = 1;
return 1;
} /* else if */
else{
choosen[n-1] = 0;
return 0;
}
} /* solve_equ */
LD a[MAX_ITEMS];
int choosen[MAX_ITEMS];
char pstr[200];
extern long int tod;
int run_solve_equ() {
int n, i, result;
LD b, sum;
printf("How many numbers? No more than %d:", MAX_ITEMS );
scanf("%d",&n);
puts("Enter b:");
scanf("%Lf",&b);
a[0] = 1;
for (i = 1; i < n; i++)
a[i] = a[i-1]*2;
result = 0;
sprintf(pstr, "time = %ld\n", tod);
printf(pstr);
result = solve_equ(b,n, a, choosen);
sprintf(pstr, "time = %ld\n", tod);
printf(pstr);
sprintf(pstr, "Solution for b = %Lf, n = %d, value = %d :\n", b,
n,result);
printf(pstr);
printf("\ni:\n");
for (i = 0; i < n; i++) {
sprintf(pstr, "%-16d",i);
printf(pstr);
} // for
printf("\na[i]:\n");
for (i = 0; i < n; i++) {
sprintf(pstr, "%-16.1Lf", a[i]);
printf(pstr);
} // for
printf("\nchoosen[i]:\n");
for (i = 0; i < n; i++) {
sprintf(pstr, "%-16d", choosen[i]);
printf(pstr);
} // for
printf("\n");
sum = 0;
for (i = 0; i < n; i++)
if (choosen[i]) {
sum += a[i];
sprintf(pstr, " + %-16.1Lf", a[i]);
printf(pstr);
} /* if */
sprintf(pstr, " = %-16.1Lf\n", sum);
printf(pstr);
return 0;
}
I need to change this program so the search will be "parallel" by two processes:
Each will search a n-1, the first user on a [n-1] and the other not.
the problem is to find a number in the array that all the number togother are equal to another number b !
Not an answer, but I do have some constructive comments for you.
Reading the above code hurts. It hurts my eyes and it hurts my brain. Why?
Variable Names are non-descriptive an often one letter (outside of I). b, n, a - I don't know what these are at a glance and I don't want to find out by understanding what you wrote. I bet you won't understand what you wrote next week either. Do everyone a favor and make the names better.
Please, please use a bit of white space between your "code thoughts". Your code looks like one long run-on sentence that also hides what it does.
Don't mix braced and non-braced code - especially when your indentation is not consistent. It is very, very difficult to follow your if logic as-is right now. Go ahead and waste a few bytes of hard disk space and perhaps .25 seconds adding braces or at least fixing your indents.
Write useful comments. /* if */ is a terrible comment and you do similar stuff everywhere. I know what an if is, but perhaps a quick not of what you are checking?
Don't mix globals and extern defines in the middle of your code. Keep them together and it makes it easier to remember what is global and what is not. This is the most minor offense though and others may disagree.
Anyways, a bit off topic for your question, which will more than likely close as you've put little effort into solving it yourself, but my comments may help you with future coding projects and will at least make it easier for others to help you going forward.

Resources