A c solution for leetcode 38 count and say confuse me - c

here is the problem count and say
my accept code below here. I wrote the main function,when submit just copy the countAndSay function.
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
char* countAndSay(int n)
{
if( n == 1 )
return "1";
char *cur = (char *)malloc(2*sizeof(char));
char *res;
cur[0]='1';
cur[1]='\0';
int len, idx, j, count;
for(int i = 2; i <= n; ++i)
{
len = strlen(cur);
res = (char *)malloc(len * 2 + 1);
memset(res, '\0', len * 2 + 1);
count = 1;
for(idx = 1, j = 0; idx < len; ++idx)
{
if(cur[idx] == cur[idx-1])
{
++count;
}
else
{
res[j++] = '0' + count;
res[j++] = cur[idx-1];
count = 1;
}
}//end of for
res[j++] = '0' + count;
res[j++] = cur[len-1];
free(cur);
cur = res;
}
return cur;
}
int main()
{
char *s = countAndSay(INT_MAX);
printf("%s\n",s);
free(s);
return 0;
}
This code i saw from the discuss part and modfiy part of it.I just confused
why use res[j++] = '0' + count since count may be 11 or 12,when count bigger than 9,res[j++] is not a char between '0' and '9',so i ran the code,and it went wrong.
ctci(1720,0x100392380) malloc: * mach_vm_map(size=18446744071713468416) failed (error code=3)
* error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
Program ended with exit code: 9
i guess may be the series is too long,my computer's memory not enough.So i change the num to 500,still got wrong.
Just can not figuer out why.
following the advice of #WhozCraig,i print the len to malloc,here is the result.
1
2
2
4
6
6
8
10
14
20
26
34
46
62
78
102
134
176
226
302
408
528
678
904
1182
1540
2012
2606
3410
4462
5808
7586
9898
12884
16774
21890
28528
37158
48410
63138
82350
107312
139984
182376
237746
310036
403966
526646
686646
894810
1166642
1520986
1982710
2584304
3369156
4391702
5724486
7462860
9727930
12680852
16530884
21549544
28091184
36619162
47736936
62226614
81117366
105745224
137842560
179691598
234241786
305351794
398049970
518891358
676414798
881752750
1149440192
ctci(1828,0x100392380) malloc: *** mach_vm_map(size=18446744071713468416) failed (error code=3)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
Program ended with exit code: 9
so 1149440192B ,1149440192/(1024*1024)MB=1096MB,i just watch the memory left,it is bigger than 1096.1915893555MB.

You ran out of memory.
Every pass around the loop for(int i = 2; i <= n; ++i) potentially doubles the size of res, and you called it with n == INT_MAX. Ain't no computer in the universe that can allocate 1<<INT_MAX bytes of RAM.
The problem statement says to run for n == 30. Your output suggests enough RAM to run for 30.

Related

Calculate maximum path cost for a matrix in C

