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 2 years ago.
Improve this question
i was trying this kick start question, the test give the right answer yet when submitting attempt it says wrong answer, it's second question i'm doing and not sure how this really works here's my code :
function :
int num_subarray (int array[], int array_size, int k) {
int sum = 0, j = 1, i;
for (i = array_size - 1; 0 <= i; i--) {
if (array[i] == j) j++;
else j = 1;
if (j == k) {
sum++;
j = 1;
}
}
return sum;
}
here's the main :
int main () {
int t, n, k, array[N], i, j = 1;
scanf ("%d", &t);
do {
scanf ("%d%d", &n, &k);
i = 0;
do {
scanf ("%d", &array[i]);
i++;
} while (i < n);
printf ("\n Case #%d: %d", j, num_subarray (array, n, k));
j++;
} while (j <= t);
return 0;
}
here's the question :
Countdown - Kick Start
Continuing from my comments, at least from my reading of the question, a k-countdown actually starts with 'k' and counts down to 1, so in the example a 3-countdown is 3, 2, 1 a 6-countdown is 6, 5, 4, 3, 2, 1, etc...
You are also given limits on the array size of 2x10^5 (200000). The consideration there is that on some compilers 200000 4-byte int values will exceed the default stack size, so you may as well make array a global or static to avoid that issue altogether.
Another check you will want to impose is on the read of the values from the file. You will have k at that point and for there to be a k-countdown, the input must contain k and it must be at an index of i < n - k in order for there to be enough elements left in that array to hold a k-countdown. so if you are given k = 10 in a 10-element input, if the 1st element isn't 10 -- that array can't hold a k-countdown (that implementation is left to you -- but if you are failing a large check -- I would suspect that as one of the probable causes)
Putting that together and using the function name kcountdowns instead of your num_subarray and using kcd as your sum, a quick attempt could look like:
#include <stdio.h>
#define NMAX 200000
int arr[NMAX]; /* global storage for array, up to 2x10^5 elements */
/** function to compute no. of kcountdowns in n elements of arr */
int kcountdowns (int n, int k)
{
int i = 0, /* array index */
in = 0, /* flag & counter in(true)/out(false) of a kcountdown */
kcd = 0; /* number of kcountdowns found */
do { /* loop over all elements */
if (in) { /* if in a kcountdown */
if (arr[i] + 1 == arr[i-1]) { /* check current is 1 less than last */
in++; /* increment in flag/count */
if (in == k) { /* full sequence found */
kcd += 1; /* add a kcountdown to sum */
in = 0; /* reset in 0/false */
}
}
else /* otherwise set flag false */
in = 0;
}
if (arr[i] == k) /* if k found, set in to 1-true */
in = 1;
} while (++i < n);
return kcd; /* return number of kcountdows found */
}
(note: the use of the global arr. Generally the use of global variables is discouraged, but here with the potential stack size issue, using a global or making the array static are two reasonable options)
A quick main() that leaves the input check to you to implement could be:
int main (void) {
int t;
if (scanf ("%d", &t) != 1 || t < 1 || 100 < t) /* read/validate t */
return 1;
for (int i = 0; i < t; i++) { /* loop over each case */
int n, k;
if (scanf ("%d %d", &n, &k) != 2 || n < 2 || n < k) /* read/validate n & k */
return 1;
for (int j = 0; j < n; j++) /* loop reading/validating elements */
if (scanf ("%d", &arr[j]) != 1)
return 1;
printf ("Case #%d: %d\n", i + 1, kcountdowns (n, k)); /* output result */
}
(note: you would normally want to read each line into a buffer so you can enforce a validation of only reading a single line of input for the array values. Reading with scanf -- it will happily ignore a '\n' and start reading the next testcase if there is a defect in the input file)
At least with the input given, the results match all testcases, e.g.
Example Test Input
3
12 3
1 2 3 7 9 3 2 1 8 3 2 1
4 2
101 100 99 98
9 6
100 7 6 5 4 3 2 1 100
Example Use/Output
$ ./bin/kcountdown <dat/kcountdown.txt
Case #1: 2
Case #2: 0
Case #3: 1
error check:
$ echo $?
0
Let me know if you have further questions.
Related
I wanna create all possible 5 digit numbers that can be created from the numbers (0-7).
The code below achieves this, but is there any way to make this depend on user input?
The number of loops equals the number of digits I want and each individual loop must be:
for(1st number;condition<=last number;1st number++)
So, for five digits, I have:
for(i=0;i<8;i++){
for(j=0;j<8;j++){
for(k=0;k<8;k++){
for(m=0;m<8;m++){
for(n=0;n<8;n++){
printf("%d %d %d %d %d\n",i,j,k,m,n);
}
}
}
}
}
Keep iterators in an array and increment them manually.
#include <assert.h>
#include <stdio.h>
#include <string.h>
void callback(unsigned n, int i[n]) {
assert(n == 5);
printf("%d %d %d %d %d\n", i[0], i[1], i[2], i[3], i[4]);
}
void iterate(unsigned n, unsigned max, void (*callback)(unsigned n, int i[n])) {
// VLA, use *alloc in real code
int i[n];
memset(i, 0, sizeof(i));
while (1) {
for (int j = 0; j < n; ++j) {
// increment first number, from the back
++i[n - j - 1];
// if it didn't reach max, we end incrementing
if (i[n - j - 1] < max) {
break;
}
// if i[0] reached max, return
if (j == n - 1) {
return;
}
// if the number reaches max, it has to be zeroed
i[n - j - 1] = 0;
}
// call the callback
callback(n, i);
}
}
int main() {
// iterate with 5 numbers to max 8
iterate(5, 8, callback);
}
The beginning and ending of what the code prints:
0 0 0 0 0
0 0 0 0 1
...
...
7 7 7 7 6
7 7 7 7 7
If you want variable numbers of loops, you generally need to use recursion.
Say if you want n digits, with the ith digit be in the range of a[i],b[i], then you will do the following:
/* whatever */
int n;
int *a,*b,*number;
void recursion(int whichdigit){
if (whichdigit==n){
/* Say you managed to output number */
return;
}
for (int i=a[whichdigit];i<=b[whichdigit];i++){
number[whichdigit]=i;
recursion(whichdigit+1);
}
return;
}
int main(){
/* Say somehow you managed to obtain n */
a=malloc(n*sizeof(int));
b=malloc(n*sizeof(int));
number=malloc(n*sizeof(int))
if (!a||!b||!number){
/* unable to allocate memory */
}
/* Say somehow you managed to read a[i],b[i] for all i in 0..n-1 */
recursion(0);
return 0;
}
Warning: if you tries to have too many digits, you will likely get a segmentation fault or stack overflow error.
I wrote a code to find the index of the largest substring in a larger string.
A substring is found when there is an equal amount of a's and b's.
For example, giving 12 and bbbbabaababb should give 2 9, since the first appearing substring starts at index 0 and ends at index 9. 3 10 is also an answer, but since this is not the first appearing substring, this will not be the answer.
The code I made is:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
void substr(char str[], int n) {
int sum = 0;
int max = -1, start;
for (int i = 0; i < n; i++) {
if (str[i]=='a') {
str[i] = 0;
} else if(str[i]=='b') {
str[i] = 1;
}
}
// starting point i
for (int i = 0; i < n - 1; i++) {
sum = (str[i] == 0) ? -1 : 1;
// all subarrays from i
for (int j = i + 1; j < n; j++) {
(str[j] == 0) ? (sum += -1) : (sum += 1);
// sum == 0
if (sum == 0 && max < j - i + 1 && n%2==0) {
max = j - i + 1;
start = i-1;
} else if (sum == 0 && max < j - i + 1 && n%2!=0) {
max = j - i + 1;
start = i;
}
}
}
// no subarray
if (max == -1) {
printf("No such subarray\n");
} else {
printf("%d %d\n", start, (start + max - 1));
}
}
/* driver code */
int main(int argc, char* v[]) {
int n; // stores the length of the input
int i = 0; // used as counter
scanf("%d", &n);
n += 1; // deals with the /0 at the end of a str
char str[n]; // stores the total
/* adding new numbers */
while(i < n) {
char new;
scanf("%c", &new);
str[i] = new;
++i;
}
substr(str, n);
return 0;
}
It works for a lot of values, but not for the second example (given below). It should output 2 9 but gives 3 10. This is a valid substring, but not the first one...
Example inputs and outputs should be:
Input Input Input
5 12 5
baababb bbbbabaababb bbbbb
Output Output Output
0 5 2 9 No such subarray
You have several problems, many of them to do with arrays sizes and indices.
When you read in the array, you want n characters. You then increase n in oder to accomodate the null terminator. It is a good idea to null-terminate the string, but the '\0' at the end is really not part of the string data. Instead, adjust the array size when you create the array and place the null terminator explicitly:
char str[n + 1];
// scan n characters
str[n] = '\0';
In C (and other languages), ranges are defined by an inclusive lower bound, but by an exclusive upper bound: [lo, hi). The upper bound hi is not part of the range and there are hi - lo elements in the range. (Arrays with n elements are a special case, where the valid range is [0, n).) You should embrace rather than fight this convention. If your output should be different, amend the output, not the representation in your program.
(And notw how your first example, where you are supposed to have a string of five characters actually reads and considers the b in the 6th position. That's a clear error.)
The position of the maximum valid substring does not depend on whether the overall string length is odd or even!
The first pass, where you convert all "a"s and "b"s to 0's and 1's is unnecessary and it destroys the original string. That's not a big problem here, but keep that in mind.
The actual problem is how you try to find the substrings. Your idea to add 1 for an "a" and subtract one for a "b" is good, but you don't keep your sums correctly. For each possible starting point i, you scan the rest of the string and look for a zero sum. That will only work, if you reset the sum to zero for each i.
void substr(char str[], int n)
{
int max = 0;
int start = -1;
for (int i = 0; i + max < n; i++) {
int sum = 0;
for (int j = i; j < n; j++) {
sum += (str[j] == 'a') ? -1 : 1;
if (sum == 0 && max < j - i) {
max = j - i;
start = i;
}
}
}
if (max == 0) {
printf("No such subarray\n");
} else {
printf("%d %d\n", start, start + max);
}
}
Why initialize max = 0 instead of -1? Because you add +1/−1 as first thing, your check can never find a substring of max == 0, but there's a possibility of optimization: If you have already found a long substring, there's no need to look at the "tail" of your string: The loop condition i + max < n will cut the search short.
(There's another reason: Usually, sizes and indices are represented by unsigned types, e.g. size_t. If you use 0 as initial value, your code will work for unsigned types.)
The algorithm isn't the most efficient for large arrays, but it should work.
I have an array in C where:
int buf[4];
buf[0] = 1;
buf[1] = 2;
buf[2] = 5;
buf[3] = 2;
and I want to count how many elements in the array that have the same value with a counter.
In the above example, the number of elements of similar value is 2 since there are two 2s in the array.
I tried:
#include <stdio.h>
int main() {
int buf[4];
int i = 0;
int count = 0;
buf[0] = 1;
buf[1] = 2;
buf[2] = 5;
buf[3] = 2;
int length = sizeof(buf) / sizeof(int);
for (i=0; i < length; i++) {
if (buf[i] == buf[i+1]) {
count++;
}
}
printf("count = %d", count);
return 0;
}
but I'm getting 0 as the output. Would appreciate some help on this.
Update
Apologies for not being clear.
First:
the array is limited to only of size 4 since it involves 4 directions, left, bottom, top and right.
Second:
if there is at least 2 elements in the array that have the same value, the count is accepted. Anything less will simply not register.
Example:
1,2,5,2
count = 2 since there are two '2's in the array.
1,2,2,2
count = 3 since there are three '2's in the array
1,2,3,4
count = 0 since there are no similarities in the array. Hence this is not accepted.
Anything less than the count = 2 is invalid.
You are really rather hamstrung by the order the values appear within buf. The only rudimentary way to handle this when limited to 4-values is to make a pass with nested loops to determine what the matching value is, and then make a single pass over buf again counting how many times it occurs (and since you limit to 4-values, even with a pair of matches, your count is limited to 2 -- so it doesn't make a difference which you count)
A short example would be:
#include <stdio.h>
int main (void) {
int buf[] = {1, 2, 5, 2},
length = sizeof(buf) / sizeof(int),
count = 0,
same = 0;
for (int i = 0; i < length - 1; i++) /* identify what value matches */
for (int j = i + 1; i < length; i++)
if (buf[i] == buf[j]) {
same = buf[i];
goto saved; /* jump out of both loops when same found */
}
saved:; /* the lowly, but very useful 'goto' saves the day - again */
for (int i = 0; i < length; i++) /* count matching numbers */
if (buf[i] == same)
count++;
printf ("count = %d\n", count);
return 0;
}
Example Use/Output
$ ./bin/arr_freq_count
count = 2
While making that many passes over the values, it takes little more to use an actual frequency array to fully determine how often each value occurs, e.g.
#include <stdio.h>
#include <string.h>
#include <limits.h>
int main (void) {
int buf[] = {1, 2, 3, 4, 5, 2, 5, 6},
n = sizeof buf / sizeof *buf,
max = INT_MIN,
min = INT_MAX;
for (int i = 0; i < n; i++) { /* find max/min for range */
if (buf[i] > max)
max = buf[i];
if (buf[i] < min)
min = buf[i];
}
int range = max - min + 1; /* max-min elements (inclusive) */
int freq[range]; /* declare VLA */
memset (freq, 0, range * sizeof *freq); /* initialize VLA zero */
for (int i = 0; i < n; i++) /* loop over buf setting count in freq */
freq[buf[i]-min]++;
for (int i = 0; i < range; i++) /* output frequence of values */
printf ("%d occurs %d times\n", i + min, freq[i]);
return 0;
}
(note: add a sanity check on the range to prevent being surprised by the amount of storage required if min is actually close to INT_MIN and your max is close to INT_MAX -- things could come to quick stop depending on the amount of memory available)
Example Use/Output
$ ./bin/freq_arr
1 occurs 1 times
2 occurs 2 times
3 occurs 1 times
4 occurs 1 times
5 occurs 2 times
6 occurs 1 times
After your edit and explanation that you are limited to 4-values, the compiler should optimize first rudimentary approach just fine. However, for any more than 4-values or when needing the frequency of anything (characters in a file, duplicates in an array, etc..), think frequency array.
The first thing that's wrong is that you are only comparing adjacent values in the buf array. You have to compare all the values to each other.
How to do this is an architectural question. The approach suggested by David Rankin in the comments is one, using an array of structs with the value and count count is a second, and using a hash table is a third option. You've got some coding to do! Good luck. Ask for more help as you need it.
You are comparing values of buf[i] and buf[i+1]. i.e. You are comparing buf[0] with buf[1], buf[1] with buf[2] etc.
What you need is a nested for loop to compare all buf values with each other.
count = 0;
for (i=0; i<4; i++)
{
for (j=i+1; j<4; j++)
{
if (buf[i]==buf[j])
{
count++;
}
}
}
As pointed out by Jonathan Leffler, there is an issue in the above algorithm in case the input has elements {1,1,1,1}. It gives a value of 6 when expected value is 4.
I am keeping it up, as the OP has mentioned that he wants to only check anything above 2. So, this method may still be useful.
I am writing a program that will ask the user for a 'n' value, they will then enter 'n' values that will be stored into an array and sorted. I have this part done easy enough.
I will compare this array with input from a number read from a text file. If the number is bigger than any of the current array values it will replace them and slide the rest down. This creates an array of the largest 'n' values
Example: n = 4 n values are : 999 972 954 462 937
a[4] = {999, 972, 954, 462, 937};
Sorted :
a[4] = {999, 972, 954, 937, 462};
if the file input is say 968 the result is.
Resorted :
a[4] = {999, 972, 968, 937, 937};
This is my current code.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
if (argc<3) //error checking
return -1;
int size = atoi(argv[2]);
int a[size];
int i, j, temp=0;
printf("Enter %d numbers\n", size); //user array input for size and n values
for(i = 0; i < size; i++)
scanf("%d", &a[i]);
for(i=0; i < size; i++){ //sorting array
for(j = i+1; j <size; j++){
if( a[i] < a[j]){
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
FILE *input;
input = fopen(argv[1], "r");
if(input ==NULL) //error checking
return -1;
if(fscanf(input, "%d", &temp) != 1)
return -1;
while(fscanf(input, "%d", &temp) ==1){ //loop while there is file input
for(i =1 < size; i++){ //check if temp is larger than array values
if(temp > a[i] && temp < a[i-1]){
for(j = size-1; j >= i; j--) //slide down the rest of the array
a[j] = a[j-1];
a[i] = temp;
}
}
}
for(i=0; i <size; i++){ //print out array
printf("%d ", a[i]);
}
return (0);
}
I have tried this on a smaller simpler skill were I have already created the array and the values instead of using user input. I also just passed the array check sequence through a loop that increases a number value instead of reading from a file. This seemed to work fine with something like
a[5] = {10, 8, 6, 4, 2};
number = 5; // number++ number = 6 number = 7... until 10
result: a[5] = {10, 9, 8, 7, 6};
I am sad to say that even if the program was not printing the right array at the beginning I could see there were numbers from the file. The loop is still going trough the file, but at one point the output just started being the sorted user array. I can't seem to get the array values right. Any ideas?
Continuing from my comments yesterday, I apologize if the errors were due to the retyping of your code, but that is the whole reason you want to try to cut and paste as Jonathan indicated -- eliminate human error in the transcription process.
I think I understand what your primary problem is. If your goal is to read some number of user input values from stdin, sort them in descending order, and then open a file and read a single additional value into the array in sort-order, then you must provide space for the final value in your array at the time it is declared (if using VLA's). Otherwise, you either need to create a second VLA large enough to store the values from the use and the file, and copy the user provided values to the new array or dynamically allocate the array originally (with malloc or calloc) and then realloc as needed to add space for additional values as required.
In this case, it's not that difficult since you know you are reading one value from the file. Just read the size from the command line argument and then create your array as int a[size + 1];
The rest of your task can be handled in a couple of ways. After you read (and validate) the user input, you can sort your values in descending order, read the value from the file, and create an insert & shuffle routine to insert the value in the correct order and move the remaining array elements down, or (probably a less error prone method) is simply to add the element from the file to the end of the array, and call your sort routine again.
(note: you should get used to using qsort rather than attempting to reinvent the bubble-sort, etc.. It is orders of magnitudes more efficient and much less error prone)
You need limit (or eliminate) your use of atoi as it provides zero error checking. A better approach is to use strtol and then check errno and check the end-pointer against the original to determine if there were any digits read. Below a simple helper function incorporates error-checking for strtol to insure you have an actual value for size.
Further, be careful. While you may expect the user will enter size integer values, there is no guarantee they will. It is better to track the number of values actually entered and use that value in subsequent iterations over the array rather than blindly iterating for (i = 0; i < size; i++) throughout the remainder of your code.
Whether you attempt an insert-in-place of the value read from the file, or just add it to the end of the array and call your sort routine again is up to you. I would encourage you to move your sort code into a function to provide that flexibility without having to duplicate the code in main. Look the following over and let me know if you have any questions. Since I presume this was a homework assignment, the insert-in-place case is shown below (but the simple add the file value to the end and call sort again code is included commented out)
#include <stdio.h>
#include <stdlib.h> /* for strtol */
#include <limits.h> /* for LONG_MAX/MIN */
#include <errno.h> /* for ERANGE,errno */
void sort_int_array_dec (int *a, size_t size);
long xstrtol (char *p, char **ep, int base);
int main (int argc, char **argv) {
/* read size as first argument, or 5 if none given */
int size = argc > 2 ? (int)xstrtol (argv[2], NULL, 10) : 5,
a[size + 1], /* variable length array for user + file values */
n = 0, /* number of values from user */
fval, /* value read from file */
temp, /* temporary value for array */
i = 0;
FILE *fp = NULL;
if (size < 1) return 1;
printf ("enter %d integers\n", size);
while (n < size) { /* read up to size values */
int result, c;
printf (" integer[%2d] : ", n + 1);
/* validate read of each value using scanf return */
if ((result = scanf ("%d", &temp)) != 1) {
if (result == EOF) { /* always check for EOF */
fprintf (stderr, "user canceled input.\n");
break;
}
fprintf (stderr, "error: invalid conversion.\n");
/* empty input buffer of invalid entry */
while ((c = getchar()) != '\n' && c != EOF) {}
}
else /* good value read, save, increment n */
a[n++] = temp;
}
sort_int_array_dec (a, n); /* sort a */
printf ("\nsorted array before inserting value from file:\n\n");
for (int i = 0; i < n; i++)
printf ("a[%2d]: %d\n", i, a[i]);
if (!(fp = fopen (argv[1], "r"))) {
fprintf (stderr, "error: file open failed '%s'\n", argv[1]);
return 1;
}
if (fscanf (fp, "%d", &fval) != 1) { /* read value from file */
fprintf (stderr, "error: read of file value failed.\n");
return 1;
}
printf ("\n value from file: %d\n\n", fval);
/* add fval into array in descending sort order
* (you can add it anywhere and simply call sort again, e.g.)
*/
// a[n] = fval; /* add it to the end of the array */
// sort_int_array_dec (a, n + 1); /* sort a again */
for (i = 1; i < n + 1; i++) {
if (fval > a[i-1]) {
temp = a[i-1];
a[i-1] = fval;
break; /* temp now holds value to insert at i */
}
}
if (i == n + 1) /* if already at last element just set it */
a[n] = fval;
else /* otherwise, insert and shuffle remaining elements down */
for (int j = i; j < n + 1; j++) {
int mov = a[j];
a[j] = temp;
temp = mov;
}
printf ("sorted array after inserting value from file:\n\n");
for (int i = 0; i < n + 1; i++)
printf (" a[%2d]: %d\n", i, a[i]);
return 0;
}
/** sort integer array descending (your code) */
void sort_int_array_dec (int *a, size_t size)
{
size_t i, j;
int temp;
if (size < 2) return; /* nothing to sort */
for (i = 0; i < size; i++) {
for (j = i + 1; j < size; j++) {
if (a[i] < a[j]) {
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
}
/** a simple strtol implementation with error checking.
* any failed conversion will cause program exit. Adjust
* response to failed conversion as required.
*/
long xstrtol (char *p, char **ep, int base)
{
errno = 0;
char *endpt = ep ? *ep : NULL;
long tmp = strtol (p, &endpt, base);
/* Check for various possible errors */
if ((errno == ERANGE && (tmp == LONG_MIN || tmp == LONG_MAX)) ||
(errno != 0 && tmp == 0)) {
perror ("strtol");
exit (EXIT_FAILURE);
}
if (endpt == p) {
fprintf (stderr, "No digits were found\n");
exit (EXIT_FAILURE);
}
if (ep) *ep = endpt;
return tmp;
}
Example Use/Output
$ cat dat/file.txt
523
$ ./bin/addintoarray dat/file.txt 4
enter 4 integers
integer[ 1] : 400
integer[ 2] : 500
integer[ 3] : 600
integer[ 4] : 700
sorted array before inserting value from file:
a[ 0]: 700
a[ 1]: 600
a[ 2]: 500
a[ 3]: 400
value from file: 523
sorted array after inserting value from file:
a[ 0]: 700
a[ 1]: 600
a[ 2]: 523
a[ 3]: 500
a[ 4]: 400
/*I'm a beginner C programmer so I don't know much of the syntax.
But I think I can help you with that problem.
I created a simple code and I hope I can really help
the integers from the file must be already sorted.
So the only integer that we will sort is the recent integer that the user inputed.
*/
/*So here's my code of sorting array of integers coming from file.
Please give it a try.
It's not the same syntax as your code but I know you can see my point*/
#include <stdio.h>
#include <stdlib.h>
//my style here is I'm declaring the max Num that I want to put in array.
//But you can do this with different style.
#define MAX_ARRAY 10
//I created separate functions
void readFile(int num_arr[]);
void sortArray(int num_arr[]);
void writeFile(int num_arr[]);
int main()
{
int num_arr[MAX_ARRAY + 1]; // take note that I added 1 (one). And you will see later why I did that
readFile(num_arr);
sortArray(num_arr);
writeFile(num_arr);
//Now we can sort them. Use a temp_num holder.
return 0;
}
void readFile(int num_arr[])
{
int x = 0;
int y = 0;
int temp_num;
FILE *sample_file_pointer = fopen("sample_file.txt", "r");
//first I read the integers from the file and put them in int array.
while(fscanf(sample_file_pointer, " %d\n", &num_arr[x]) == 1)
{
x++;
}//after reading the integers, the last element of the array we declared is still unused.. Now we will use it.
fclose(sample_file_pointer);
//now we will use the unused element by entering the 'n'. Then we will sort the array later.
printf("Enter value of n: ");
scanf(" %d", &num_arr[MAX_ARRAY]);//We put the n value in the last element of the array
}
void sortArray(int num_arr[])
{
int x = MAX_ARRAY;//We will use this to point the last element of the array.
int temp_num;
/*because the array from
the file is already
sorted, (I know you can
do the sorting of that.
That's why I didn't include
it here to make this short)
we can just test the most recent
integer that is added by the user*/
//We do that with this loop
for(int i = MAX_ARRAY; i > 0; i--)
{
if(num_arr[x] >= num_arr[i - 1])
{
temp_num = num_arr[x];
num_arr[x] = num_arr[i - 1];
num_arr[i - 1] = temp_num;
//now set the x to the swapped element to follow the recent number all through. Till the element test becomes 1.
x = i - 1;
}
}
//now we're ready to write this sorted array to a file again
}
void writeFile(int num_arr[])
{
FILE *sample_file_pointer = fopen("sample_file.txt", "w");
for(int i = 0; i < MAX_ARRAY; i++)
{
fprintf(sample_file_pointer, "%d\n", num_arr[i]);
}
//We can ignore the last element of the array. She's out of the group now. It's her fault for being the lowest.. LOL..
fclose(sample_file_pointer);
}
UPDATE: Thanks a lot M Oehm for your awesome answer, really helped me a lot. That struct pos moves is really helpful, haven't studied it yet on class. Im working on a fully solution of my code adding yours as a bone on the programs skeleton. Already fixed the problem of updating fila and columna, the random choice and the switch from 0 to 7 without the ' ' because they're not characters as you and davidc pointed. My program still have some problems which im working on before posting the fully operational program here. I'll update the code tomorrow if not today. Thank you all for your comments and solutions, and M oehm for the time you spent making that wonderful answer.
------------------------------------------------------------------------------------------------------------------------------------
UPDATE 2: Finnished it, made some little changes on M Oehm code and instead of putting manually the first location of the horse i used my previous PosicionCaballo(). Had to delete the code of the MoverCaballo() which had a Switch with 8 possible moves which was set by a random number because i couldn't make it work (i guess the main problem was that part because already was a mess). Now the program with the code below should ask the user for the initial position of the horse, after that the screen will print a 10x10 table filled with 0's (free spaces), fill it with 1's (taken spaces which did the horse moving randomly) and when it finnishes display a message on how many positions did it take.
COORD cxy;
#define posicion(x,y) {(cxy.X)= (x);(cxy.Y)= (y); SetConsoleCursorPosition((GetStdHandle(STD_OUTPUT_HANDLE)), (cxy) );}
int ajedrez[10][10];
int fila, columna;
void GenerarTablero(int m[10][10]){
int i, j;
for (i = 0; i < 10; i++){
for (j = 0; j < 10; j++){
m[i][j] = 0;
}
}
}
GenerarTablero makes the chess board and fills it with 0's.
Global are fila (row) and columna (column) the parts of the ajedrez[10][10]
ajedrez[10][10] is the chess table in a 10x10 size.
void PosicionCaballo(int m[10][10]){
printf("Fila: ");
scanf_s("%d", &fila);
printf("Columna: ");
scanf_s("%d", &columna);
printf("\n");
m[fila][columna] = 2;
system("cls");
}
PosicionCaballo does ask the user for the initial position of the horse and puts the horse on the table.
Example: Row: 5 Column: 5
int horse(int y, int x)
{
int visited[SIZE][SIZE] = { { 0 } };
int count = 0;
if (on_board(y, x) == 0) return -1;
/* Set starting position */
visited[y][x] = 1;
while (1) { /* Infinite loop - must use break */
int poss[8]; /* Possible moves */
int nposs = 0; /* Actual length of poss */
int i, k = 1;
for (i = 0; i < 8; i++) {
int xx = x + moves[i].x;
int yy = y + moves[i].y;
if (on_board(yy, xx) && visited[yy][xx] == 0) {
poss[nposs++] = i;
}
}
/* No more valid moves: return */
if (nposs == 0){
posicion(0, 11);
printf("El tablero se ha bloqueado con ");
return count;
}
/* pick one of the valid moves */
i = poss[rand() % nposs];
x = x + moves[i].x;
y = y + moves[i].y;
/* update horse's position */
visited[y][x] = 1;
count++;
/* print position */
posicion(y, x);
printf("1");
}
return -1; /* Should never be reached */
}
void MostrarMapa(int m[10][10]){
int i, j;
for (i = 0; i < 10; i++){
for (j = 0; j < 10; j++){
printf("%d", ajedrez[i][j]);
}
printf("\n");
}
}
MostrarMapa only prints the chess table on the screen.
int main(void){
int n;
srand(time(NULL));
GenerarTablero(ajedrez);
PosicionCaballo(ajedrez);
MostrarMapa(ajedrez);
n = horse(fila, columna);
posicion(31, 11);
printf("%d movimientos\n", n);
getch();
return 0;
}
and then my main which im using all the functions stated upside.
Thank you very much in advance for your help guys :).
I guess that your assignment is about finding a valid path that visits all squares. Your code tries to find one random path.
Your code has several errors:
When you test ajedrez[fila - 2][columna - 1], you don't check whether fila - 2 or columna - 1 are really valid indices of your chess board. If you access invalid indices, way -1 or 11, you invoke undefined behaviour.
You don't update fila and columna, that is: You don't move your horse.
You overwrite the board twice. That's not an error, but your code shouldn't do double duty.
Your random choice is broken. You have eight possible moves, so you want rand() % 8, which yields numbers from 0 to 7. (David has already pointed this out in a comment.)
Your case labels are charater constants, not numbers. Use case 0:, not case '0':.
You just skip invalid moves. When there are no more valid moves, this will result in an infinite loop. You should check this condition and terminate the loop if it occurs.
As I understand it, the ´posicion` macro is just to show ehere the horse is. Maybe you should skip that at the moment and just print the new coordinates, which isn't as pretty, but straightforward.
Your eight switch cases manifest another flaw: You have the same repeated code eight times over. The only difference is the jump pattern. Such a set-up lends itself to either writing a function where you pass the row and columns distance to jump or to using an array of possible jump patterns.
Your code should instead do something like this for each move:
Loop over all eight jump patterns. If the horse would jump off the board or if the horse would visit a tile that has already been visited, skip that possibility. Otherwise, add the move to an auxiliary array.
If the number of possibilities is zero, terminate the loop - the horse has nowhere to go.
Pick one of the valid moves.
Move the horse, mark the current tile visited.
Report the jump, if desired: Print the new position or place the cursor, whatever.
Below is an example implementation that uses an array of jump patterns. It will give one random path. You can adapt this code to your problem.
#include <stdlib.h>
#include <stdio.h>
#include <time.h> /* for time() */
#define SIZE 10 /* Fixed board size */
struct pos {
int x, y;
};
struct pos moves[8] = { /* Jump patterns */
{1, 2},
{2, 1},
{2, -1},
{1, -2},
{-1, -2},
{-2, -1},
{-2, 1},
{-1, 2}
};
/*
* Is position (y, x) a valid board coordinate?
*/
int on_board(int y, int x)
{
if (x < 0 || x >= SIZE) return 0;
if (y < 0 || y >= SIZE) return 0;
return 1;
}
/*
* Move the horse randomly, starting from (y, x). Print the
* visited fields and return the number of moves made or
* -1 if an error occurs.
*/
int horse(int y, int x)
{
int visited[SIZE][SIZE] = {{0}};
int count = 0;
if (on_board(y, x) == 0) return -1;
/* Set starting position */
visited[y][x] = 1;
printf("%c%d, ", 'A' + y, x + 1);
while (1) { /* Infinite loop - must use break */
int poss[8]; /* Possible moves */
int nposs = 0; /* Actual length of poss */
int i;
for (i = 0; i < 8; i++) {
int xx = x + moves[i].x;
int yy = y + moves[i].y;
if (on_board(yy, xx) && visited[yy][xx] == 0) {
poss[nposs++] = i;
}
}
/* No more valid moves: return */
if (nposs == 0){
printf("whoa!\n");
return count;
}
/* pick one of the valid moves */
i = poss[rand() % nposs];
x = x + moves[i].x;
y = y + moves[i].y;
/* update horse's position */
visited[y][x] = 1;
count++;
/* print position */
printf("%c%d, ", 'A' + y, x + 1);
}
return -1; /* Should never be reached */
}
int main()
{
int n;
srand(time(NULL));
n = horse(3, 6);
printf("%d moves\n", n);
return 0;
}
You seem to update the position using posicion(), but not update fila and columna