I have been working on Project Euler lately. I am programming in C and have a query related to Problem 8. The question is:
Find the greatest product of five consecutive digits in the 1000-digit number.
73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450
Here is my own done work yet:
#include <stdio.h>
#include <string.h>
int main(void)
{
char *string = "731671765313306249192251196744.............";
char *x;
x = string;
for(int counter = 0;counter < 2;counter++)
{
printf("%s\n", x + strlen(x) - 5);
x = x + strlen(x) - 5;
}
}
SO, the problem is that unable to understand what to do next. I am able to extract the digits, but what would be the algorithm to use these digits and create an algorithm thats fast and efficient. So, any help, please! Another problem is that when I try to convert the char to an int value, it fails and gives the error "error: incompatible pointer to integer conversion initializing 'char' with an expression of type'char[1001]'. I have used the methods to convert values as here:Coversion of char to int, and so thats it. If any more suggestions, please suggest the better things...
You can read the characters in the string, convert them to integers and then find their product to check which group of 5 consecutive integers give the highest product. At the loss of fun and learning that you can have trying to do it yourself, you can try this.
#include <stdio.h>
#include <string.h>
// calculates the product of a group of numeric chars
// after converting them to int type
int gproduct(char *s, int glen) {
int i = 0;
int val = 1;
// convert a numeric char to int value by subtracting '0'
// assuming the chars are encoded in ascii. consider using
// the standard library function atoi for portability.
while(i < glen)
val *= (s[i++] - '0');
return val;
}
int main(void) {
char *numstr = "731671765313306249192251196744.............";
int glen = 5; // group length
int maxcount = strlen(numstr) - glen;
int maxval = gproduct(numstr, glen); // initialize maxval
int tempval;
for(int i = 1; i < maxcount; i++) {
tempval = gproduct(numstr + i, glen);
if(tempval > maxval)
maxval = tempval;
}
printf("%d\n", maxval);
return 0;
}
Related
I'm working on a project that does an algorithm with the given input. I have the input stored in a long. with the given input, I need to convert “number” into an array so I can have access to each digit. for example, if “number = 73757383” I need to convert that into an array: array = [7, 3, 7, 5, 7...] to be able to do the algorithm (multiply every other digit, then add the others together). But I can't seem to figure out how to do this.
Any help is appropriate.
Also just as a note, I'm using the cs50 library.
Thank you!
#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main(){
long credit;
int number;
int arr[digit];
int i;
do
{
credit = get_long("Number: ");
number = floor(log10(credit) + 1);
}
while (number < 13 || number > 16);
You could simply compare the number with 1000000000000 (at least 13 digits) and 9999999999999999 (at most 16 digits), but you probably need the number of digits later in the code:
#include <stdio.h>
#include <cs50.h>
int main() {
long credit;
int arr[16];
int i;
do {
credit = get_long("Number: ");
}
while (credit < 1000000000000 || credit > 9999999999999999);
...
Alternative:
#include <stdio.h>
#include <cs50.h>
int main() {
long credit;
int arr[16];
int number, i;
do {
credit = get_long("Number: ");
number = snprintf(NULL, 0, "%lu", credit);
}
while (number < 13 || number > 16);
for (i = number; i --> 0;) {
arr[i] = credit % 10;
credit /= 10;
}
Also note that type long may be too small to accommodate numbers larger than 231. You should use long long or even unsigned long long for this or better use a string.
The easiest way is to create a string out of the number and then process 1 digit after another:
#include <stdio.h>
#include <string.h>
int main(){
long credit = 4564894564846;
int arr[20];
char buffer[21];
sprintf(buffer, "%ld", credit);
int n = strlen(buffer);
for (int i = 0; i < n; i++)
arr[i] = buffer[i] - '0';
for (int i = 0; i < n; i++)
printf("%d\n", arr[i]);
}
https://godbolt.org/z/YY4znd
Another possibility is to extract the digit from the number with % 10 and divide by 10 afterwards, but then you get the digits in the wrong order.
You may use a long to ascii function:
ltoa()
or the the well known and standard library function:
sprintf()
In the ascii buffer you can access each individual digit as a char digit.
If you need an array of integer instead, just subtract '0' to each char digit:
buffer[k] - '0'
using % operator can be a good solution
while(input != 0) {
digit = input%10; // store this one
input = input/10;
}
alternatively, you can use 'sprintf' for converting the input to a string. Then, you can access every digit using the index of each digit.
This question already has answers here:
Converting string, to float (without atof) in C
(11 answers)
Closed 6 years ago.
I need to convert a string such as "3.456" to a float without atof() or any other string manipulation functions. Below is my code that works for a c string to int conversion but obviously does not work with a float because of the period. What do I need to add to deal with the period? Thank you.
#include <stdio.h>
int size;
char string[] = "345";
int result = 0;
int i = 0;
int findLength(char string[]){
for(size = 0; string[size]!='\0'; size++){
}
return size;
};
void conversion(char string[]){
result = result * 10 + ( string[i] - '0' );
if (i < size - 1) {
i++;
conversion(string);
}
}
int main(int argc, const char * argv[]) {
findLength(string);
conversion(string);
printf("%d\n", result);
return 0;
}
Before anything else, I think it's important for you to understand how floating point numbers work and how they are represented, at least in C. Look at this question/reply for more information.
Now back to your question. Because of how float are represented in memory, you might not be able to get an exact conversion. That is you might not be able to convert "3.456" to exactly a float that holds the value 3.456. You will only be able to get close to the exact value you want.
First a couple of things wrong with your code:
I would stay away from using global variables in my code unless necessary. You defined "size" as a global variable and that's not good practice.
Use the standard library strlen function to get the length of a string instead of rewriting a function that does so.
Below, you'll find a working solution. The way to do the conversion is as follow:
Scan through the string to get the position of the decimal point
If a non-dot character is encountered, add it to the result
When you'r done scanning through the string, you need to account for the power of the digits before the decimal point. For example, the first digit before the decimal point is simply added to the result. The second digit before the decimal point is multiplied by 10.0 and added to the result and so on. That is accomplished with a simple while loop as shown in the code.
#include <stdio.h>
#include <string.h>
float stringToFloat(char *string)
{
float result= 0.0;
int len = strlen(string);
int dotPosition = 0;
for (int i = 0; i < len; i++)
{
if (string[i] == '.')
{
dotPosition = len - i - 1;
}
else
{
result = result * 10.0 + (string[i]-'0');
}
}
while (dotPosition--)
{
result /= 10.0;
}
return result;
}
int main()
{
char string[] = "3.456";
printf("%f\n",stringToFloat(string));
}
I hope this helps.
P.S: You could increase the precision by using a double instead of a float.
I'm new to c. Please help me
Why do I get this error using eclipse
Multiple markers at this line
- request for member 'ToString' in something not a structure or union
- Method 'ToString' could not be resolved
Here is my code
#include <stdio.h>
int main()
{
int s = 5;
int n = 4;
char g = s.ToString();
char l = n.ToString();
printf(g+l);
return 0;
}
s and n are just ints; they don't have a ToString() method. Also, as #remyabel pointed out, char is not the appropriate type for storing a string value, anyway; it stores only one character.
You don't need to convert your ints to strings at all to do what you're trying to accomplish, so you actually want something like this:
#include <stdio.h>
int main()
{
int s = 5;
int n = 4;
printf("%d%d", s, n); // you can't add l to g here!
return 0;
}
// output 54
DEMO
Oh, and please use more descriptive variable names!
EDIT: To save the string, as requested in the comments, you could do this:
char myString[10];
sprintf(myString, "%d%d", s, n); // myString is now "54"
I'd suggest picking up a C tutorial and starting from the beginning. The use of ToString isn't the only thing that's wrong. You could rewrite it this way and it should work (assuming you want to print "54"):
#include <stdio.h>
int main()
{
int s = 5;
int n = 4;
char g = '0' + s;
char l = '0' + n;
printf("%c%c", g, l);
return 0;
}
But this only works as long as s and n are less than 10, and besides is overly complicated since printf is made for formatting and printing values of different types. This would work just as well:
#include <stdio.h>
int main()
{
int s = 5;
int n = 4;
printf("%d%d", s, n);
return 0;
}
If you want to use the string for something else than printing, the answer depends on what you want to do.
I'm working on my homework and trying to get two characters which are numbers from an array for example ABC10DEF
I want to get 10 and store it in an int type.
number_holder_1 = back[3] - '0';
number_holder_2 = back[4] - '0';
number = number_holder_1 * 10 + number_holder_2;
This doesn't work I don't know why.
When I print out the value of number_holder_1 it does display 1 and when I display number_holder_2 it display 0 but when I print number it just display 0
I don't know how.
UPDATE:
The number, number_holder_1 and number_holder_2 are define as int type.
the array called back that holding ABC10DEF is passing from the main.
It appears to be an implementation mistake, because using what you have given, with some better variable names, it does work.
#include <stdio.h>
#include <ctype.h>
int letter2int(char c) {
int n;
if (isdigit(c)) {
n = c - '0';
} else {
n = -1; /* error */
}
/* for debugging */
printf("For character '%c' we get number '%d'.\n", c, n);
return n;
}
int main(int argc, char** argv) {
const char str[] = "ABC10DEF";
int tens, ones;
int result;
tens = letter2int(str[3]);
ones = letter2int(str[4]);
result = tens * 10 + ones;
printf("Result: %d\n", result);
return 0;
}
This can be generalized to either form a atoi function (ASCII to integer) or extract the first number that occurs in a string (terminated by any non-digit character) by using a loop and a char pointer to index over the string str.
Using i as the zero-based index, result += number * (int)pow(10, i);.
I am looking for a (relatively) simple way to parse a random string and extract all of the integers from it and put them into an Array - this differs from some of the other questions which are similar because my strings have no standard format.
Example:
pt112parah salin10n m5:isstupid::42$%&%^*%7first3
I would need to eventually get an array with these contents:
112 10 5 42 7 3
And I would like a method more efficient then going character by character through a string.
Thanks for your help
A quick solution. I'm assuming that there are no numbers that exceed the range of long, and that there are no minus signs to worry about. If those are problems, then you need to do a lot more work analyzing the results of strtol() and you need to detect '-' followed by a digit.
The code does loop over all characters; I don't think you can avoid that. But it does use strtol() to process each sequence of digits (once the first digit is found), and resumes where strtol() left off (and strtol() is kind enough to tell us exactly where it stopped its conversion).
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
int main(void)
{
const char data[] = "pt112parah salin10n m5:isstupid::42$%&%^*%7first3";
long results[100];
int nresult = 0;
const char *s = data;
char c;
while ((c = *s++) != '\0')
{
if (isdigit(c))
{
char *end;
results[nresult++] = strtol(s-1, &end, 10);
s = end;
}
}
for (int i = 0; i < nresult; i++)
printf("%d: %ld\n", i, results[i]);
return 0;
}
Output:
0: 112
1: 10
2: 5
3: 42
4: 7
5: 3
More efficient than going through character by character?
Not possible, because you must look at every character to know that it is not an integer.
Now, given that you have to go though the string character by character, I would recommend simply casting each character as an int and checking that:
//string tmp = ""; declared outside of loop.
//pseudocode for inner loop:
int intVal = (int)c;
if(intVal >=48 && intVal <= 57){ //0-9 are 48-57 when char casted to int.
tmp += c;
}
else if(tmp.length > 0){
array[?] = (int)tmp; // ? is where to add the int to the array.
tmp = "";
}
array will contain your solution.
Just because I've been writing Python all day and I want a break. Declaring an array will be tricky. Either you have to run it twice to work out how many numbers you have (and then allocate the array) or just use the numbers one by one as in this example.
NB the ASCII characters for '0' to '9' are 48 to 57 (i.e. consecutive).
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
int main(int argc, char **argv)
{
char *input = "pt112par0ah salin10n m5:isstupid::42$%&%^*%7first3";
int length = strlen(input);
int value = 0;
int i;
bool gotnumber = false;
for (i = 0; i < length; i++)
{
if (input[i] >= '0' && input[i] <= '9')
{
gotnumber = true;
value = value * 10; // shift up a column
value += input[i] - '0'; // casting the char to an int
}
else if (gotnumber) // we hit this the first time we encounter a non-number after we've had numbers
{
printf("Value: %d \n", value);
value = 0;
gotnumber = false;
}
}
return 0;
}
EDIT: the previous verison didn't deal with 0
Another solution is to use the strtok function
/* strtok example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] = "pt112parah salin10n m5:isstupid::42$%&%^*%7first3";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str," abcdefghijklmnopqrstuvwxyz:$%&^*");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " abcdefghijklmnopqrstuvwxyz:$%&^*");
}
return 0;
}
Gives:
112
10
5
42
7
3
Perhaps not the best solution for this task, since you need to specify all characters that will be treated as a token. But it is an alternative to the other solutions.
And if you don't mind using C++ instead of C (usually there isn't a good reason why not), then you can reduce your solution to just two lines of code (using AXE parser generator):
vector<int> numbers;
auto number_rule = *(*(axe::r_any() - axe::r_num())
& *axe::r_num() >> axe::e_push_back(numbers));
now test it:
std::string str = "pt112parah salin10n m5:isstupid::42$%&%^*%7first3";
number_rule(str.begin(), str.end());
std::for_each(numbers.begin(), numbers.end(), [](int i) { std::cout << "\ni=" << i; });
and sure enough, you got your numbers back.
And as a bonus, you don't need to change anything when parsing unicode wide strings:
std::wstring str = L"pt112parah salin10n m5:isstupid::42$%&%^*%7first3";
number_rule(str.begin(), str.end());
std::for_each(numbers.begin(), numbers.end(), [](int i) { std::cout << "\ni=" << i; });
and sure enough, you got the same numbers back.
#include <stdio.h>
#include <string.h>
#include <math.h>
int main(void)
{
char *input = "pt112par0ah salin10n m5:isstupid::42$%&%^*%7first3";
char *pos = input;
int integers[strlen(input) / 2]; // The maximum possible number of integers is half the length of the string, due to the smallest number of digits possible per integer being 1 and the smallest number of characters between two different integers also being 1
unsigned int numInts= 0;
while ((pos = strpbrk(pos, "0123456789")) != NULL) // strpbrk() prototype in string.h
{
sscanf(pos, "%u", &(integers[numInts]));
if (integers[numInts] == 0)
pos++;
else
pos += (int) log10(integers[numInts]) + 1; // requires math.h
numInts++;
}
for (int i = 0; i < numInts; i++)
printf("%d ", integers[i]);
return 0;
}
Finding the integers is accomplished via repeated calls to strpbrk() on the offset pointer, with the pointer being offset again by an amount equaling the number of digits in the integer, calculated by finding the base-10 logarithm of the integer and adding 1 (with a special case for when the integer is 0). No need to use abs() on the integer when calculating the logarithm, as you stated the integers will be non-negative. If you wanted to be more space-efficient, you could use unsigned char integers[] rather than int integers[], as you stated the integers will all be <256, but that isn't a necessity.