I am learning c and encountered maximum cost path question in which
Rules:
matrix is n x n size
Starting from the cell (bottommost leftmost cell), you want to go to the topmost
rightmost cell in a sequence of steps. In each step, you can go either right or up from
your current location.
I tried to solve using dynamic programming and this is the function I have written
computecost(int *utr,int n)//utr is the input matrix
{
int *str;
int i,j;
str=(int *)malloc(n*n*sizeof(int));
for(j=0;j<n;j++)//intialization of bottom row
{
str[n*(n-1)+j]=utr[n*(n-1)+j];
}
for(i=n-2;i>=0;i--)
{
for(j=0;j<n;j++)
{
str[n*i+j]=utr[n*i+j]+max(str[n*(i+1)+j],str[n*(i+1)+(j+1)]);
}
}
printf("%d",str[n*0+0]);
return 0;
}
and this is the input
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
scanf("%d",&str[n*i+j]);
}
}
but
for the matrix 5 x5
1 4 8 2 9
32 67 18 42 1
4 86 12 7 1
8 4 12 17 44
1 43 11 45 2
the desired output is 272 but I am getting 211.
the output matrix for my case
1 43 11 45 2
51 47 57 62 46
55 143 74 69 47
175 210 92 111 52
211 214 119 113 64
Can anyone help me?
You don't need dynamic programming for this since there are no overlapping sub-problems. Just use a simple recursion.
const int n = 5;
int mat[n][n] = {
{1,4,8,2,9},
{32,67,18,42,1},
{4,86,12,7,1},
{8,4,12,17,44},
{1,43,11,45,2}
}; // input matrix
int f(int x, int y, int sum){
if(x == 0 && y == 4)
return sum;
int p = 0, q = 0;
if(x - 1 >= 0)
p = f(x-1, y, sum + mat[x-1][y]);
if(y + 1 <= 4)
q = f(x, y+1, sum+mat[x][y+1]);
return max(p,q);
}
int main(){
int maxSum = f(4,0, mat[4][0]);
printf("%d\n", maxSum);
}
You were not very far to succeed.
In practice, you did not initialize correctly the bottom row.
Moreover, there was a little mistake in the iteration calculation.
This is the corrected code.
As said in a comment, it could be further simplified, by avoiding the use of a new array, simply updating the input array.
#include <stdio.h>
#include <stdlib.h>
int max (int a, int b) {
return (a > b) ? a : b;
}
int computecost(int *utr,int n) { //utr is the input matrix
int *str;
str = malloc (n*n*sizeof(int));
str[n*n - 1] = utr[n*n - 1];
for (int j = n-2; j >= 0; j--) { //intialization of bottom row {
str[n*(n-1)+j] = utr[n*(n-1)+j] + str[n*(n-1)+j+1]; // corrected
}
for (int i=n-2; i>=0; i--) {
str[n*i+n-1] = utr[n*i+n-1] + str[n*(i+1)+n-1];
for(int j = n-2; j >= 0; j--) {
str[n*i+j] = utr[n*i+j] + max(str[n*(i+1)+j],str[n*i + j+1]); // corrected
}
}
int cost = str[0];
free (str);
return cost;
}
int main() {
int A[25] = {
1,43,11,45,2,
8,4,12,17,44,
4,86,12,7,1,
32,67,18,42,1,
1,4,8,2,9
};
int ans = computecost (A, 5);
printf ("%d\n", ans);
return 0;
}

Is there a way of assigning array items to struct values?

so what I have is the following array:
10
1 250 350 50
2 525 200 80
3 425 700 60
4 675 475 65
5 850 850 40
6 925 200 90
7 1050 575 80
8 1250 800 70
9 1375 400 60
10 1500 650 40
Each lines' value means something different, per instance
1 250 350 50
id lat long value
I want to assign each of those line values to a structure so I can play with them, but after googling and coming up with the graph theory (which is kind of similar to what I am trying to do) nothing worked... I may say that this array is being pulled from a text file, whether that is or not relevant.
struct population{
int id;
int latitude;
int longitude;
int value;
};
I can't come up with any solution, can anyone help me out or at least provide some tutorials or articles to help me clear my mind?
Here is my code:
#include <stdio.h>
#include <math.h>
#include <string.h>
#define RSIZE 20
#define CSIZE 11
struct population{
int id;
int latitude;
int longitude;
int value;
};
int main(void)
{
char line[CSIZE][RSIZE];
char fname[20];
FILE *fptr = NULL;
int i = 0;
int tot = 0;
printf("\n\n Read the file and store the lines into an array :\n");
printf("------------------------------------------------------\n");
printf(" Input the filename to be opened : ");
scanf("%s",fname);
fptr = fopen("cord.txt", "r");
while(fgets(line[i], RSIZE, fptr))
{
line[i][strlen(line[i]) - 1] = '\0';
i++;
}
tot = i;
printf("\n The contents of the file %s are : \n",fname);
for(i = 0; i < tot; ++i)
{
printf(" %s\n", line[i]);
}
printf("\n");
return 0;
}
A good way to read, validate and save a line of file text into a struct is to use a helper function with fgets() and sscanf() #kaylum. Use " %n" to detect successful parsing completion.
#define INT_TEXT_SIZE 12 // INT_MIN
#define POPULAITON_LINE_SIZE ((INT_TEXT_SIZE + 1 /* separator */)*4 + 1)
// Return:
// 1 on success
// 0 on failure
// EOF on end-of-file/input error
int population_read(struct population *p, fptr) {
// Be generous in buffer size, suggest 2x max expected
char buf[POPULAITON_LINE_SIZE * 2];
if (fgets(buf, sizeof buf, fptr) == NULL) {
return EOF;
}
int n = 0;
// Use %n to store offset
sscanf(buf, "%d%d%d%d %n", &p->id,
&p->latitude, &p->longitude, &p->value, &n);
if (n == 0 || buf[n] || n >= sizeof buf - 1) {
// Parsing failed, junk at the end or very long
return 0;
}
// Maybe some range/value tests per member
if (p->latitude < LATITUDE_MIN || p->latitude > LATITUDE_MAX) {
return 0;
}
... // likewise for other members.
return 1;
}
Usage example:
struct population pop[CSIZE];
int count;
for (count = 0; count < CSIZE; count++) {
int result = population_read(&pop[count], fptr));
if (result == 0) {
report_error_with_TBD_code();
return -1;
}
if (result != 1) {
break;
}
}
for (int c = 0; c < count; c++) {
// Use pop[c];
}

