I am trying to create a program that outputs in a txt file the results of Collatz conjecture. However when I try to do it with big numbers, like 1,000,000, it does not work properly and always stops at 113383.
Here is the code:
int n, count, number, mayor, masvueltas, top;
char c = '#';
freopen("output MILLION.txt", "w", stdout);
count = 0;
number = 1;
mayor = 0;
masvueltas = 0;
while(number != 1000000) {
printf("\n%d did ", number);//this will say that number did COUNT loops
n = number;
while (n != 1) {
if (n % 2 == 0) {
n = n / 2;
count++;
}
else {
n = 3 * n + 1;
count++;
}
}
printf(" %d saltos.\n", count);//Here continoues the sentence
char graf[count];//creates an array to print the # character COUNT times
for (int i = 0; i < count; i++) {
graf[i] = c;
printf("%c", graf[i]);
}
if(masvueltas < count) {
masvueltas = count;
mayor = number;
}
number++;
count = 0;
}
Also if you know how to print the ASCII character 219, block, in a txt file it would be great. Is not important just so I have a cleaner txt file.
This happened because for number = 113,383 the calculations reach the value of 827,370,449 after 119 counts, the next count max the value 2,482,111,348 which is more than the maximum value of int variable 2,147,483,647, which makes the value of n becomes negative, -1812855948, and the loop fails to reach 1. You should use long long n instead to get the results you want. I also recommend that you use for loop instead of while loop.
Related
I am writing a program that will take any number of integers. The program will end when the terminal 0 has been entered. It will then output the number closest to 10 (except for the terminal character). If there are several numbers closest to 10 then it should output the last number entered.
My current code does read the numbers from the input stream, but I don't know how to implement the logic so that the program will give me the number that is closest to 10.
I know, that I need to keep track of the minimum somehow in order to update the final result.
#include <stdio.h>
int main() {
int n = 1;
int number = 1;
int numberArray[n];
int resultArray[n];
int min;
int absMin;
int result;
int finalResult;
while (number != 0) {
scanf("%d", &number);
numberArray[n] = number;
n++;
}
for (int i = 0; i < n; i++) {
min = 10 - numberArray[i];
if (min < 0) {
absMin = -min;
}
else {
absMin = min;
}
resultArray[i] = absMin;
result = resultArray[0];
if (resultArray[i] < result) {
finalResult = resultArray[i];
}
}
printf("%d\n", finalResult);
return 0;
}
here's a simple code I wrote
One thing I must say is you can't simply declare an array with unknown size and that's what you have done. Even if the no. of elements can vary, you either take input the number of elements from the user OR (like below) create an array of 100 elements or something else according to your need.
#include <stdio.h>
#define _CRT_NO_WARNINGS
int main() {
int n = 0;
int number = 1;
int numberArray[100];
int resultArray[100];
int minNumber;
int *min;
do {
scanf("%d", &number);
numberArray[n] = number;
n++;
}
while (number != 0);
resultArray[0] = 0;
min = &resultArray[0];
minNumber = numberArray[0];
for (int i = 0; i < n-1; i++) {
if(numberArray[i]>=10){
resultArray[i] = numberArray[i] - 10;
}
if(numberArray[i]<10){
resultArray[i] = 10 - numberArray[i];
}
if(resultArray[i] <= *min){
min = &resultArray[i];
minNumber = numberArray[i];
}
}
printf("\n%d",minNumber);
return 0;
}
I have improved your script and fixed a few issues:
#include <stdio.h>
#include <math.h>
#include <limits.h>
int main()
{
int n;
int number;
int numberArray[n];
while (scanf("%d", &number) && number != 0) {
numberArray[n++] = number;
}
int currentNumber;
int distance;
int result;
int resultIndex;
int min = INT_MAX; // +2147483647
for (int i = 0; i < n; i++) {
currentNumber = numberArray[i];
distance = fabs(10 - currentNumber);
printf("i: %d, number: %d, distance: %d\n", i, currentNumber, distance);
// the operator: '<=' will make sure that it will update even if we already have 10 as result
if (distance <= min) {
min = distance;
result = currentNumber;
resultIndex = i;
}
}
printf("The number that is closest to 10 is: %d. It is the digit nr: %d digit read from the input stream.\n", result, resultIndex + 1);
return 0;
}
Reading from the input stream:
We can use scanf inside the while loop to make it more compact. Also, it will loop one time fewer because we don't start with number = 1 which is just a placeholder - this is not the input - we don't want to loop over that step.
I used the shorthand notation n++ it is the post-increment-operator. The operator will increase the variable by one, once the statement is executed (numberArray entry will be set to number, n will be increased afterwards). It does the same, in this context, as writing n++ on a new line.
Variables:
We don't need that many. The interesting numbers are the result and the current minimum. Of course, we need an array with the inputs as well. That is pretty much all we need - the rest are just helper variables.
Iteration over the input stream:
To get the result, we can calculate the absolute distance from 10 for each entry. We then check if the distance is less than the current minimum. If it is smaller (closer to 10), then we will update the minimum, the distance will be the new minimum and I have added the resultIndex as well (to see which input is the best). The operator <= will make sure to pick the latter one if we have more than one number that has the same distance.
I have started with the minimum at the upper bound of the integer range. So this is the furthest the number can be away from the result (we only look at the absolute number value anyway so signed number don't matter).
That's pretty much it.
My objective for this program is to let the user determine the size of the array and dynamically allocate memory for whatever size they choose. Once the user defines the size of the array, random numbers that do no exceed the size of the array are placed into all of the allotted positions. Where I am having issues is removing duplicates from the array and replacing them with a value that is not being used,
Example:
Please enter the size of the array:
User Input: 5
Output of code: 5, 3, 3, 1, 2
I would need it to be something like this:
Please enter the size of the array:
User Input: 3
Output of program: 3, 1, 2
Currently reading "C Programming - A Modern Approach" by K.N. King (Second Edition).
if someone could point me in the right direction on how to approach this, it would be much appreciated.Here is my code thus far.
#include <stdio.h>
#include <stdlib.h>
#define true 1
#define false 0
typedef int bool;
int main() {
int *UserData;
int TempPost;
int replace;
int UserInput;
int i;
int result;
bool digit_seen[UserInput];
int digit;
srand ((unsigned) time(NULL));
printf("Please enter the size of the array using a whole number: \n");
scanf("%d", &UserInput);
UserData = malloc(sizeof(int) * (UserInput ) +1);
for(i=0; i < UserInput; i ++) {
result = (( rand() % UserInput) + 1);
}
// check for duplicate values while putting values in array
while(UserInput>0){
digit = UserInput % UserInput;
if(digit_seen[digit])
break;
digit_seen[digit] = true;
UserInput /= UserInput;
if(UserInput > 0)
printf("Repeated digit \n");
else
printf("No repeated digit \n");
}
// Sorting the array using a Bubble sort
while(1){
replace = 0;
for (i=0; i<(UserInput - 1); i++){
if(UserData[i]>UserData[i+1]){
TempPost = UserData[i];
UserData[i] = UserData[i+1];
UserData[i+1] = TempPost;
replace = 1;
}
}
if(replace==0){
break;
}
}
printf("%d \n", result);
return 0;
}
It's not the most efficient way, but you can do it as you're generating the random numbers. When you pick a random number, go through all the previous elements of the array and see if it's already been used. Keep looping until you pick an unused number.
for (i = 0; i < UserInput; i++) {
do {
result = ( rand() % UserInput) + 1;
} while (in_array(result, UserData, i-1));
UserData[i] = result;
}
int in_array(int val, int* array, int array_size) {
for (int i = 0; i < array_size; i++) {
if (array[i] == val) {
return 1;
}
}
return 0;
}
A slightly more efficient way to do it is to initialize the array to 0. Then instead of picking random numbers, pick a random index to fill in, and repeat this until you pick an index that contains 0.
UserData = calloc(UserInput, sizeof(int));
for (i = 1; i <= UserInput; i++) {
int index;
do {
index = rand() % UserInput;
} while (UserData[index] != 0)
UserData[index] = i;
}
What you can do is shuffle the array instead. Just fill the array with all the numbers in order using a simple for loop, then shuffle it with something like this:
//read user input
//create array and fill with all the numbers in order
//[0,1,2,3,4,5 .. ... ]
int index, temp;
// size is the size of the array
for(int i = 0; i < size; i++)
{
index = rand()%size;//random place to pick from
temp = array[i];
array[i] = array[index];
array[index] = temp;
}
This is a lot more effecient -and less error prone- than your current approach.
I am trying to learn how to code in C, and I am trying to add unique characters to an array, from an input array, only if the character does not already exist in the unique array, in a very simple way.
I am really stumped and would appreciate some assistance how to think it through correctly.
Here's my code:
/* get each character and how many times it shows up
* to do this we need to store each unique char in a char array, and the count for each
* unique char in an int array */
char unique_chars[count];
for(int each = 0; each < count; ++each)
unique_chars[each] = '0';
/* count is the total number of chars stored in theinput array. */
int no_times = 0;
for(int each = 0; each < count; ++each)
{
if(theinput[each] != unique_chars[each])
unique_chars[each] = theinput[each];
if(theinput[each] == unique_chars[each])
continue;
for(int item = 0; item < count; ++item){
if(theinput[each] == unique_chars[item]){
++no_times;
}
}
printf("%c is in theinput array %d times.\n", theinput[each], no_times);
no_times = 0;
}
/* print all the values in the unique_chars array*/
printf("values in unique_chars are: \n");
for(int each = 0; each < count; ++each);
printf("\n");
return 0;
This is one of the many things I have tried. It returns the following:
./uniquely
exsss
The characters typed in are: exsss
Number of characters are: 6
values in unique_chars are:
e x s s s
Please how can I do this right?
You should rework the algorithm of your program as follows:
set count_unique to zero
for each index in the input
set count to zero
go through input to again using index i
if input[index] is the same as input[i]
count++
if count is 1 after the loop
unique_chars[count_unique++] = input[index]
for each index from zero to count_unique
print unique_chars[index]
However, this is the long way of doing it. The short way is to walk through the input once, increment counts, then walk through the counts, and print indexes of values of 1:
int counts[256];
for (int i = 0 ; i != count ; i++) {
counts[(unsigned)input[i]]++;
}
for (int i = 0 ; i != 256 ; i++) {
if (counts[i] == 1) {
printf("%c ", i);
}
}
printf("\n");
For school I have to create a function that prints the mode of a sorted array. It has to account for there being multiple modes and there being no modes as well. For some reason even if there is a mode in the array the function always prints "no mode"
void findMode(double *mode, double a[], unsigned int size)
{
double number = a[0]; //Used to to compare values in the array to see if they're similar
int count = 1; //Keeps track of number of occurences for each number
int max = 1; //Keeps track of max number of occurences found for each number
int uniqueNum = 1; //Keeps track of how many unique values in the array
int maxCount = 1; //Counts how many set's of numbers occur the max ammount of times
int elementNum = 0; //Keeps track of element number in mode array
for (unsigned i = 1; i < size; ++i)//loop to determine how many modes and unique numbers there are
{
if (number == a[i])
{
++count; //if the numbers the two numbers compared are the same, count is increased by 1
}
else
{
if (count == max)
{
++maxCount; //Keeps track of how many modes are in the array
}
if (count > max)
{
//If the two numbers compared are not the same and the count of the previous "set" of similar numbers is higher than the current max count, max is equal to the new count
max = count;
maxCount = 1; //Reset the max count if a new max is found
}
//Count is set back to 1 as we are counting a different number
count = 1;
number = a[i];
++uniqueNum; //Unique number variable gets incremented
}
}
printf("\n%d, %d, %d", max, maxCount, uniqueNum);
count = 1; //sets count back to 1 for next loop
if ((double)size / max == uniqueNum)
{
mode = malloc(1);
mode[0] = (a[size - 1] + 1); //Returns a value that can't exist in the array there is no mode
}
else
{
mode = malloc(sizeof(double) * maxCount); //makes the mode array the right size to store all the modes
for (unsigned i = 1; i < size; ++i)//loop to determine what the modes are
{
if (number == a[i])
{
++count; //if the numbers the two numbers compared are the same, count is increased by 1
}
else
{
if (count == max)
{
mode[elementNum] = a[i];
++elementNum;
}
//Count is set back to 1 as we are counting a different number
count = 1;
}
}
if (mode[0] = (a[size - 1] + 1))
{
printf("\nMode: no mode");
}
else
{
printf("\nMode: {");
for (int i = 0; i <= (sizeof(mode) / sizeof(mode[0])); ++i)
{
printf(" %.3lf ", mode[i]);
}
printf("}");
}
}
}
I have no clue how close or far away I am from the correct logic in this, so if I'm way way off and need to start from scratch let me know.
Thanks!
Your problem is your comparison if (mode[0] = (a[size - 1] + 1))
The single = is doing assignment not equivalence testing. You assign mode[0] to the value of a[size -1] + 1
The assignment operator in c returns the value of the left operand as you can read in the answer to this question. In your case it will return a positive number which will be cast to a boolean and be evaluated as true every time.
I have a problem, then given some input number n, we have to check whether the no is factorial of some other no or not.
INPUT 24, OUTPUT true
INPUT 25, OUTPUT false
I have written the following program for it:-
int factorial(int num1)
{
if(num1 > 1)
{
return num1* factorial(num1-1) ;
}
else
{
return 1 ;
}
}
int is_factorial(int num2)
{
int fact = 0 ;
int i = 0 ;
while(fact < num2)
{
fact = factorial(i) ;
i++ ;
}
if(fact == num2)
{
return 0 ;
}
else
{
return -1;
}
}
Both these functions, seem to work correctly.
When we supply them for large inputs repeatedly, then the is_factorial will be repeatedly calling factorial which will be really a waste of time.
I have also tried maintaining a table for factorials
So, my question, is there some more efficient way to check whether a number is factorial or not?
It is wasteful calculating factorials continuously like that since you're duplicating the work done in x! when you do (x+1)!, (x+2)! and so on.
One approach is to maintain a list of factorials within a given range (such as all 64-bit unsigned factorials) and just compare it with that. Given how fast factorials increase in value, that list won't be very big. In fact, here's a C meta-program that actually generates the function for you:
#include <stdio.h>
int main (void) {
unsigned long long last = 1ULL, current = 2ULL, mult = 2ULL;
size_t szOut;
puts ("int isFactorial (unsigned long long num) {");
puts (" static const unsigned long long arr[] = {");
szOut = printf (" %lluULL,", last);
while (current / mult == last) {
if (szOut > 50)
szOut = printf ("\n ") - 1;
szOut += printf (" %lluULL,", current);
last = current;
current *= ++mult;
}
puts ("\n };");
puts (" static const size_t len = sizeof (arr) / sizeof (*arr);");
puts (" for (size_t idx = 0; idx < len; idx++)");
puts (" if (arr[idx] == num)");
puts (" return 1;");
puts (" return 0;");
puts ("}");
return 0;
}
When you run that, you get the function:
int isFactorial (unsigned long long num) {
static const unsigned long long arr[] = {
1ULL, 2ULL, 6ULL, 24ULL, 120ULL, 720ULL, 5040ULL,
40320ULL, 362880ULL, 3628800ULL, 39916800ULL,
479001600ULL, 6227020800ULL, 87178291200ULL,
1307674368000ULL, 20922789888000ULL, 355687428096000ULL,
6402373705728000ULL, 121645100408832000ULL,
2432902008176640000ULL,
};
static const size_t len = sizeof (arr) / sizeof (*arr);
for (size_t idx = 0; idx < len; idx++)
if (arr[idx] == num)
return 1;
return 0;
}
which is quite short and efficient, even for the 64-bit factorials.
If you're after a purely programmatic method (with no lookup tables), you can use the property that a factorial number is:
1 x 2 x 3 x 4 x ... x (n-1) x n
for some value of n.
Hence you can simply start dividing your test number by 2, then 3 then 4 and so on. One of two things will happen.
First, you may get a non-integral result in which case it wasn't a factorial.
Second, you may end up with 1 from the division, in which case it was a factorial.
Assuming your divisions are integral, the following code would be a good starting point:
int isFactorial (unsigned long long num) {
unsigned long long currDiv = 2ULL;
while (num != 1ULL) {
if ((num % currDiv) != 0)
return 0;
num /= currDiv;
currDiv++;
}
return 1;
}
However, for efficiency, the best option is probably the first one. Move the cost of calculation to the build phase rather than at runtime. This is a standard trick in cases where the cost of calculation is significant compared to a table lookup.
You could even make it even mode efficient by using a binary search of the lookup table but that's possibly not necessary given there are only twenty elements in it.
If the number is a factorial, then its factors are 1..n for some n.
Assuming n is an integer variable, we can do the following :
int findFactNum(int test){
for(int i=1, int sum=1; sum <= test; i++){
sum *= i; //Increment factorial number
if(sum == test)
return i; //Factorial of i
}
return 0; // factorial not found
}
now pass the number 24 to this function block and it should work. This function returns the number whose factorial you just passed.
You can speed up at least half of the cases by making a simple check if the number is odd or even (use %2). No odd number (barring 1) can be the factorial of any other number
#include<stdio.h>
main()
{
float i,a;
scanf("%f",&a);
for(i=2;a>1;i++)
a/=i;
if(a==1)
printf("it is a factorial");
else
printf("not a factorial");
}
You can create an array which contains factorial list:
like in the code below I created an array containing factorials up to 20.
now you just have to input the number and check whether it is there in the array or not..
#include <stdio.h>
int main()
{
int b[19];
int i, j = 0;
int k, l;
/*writing factorials*/
for (i = 0; i <= 19; i++) {
k = i + 1;
b[i] = factorial(k);
}
printf("enter a number\n");
scanf("%d", &l);
for (j = 0; j <= 19; j++) {
if (l == b[j]) {
printf("given number is a factorial of %d\n", j + 1);
}
if (j == 19 && l != b[j]) {
printf("given number is not a factorial number\n");
}
}
}
int factorial(int a)
{
int i;
int facto = 1;
for (i = 1; i <= a; i++) {
facto = facto * i;
}
return facto;
}
public long generateFactorial(int num){
if(num==0 || num==1){
return 1;
} else{
return num*generateFactorial(num-1);
}
}
public int getOriginalNum(long num){
List<Integer> factors=new LinkedList<>(); //This is list of all factors of num
List<Integer> factors2=new LinkedList<>(); //List of all Factorial factors for eg: (1,2,3,4,5) for 120 (=5!)
int origin=1; //number representing the root of Factorial value ( for eg origin=5 if num=120)
for(int i=1;i<=num;i++){
if(num%i==0){
factors.add(i); //it will add all factors of num including 1 and num
}
}
/*
* amoong "factors" we need to find "Factorial factors for eg: (1,2,3,4,5) for 120"
* for that create new list factors2
* */
for (int i=1;i<factors.size();i++) {
if((factors.get(i))-(factors.get(i-1))==1){
/*
* 120 = 5! =5*4*3*2*1*1 (1!=1 and 0!=1 ..hence 2 times 1)
* 720 = 6! =6*5*4*3*2*1*1
* 5040 = 7! = 7*6*5*4*3*2*1*1
* 3628800 = 10! =10*9*8*7*6*5*4*3*2*1*1
* ... and so on
*
* in all cases any 2 succeding factors inf list having diff=1
* for eg: for 5 : (5-4=1)(4-3=1)(3-2=1)(2-1=1)(1-0=1) Hence difference=1 in each case
* */
factors2.add(i); //in such case add factors from 1st list " factors " to " factors2"
} else break;
//else if(this diff>1) it is not factorial number hence break
//Now last element in the list is largest num and ROOT of Factorial
}
for(Integer integer:factors2){
System.out.print(" "+integer);
}
System.out.println();
if(generateFactorial(factors2.get(factors2.size()-1))==num){ //last element is at "factors2.size()-1"
origin=factors2.get(factors2.size()-1);
}
return origin;
/*
* Above logic works only for 5! but not other numbers ??
* */
}