I'm having trouble conceptualising how to go about some of my code.
My C program wishes to compare each individual element of an array of structs aka arr_person[i].name against a user's input to see if there's a match. (i.e. if the user types in "Billy" and "Billy" is also a string in arr_person[].name array)
for(i=0;i<num_of_lines;i++)
{
if(strcmp(nameInput, arr_person[i].name)==0) {
printf("Match at element %d\n", i);
}
}
Then, a separate function finds reoccurring elements within arr_person[i].name by iterating through the array, and if the same name occurs twice, it will take the corresponding integer values of the same elemental positions and will add them up and store in new variable newChange. For example, if "Billy" occurs twice in the array, at arr_person[0].name and arr_person[4].name, and arr_person[0].number = 15 and arr_person[4].number = 10, then I want to update the number such that it becomes 25.
for(i = 0; i < num_of_lines; i++) {
for(j=0;j<num_of_lines;j++) {
if(strcmp(arr_person[j].name, arr_person[i].name)==0)
*newNumber = arr_person[i].number + arr_person[j].number;
}
}
How do I go about this so that any elements in the array that don't reoccur are still kept the same?
If the user inputs "Rachel" and Rachel only appears once in the array, and her corresponding number is 85, I want to print
Rachel 85
But if the user inputs "Billy" and Billy occurs twice, and he has the two numbers 10 and 15 as corresponding integers in another array, I want to print
Billy 25
I've only been programming for a few months. Thanks in advance.
Seems like the only thing you need to do is this:
int sum = 0;
for(int i=0;i<num_of_lines;i++)
{
if(strcmp(nameInput, arr_person[i].name)==0)
sum += arr_person[i].number;
}
I would structure it like this:
// Previous code from your post slightly modified to function
// returns -1 on no match and index otherwise
int match(struct person *arr_person, char *nameInput, int num_of_lines)
{
for(int i=0;i<num_of_lines;i++) {
if(strcmp(nameInput, arr_person[i].name)==0)
return i;
}
return -1;
}
int sum(struct person *arr_person, char *nameInput, int num_of_lines)
{
int sum = 0;
for(int i=0;i<num_of_lines;i++) {
if(strcmp(nameInput, arr_person[i].name)==0)
sum += arr_person[i].number;
}
return sum;
}
int main()
{
// Insert code for declaration and initialization
int index = match(arr_person, nameInput, num_of_lines);
if(index >= 0) {
printf("Match at element %d\n", index);
printf("%s %d\n", nameInput, sum(arr_person, nameInput, num_of_lines));
} else {
printf("No match\n");
}
}
Related
In this task, you are to get a list of the most critical reviewers. A
critical reviewer is defined as:
A reviewer who has the same amount of negative recommendations (‘n’)
as the reviewer with the most negative recommendations.
Using this definition of what a critical reviewer is, you are to look
through the list of reviewer’s recommendations and determine if they
are a critical reviewer or not.
** The function’s return value should be the number of critical reviewers. **
In addition, the list of critical reviewer’s names created by the
function must also be accessible outside of the function.
In this example, the highest number of ‘n’ recommendations for a
single reviewer is 2. Once you have determined the highest amount of
‘n’ recommendations, you can check to see which reviewers are
“critical reviewers”. In this example we can determine that reviewers
"Larry", "Judi", "Manisha", "Dora", and "Nick" are critical reviewers
as they are the reviewers represented by array indices 1, 3, 6, 8,
and 9 respectively. The number 5 would be returned by the function’s
return value as that is the count of critical reviewers found in the
list. This function has no print statements.
struggling to pass the names of only the critical reviewers to the array to be displayed in main.
//Function prototypes
void Recommendations(); //task 1
int criticalReviewers(); //task 2
//MAIN FUNCTION
int main(void) {
//Variables
char reviewerNames[NUMBER_REVIEWERS][30] = { "Ritu",
"Larry",
"Dan",
"Judi",
"Eric",
"Isabelle",
"Manisha",
"Terra",
"Dora",
"Nick" };
char movieNames[NUMBER_MOVIES][50] = { "Star Wars",
"Incredibles",
"Gone with the wind" };
char userReviews[NUMBER_REVIEWERS][NUMBER_MOVIES];
char reviewerAnswers[10][3];
char negativeReviewers[10][30];
//TASK TWO
printf("\n**********************************************\n");
printf("Task 2: Get names of critical reviewers\n\n");
//call to task 2 function
printf("Number of Critical Reviewers: %d\n", criticalReviewers(reviewerAnswers, reviewerNames, negativeReviewers));
printf("Critical Reviewers: ");
for (int k=0; k<criticalReviewers(reviewerAnswers, reviewerNames, negativeReviewers); k++) {
printf("%s, ", negativeReviewers + k);
}
printf("%s", negativeReviewers + criticalReviewers(reviewerAnswers, reviewerNames, negativeReviewers));
//CALL TO TASK 3 FUNCTION
mostRecommended(reviewerAnswers, movieNames);
WINPAUSE; // REMOVE BEFORE SUBMITTING
return 0;
}
//TASK ONE FUNCTION
//TASK 2 FUNCTION
int criticalReviewers(char userAnswers[10][3], char Reviewers[][30], char critReviewers[][30]) {
int i=0;
int j=0;
int numCriticalReviewers = 0;
int criticalScore = 0;
int criticalReviewers[10];
int timesSkipped=0;
//loop to determine number of critical REVIEWERS
for (i=0; i<10; i++) {
criticalReviewers[i] = 0;
for (j=0; j<3; j++) {
if (userAnswers[i][j] == 'n') {
criticalReviewers[i] = criticalReviewers[i] + 1;
}
if (criticalReviewers[i] > criticalScore) {
criticalScore = criticalReviewers[i];
}
}
}
for (i=0; i<10; i++) {
if (criticalReviewers[i] == criticalScore) {
numCriticalReviewers = numCriticalReviewers + 1;
for (int k=i; k<i+1; k++) {
critReviewers[k-timesSkipped][30] = Reviewers[k][30];
timesSkipped = 0;
}
}
else {
timesSkipped = timesSkipped + 1;
}
}
for (i=0; i<10; i++) {
if (criticalReviewers[i] == criticalScore) {
critReviewers = Reviewers + i;
}
}
return numCriticalReviewers;
}
I have properly printed in main the number of critical reviewers, but below it should print the names of critical reviewers which i can not figure out. everytime i try to pass the values it prints a random string of letters and symbols.
The issue is where you assign the reviewers to the critReviewers array in function criticalReviewers. Notice how you have the second index as 30. By doing this, you are assigning only the 30th index in the array (which is beyond the bounds of the array, indices 0-29, but that is a different issue).
What you should be doing is either looping through the string to copy each index one by one, or copying the string using a function like strcpy in the string.h library. Otherwise, everything looks like it works fine.
Solution 1:
for(i = 0; i < 30; i++) {
array1[someIndex][i] = array2[someIndex][i];
}
This will copy each entry in array2[someIndex] one by one.
Solution 2:
strcpy(array1[someIndex], array2[someIndex]);
This will copy the entire string in array2[someIndex] to array1[someIndex].
I would also take a while to read up on 2d arrays, if you're still confused after reading this. I always like geeksforgeeks.com for stuff like this: https://www.geeksforgeeks.org/multidimensional-arrays-c-cpp/
I am a novice programmer in C and am running into an issue that is almost painfully simple. I am writing a basic program that creates two arrays, one of student names and one of student ID numbers, then sorts them and prints them in various ways, and finally allows the user to search the arrays by ID number. Here is the code:
#include <stdio.h>
#include <string.h>
#define ARRAY_SIZE 3
#define MAX_NAME_LENGTH 32
int main()
{
// Student info arrays
char NAME[ARRAY_SIZE][MAX_NAME_LENGTH];
int ID[ARRAY_SIZE];
// Array for student IDs, shifted twice to the right
int shiftedID[ARRAY_SIZE];
// Boolean value to keep while loop running and
// the ID search prompt repeating
int loop = 1;
// Counter variable for the for loop
int counter;
// Gets input values for the student info arrays
for (counter = 0; counter < ARRAY_SIZE; counter++)
{
printf("Input student name: ");
scanf("%s", NAME[counter]);
printf("Input student ID: ");
scanf("%d", &ID[counter]);
}
// Sorts the arrays
sort(NAME, ID);
// Prints the arrays
print_array(&NAME, ID);
// Shifts the ID value two bits to the right
shiftright(ID, shiftedID);
print_array(NAME, shiftedID);
// Repeatedely prompts the user for an ID to
// search for
while(loop == 1)
{
search_id(NAME, ID);
}
}
And here are the function definitions:
#define ARRAY_SIZE 3
#define MAX_NAME_LENGTH 32
// Sorts the two arrays by student ID. (Bubble sort)
void sort(char **nameArray, int idArray[])
{
// Counter variables for the for loop
int firstCounter = 0;
int secondCounter = 0;
for(firstCounter = 0; firstCounter < ARRAY_SIZE; firstCounter++)
{
for(secondCounter = 0; secondCounter < ARRAY_SIZE - 1;
secondCounter++)
{
if(idArray[secondCounter] > idArray[secondCounter + 1])
{
// Temporary variables for the sort algorithm
int tempInt = 0;
char tempName[32];
tempInt = idArray[secondCounter + 1];
idArray[secondCounter + 1] = idArray[secondCounter];
idArray[secondCounter] = tempInt;
strcpy(tempName, nameArray[secondCounter + 1]);
strcpy(nameArray[secondCounter + 1],
nameArray[secondCounter]);
strcpy(nameArray[secondCounter], tempName);
}
}
}
}
// Searches the ID array for a user input student
// ID and prints the corresponding student's info.
void search_id(char **nameArray, int idArray[])
{
// A boolean value representing whether or not
// the input ID value was found
int isFound = 0;
// The input ID the user is searching for
int searchID = 0;
printf("Input student ID to search for: ");
scanf("%d", &searchID);
// Counter variable for the for loop
int counter = 0;
while (counter < ARRAY_SIZE && isFound == 0)
{
counter++;
if (idArray[counter] == searchID)
{
// Prints the name associated with the input ID
isFound = 1;
printf("%s", nameArray[counter]);
}
}
// If the input ID is not found, prints a failure message.
if (isFound == 0)
{
printf("ID not found.\n");
}
}
// Prints the name and ID of each student.
void print_array(char **nameArray, int idArray[])
{
// Counter variable for the for loop
int counter = 0;
printf("Student Name & Student ID: \n");
for (counter = 0; counter < ARRAY_SIZE; counter++)
{
printf("%s --- %d\n", nameArray[counter], idArray[counter]);
}
}
// Shifts the ID value to the right by two bits
void shiftright(int idArray[], int shiftedID[])
{
// Counter variable for the for loop
int counter = 0;
for (counter = 0; counter < ARRAY_SIZE; counter++)
{
shiftedID[counter] = idArray[counter] >> 2;
}
}
I am aware that this program is fairly basic in nature, and more than anything it is an exercise to get me more well versed in a language such as C. I've been working on it for some time, and have worked through several problems, but seem to be stuck on three issues:
If the input ID numbers are not input already in order, a segmentation fault results. If the ID numbers are input already in order, the sort function never passes through the if statement, and no problems arise.
When passing the arrays of names/IDs to the print_array function, the IDs are printed just fine, but the names will be printed either entirely blank or as a series of strange characters.
When searching by ID at the end of the program, the ID number that was entered first (so, the number in ID[0]) displays an ID not found message, where all numbers at index 1 or greater will work fine - aside from the corresponding names that should be printed being printed as blank, as mentioned in the second issue.
Any advice that I can get would be greatly appreciated! I find the power behind the fine details needed in C to be both really interesting but also very confusing, intimidatingly so, and that means any help I can get makes a big difference.
The problem is that you are assuming that char [ARRAY_SIZE][MAX_NAME_LENGTH] and char ** are interchangeable
void sort(char **nameArray, int idArray[])
should be
void sort(char nameArray[][MAX_NAME_LENGTH], int idArray[])
or
void sort(char (*nameArray)[MAX_NAME_LENGTH], int idArray[])
in order to use a pointer to an array of MAX_NAME_LENGTH chars, same for your search_id function.
Take a look to question 6.13 of C-FAQ
I would advise you to restructure your program. Rather than storing two independent arrays for names and IDs, you can store one array of structs which contain all the necessary data:
typedef struct student
{
int id;
char name[MAX_NAME_LENGTH];
} student_t;
student_t students[ARRAY_SIZE];
Now you have a single array which can never become "mismatched" by sorting the IDs without the names, etc.
You can sort an array in C using the standard library function qsort():
qsort(students, ARRAY_SIZE, sizeof(student_t), comparator);
This requires you define a comparator, which is fairly simple. One example would be:
int comparator(const void *lhs, const void *rhs)
{
const student_t *s1 = lhs, *s2 = rhs;
return s1->id - s2->id;
}
You can use the same comparator with another standard library function bsearch() to search the array of students after it is sorted:
student_t key = { 42 }; // name doesn't matter, search by ID
student_t* result = bsearch(&key, students, ARRAY_SIZE, sizeof(student_t), comparator);
These standard functions are more efficient than what you had, and require you to write much less code, with fewer chances for mistakes.
I am getting unexpected results from my bubble sort program in C.
The program below is a program which takes 5 inputs from the user, performs selection sort on them, then performs exchange sort on them.
If i use these inputs:
50
150
75
175
23
It should sort them to the following:
23
50
75
150
175
However, it doesnt sort correctly and sorts like the following (opposite way around for exchange as it does it in Descending order):
150
175
23
50
75
Its quite strange because if you enter certain values it will sort them correctly such as:
73
84
03
26
83
Not quite sure whats going on with it. I cant start making changes to it when it technically works for certain values.
I must be missing something somewhere.
Any help would be appreciated.
CODE IN FULL:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
int main(int argc, char *argv[])
{
char arc5Strings[5][256];
int nCount, nCount2, nCount3, nCount4, nCount5, nCount6, nCount7, letter, sorted;
int fMinVal[1][2] = {1,1};
int nMinValPosition;
int nMoves;
int nRow;
int i, j, k, indexOfCurrentSmallest, q, temp;
char arcTemp[256];
int nOutOrder;
int nNumValues;
int clean1, clean2;
//input the values
for(nCount=0; nCount < 5; nCount++)
{
printf("Please input string %d/5: ", nCount + 1);
fgets(arc5Strings[nCount], 256, stdin);
if(strlen(arc5Strings[nCount]) > 11)
{
printf("Your string contains more than 10 characters. Please try again.");
nCount = 5;
exit(0);
}
}
//------------------------------------------------------------------------------
//Selection Sort
printf("\n\n");
for(i=0;i<5;i++)
{
indexOfCurrentSmallest = i;
for(j=i;j<5;j++)
{
for(k=0;k<255;k++)
{
if(arc5Strings[j][k] < arc5Strings[indexOfCurrentSmallest][k])
{
//we found a new possible smallest
indexOfCurrentSmallest = j;
break;
}
else if(arc5Strings[j][k] > arc5Strings[indexOfCurrentSmallest][k])
{
//no point in searching further, the one we are looking at is already larger than the one we found.
break;
}
}
}
//let's do a swap
for(q=0;q<255;q++)
{
temp = arc5Strings[i][q];
arc5Strings[i][q] = arc5Strings[indexOfCurrentSmallest][q];
arc5Strings[indexOfCurrentSmallest][q] = temp;
}
}
//---------------------------------------------------------------
//print entire array
printf("This is your selection sorted array based on ASCII values\n\n");
for(nCount3 = 0; nCount3 < 5; nCount3++)
{
for(nCount4 = 0; arc5Strings[nCount3][nCount4] != '\0'; nCount4++)
{
printf("%c", arc5Strings[nCount3][nCount4]);
}
}
//---------------------------------------------------------------------
//Exchange Sort
nNumValues = 5;
nOutOrder = TRUE;
nMoves = 0;
while(nOutOrder && nNumValues > 0)
{
nOutOrder = FALSE;
for(i=0;i<5;i++)
{
for(nCount=0; nCount < nNumValues -1; nCount++)
{
for(nCount2=0, sorted=0; sorted==0; nCount2++)
{
if(arc5Strings[nCount][nCount2] < arc5Strings[nCount+1][nCount2])
{
for(letter=0; letter<256; letter++)
{
arcTemp[letter] = arc5Strings[nCount][letter];
}
for(letter=0; letter<256; letter++)
{
arc5Strings[nCount][letter]= arc5Strings[nCount+1][letter];
}
for(letter=0; letter<256; letter++)
{
arc5Strings[nCount+1][letter] = arcTemp[letter];
}
sorted = 1;
nMoves++;
}
else if (arc5Strings[nCount][nCount2] < arc5Strings[nCount+1][nCount2])
sorted = 1;
}
}
nNumValues--;
}
}
printf("\n\n\nThe sorted list in Descending order is: \n\n\n");
for(nCount5 = 0; nCount5 < 5; nCount5++)
{
printf("%s", arc5Strings[nCount5]);
}
//-----------------------------------------------
printf("\n %d moves were required to sort this list\n\n", nMoves);
return 0;
}
It's because you're sorting strings rather than numbers, so it's using character-based sorting.
In other words, "175" is less than "23" because "1" is less than "2".
If you want to sort them as numbers, convert them to numbers first.
You are using strings while you should be using integers. Either convert your string to integer or use int straight away
See this link an example if you want to compare string
compare two alphanumeric string
Again use Array of integers if you dont need text as an input to compare
I currently have a 2D char array size: [5][256].
The array can hold either numbers or letters.
I have been tasked with using the Selection Sort to sort the strings into ascending order.
My idea is to convert each row into ASCII and then sort the values in ascending order then convert back to chars.
Ive implemented a 2D Array Selection sort for another task, however, it doesnt work here as i coded it to work with 2 columns not 256 like here (not sure how to change it).
What i need help with is how do i use the ASCII value for each row and use it in a selection sort.
Been trying to figure this out for hours now, driving me mental.
Any help is appreciated.
Im not necessarily looking for someone to code everything for me, more of a kick in the right direction. Im new to C and not aware of every function C can do.
Here is my current code in full:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char arc5Strings[5][256];
int nCount, nCount2, nCount3, nCount4, nCount5, nCount6, nCount7;
int fMinVal[1][2] = {1,1};
int nMinValPosition;
int nMoves;
int nRow;
int fTemp[1][2] = {1,1};
int fTemp2[1][2] = {1,1};
//input the values
for(nCount=0; nCount < 5; nCount++)
{
printf("Please input string %d/5: ", nCount + 1);
fgets(arc5Strings[nCount], 256, stdin);
}
printf("\n\n");
//print entire array
for(nCount3 = 0; nCount3 < 5; nCount3++)
{
for(nCount4 = 0; arc5Strings[nCount3][nCount4] != '\0'; nCount4++)
{
printf("%d ", arc5Strings[nCount3][nCount4]);
//ASCII values outputted in a line instead of in array format when using %c
}
}
return 0;
}
Old 2D Array selection sort i devised - extracted from code:
//-----------------------------------
//set up the switch
for(nCount5 = 0; nCount5 < 5; nCount5++)
{
fMinVal[0][0] = arc5Strings[nCount5][0]; //min value is row 0 col 1
nMinValPosition = nCount5;
for(nCount6 = nCount5 + 1; nCount6 < 5; nCount6++)
{
if(arc5Strings[nCount6][1] < fMinVal[0][0])
{
fMinVal[0][0] = arc5Strings[nCount6][0];
nMinValPosition = nCount6;
}
/* Perform the switch - actually switch the values */
if(fMinVal[0][0] < arc5Strings[nCount5][0])
{
fTemp[0][1] = arc5Strings[nCount5][1];
fTemp2[0][0] = arc5Strings[nCount5][0];
arc5Strings[nCount5][1] = arc5Strings[nMinValPosition][1];
arc5Strings[nCount5][0] = arc5Strings[nMinValPosition][0];
arc5Strings[nMinValPosition][1] = fTemp[0][1];
arc5Strings[nMinValPosition][0] = fTemp2[0][0];
nMoves++;
}
}
}
//------------------------------
printf("\n\n");
printf("The sorted list, in ascending order, using selection sort, is:\n\n");
for(nCount3 = 0; nCount3 < 5; nCount3++)
{
for(nCount4 = 0; arc5Strings[nCount3][nCount4] != '\0'; nCount4++)
{
printf("%c", arc5Strings[nCount3][nCount4]);
}
}
printf("\n %d moves were made to sort this list\n", nMoves);
EDIT - RESULTS OF GEORGE'S ANSWER:
Input1 = 90
Input2 = 70
Input3 = abc
Input4 = 500
Input5 = 200
Sorted Array Results:
200
90
70
abc
500
You're on the right track. I would implement this as follows:
for(i=0;i<5;i++)
{
indexOfCurrentSmallest = i;
for(j=i;j<5;j++)
{
for(k=0;k<255;k++)
{
if(arc5Strings[j][k] < arc5Strings[indexOfCurrentSmallest][k])
{
//we found a new possible smallest
indexOfCurrentSmallest = j;
break;
}
else if(arc5Strings[j][k] > arc5Strings[indexOfCurrentSmallest][k])
{
//no point in searching further, the one we are looking at is already larger than the one we found.
break;
}
}
}
//here, we have found the actual smallest, let's do a swap
for(q=0;q<255;q++)
{
temp = arc5Strings[i][q];
arc5Strings[i][q] = arc5Strings[indexOfCurrentSmallest][q];
arc5Strings[indexOfCurrentSmallest][q] = temp;
}
}
I haven't tested this code, but it should be roughly what you're looking for. Basically, it compares ASCII values starting at the left, until it finds a difference, and stores the index for later swapping after comparing all 5 strings.
EDIT I've now tested the code above, and it works now.
First find each string length
int length[5];
for(i = 0, i < 5, i++){
length[i] = strlen(arc5Strings[i]);
}
Sort the lengths. Those with the same, compare the value of the first letter.
Thats it.
valter
I've got an IndexOutOfBounds exception in the following program. It consists of three files:
Important are only two of them, the GUI is working fine. Here is the first one:
interface SudokuObserver {
public void modified(int i, int j);
}
public class SudokuData
{
public int[][] feld = new int[9][9];
public SudokuObserver obs = null;
public SudokuData()
{
int i,j;
for (i=0; i<9; i++) {
for (j=0; j<9; j++) {
feld[i][j] = 0;
}
}
}
public int getNumber(int x, int y)
{
return feld[x][y];
}
public void setNumber(int x, int y, int v)
{
feld[x][y] = v;
if (obs != null)
obs.modified(x, y);
}
public void setObserver(SudokuObserver o)
{
obs = o;
}
So the Sudoku field is allocated as a 9x9 integer array. The following file is called SudokuSolver and has an algorithm to write the possible numbers for each square into an ArrayList. Then the second algorithm works as following: He finds the square which has the minimum of possible numbers, sets the first of the numbers saved in the ArrayList on that square and does this recursive, so he starts again at defining the possible numbers for each square, taking the one with the smallest number of possibilities and picks the first one to put it into that field. A for-loop runs over the possible Numbers for each square while doing that.
import java.util.*;
public class SudokuSolver
{
SudokuData data;
public SudokuSolver(SudokuData d)
{
data = d;
}
{
/*Pseudoalgorithm:
- Inserts the numbers 1-9 into a Collection called res
- Looks at line x, which numbers are in there and erases them out of the
collection
- Looks at column y, which numbers are in there and erases them out of the
collection
- Looks in the 3x3 Square (x,y) which numbers are already in there and erases
them out of the collection
- Gives back the possible candidates for that field
*/
Here i initialize my ArrayList.
public ArrayList<Integer> offen(int x, int y)
{
ArrayList<Integer> res = new ArrayList<Integer>();
/* The collection is saved in an ArrayList */
int k = 0;
Here I just fill in the numbers 1-9 in my ArrayList.
for (int i=1;i<10;i++)
{
res.add(i);
}
Now comes the difficult part: I loop over j from zero to nine, then over k. The line is constant with the given x, the j runs over the columns, so i got every square in the given line, and in every square i check for every number from 1-9. Care: the index goes from 0-9 while the elements go from 1-9 so k has to be 0-9 cause the get()-method takes an index as input. If there is any compliance I remove the element from the ArrayList.
for (int j=0;j<9;j++)
{
for (k=0;k<9;k++)
{
if (this.data.feld[x][j] == (res.get(k)))
res.remove(k);
}
Same stuff as above for the columns, constant column and j loops.
for (k=0;k<9;k++)
{
if (this.data.feld[j][y] == res.get(k))
res.remove(k);
}
}
Now i get my inputs in two new variables, just because i had typed the code part below before with wrong variable names.
int m = x;
int n = y;
Here is the part for the 3x3 squares, i do this with if conditions, so this is just one of the 9 parts, I didn't want to post them all here, cause they just differ in a few constants. I check in which square my input x,y is, and then I loop over the square and check which numbers are there, which are also still in my ArrayList and remove them.
if (m<=2 && n<=2)
{
for (m=0;m<3;m++)
{
for (n=0;n<3;n++)
{
for (k=0;k<9;k++)
{
if (this.data.feld[m][n] == res.get(k))
res.remove(k);
}
}
}
}
Now I return the ArrayList
return res;
}
//findSolution() finds a Solution
public boolean findSolution()
{
/*Possible Strategy:
- Find the square, which has the fewest possible candidates
- If there are more than one candidates, who have the minimum of candidates,
take any of them
- If there are no more open candidates, there is a solution found. Return
true
- Loop over the candidates of this square and by setting the first possible
candidate into this square[x][y]
- Call the method findSolution() recursive to find in dependence of the set
value the values for the other fields
If there is a blind alley, take the next possible candidate (Backtracking!)
*/
int j = 0;
int k = 0;
int x = 0; // x coordinate of the field with the fewest open candidates
int y = 0; // y coordinate of the field with the fewest open candidates
int counter_offene_felder = 0; // counts the number of open fields
int min = 9;
I'm looping over j and k, looking if the number of possible candidates is more than 0, that means I'm running through the whole sudoku field and count the number of open fields.
for (j=0;j<9;j++)
{
for (k=0;k<9;k++)
{
if ( this.offen(j,k).size() >= 0)
{
counter_offene_felder += 1;
}
If the number is < than min = 9 possible candidates, i take it as the min and save the coordinates of that field
if ( (this.offen(j,k)).size() < min )
{
x = j;
y = k;
}
}
}
now i initialize and ArrayList for the field with the fewest possible candidates and put them into this ArrayList with my offen-method
ArrayList<Integer> candidate_list = this.offen(x,y);
for (k=0;k<this.offen(x,y).size();k++)
{ // runs over candidates
int v = this.offen(x,y).get(k); // takes the first candidate
this.data.setNumber(x,y,v); // writes the first candidate into square [x][y]
this.findSolution(); // calls findSolution() recursive
}
If there are no more open fields, I've found a solution
if (counter_offene_felder == 0)
{
return true;
}
else return false;
}
}
The problem is, that I get an IndexOutOfBounds Exception at line 39, at Index 8 Size 8. But I don't know why. :(
Not positive that this is where you are getting your error... but you could run into an issue when you do something like this.
for (k=0;k<9;k++)
{
if (this.data.feld[j][y] == res.get(k))
res.remove(k);
}
For instance, say that at k=1 the if statement evaluates to true. Then you will remove an element from the ArrayList. Then when k=8, and IndexOutOfBounds exception will be thrown because the ArrayList only contains 8 elements (0-7)
Assuming that no other threads will be modifying this.data.feld[][], you will only ever get one match when going through this loop.. so you could do something like this...
int match = -1;
for (k=0;k<res.size();k++) {
if (this.data.feld[j][y] == res.get(k)){
match = k;
break;
}
}
if(match != -1)
res.remove(match);
I think the contains() method will help eliminate your exceptions for this loop.
Try replacing your code with this:
for (m=0;m<3;m++)
{
for (n=0;n<3;n++)
{
if (res.contains(this.data.field[m][n]))
res.remove(res.indexOf(this.data.field[m][n]));
}
}
It will iterate over the data.field, and check the ArrayList to see if it contains the value at m,n. If it does, it will remove it.