How do I queue numbers in Numbers.txt? and if the tens digit is 0, how do I print 1 in the tens digit?

Random numbers are printed in "numbers.txt". "numbers.txt" exists as a single line. The values here will be taken as two digits and assigned to the queue. I'm having trouble with the while part.
When the numbers in the Numbers.txt file are separated by two digits, I want to make the 0 in the tens digit a 1.
Example
numbers.txt :
839186660286459132876040232609
Output:
two-digit
83 91 86 66 2 86 45 91 32 87 60 40 23 26 9.
As you can see 02 and 09 written as 2 and 9. i want to 12 and 19.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define SIZE 30
typedef struct stack
{
int value;
} Stack;
int *first, *last, *queue;
void kuyrukList()
{
printf("\nKuyruktaki Elemeanlar\n");
int *temp = first;
while (temp < last)
{
printf("%d ", *temp);
temp++;
}
}
void insert(int value)
{
*last = value;
last++;
}
int main()
{
//Random number.
srand(time(NULL));
int text[30] = {0};
FILE *dosyaYaz = fopen("numbers.txt", "w");
printf("\nOlusturulan number degeri:\n");
for (int i = 0; i < SIZE; i++)
{
text[i] = (rand() % 10);
printf("%d", text[i]);
fprintf(dosyaYaz, "%d", text[i]);
}
fclose(dosyaYaz);
printf("\n ");
//***********************************
char ch;
int number = 0;
int counter = 1;
queue = (int *)malloc(sizeof(int) * SIZE);
first = queue;
last = queue;
FILE *dosyaAc = fopen("numbers.txt", "r");
if (dosyaAc == NULL)
{
printf("\nDosya bulunamadi.\n");
exit(0);
}
while ((ch = fgetc(dosyaAc)) != -1)
{
if (counter % 2 == 1)
{
number += (ch - '0') * 10;
}
if (counter % 2 == 0)
{
number += (ch - '0');
insert(number);
number = 0;
}
counter++;
}
fclose(dosyaAc);
kuyrukList();
return 0;
}
So you are creating random numbers, but afterwards you modify them when they are smaller than 10? The easiest solution is to create random numbers who only vary from 10 to 99. This can be done as follows:
Imagine that double rand() generates a random number from 0 to 1 (both never being generated).
Then, 90 * rand() generates a random number from 0 to 90 (both never being generated).
Then, 10 + 90 * rand() generates a random number from 10 to 100 (both never being generated).
Then, (int)(10 + 90 * rand()) generates a random natural number, from 10 to 99 (both might be generated because of the rounding mechanism).
It appears from your stated goals that an array of 15 numbers ranging from 10 - 99 is the need. If that is true, skip writing to a file, and reading them back as a intermediate step and just create an array of 15, two digit numbers directly.
To do this, consider using a function to accept range and offset parameters (upper and lower values) and an array sized for each of the values to use with configuring rand(),.
The following can serve as the core of what you are doing by generating an array of pseudo randoms in the range you specify:
//generate an array of pseudo random values between lower and upper values
void gen_rand(int lower, int upper, int count, int *arr)
{
int i;
for (i = 0; i < count; i++)
{
arr[i] = (rand() % (upper - lower + 1)) + lower;
}
}
int main(void)
{
int arr[15];
srand(time(NULL));
gen_rand(10, 99, 15, arr);
return 0;
}

c segmentation fault, reading large file

I'm trying to read a file and store what it contains, but I'm getting segmentation fault, here is part of my code:
int nnodes;
int main(){
FILE * file = fopen("pub08.in", "r");
int nkeys;
fscanf(file, "%d %d", &nnodes, &nkeys);
long int graphsize = nnodes * nnodes;
long int * graph = malloc(graphsize * sizeof (long int));
for (int i = 0; i < graphsize; i++) {
graph[i] = IN;
}
for (int i = 0; i < nnodes; i++) {
long int a, b, prize;
fscanf(file, "%ld %ld %ld", &a, &b, &prize);
graph[a * nnodes + b] = prize;
graph[b * nnodes + a] = prize;
}
}
the file pub08.in looks like this:
100000 10000
61268 56095 10
40567 20917 17
97937 47973 13
74088 21826 13
62183 30464 11
97793 80708 12
35121 90180 10
77067 97297 17
4657 33995 16
88147 42709 18
95937 25936 19
79853 24452 11
9677 36288 11
91869 48767 15
34585 46478 17
41874 40622 15
13700 19942 18
15660 79277 14
...
Full file is here
The segmentation fault happens, I think, on line:
graph[a * nnodes + b] = prize;
What am I doing wrong?
Here is a list of things you are doing wrong:
Check the return values from fscanf.
Validate a and b to ensure that they are in range.
Check the return value from malloc
As per comment - check the return value from fopen

