I am trying my hands at making a 4x4 Sudoku solver but I do not understand why the code produce any output. Is the loop running for too long or have I done a stupid yet fatal mistake in the do while loop. I do not seem to get into running the anotherround() function.
Here is my first attempt. The logic should be fine.
#include <stdio.h>
#define SIZE 4
void printBoard(int[][SIZE]);
void solve(int[][SIZE]);
int anotherRound(int[][SIZE]);
void checkBox(int[][SIZE], int, int, int, int);
int main(void)
{
int board[4][4] = {
{0,3,4,0},
{4,0,0,2},
{1,0,0,3},
{0,2,1,0}
};
solve(board); // solve the puzzle now!
printf("Sudoku puzzle solved:\n");
printBoard(board);
return 0;
}
// To print the 4x4 Sudoku board.
void printBoard(int board[][SIZE])
{
int r, c;
for (r = 0; r < SIZE; r++)
{
for (c = 0; c < SIZE; c++)
printf("%d ", board[r][c]);
printf("\n");
}
}
// Solving a Sudoku puzzle using a very simple
// algorithm (algorithm A in the write-up).
// It only solves the simplest puzzles.
void solve(int board[][SIZE])
{
int blankCellFound; // indicate whether there is still some blank cell
do
{
blankCellFound = anotherRound(board);
} while (blankCellFound == 1);
}
// Apply loop body of algorithm A and return 1 if there are still
// blank cells, or 0 if there is no more blank cell.
int anotherRound(int board[][SIZE])
{
int r, c,
sum, // Sum of elements in a row or column
countZero; // Number of zeroes in a row or column
// Check every row
for (r = 0; r < SIZE; r++)
{
sum = 0;
countZero = 0;
for (c = 0; c < SIZE; c++)
{
if (board[r][c] == 0)
countZero++;
else
sum += board[r][c];
}
if (countZero == 1)
{ // A single zero is present
for (c = 0; c < SIZE; c++)
{ // To find the position of the single zero
if (board[r][c] == 0)
{
board[r][c] = 10 - sum; // Replace the single zero with the obvious value
break;
}
}
}
}
// Check every column
for (c = 0; c < SIZE; c++)
{
sum = 0;
countZero = 0;
for (r = 0; r < SIZE; r++)
{
if (board[r][c] == 0)
countZero++;
else
sum += board[r][c];
}
if (countZero == 1)
{ // A single zero is present
for (r = 0; r < SIZE; r++)
{ // To find the position of the single zero
if (board[r][c] == 0)
{
board[r][c] = 10 - sum; // Replace the single zero with the obvious value
break;
}
}
}
}
// Check every box
checkBox(board, 0, 2, 0, 2);
checkBox(board, 0, 2, 2, 4);
checkBox(board, 2, 4, 0, 2);
checkBox(board, 2, 4, 2, 4);
// Check if there are any blank cells
for (r = 0; r < SIZE; r++)
{
for (c = 0; c < SIZE; c++)
{
if (board[r][c] == 0) // Blank cell found
return 1;
}
}
return 0; // No blank cell
}
// This function checks a 2X2 box if there is a single zero.
// If so, it replaces the zero with the obvious value.
// Precond: lrow <= urow, lcol <= ucol, 0 <= lrow, urow, lcol, ucol <= SIZE
void checkBox(int board[][SIZE], int lrow, int urow, int lcol, int ucol)
{
int r, c,
sum = 0, // Sum of elements in the 2X2 box
countZero = 0; // Number of zeroes in the 2X2 box
for (r = lrow; r < urow; r++)
{ // lrow and urow are the lower and upper limits of the rows
for (c = lcol; c < ucol; c++)
{ // lcol and ucol are the lower and upper limits of the columns
if (board[r][c] == 0)
countZero++;
else
sum += board[r][c];
}
}
if (countZero == 1)
{ // A single zero is present
for (r = lrow; r < urow; r++)
{
for (c = lcol; c < ucol; c++)
{ // To find the position of the single zero
if (board[r][c] == 0)
{
board[r][c] = 10 - sum; // Replace the single zero with the obvious value
break;
}
}
}
}
} ```
As you wrote, this algorithm can only solve the simplest puzzles.
Basically, it checks if there is a single zero in any row, column or 2x2 box, and then replace this zero with the missing value.
However, you test it with a more complex puzzle, when no row, column or box have this property. It therefore enter in an infinite loop,
in the solve(.) function.
For example, your code provides the correct answer, with this slightly modified puzzle:
int board[4][4] = {
{2,3,4,0},
{4,0,0,2},
{1,0,0,3},
{0,2,1,0}
};
Related
I have a task where I have to fill an array with 16 random numbers, in random indexes.
4 of those elements have to be -1, and all the other left indexes have to be 0-15, but different from another, meaning it is impossible for two different indexes have the same number (0-15).
Filling 4 random indexes is easy, and so is filling the other indexes with random numbers between 0-15, but how do I feel them in such way that they are necessarily different from each other?
There are also two more conditions which complicate this task much more, the first one is that the number of the index cannot have the same number within it, meaning arr[3] == 3 is impossible, and another condition is that
(m[p] == j && m[j] == mp && m != j)
is something that we must take care of so it won't happen. For example, if arr[2] == 0 and arr[0] == 2, we have to change it so it won't happen.
I'm so confused, I had literally sat 8 hours yesterday in front of this, trying all sort of things, and I have no idea, honestly..
void FillArray(int *sites, int length)
{
int checkarr[N] = { 0 };
int i,
cnt = 0,
j = 0,
t = 0,
k,
times = 0;
int *p = sites;
while (cnt < C)
{
i = rand() % length;
if (p[i] - 1)
cnt = cnt;
p[i] = -1;
cnt++;
}
while (j < length)
{
if (p[j] == -1) j++;
else
{
p[j] = rand() % length;
checkarr[p[j]]++;
j++;
}
}
j =0;
while (j<length)
{
for (k=0; k<length;k++)
{
while (checkarr[k] > 1)
{
while (t < length)
{
if (p[j] == p[t] && p[j] != -1 && j != t)
{
checkarr[p[t]]--;
p[t] = rand() % length;
checkarr[p[t]]++;
times++;
}
else t++;
}
if (times < 11)
{
j++;
t = 0;
times = 0;
}
}
}
}
}
I tried using the Fisher-Yates shuffle method, but for somereason it doesn't even fill the array. I don't know why
while (j
if (p[j] == -1)
j++;
else {
while (m < length) {
m = rand() % length;
if (helpingArray[m] != -2)
{
p[j] = helpingArray[m];
helpingArray[m] = -2;
j++;
}
else if (helpingArray[m] == -2)
{
j = j;
}
for (w = 0; w < length; w++)
{
if (helpingArray[w] == -2)
count++;
}
if (count == 12) {
m = length;
}
}
}
}
}
I hope this will help, I tried to stay in the line with your first draft and what you were going for, just to note that this should work for an N length array. I changed the conditions on your second while to check the conditions before placing the value- and now you don't need to go over the set array and check and update the values.
you can also go another way as was commented here and just fill the array with values with help of one aux array to check each value is used only once and then randomly swap the indexes under the conditions.
I wrote this down but I didn't run tests- so make sure you understand whats going on and upgrade it to your needs. I do recommend using only one aux array, easy on memory and less whiles and checks.
GOOD LUCK
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 16
#define C 4
void FillArray(int *sites, int length) {
/*these aux arrays will keep track if an index was fill of if a value was used*/
int checkarrIndex[N] = { 0 };
int checkarrVal[N] = { 0 };
int i, cnt = 0, full=0; /*full is when all index are filled */
int *p = sites;
while (cnt < C) {
i = rand() % length;
if (checkarrIndex[i] == 0) /* checkarrIndex will let you know if an index has been gvin a value*/
{
++checkarrIndex[i]; /*now checkarrIndex[i] will be one so this index is now not valid for placement next time*/
p[i] = -1;
++full;/*at the end of this while full will equal 4*/
cnt++;
}
}
while (full < length) /*here you need to draw a random index and a random value for it,
not just a random value for a fixed index like you did, if I got this wrong just
go over the free indexes and place a rand value one at a time in the same manner*/
{
int index; /*will store new random index */
int value; /*will store new random value */
index = rand() % N;
value = rand() % N;/*max value is 15*/
while(checkarrIndex[index]!= 0) /*check if this index was already placed */
{
index = rand() % N; /*try a another one */
}
/*I made this while loop to check all the con before filling the array */
while(checkarrVal[value]!= 0 || p[value]== index || index == value) /*check if this value was already used or if p[i]=j&&p[j]=i cond happens and make sure p[a] != a*/
{
value = rand() % N; /*try a another one */
}
++checkarrIndex[index];/*set index as used */
++checkarrVal[value];/*set value as used */
p[index] = value;
++full; /*another place was filled */
}
}
static void PrintArray(int* arr, size_t size)
{
int i = 0 ;
for (i = 0 ; i< size; ++i)
{
printf("%d| ", arr[i]);
}
printf("\n");
}
int main(void)
{
int array[N] = {0};
FillArray(array, N);
PrintArray(array, N);
return 0;
}
I'm not completely sure, but I think the following meets all your special constraints [hopefully].
The random list function is a variation on Fisher Yates. You could recode it to use Durstenfeld if you wish.
I'm not sure that the constraints can be done cleanly in a single pass. That is, apply them while generating the random list.
What I've done is to generate a simple random list. Then, try to detect/fix (by swapping) some of the constraint violations.
Then, fill with negative values, trying to fix the self constraint violations if possible.
If that can't be done, repeat the whole process.
Anyway, here is my version. I split up the large function into several smaller ones. I also added a check function and a diagnostic loop. It is quite a bit different from yours, but other answers did this as well:
#include <stdio.h>
#include <stdlib.h>
#define NEG 4
int opt_N;
int opt_v;
int opt_T;
#ifdef DEBUG
#define dbg(_fmt...) \
do { \
if (opt_v) \
printf(_fmt); \
} while (0)
#else
#define dbg(_fmt...) /**/
#endif
// prtarray -- print array
void
prtarray(int *arr,int len)
{
int idx;
int val;
int hangflg = 0;
int cnt = 0;
for (idx = 0; idx < len; ++idx) {
val = arr[idx];
if (val < 0)
printf(" [%2.2d]=%d",idx,val);
else
printf(" [%2.2d]=%2.2d",idx,val);
hangflg = 1;
if (++cnt >= 8) {
printf("\n");
cnt = 0;
hangflg = 0;
continue;
}
}
if (hangflg)
printf("\n");
}
// fillrand -- generate randomized list (fisher yates?)
void
fillrand(int *arr,int len)
{
char idxused[len];
char valused[len];
int fillcnt = 0;
int idx;
int val;
for (idx = 0; idx < len; ++idx) {
idxused[idx] = 0;
valused[idx] = 0;
}
for (fillcnt = 0; fillcnt < len; ++fillcnt) {
// get random index
while (1) {
idx = rand() % len;
if (! idxused[idx]) {
idxused[idx] = 1;
break;
}
}
// get random value
while (1) {
val = rand() % len;
if (! valused[val]) {
valused[val] = 1;
break;
}
}
arr[idx] = val;
}
}
// swap2 -- swap elements that are (e.g.) arr[i] == arr[arr[i]])
int
swap2(int *arr,int len)
{
int idx;
int lhs;
int rhs;
int swapflg = 0;
dbg("swap2: ENTER\n");
for (idx = 0; idx < len; ++idx) {
lhs = arr[idx];
rhs = arr[lhs];
// don't swap self -- we handle that later (in negfill)
if (lhs == idx)
continue;
if (rhs == idx) {
dbg("swap2: SWAP idx=%d lhs=%d rhs=%d\n",idx,lhs,rhs);
arr[idx] = rhs;
arr[lhs] = lhs;
swapflg = 1;
}
}
dbg("swap2: EXIT swapflg=%d\n",swapflg);
return swapflg;
}
// negfill -- scan for values that match index and do -1 replacement
int
negfill(int *arr,int len)
{
int idx;
int val;
int negcnt = NEG;
dbg("negfill: ENTER\n");
// look for cells where value matches index (e.g. arr[2] == 2)
for (idx = 0; idx < len; ++idx) {
val = arr[idx];
if (val != idx)
continue;
if (--negcnt < 0)
continue;
// fill the bad cell with -1
dbg("negfill: NEGFIX idx=%d val=%d\n",idx,val);
arr[idx] = -1;
}
// fill remaining values with -1
for (; negcnt > 0; --negcnt) {
while (1) {
idx = rand() % len;
val = arr[idx];
if (val >= 0)
break;
}
dbg("negfill: NEGFILL idx=%d\n",idx);
arr[idx] = -1;
}
dbg("negfill: EXIT negcnt=%d\n",negcnt);
return (negcnt >= 0);
}
// fillarray -- fill array satisfying all contraints
void
fillarray(int *arr,int len)
{
while (1) {
// get randomized list
fillrand(arr,len);
if (opt_v)
prtarray(arr,len);
// swap elements that are (e.g. arr[i] == arr[arr[i]])
while (1) {
if (! swap2(arr,len))
break;
}
// look for self referential values and do -1 fill -- stop on success
if (negfill(arr,len))
break;
}
}
// checkarray -- check for contraint violations
// RETURNS: 0=okay
int
checkarray(int *arr,int len)
{
int idx;
int lhs;
int rhs;
int negcnt = 0;
int swapflg = 0;
dbg("checkarray: ENTER\n");
if (opt_v)
prtarray(arr,len);
for (idx = 0; idx < len; ++idx) {
lhs = arr[idx];
if (lhs < 0) {
++negcnt;
continue;
}
rhs = arr[lhs];
if (rhs == idx) {
printf("checkarray: PAIR idx=%d lhs=%d rhs=%d\n",idx,lhs,rhs);
swapflg = 2;
}
if (lhs == idx) {
printf("checkarray: SELF idx=%d lhs=%d\n",idx,lhs);
swapflg = 1;
}
}
if (negcnt != NEG) {
printf("checkarray: NEGCNT negcnt=%d\n",negcnt);
swapflg = 3;
}
dbg("checkarray: EXIT swapflg=%d\n",swapflg);
return swapflg;
}
int
main(int argc,char **argv)
{
char *cp;
int *arr;
--argc;
++argv;
opt_T = 100;
opt_N = 16;
for (; argc > 0; --argc, ++argv) {
cp = *argv;
if (*cp != '-')
break;
switch (cp[1]) {
case 'N':
opt_N = (cp[2] != 0) ? atoi(cp + 2) : 32;
break;
case 'T':
opt_T = (cp[2] != 0) ? atoi(cp + 2) : 10000;
break;
case 'v':
opt_v = ! opt_v;
break;
}
}
arr = malloc(sizeof(int) * opt_N);
for (int tstno = 1; tstno <= opt_T; ++tstno) {
printf("\n");
printf("tstno: %d\n",tstno);
fillarray(arr,opt_N);
if (checkarray(arr,opt_N))
break;
prtarray(arr,opt_N);
}
free(arr);
return 0;
}
My C is rusty, and I don't want to implement a Fisher-Yates shuffle or deal with the bad behavior of C PRNGs, so I'm expressing the algorithm in pseudo-code. Okay, I lie. It's Ruby, but it reads like pseudo-code and is heavily commented to show the logic of the solution. Consider the comments to be the solution, and the stuff in between a concrete illustration that the algorithm being described actually works.
N = 16
# Create + populate an array containing 0,...,N-1
ary = Array.new(N) { |i| i }
# Shuffle it
ary.shuffle!
# Iterate through the array. If any value equals its index, swap it with
# the value at the next index, unless it's the last array element
ary.each_index { |i| ary[i], ary[i + 1] = ary[i + 1], ary[i] if ary.length - i > 1 && ary[i] == i }
# If the last element equals its index, swap it with any other element
# selected at random. The rand function generates a random integer
# between 0, inclusive, and its argument, exclusive.
last = ary.length - 1
if ary[last] == last
random_index = rand(last)
ary[last], ary[random_index] = ary[random_index], ary[last]
end
# Replace 4 randomly selected entries with -1
4.times { ary[rand(ary.length)] = -1 }
# The array now contains unique elements (except for the -1's),
# none of which are equal to their index value
p ary
# Produces, e.g.: [4, 10, -1, 5, 9, -1, 15, 14, 7, 8, 12, 1, -1, 0, -1, 2]
All of this takes O(N) work. If your last constraint is violated, reject the solution and retry.
I believe the following generates a solution to the constraints with uniform distribution over all the solutions that satisfy the constraints:
Put the numbers 0 to 15 in pool A.
Put the numbers 0 to 15 in pool B.
12 times, draw a number a from pool A and a number b from pool B (in each case drawing randomly with uniform distribution and removing the drawn number from its pool, so it will not be chosen again later). Assign m[a] = b.
For each of the four numbers a remaining in pool A, assign m[a] = -1.
For all i from 0 to 15 (inclusive) and all j from i to 15 (inclusive), test whether m[i] == j && m[j] == i (note that this tests for both swaps and for m[i] == i, as it includes i == j). If such a case is found, reject the assignments and repeat the algorithm from the beginning.
I expect algorithmic improvements are possible to reduce or eliminate the frequency of rejection, but this establishes a baseline correct algorithm.
It is also possible to use a single pool instead of two and instead do some rearranging when the −1 elements are assigned, but the algorithm above is more easily expressed.
I am confused with your description. For placing N elements into N positions, I have a solution.
Question:
Place N elements into N positions with constraints:
(1) arr[i] != i;
(2) if arr[i] = j, then arr[j] != i
Solution:
For current element i (0 <= i < N)
(1) Find candidate position count
(a) count = N - i
(b) if arr[i] is empty => count -= 1
else if arr[arr[i]] is empty => count -= 1
(2) Select a random position from candidates
(a) relative_index = random() % count
(Note: relative_index means the position index in candidates)
(b) Find absolute_index by searching candidates
a candidate index j satisfies following constrains
<1> arr[j] is empy
<2> j != i
<3> j != arr[i] when arr[i] is not empty
I posted earlier about a runtime error in my C program but now I'm having another issue with the code. My program runs fine without any errors but it always prints 0 no matter what the input. I've spent the last 4 hours trying to figure out why my code is doing that but I've had no luck. I would really appreciate if someone could give me a hand.
My program takes in an input of a sequence of integers, using another program that works like scanf. Getint() reads an input of a sequence of integers and stops reading the input when it reaches EOF (-1). The number of integers in the sequence is 1000.
// ar_max(a[]) returns the max entry of a
int ar_max(int a[]) {
int max_so_far = a[0];
for (int i = 1; i < 1000; i++) {
if (a[i] > max_so_far) {
max_so_far = a[i];
}
}
return max_so_far;
}
int main() {
int inputnum = getint();
// array containing the distinct numbers seen
int a_num[1000] = {};
// array containing the frequencies of the distinct numbers seen
int a_freq[1000] = {};
int len_n = 0;
while (inputnum != EOF) {
int i = 0;
len_n = i + 1;
int len_f = len_n;
// update the frequency of inputnum if it's already been seen
for (i = 0; i < len_f; i++, len_n += 1) {
if (a_num[i] == inputnum) {
a_freq[i] = a_freq[i] + 1;
}
}
// add inputnum into the array if it hasn't already been seen
if (i == len_n) {
a_num[i+1] = inputnum;
a_freq[i+1] = 1;
}
inputnum = getint();
}
// print the first number with the highest frequency
for (int j = 0; j < len_n; j++) {
if (a_freq[j] == ar_max(a_freq)) {
printf("%d\n", a_num[j]);
break;
}
}
}
For example, an input of
10 20 30 20
should result in 20
The code has the right idea, but it still has some problems.
First, you have two arrays with related information. You keep two lengths for each of these arrays and try to keep the lengths the same. That's complicated. Instead, consider having just one length for both arrays.
When you loop thorugh the array in oder to check whether the given number is already contained in the array:
for (i = 0; i < len_f; i++, len_n += 1) {
if (a_num[i] == inputnum) {
a_freq[i] = a_freq[i] + 1;
}
}
you update then length of the number array with each iteration. You shouldn't, because you are not changing the length of anything while iterating though the loop.
Next, you check whether the number hasn't been found with:
if (i == len_n) ...
That doesn't work, because you update the frequency in the first loop, but don't terminate the loop; your condition will always be true. You can fix this by breaking out of the loop explicitly with break when you have found the number. (Better yet, make the look-up and frequency update a function whose return value indicates whether the element was found and add the elemen if it wasn't.)
When you append the new element:
if (i == len_n) {
a_num[i+1] = inputnum;
a_freq[i+1] = 1;
}
you should, of course, increment the length of the array you append to. In general, appending an item to an array looks like this:
array[len++] = item;
Recall that the first index is zero and that the actual length is one beyond the valid indices.
There are other points:
When you add an element, you should make sure that you don't overflow the array. The dimension of 1000 is generous, but not infinite.
In your function ar_max, you iterate over all 1000 elements of the array. You have initialised the arrays to zero, so the maximum will still be right, but it is better to pass the array size to the function, too, so that you can iterate over only the actual items.
If your function ar_max returned an index instead of a value, you could access both array with that index and you wouldn't need the last loop over j, because j is just that index.
If you have two parallel arrays, it is a good idea to create a struct that hold the item and frequency and always keeps them together. That simplifies the code, because you don't have to keep anything in sync. Such a data layout also lends itself to sorting and filtering other common operations.
Here's a version that implements the fixes described above. It also uses a function to look up an element by value and makes ar_max return an array index instead of a value.
#include <stdlib.h>
#include <stdio.h>
#define MAX 1000
int getint()
{
int x;
if (scanf("%d", &x) < 1) return EOF;
return x;
}
int ar_max(const int a[], int len)
{
if (len == 0) return -1;
int max_so_far = a[0];
int max_index = 0;
for (int i = 1; i < len; i++) {
if (a[i] > max_so_far) {
max_so_far = a[i];
max_index = i;
}
}
return max_index;
}
int ar_find(const int a[], int len, int which)
{
for (int i = 0; i < len; i++) {
if (a[i] == which) return i;
}
return -1;
}
int main()
{
int inputnum = getint();
int a_num[MAX] = { }; // distinct numbers seen
int a_freq[MAX] = { }; // frequencies of the distinct numbers
int len = 0; // actual length of both arrays
while (inputnum != EOF) {
int i = ar_find(a_num, len, inputnum);
if (i < 0) { // append new item
if (len >= MAX) {
fprintf(stderr, "Array size %d exceeded\n", MAX);
exit(1);
}
a_num[len] = inputnum;
a_freq[len] = 1;
len++;
} else { // increment existing item
a_freq[i]++;
}
inputnum = getint();
}
int imax = ar_max(a_freq, len);
if (imax >= 0) {
printf("%d (%d times)\n", a_num[imax], a_freq[imax]);
} else {
puts("Empty input.");
}
return 0;
}
int main()
{
// array containing the distinct numbers seen
int a_num[1000] = {0};
// array containing the frequencies of the distinct numbers seen
int a_freq[1000] = {0};
int len_n = 0;
int i = 0, j = 0;
// Read first entry
int inputnum = getint();
if (EOF == inputnum)
{
printf("No valid number input given\n");
return -1;
}
// Make first entry in a_num and a_freq
a_num[0] = inputnum;
a_freq[0] = 1;
// Update len_n to 1
len_n = 1;
// Get new entry from user and update number array and frequency array
inputnum = getint();
while (inputnum != EOF)
{
// update the frequency of inputnum if it's already been seen
for (i = 0; i < len_n; i++)
{
if (a_num[i] == inputnum)
{
a_freq[i] = a_freq[i] + 1;
break;
}
}
// add inputnum into the array if it hasn't already been seen
if (i == len_n)
{
a_num[i] = inputnum;
a_freq[i] = 1;
// Update len_n
len_n++;
}
// Check if we have already reached 1000
if (1000 == len_n)
{
printf("Reached 1000 entry read\n");
break;
}
// Next entry
inputnum = getint();
}
// print the number with the highest frequency
int max_freq = ar_max(a_freq);
for (j = 0; j < len_n; j++)
{
if (a_freq[j] == max_freq)
{
printf("%d\n", a_num[j]);
break;
}
}
}
NOTE:
1. #define MAX_SIZE 1000 can be used since hardcoded value 1000 is used repeatedly in code. This will help when you have use new size (say 1500) and you need to change only the #define MAX_SIZE 1500, other code remains unchanged.
2. ar_max() function can be modified to give array index where max occurs to avoid the for loop in main to find the array index. e.g.
int ar_max(int a[])
{
int index = 0;
int max_so_far = a[0];
for (int i = 1; i < 1000; i++) {
if (a[i] > max_so_far) {
max_so_far = a[i];
index = i;
}
}
return index;
}
In main():
printf("%d\n", a_num[ar_max(a_freq)]);
I have found a function on internet here for solving my problem on Sudoku written in C language.I have almost everything done but I am stuck here, I can't check the 3x3 box if any value is duplicated:
/**
* Check if a value contains in its 3x3 box for a cell.
* #param row current row index.
* #param col current column index.
* #return true if this cell is incorrect or duplicated in its 3x3 box.
*/
private boolean containedIn3x3Box(int row, int col, int value) {
// Find the top left of its 3x3 box to start validating from
int startRow = row / 3 * 3;
int startCol = col / 3 * 3;
// Check within its 3x3 box except its cell
for (int i = startRow; i < startRow + 3; i++)
for (int j = startCol; j < startCol + 3; j++) {
if (!(i == row && j == col)) {
if (cells[i][j] == value){
return true;
}
}
}
return false;
}
Up here is the function and I put it in my program here:
int valid(int k, int ii, int jj)
{
int i,start,final,j;
start=ii/3*3;
final=jj/3*3;
for(i = 1; i <= 9; ++i) {
if (i != ii && v[i][jj] == k)
return 0;
if (i != jj && v[ii][i] == k)
return 0;
}
for(i=start;i<=start+3;i++)
for(j=final;j<=final+3;j++)
{
if(!(i==ii && j==jj))
{
if(v[i][j]==k)
return 0;
}
}
return 1;
}
I have read on the website where I took this function and tried to understand the program. The program compares values with value part. My loop is not working well.
Your problem is with the loop start and end value.
The example uses 0-based counts. The three triplets have indexes (0,1,2) (3,4,5) (6,7,8).
You want to use 1-based loops.
You have missed to change the lower limit on the double loop:
int valid(int k, int ii, int jj)
{
int i,start,final,j;
start=ii/3*3;
final=jj/3*3;
for(i = 1; i <= 9; ++i) {
if (i != ii && v[i][jj] == k)
return 0;
if (i != jj && v[ii][i] == k)
return 0;
}
for(i=start+1;i<=start+3;i++) // Changed lower limit
for(j=final+1;j<=final+3;j++) // Changed lower limit
{
if(!(i==ii && j==jj))
{
if(v[i][j]==k)
return 0;
}
}
return 1;
}
Consider a zero-indexed array A of N integers. Indices of this array are integers from 0 to N−1. Take an index K.
Index J is called an ascender of K if A[J] > A[K]. Note that if A[K] is a maximal value in the array A, then K has no ascenders.
Ascender J of K is called the closest ascender of K if abs(K−J) is the smallest possible value (that is, if the distance between J and K is minimal).
Note that K can have at most two closest ascenders: one smaller and one larger than K.
Here is a C++ solution where complexity is O(n).
Note that there are two loops however each iteration the number of element goes by a factor of 1/2 or the search range goes up by a factor of x2.
For example the first iteration take N time, but the second iteration is already N/2.
vector<long> ascender(vector <long> A)
{
long N = A.size();
vector<long> R(N,0);
vector<long> IndexVector(N,0); //This vector contains the index of elements with R=0
vector<long> RangeVector(N,0); //This vector define the loop range for each element
IndexVector[N-1]=N-1;
unsigned long CompxTest = 0;
for (long counter=0;counter<N;counter++)
{
IndexVector[counter] = counter; // we start that all elements needs to be consider
RangeVector[counter] = 1; // we start by looking only and neighbors
}
long Length = N;
long range;
while (Length>1)
{
long index = 0;
cout<<endl<<Length;
long J;
for (long counter=0;counter<Length;counter++)
{
CompxTest++; // Just to test complexity
J = IndexVector[counter]; // Get the index that need to be consider
range = RangeVector[J];
//cout<<" ("<<A[J]<<","<<J<<")";
if (range > N)
{
cout<<endl<<"Mini assert "<<range<<" N "<<N;
break;
}
if (J<(N-range) && A[J+range] > A[J])
{
R[J] = range;
}
if (J<(N-range) && A[J+range] < A[J] && R[J+range]==0)
{
R[J+range] = range;
}
if (J<(N-range) && A[J] == A[J+range] && R[J+range]==0)
{
R[J+range] = - range;
}
if (R[J]==0) // Didn't find ascender for this element - need to consider in next iteration
{
if (R[J+range]>2) //We can increase the range because the current element is smaller
RangeVector[J] += R[J+range]-2;
if (R[J+range]<-2)
RangeVector[J] += -R[J+range]-2;
RangeVector[J]++;
IndexVector[index] = J;
index++;
}
}
Length = index;
}
for (long counter=0;counter<N;counter++)
{
if (R[counter] < 0)
{
unsigned Value = abs(R[counter]);
if (counter+Value<N && A[counter]<A[counter+Value])
R[counter] = Value;
if (counter > Value && R[counter-Value]==0)
R[counter] = 0;
R[counter] = Value + R[counter-Value];
if (counter > Value && Value < R[counter - Value])
{
long PossibleSolution = R[counter - Value] + Value;
if (PossibleSolution <N && A[PossibleSolution]>A[counter])
R[counter] = abs(counter - PossibleSolution);
}
}
}
cout<<endl<<"Complex "<<CompxTest;
return R;
}
//
// C++ using multimap. -- INCOMPLETE
// The multimap MM is effectively the "inverse" of the input array AA
// since it is ordered by pair(value, index), where index refers to the index in
// input array AA, and value is the value in AA at that index.
// Input AA is of course ordered as (index, value).
// So when we read out of MM in value order, (a sorted set of values), each value
// is mapped to the index in the original array AA.
//
int ascender(int AA[], int N, int RR[]) {
multimap<int, int> MM;
// simply place the AA array into the multimap
int i;
for (i = 0; i < N; i++) {
int value = AA[i];
int index = i;
MM.insert(make_pair(value, index));
}
// simply read the multimap in order,
// and set output RR as the distance from one value's
// original index to the next value's original index.
//
// THIS code is incomplete, since it is wrong for duplicate values.
//
multimap<int, int>::iterator pos;
for (pos = MM.begin(); pos != MM.end(); ++pos) {
int value = pos->first;
int index = pos->second;
++pos;//temporarily move ahead to next item
// NEED to FURTHER CONSIDER repeat values in setting RR
RR[index] = (pos)->second - index;
--pos;
}
return 1;
}
1. Sort the array (if not pre-sorted)
2. Subtract every element with its adjacent element and store result in another
array.
Example: 1 3 5 6 8 -----> (after subtraction) 2 2 1 2
3. Find the minimal element in the new array.
4. Device a logic which would relate the minimal element in the new array to the
two elements in the original one.
public class Solution {
final static int MAX_INTEGER = 2147483647;
public static int maximal(int[] A) {
int max = A[0];
int length = A.length;
for (int i = 1; i < length; i++) {
if (A[i] > max) {
max = A[i];
}
}
return max;
}
public static int ascender(int[] a,int length, int k) {
int smallest = MAX_INTEGER;
int index = 0;
if (k<0 || k>length-1) {
return -1;
}
for (int i = 0; i < length; i++) {
// Index J is called an ascender of K if A[J] > A[K].
if(a[i] > a[k]) {
int abs = Math.abs(i-k);
if ( abs < smallest) {
smallest = abs;
index = i;
}
}
}
return index;
}
public static int[] array_closest_ascenders(int[] A) {
int length = A.length;
int[] R = new int[length];
for (int K = 0; K < length; K++) {
// Note that if A[K] is a maximal value in the array A,
// then K has no ascenders.
// if K has no ascenders then R[K] = 0.
if (A[K] == maximal(A)) {
R[K] = 0;
break;
}
// if K has the closest ascender J, then R[K] = abs(K-J);
// that is, R[K] is equal to the distance between J and K
int J = ascender(A, A.length, K);
if (J != -1) {
R[K] = Math.abs(K - J);
}
}
return R;
}
public static void main(String[] args) {
int[] a = { 4, 3, 1, 4, -1, 2, 1, 5, 7 };
/* int[] a = {-589630174, 806785750, -495838474, -648898313,
149290786, -798171892, 584782920, -288181260, -252589640,
133741336, -174886978, -897913872 }; */
int[] R = array_closest_ascenders(a);
for (int element : R) {
System.out.print(element + " ");
}
}
}
Some notes about the code. I guess break in array_closest_ascenders method should be replaced by continue so that all elements are analyzed for their ascenders.
And, surely, maximal(A) have to be moved out of a loop; instead assign maximal value to some variable before entering the loop and use it within the loop, thus avoiding redundant calculation of max value.
Here is C# Solution
class Program
{
static void Main(string[] args)
{
int[] A = new int[] { 4, 3, 1, 4, -1, 2, 1, 5, 7 };
int[] B = new int[A.Length];
int[] R = new int[A.Length];
Program obj = new Program();
obj.ABC(A,B, R);
}
public void ABC(int[] A,int[]B, int[] R)
{
int i, j, m,k;
// int temp = 0;
int n = A.Length - 1;
for (i = 0; i < n; i++)
{
for (j = 0; j <= n; j++)
{
if (A[i] < A[j])
{
m = Math.Abs(j - i);
R[i] = m;
break;
}
}
for (j = i-1; j > 0; j--)
{
if (A[i] < A[j])
{
k = Math.Abs(j - i);
B[i] = k;
break;
}
}
}
for (i = 0; i < n; i++)
{
if (R[i] > B[i] && (B[i] == 0))
{
R[i] = R[i];
//Console.WriteLine(R[i]);
//Console.ReadLine();
}
else { R[i] = B[i]; }
}
}
}
Basically in the search function I compare the first element of the array with the one immediately right, if it's bigger this means it is the first closest ascendant. For the other elements I compare the one immediately at left and afterward the one immediately right his first right element. The first one which is bigger is the closest ascendant, and I keep iterate this way until I don't find an element bigger than one I am considering or I return 0.
class ArrayClosestAscendent {
public int[] solution(int[] A) {
int i;
int r[] = new int[A.length];
for(i=0;i<A.length;i++){
r[i] = search(A, i);
}
return r;
}
public int search(int[] A, int i) {
int j,k;
j=i+1;
k=i-1;
int result = 0;
if(j <= A.length-1 && (A[j]>A[i]))
return Math.abs(j-i);
j++;
while(k>=0 || j < A.length){
if(k >= 0 && A[k] > A[i]){
return Math.abs(i-k);
}else if(j < A.length && A[j] > A[i]){
return Math.abs(i-j);
}else{
j++;
k--;
}
}
return result;
}
}
I was trying to calculate the determinant of a 3 * 3 matrix (or more) with the matrix values ranging from (-1, to 1). However, I get a result of 0 when I calculate the determinant.
[...]
srand(time(NULL));
//Random generation of values between -1 and 1
for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
{
temp = (rand() % (500)) + 0;
temp = temp/250;
array[i][j] = (temp - 1);
}
[...]
double array2[10][10];
double detrm = 0;
int s = 1;
int i, j, m, n, c;
for (c = 0; c < x; c++)
{
m = 0;
n = 0;
for (i = 0; i < x; i++)
{
for (j = 0; j < x; j++)
{
array2[i][j] = 0;
if (i != 0 && j != c)
{
array2[m][n] = a[i][j];
if ( n < (x - 2))
{
n++;
}
else
{
n = 0;
m++;
}
}
}
}
detrm = detrm + (s*a[0][c]*determinant(array2, (x - 1)));
s = -1*s;
}
return(detrm);
This may Help - see comments within the code for an explanation:
static int CalcDeterminant(vector<vector<int>> Matrix)
{
//this function is written in c++ to calculate the determinant of matrix
// it's a recursive function that can handle matrix of any dimension
int det = 0; // the determinant value will be stored here
if (Matrix.size() == 1)
{
return Matrix[0][0]; // no calculation needed
}
else if (Matrix.size() == 2)
{
//in this case we calculate the determinant of a 2-dimensional matrix in a
//default procedure
det = (Matrix[0][0] * Matrix[1][1] - Matrix[0][1] * Matrix[1][0]);
return det;
}
else
{
//in this case we calculate the determinant of a squared matrix that have
// for example 3x3 order greater than 2
for (int p = 0; p < Matrix[0].size(); p++)
{
//this loop iterate on each elements of the first row in the matrix.
//at each element we cancel the row and column it exist in
//and form a matrix from the rest of the elements in the matrix
vector<vector<int>> TempMatrix; // to hold the shaped matrix;
for (int i = 1; i < Matrix.size(); i++)
{
// iteration will start from row one cancelling the first row values
vector<int> TempRow;
for (int j = 0; j < Matrix[i].size(); j++)
{
// iteration will pass all cells of the i row excluding the j
//value that match p column
if (j != p)
{
TempRow.push_back(Matrix[i][j]);//add current cell to TempRow
}
}
if (TempRow.size() > 0)
TempMatrix.push_back(TempRow);
//after adding each row of the new matrix to the vector tempx
//we add it to the vector temp which is the vector where the new
//matrix will be formed
}
det = det + Matrix[0][p] * pow(-1, p) * CalcDeterminant(TempMatrix);
//then we calculate the value of determinant by using a recursive way
//where we re-call the function by passing to it the new formed matrix
//we keep doing this until we get our determinant
}
return det;
}
}
};
You have a crufty way of updating m and n. You should increment m in the outer loop over i, and initialize n within the outer loop and increment it within the inner loop. I think that your code would work as you wrote it, but I think that your conditional should have been i < n-1 instead of i < n-2. But instead of changing the fewest number of characters to get the code to work, I recommend restructuring the increments so that the issue doesn't arise.