Donald Knuth algorithm for Mastermind - c

I'm working onto the Donald Knuth 1977 algorithm for Mastermind (here). I've implemented some steps, but I don't know how to calculate the number of possibilites that would be eliminated for each possible score.
Integer Bulls <- 0
WHILE Bulls <= 4
Integer Cows <- 0
WHILE Cows <= 4
Integer CurrentSetSize <- 0
WHILE CurrentSetSize <= Set.size
// Now, I should know if this possibility can be eliminated. But how ?
END WHILE
END WHILE
END WHILE
Do you have any way to do this ?
Thanks.
Edit : I did it with C. It isn't Mastermind in reality but Bulls & Cows, but it's the same.
// ASCII-compatible
#define POSSIBILITIES 6720
struct Guess {
int i[5];
};
struct Answer {
int bulls;
int cows;
};
static struct Set {
struct Guess value;
int score;
} *CurrentSet;
void
initSet(void)
{
for (int i = 'a'; i <= 'h'; ++i) {
for (int j = 'a'; j <= 'h'; ++j) {
if (j == i) continue;
for (int k = 'a'; k <= 'h'; ++k) {
if (k == j || k == i) continue;
for (int l = 'a'; l <= 'h'; ++l) {
if (l == k || l == j || l == i) continue;
for (int m = 'a'; m <= 'h'; ++m) {
if (m == l || m == k || m == j || m == i) continue;
CurrentSet->value.i[0] = i;
CurrentSet->value.i[1] = j;
CurrentSet->value.i[2] = k;
CurrentSet->value.i[3] = l;
CurrentSet->value.i[4] = m;
CurrentSet->score = 0;
}
}
}
}
}
}
void
computeScore(int index)
{
struct answer p;
for (p.bulls = 0; p.bulls <= 4; ++p.bulls) {
for (p.cows = 0; p.cows <= 4; ++p.cows) {
for (int i = 0; i < POSSIBILITIES; ++i) {
}
}
}
}
void
updateSet(void)
{
for (int i = 0; i < POSSIBILITIES; ++i)
computeScore(i);
}

Related

confused about dynamic programming state

I was trying to solve the problem where if I was given an array of int which allows duplicate,
I need to find the count of how many permutation of this array there are such that each adjacent pair of integer in the array whose sum is a perfect square. I have derived the dp solution, but it was wrong, I looked at the solution, it was very similar to mine but with slight difference, can someone please look at it and tell me why mines won't work but the sample answer does?
My train of thought is, if I have g[i][j] == 1 telling me i and j forms a pair whose sum is a perfect square, 0 otherwise. And I have a dp[s][j] tells me if my node visited state is s, whose binary representation tells me all the node index that I have visited, and it ends in node with index j, I need DP for hamitonian path in a graph to calculate all possible ways to reach state s that ends in node index j, then the answer will be the sum of state s where all node is visited and it ends in node from 0 to n - 1. In terms of avoiding duplicate, I sort the input array of number and if in same layer of search, if we have nums[i - 1] == nums[i] but we have not visited nums[i], it means we just back out from an earlier dfs that visited the same number, we will not do that again.
I will paste the code here
The below is my answer, which will fail if the array contains duplicate
int n = nums.length;
int[][] dp = new int[1 << n][n];
int[][] g = new int[n][n];
Arrays.sort(nums);
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
if(i != j && (Math.ceil(Math.sqrt(nums[i] + nums[j])) ==
Math.sqrt(nums[i] + nums[j]))) {
g[i][j] = 1;
}
}
}
for(int s = 0; s < (1 << n); s++) {
for(int j = 0; j < n; j++) {
if(s == (1 << j)) {
dp[1 << j][j] = (j == 0 || nums[j - 1] != nums[j]) ? 1 : 0;
continue;
}
if((s & (1 << j)) == 0) continue;
for(int i = 0; i < n; i++) {
if(g[i][j] == 0) continue;
if((s & (1 << i)) == 0) continue;
if(i > 0 && nums[i - 1] == nums[i] && ((s & (1 << (i - 1))) == 0)) continue;
dp[s][j] += dp[s & ~(1 << j)][i];
}
}
}
int res = 0;
int finish = (1 << n) - 1;
for(int i = 0; i < n; i++) {
res += dp[finish][i];
}
return res;
The below is the sample answer:
int n = nums.length;
boolean[][] g = new boolean[n][n];
int[][] dp = new int[1 << n][n];
Arrays.sort(nums);
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
if(Math.floor(Math.sqrt(nums[i] + nums[j])) * Math.floor(Math.sqrt(nums[i] + nums[j])) == nums[i] + nums[j]) {
g[i][j] = g[j][i] = true;
}
}
}
for(int i = 0; i < nums.length; i++) {
if(i == 0 || (i > 0 && nums[i - 1] != nums[i]))
dp[1 << i][i] = 1;
}
for(int s = 0; s < (1 << n); s++) {
for(int j = 0; j < n; j++) {
if((s & (1 << j)) == 0) continue;
for(int i = 0; i < n; i++) {
if(g[i][j]) {
if((s & (1 << i)) != 0) continue;
if(i > 0 && nums[i] == nums[i - 1] && ((s & (1 << (i - 1))) == 0)) continue;
dp[s | (1 << i)][i] += dp[s][j];
}
}
}
}
int ans = 0;
for(int l = 0; l < n; l++) {
ans += dp[(1 << n) - 1][l];
}
return ans;