use of rand function to assign a value randomly [duplicate]

This question already has answers here:
How to create a random permutation of an array?
(3 answers)
Closed 6 years ago.
i am doing a homework. i put rand function in a loop.
int counter = 1;
while ( counter <= 10 ){
variable1 = rand() % 5 + 1;
printf("%d", variable);
counter = counter + 1;
In this code, rand function assigns different value to variable called variable1 but sometimes it assigns same value because range of rand function is narrow. how can i perform that rand function assign different number to variable at the time when loop returns every time.
While rand() is not the greatest random function it should do the trick for many jobs and certainly for most homework. It is perfectly valid to have the same number returned twice in a row from a random function -- as the function should not have any memory of what values were previously returned.
The best way to understand this, is with an example of a coin-toss. Every coin toss is random, and the coin has no memory of the previous toss, so it is possible to flip a coin 32 times in a row and they all comes up head -- if every coin toss is a bit in a 32 bit integer you have created the binary value of integer zero.
However human tend to think (intuition) that having the same value returned more than once is "wrong" for a random function -- but our intuition is wrong on this account.
If you for some reason do want to not repeat the number from one loop to the next, then you will need to program that regardless of which random functions you use -- since any random function would be capable of returning the same values twice.
So something like this would do it;
int counter = 1;
int prevValue = -1;
while ( counter <= 10 ){
do {
variable1 = rand();
} while (variable1 == prevValue);
prevValue = variable1;
variable1 = variable1 % 5 + 1;
printf("%d", variable);
counter = counter + 1;
}
Note that this is still capable of printing the same value twice, since 10 and 15 would be different values before the %5 but would be the same after. If you want the %5 to be taken into account, so the printf never print the same value twice in a row, you would need to move the %5 inside the loop.
In your code snippet i can't find which instruction is the last one inside while. If you want to get different numbers every program run you should use srand() function before while.
But as you mentioned before. Your range (1 - 5) is to narrow to get 10 unique values every time.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
int counter = 1;
int variable1 = 0;
srand(time(NULL));
while ( counter <= 10 ) {
variable1 = rand() % 5 + 1;
printf("%d ", variable1);
counter = counter + 1;
}
putchar('\n');
return 0;
}
how can i perform that rand function assign different number to variable at the time when loop returns every time?
I take this to mean OP does not want to generate the same number twice in a row.
On subsequent iterations, use %(n-1)
int main(void) {
int counter;
int variable;
for (counter = 1; counter <= 10; counter++) {
// First time in loop
if (counter <= 1) {
variable = rand() % 5 + 1;
} else {
int previous = variable;
variable = rand() % (5 - 1) + 1;
if (variable >= previous) variable++;
}
printf("%d\n", variable);
}
return 0;
}
In order to generate a unique list of random numbers, you must check each number generated against the list of numbers previously generated to insure there is no duplicate. The easiest way is to store your previously generated numbers in an array to check against. Then you simply iterate over the values in the array, and if your most recent number is already there, create a new one.
For example, you can use a simple flag to check if your are done. e.g.
while (counter < MAXI){
int done = 0;
while (!done) { /* while done remains 0 (not done) */
done = 1;
tmp = rand() % MAXI + 1; /* generate radom number */
for (i = 0; i < counter; i++) /* check again previous */
if (tmp == array[i]) /* if num already exists */
done = 0; /* set as (not done) */
}
array[counter++] = tmp; /* assign random value */
}
Or you can use the old faithful goto to do the same thing:
while (counter < MAXI) {
gennum:
tmp = rand() % MAXI + 1;
for (i = 0; i < counter; i++)
if (tmp == array[i])
goto gennum;
array[counter++] = tmp;
}
Whichever makes more sense to you. Putting together a full example, you could do:
#include <stdio.h>
#include <stdlib.h> /* for rand */
#include <time.h> /* for time */
enum { MAXI = 10 };
int main (void) {
int array[MAXI] = {0}, counter = 0, i, tmp;
srand (time (NULL)); /* initialize the semi-random number generator */
while (counter < MAXI){
int done = 0;
while (!done) { /* while done remains 0 (not done) */
done = 1;
tmp = rand() % MAXI + 1; /* generate radom number */
for (i = 0; i < counter; i++) /* check again previous */
if (tmp == array[i]) /* if num already exists */
done = 0; /* set as (not done) */
}
array[counter++] = tmp; /* assign random value */
}
for (i = 0; i < MAXI; i++)
printf (" array[%2d] = %d\n", i, array[i]);
return 0;
}
(note: the number your mod (%) the generated number by must be equal to or greater than the number of values you intend to collect -- otherwise, you cannot generate a unique list.)
Example Use/Output
$ ./bin/randarray
array[ 0] = 8
array[ 1] = 2
array[ 2] = 7
array[ 3] = 9
array[ 4] = 1
array[ 5] = 4
array[ 6] = 3
array[ 7] = 10
array[ 8] = 6
array[ 9] = 5
A Shuffled Sequence
Given the discussion in the comments, a good point was raised concerning whether your goal was to create unique set of random numbers (above) or a random set from a sequence of numbers (e.g. any sequence, say 1-50 in shuffled order). In the event you are looking for the latter, then an efficient method to create the shuffled-sequence is using a modified Fisher-Yates shuffle knows as The "inside-out" algorithm.
The algorithm allows populating an uninitialized array with a shuffled sequence from any source of numbers (whether the source can be any manner of generating numbers). Essentially, the function will swap the values within an array at the current index with the value held at a randomly generated index. An implementation would look like:
/** fill an uninitialized array using inside-out fill */
void insideout_fill (int *a, int n)
{
int i, val;
for (i = 0; i < n; i++) {
val = i ? randhq (i) : 0;
if (val != i)
a[i] = a[val];
a[val] = i; /* i here can be any source, function, etc.. */
}
}
(where randhq is any function that generates a random value (0 <= val < n))
A short example program that uses the function above to generate a shuffled array of value from 0 - (n-1) is shown below. The example generates a shuffled sequence of values in array using the inside-out algorithm, and then confirms the sequence generation by sorting the array:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void insideout_fill (int *a, int n);
int randhq (int max);
void prnarray (int *a, size_t n, size_t strd, int wdth);
int intcmp (const void *a, const void *b);
int main (int argc, char **argv) {
srand (time (NULL));
int arrsz = argc > 1 ? (int)strtol (argv[1], NULL, 10) : 50;
int array[arrsz];
insideout_fill (array, arrsz);
printf ("\n array initialized with inside-out fill:\n\n");
prnarray (array, arrsz, 10, 4);
qsort (array, arrsz, sizeof *array, intcmp);
printf ("\n value confirmation for inside-out fill:\n\n");
prnarray (array, arrsz, 10, 4);
return 0;
}
/** fill an uninitialized array using inside-out fill */
void insideout_fill (int *a, int n)
{
int i, val;
for (i = 0; i < n; i++) {
val = i ? randhq (i) : 0;
if (val != i)
a[i] = a[val];
a[val] = i; /* i here can be any source, function, etc.. */
}
}
/** high-quality random value in (0 <= val <= max) */
int randhq (int max)
{
unsigned int
/* max <= RAND_MAX < UINT_MAX, so this is okay. */
num_bins = (unsigned int) max + 1,
num_rand = (unsigned int) RAND_MAX + 1,
bin_size = num_rand / num_bins,
defect = num_rand % num_bins;
int x;
/* carefully written not to overflow */
while (num_rand - defect <= (unsigned int)(x = rand()));
/* truncated division is intentional */
return x/bin_size;
}
/** print array of size 'n' with stride 'strd' and field-width 'wdth' */
void prnarray (int *a, size_t n, size_t strd, int wdth)
{
if (!a) return;
register size_t i;
for (i = 0; i < n; i++) {
printf (" %*d", wdth, a[i]);
if (!((i + 1) % strd)) putchar ('\n');
}
}
/** qsort integer compare */
int intcmp (const void *a, const void *b)
{
return *((int *)a) - *((int *)b);
}
Example Use/Output
$ ./bin/array_io_fill
array initialized with inside-out fill:
40 15 35 17 27 28 20 14 32 39
31 25 29 45 4 16 13 9 49 7
11 23 8 33 48 37 41 34 19 38
24 26 47 44 5 0 6 21 43 10
2 1 18 22 46 30 12 42 3 36
value confirmation for inside-out fill:
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47 48 49
Look it over and let me know if you have any questions.

Resources