optimizing C code with imbedded for loops

void evolve(board prv, board nxt){
int i, j;
int n;
printf("\rGeneration %d\n", generation++);
if (printLazy == 1){
lazyPrint(prv);
for (j=0; j < WIDTH; ++j) {
for (i = 0; i < HEIGHT; ++i) {
n = neighbors(prv, i, j);
if (prv[i][j] && (n == 3 || n == 2))
nxt[i][j] = true;
else if (!prv[i][j] && (n == 3))
nxt[i][j] = true;
else
nxt[i][j] = false;
}
}
}
** Some asked me to add the neighbors method so
static int neighbors (board b, int i, int j) {
int n = 0;
int i_left = max(0,i-1);
int i_right = min(HEIGHT, i+2);
int j_left = max(0,j-1);
int j_right = min(WIDTH, j+2);
int ii, jj;
for (ii = i_left; ii < i_right; ++ii) {
for (jj = j_left; jj < j_right; ++jj) {
n += b[ii][jj];
}
}
return n - b[i][j];
}
So I am working on optimizing this so that it will go faster and I'm stuck on how to optimize this more. Here's what I have so far
void evolve(board prv, board nxt) {
register int i, j;
int n;
bool next;
printf("\rGeneration %d\n", generation++);
if (printLazy == 1){
lazyPrint(prv);
}
for (j=0; j < WIDTH; ++j) {
for (i = 0; i < HEIGHT; ++i) {
n = neighbors(prv, i, j);
if (prv[i][j])
if (n == 2)
next = true;
else if (n == 3)
next = true;
else
next = false;
else
if(n == 3)
next = true;
else
next = false;
nxt[i][j] = next;
}
}
}
Is there a better way to do this or are there any resources or videos y'all recommend?
Thanks, any help is appreciated.
Some ideas Inline your function neighbors(). Or turn it into a macro. Tidy up the conditional. To unroll the inner loop replace every use of i with the literal values so your code looks like :
for (j =0;.......
n = fun(prev, 0 ,j);
If.....
n = fun(prev, 1, j);
if......
and so on.
If the value of HEIGHT was let's say 100, then you get a code explosion of 100 function calls and 100 compound conditionals. Even worse if you unroll the outer loop.
If n was limited to say 8 neighbors, use a lookup table
bool foo[2][8] = { [1][2] = true, [1][3] = true, [0][3] = true };
for (j=0; j < WIDTH; ++j) {
for (i = 0; i < HEIGHT; ++i) {
n = neighbors(prv, i, j);
nxt[i][j] = foo[prv[i][j]][n];
}
}
A common weakness is the neighbors(prv, i, j) function itself. One trick to to oversize the 2D array by 1 on all four sides and populate the edge with false so neighbors() can always check 8 neighbors as it is never used on the edge/corners.
Making sure the 2nd dimension is a power of 2 helps also - simplifies index calculation. So if the original array way 12*11, make the new array (1+12+1)*(1+11+1+4) or 14*16.

Generate all possible permutations in C

I'm trying to develop a code to solve the Travelling salesman problem in C, but I have some restrictions: I can only use "for, "while", "do", arrays, matrix and simple things like that, so, no functions or recursion (unfortunately).
What I've got so far:
The user will will type the city coordinates X and Y like this:
8.15 1.58
9.06 9.71
1.27 9.57
9.13 4.85
The code to storage the coordinates.
float city[4][2];
int i;
for (i=0; i<4; i++)
scanf("%f %f", &cidade[i][0], &cidade[i][1]);
There are 4 cities, so "i" goes from 0 to 3. X and Y are storaged on the second dimension of the matrix, [0] and [1].
The problem now is that I have to generate ALL POSSIBLE permutations of the first dimension of the matrix. It seems easy with just 4 cities, because all possible routes are (it must starts with city A everytime):
A B C D
A B D C
A C B D
A C D B
A D C B
A D B C
But I'll have to expand it for 10 cities. People have told me that it will use 9 nested foor loops, but I'm not being able to develop it =(
Can somebody give me an idea?
Extending to 10 (and looking up city names) as an exercise for the reader. And it's horrid, but that's what you get with your professor's limitations
#include <stdio.h>
int main(void) {
for (int one = 0; one < 4; one++) {
for (int two = 0; two < 4; two++) {
if (two != one) {
for (int three = 0; three < 4; three++) {
if (one != three && two != three) {
for (int four = 0; four < 4; four++)
if (one != four && two != four && three != four) {
printf("%d %d %d %d\n", one, two, three, four);
}
}
}
}
}
}
return 0;
}
This is based on https://stackoverflow.com/a/3928241/5264491
#include <stdio.h>
int main(void)
{
enum { num_perm = 10 };
int perm[num_perm];
int i;
for (i = 0; i < num_perm; i++) {
perm[i] = i;
}
for (;;) {
int j, k, l, tmp;
for (i = 0; i < num_perm; i++) {
printf("%d%c", perm[i],
(i == num_perm - 1 ? '\n' : ' '));
}
/*
* Find largest j such that perm[j] < perm[j+1].
* Break if no such j.
*/
j = num_perm;
for (i = 0; i < num_perm - 1; i++) {
if (perm[i + 1] > perm[i]) {
j = i;
}
}
if (j == num_perm) {
break;
}
for (i = j + 1; i < num_perm; i++) {
if (perm[i] > perm[j]) {
l = i;
}
}
tmp = perm[j];
perm[j] = perm[l];
perm[l] = tmp;
/* reverse j+1 to end */
k = (num_perm - 1 - j) / 2; /* pairs to swap */
for (i = 0; i < k; i++) {
tmp = perm[j + 1 + i];
perm[j + 1 + i] = perm[num_perm - 1 - i];
perm[num_perm - 1 - i] = tmp;
}
}
return 0;
}

printing an string in cross manner using c program

I'am trying to write a program for converting the given string in cross manner(i.e Diagonal from left-right and from right-left). If the string length is even it returns a message else arrange it in a cross form.
The code is:
#include<stdio.h>
#include<string.h>
int main()
{
char str[50];
char str2[50][50];
int lenstr;
int i,j;
char temp;
printf("Enter the string :\n");
scanf("%s",str);
lenstr = strlen(str);
if(lenstr %2 == 0)
{
printf("The string length must be an odd length");
}
else
{
j = 0;
temp = 0;
for(i = 0;i == lenstr;i++)
{
str2[i][j] = str[i];
j = j + 1;
}
for(i = lenstr; i==0 ;i--)
{
j = lenstr;
str2[i][j] = str[temp];
temp = temp + 1;
j = j - 1;
}
for(i = 0;i<lenstr;i++)
{
for(j = 0;j<lenstr;j++)
{
printf("%c",str2[i][j]);
}
printf("\n");
}
}
return 0;
}
The output to the program must be for example: geeks
g g
e e
e
k k
s s
But the output obtained consists of different shapes(like heart,smiley face etc...). Explain the concept behind to correct it and if can please explain when using pointers for the same program. Any help appreciated.
In your code, you need to change the for loop condition checking expressions, like i == lenstr and later i==0. They are not entering the loop, essentially.
Instead, you can replace the whole block
for(i = 0;i == lenstr;i++)
{
str2[i][j] = str[i];
j = j + 1;
}
for(i = lenstr; i==0 ;i--)
{
j = lenstr;
str2[i][j] = str[temp];
temp = temp + 1;
j = j - 1;
}
in your code by
for(i = 0;i<lenstr;i++)
for(j = 0;j<lenstr;j++)
str2[i][j] = ' '; //fill 2D array with space
for(i = 0;i < lenstr;i++)
{
str2[i][i] = str[i]; //set the character
str2[i][lenstr- i -1] = str[i]; //reverse position
}
and get the desired output.
See it LIVE.
Your logic to store diagonal string seems to be wrong. In the first loop you store left-right diagonal and your index goes from 0 to length-1 and your column starts from 0; increment it by 1. Its same for right-left diagonal, only difference being column starts from length-1 and ends at 0. Hence you need to initialize temp = lenstr -1;
temp = lenstr -1;
for(i = 0;i <lenstr;i++)
{
str2[i][j] = str[i];
j = j + 1;
}
for(i = 0;i <lenstr;i++)
{
str2[i][temp] = str[i];
temp = temp - 1;
}
I think the problem is that str2 is not getting initialized. The first two for loops should be something like
for(i = 0;i < lenstr;i++)
and
for(i = lenstr; i>=0 ;i--)
Here is my five cents. The program allows to enter words with an odd or even number of letters.
Enjoy!:)
#include <stdio.h>
#include <string.h>
#define N 25
int main(void)
{
while ( 1 )
{
char s[N];
printf( "Enter a string less than %zu characters (Enter-exit): ", N );
if ( !fgets( s, N, stdin ) || s[0] == '\n' ) break;
size_t n = strlen( s );
if ( s[n-1] == '\n' ) s[--n] = '\0';
printf( "\n" );
for ( size_t i = 1, j = n; i <= n; i++, j-- )
{
char c = s[i-1];
if ( i < j ) printf( "%*c%*c\n", i, c, j - i, c );
else if ( j < i ) printf( "%*c%*c\n", j, c, i - j, c );
else printf( "%*c\n", i, c );
}
}
return 0;
}
If to enter
Stackoverflow
hello
then the program output will be
Enter a string less than 25 characters (Enter-exit): Stackoverflow
S S
t t
a a
c c
k k
o o
v
e e
r r
f f
l l
o o
w w
Enter a string less than 25 characters (Enter-exit): hello
h h
e e
l
l l
o o
Enter a string less than 25 characters (Enter-exit):
import java.util.*;
public class CrossCharacter {
public static void main(String[] args){
Scanner in = new Scanner(System.in);
String str = in.next();
int len = str.length();
char[][] ch_matrix = new char[len][len];
len--;
for(int i=0;i<=len;i++)
ch_matrix[i][i] = ch_matrix[i][len-i] = str.charAt(i);
for(int i=0;i<=len;i++){
for(int j=0;j<=len;j++)
System.out.print(ch_matrix[i][j]);
System.out.println();
}
}
}
# include<stdio.h>
void main() {
char n[100],temp;
int i = 0, j;
scanf("%s", &n);
m = strlen(n);
for(i = 0; i <= m - 1;)
temp[i];
i++;
for(j = 0; j < m - 1; j++)
{
if(i == j + 1 || j == m - 1 - i + 1)
printf("%c",temp);
else
printf(" "):
}
printf("\n");
getch();
}

Knuth-Morris-Pratt implementation in pure C

I have the next KMP-implementation:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int kmp(char substr[], char str[])
{
int i, j, N, M;
N = strlen(str);
M = strlen(substr);
int *d = (int*)malloc(M * sizeof(int));
d[0] = 0;
for(i = 0, j = 0; i < M; i++)
{
while(j > 0 && substr[j] != substr[i])
{
j = d[j - 1];
}
if(substr[j] == substr[i])
{
j++;
d[i] = j;
}
}
for(i = 0, j = 0; i < N; i++)
{
while(j > 0 && substr[j] != str[i])
{
j = d[j - 1];
}
if(substr[j] == str[i])
{
j++;
}
if(j == M)
{
free(d);
return i - j + 1;
}
}
free(d);
return -1;
}
int main(void)
{
char substr[] = "World",
str[] = "Hello World!";
int pos = kmp(substr, str);
printf("position starts at: %i\r\n", pos);
return 0;
}
You can test it here: http://liveworkspace.org/code/d2e7b3be72083c72ed768720f4716f80
It works well on small strings, and I have tested it with a large loop, on this way all is fine.
But if I change the substring I'm searching for and the complete string to these:
char substr[] = "%end%",
str[] = "<h1>The result is: <%lua% oleg = { x = 0xa }
table.insert(oleg, y) oleg.y = 5 print(oleg.y) %end%></h1>";
Only after first try, this implementation fails...
Please, could you help me with repairing implementation of KMP to make the algorithm work with such data in strings...
In one place you deviate from your source, the source has
while(j>0 && p[j]!=p[i]) j = d[j-1];
if(p[j]==p[i])
j++;
d[i]=j;
while you have
while(j > 0 && substr[j] != substr[i])
{
j = d[j - 1];
}
if(substr[j] == substr[i])
{
j++;
d[i] = j;
}
being deceived by the source's indentation. In the source, there are no braces around the if() branch, so only the increment j++; is controlled by the if; d[i] = j; is unconditional.
Then, the source has an error, probably due to the unusual use of indices. The correct way to set up the array is
int *d = (int*)malloc(M * sizeof(int));
d[0] = 0;
for(i = 1, j = 0; i < M; i++)
{
while(j > 0 && substr[j-1] != substr[i-1])
{
j = d[j - 1];
}
if(substr[j] == substr[i])
j++;
d[i] = j;
}
But it's confusing, since the setup here uses the indices i-1 and j-1 as well as i and j to determine d[i]. The usual way to implement it is different; the way it is implemented in C#. Since that's the form you find in most sources, it's far easier to convince yourself of the correctness of that.

Resources