I'm having trouble with the alpha-beta pruning algorithm from Wikipedia:
function alphabeta(node, depth, α, β, Player)
if depth = 0 or node is a terminal node
return the heuristic value of node
if Player = MaxPlayer
for each child of node
α := max(α, alphabeta(child, depth-1, α, β, not(Player) ))
if β ≤ α
break (* Beta cut-off *)
return α
else
for each child of node
β := min(β, alphabeta(child, depth-1, α, β, not(Player) ))
if β ≤ α
break (* Alpha cut-off *)
return β
Specifically the recursive call of alpha-beta. I keep getting a SegFault error on the first pass of alpha-beta.
Here is my alpha-beta function:
int alphabeta(int board[9], int depth, int alpha, int beta, bool max_player) {
int score = 0;
max_player = true;
if(depth == 0){
return score;
}
if(max_player) {
alpha = INT_MIN;
while (depth != 0) {
score = alphabeta(board[9], depth - 1, alpha, beta, !max_player); <--- where error originates
alpha = MAX(alpha, score );
if (beta <= alpha) break;
}
return alpha;
}
else {
beta = INT_MAX;
while (depth != 0) {
score = alphabeta(board[9], depth - 1, alpha, beta, !max_player);
beta = MIN(beta, score );
if (beta <= alpha) break;
}
return beta;
}
}
with the overall implementation here:
# include "stdio.h"
# include "limits.h"
int MAX (int x, int y) {
if (x > y) {
return x;
}
else {
return y;
}
}
int MIN (int x, int y) {
if (x < y) {
return x;
}
else {
return y;
}
}
char gridChar(int i) {
switch(i) {
case -1:
return 'X';
case 0:
return ' ';
case 1:
return 'O';
}
}
void draw(int b[9]) {
printf(" %c | %c | %c\n",gridChar(b[0]),gridChar(b[1]),gridChar(b[2]));
printf("---+---+---\n");
printf(" %c | %c | %c\n",gridChar(b[3]),gridChar(b[4]),gridChar(b[5]));
printf("---+---+---\n");
printf(" %c | %c | %c\n",gridChar(b[6]),gridChar(b[7]),gridChar(b[8]));
}
int win(const int board[9]) {
//determines if a player has won, returns 0 otherwise.
unsigned wins[8][3] = {{0,1,2},{3,4,5},{6,7,8},{0,3,6},{1,4,7},{2,5,8},{0,4,8},{2,4,6}};
int i;
for(i = 0; i < 8; ++i) {
if(board[wins[i][0]] != 0 &&
board[wins[i][0]] == board[wins[i][1]] &&
board[wins[i][0]] == board[wins[i][2]])
return board[wins[i][2]];
}
return 0;
}
int alphabeta(int board[9], int depth, int alpha, int beta, bool max_player) {
int score = 0;
max_player = true;
if(depth == 0){
return score;
}
if(max_player) {
alpha = INT_MIN;
while (depth != 0) {
score = alphabeta(board[9], depth - 1, alpha, beta, !max_player);
alpha = MAX(alpha, score );
if (beta <= alpha) break;
}
return alpha;
}
else {
beta = INT_MAX;
while (depth != 0) {
score = alphabeta(board[9], depth - 1, alpha, beta, !max_player);
beta = MIN(beta, score );
if (beta <= alpha) break;
}
return beta;
}
}
void computerMove(int board[9]) {
int move = -1;
int score = -2;
int i;
for(i = 0; i < 9; ++i) {
if(board[i] == 0) {
board[i] = 1;
int tempScore = -alphabeta(board[9],6, -10000, 10000, true);
board[i] = 0;
if(tempScore > score) {
score = tempScore;
move = i;
}
}
}
//returns a score based on minimax tree at a given node.
board[move] = 1;
}
void playerMove(int board[9]) {
int move = 0;
do {
printf("\nInput move ([0..8]): ");
scanf("%d", &move);
printf("\n");
} while (move >= 9 || move < 0 && board[move] == 0);
board[move] = -1;
}
int main() {
int board[9] = {0,0,0,0,0,0,0,0,0};
//computer squares are 1, player squares are -1.
printf("Computer: O, You: X\nPlay (1)st or (2)nd? ");
int player=0;
scanf("%d",&player);
printf("\n");
unsigned turn;
for(turn = 0; turn < 9 && win(board) == 0; ++turn) {
if((turn+player) % 2 == 0)
computerMove(board);
else {
draw(board);
playerMove(board);
}
}
switch(win(board)) {
case 0:
printf("A draw. How droll.\n");
break;
case 1:
draw(board);
printf("You lose.\n");
break;
case -1:
printf("You win. Inconceivable!\n");
break;
}
}
I'm thinking that my implementation is not correctly identifying the "child nodes" of the current board, but I am lost as to how to code that with regard to an array of integers. Any advice would be greatly appreciated.
One error is here (and you are making similar mistakes in other places in your code):
score = alphabeta(board[9], depth - 1, alpha, beta, !max_player);
The first parameter, board[9] is accessing an out-of-bounds element of the board array. You're sending a single int, namely board[9], but board[9] is an element that is out-of-bounds of board, thus you're invoking undefined behavior.
I don't know what your intentions are with the code above, but if you are trying to pass the buffer pointed to by board:
score = alphabeta(board, depth - 1, alpha, beta, !max_player);
If you're trying to pass the last element of the board:
score = alphabeta(board[8], depth - 1, alpha, beta, !max_player);
In addition, if you're not aware, function prototypes like this:
int win(const int board[9])
are no different than this:
int win(const int* board)
Arrays decay to pointers -- you are not actually passing an array.
The example here shows what the program would look like when corrected (the runtime error is due to missing input).
You also have some very suspicious code, for example:
while (move >= 9 || move < 0 && board[move] == 0);
If move < 0, you are accessing board with a negative index, which is another out-of-bounds access.
Related
I want to make a program to find if a path exists from upper right corner to down left corner in a maze via backtracking. The input numbers are n and m which are the dimensions of rectangular maze and a maze, character '.' means a tile which you can go through and character 'x' means a tile which you cant go through. I have wrote the code, its fairly simple but nothing gets displayed whilst it should display "da" (on Serbian "yes") and "ne" (on Serbian "no").
#include <bits/stdc++.h>
using namespace std;
bool maze[20][20]; //defined maze of maximum size 20x20
//checking if a position is viable for moving through
bool Safe(int n, int m, int x, int y)
{
if(x >= 0 && x < n && y >= 0 && y < m)
{
if(maze[x][y] == 1) return true;
}
return false;
}
bool Utility(int n, int m, int x, int y) //main utility function
{
if(x == n - 1 && y == m - 1 && maze[x][y] == 1) // base case, end of maze
{
return true;
}
if(Safe(n, m, x, y))
{
if(Safe(n, m, x + 1, y)) // checking if it is viable to move down
{
if(Utility(n, m, x + 1, y))
{
return true;
}
}
if(Safe(n, m, x, y + 1))
{
if(Utility(n, m, x, y + 1)) // checking if it is viable to move right
{
return true;
}
}
if(Safe(n, m, x - 1, y))
{
if(Utility(n, m, x - 1, y)) // checking if it is viable to move up
{
return true;
}
}
if(Safe(n, m, x, y - 1))
{
if(Utility(n, m, x, y - 1)) // checking if it is viable to move left
{
return true;
}
}
}
return false; // returning false
}
int main()
{
int n, m;
cin >> n >> m; // input dimensions of the maze
for(int i = 0; i < n; i++) // input maze
{
for(int j = 0; j < m; j++)
{
char c;
cin >> c;
if(c == '.') //character '.' means a tile which you can go through
{
maze[i][j] = 1;
}
else //character 'x' means a tile which you cannot go through
{
maze[i][j] = 0;
}
}
}
if(Utility(n, m, 0, 0)) //printing yes or no
{
cout << "da";
}
else
{
cout << "ne";
}
return 0;
}
Sample Input:
8 8
.x.....x
.x.x.x.x
.x.x.x.x
.x.x.x.x
.x.x.x.x
.x.x.x.x
.x.x.x.x
...x.x..
Sample output: da
The problem was that, say if you go from (0, 0) -> (1, 0), then at (1, 0) you can again go back to (0, 0) and this would loop forever. To avoid that, I created a visited array which will have value true if cell (x, y) is already visited, else false.
I have marked where I made the changes with ///////////// change here ///////////// comment
#include <bits/stdc++.h>
using namespace std;
bool maze[20][20]; //defined maze of maximum size 20x20
///////////// change here /////////////
bool visited[20][20];
bool Safe(int n, int m, int x, int y) //checking if a position is viable for moving through
{
if(x >= 0 && x < n && y >= 0 && y < m)
{
if(maze[x][y] == 1) return true;
}
return false;
}
bool Utility(int n, int m, int x, int y) //main utility function
{
if(x == n - 1 && y == m - 1 && maze[x][y] == 1) // base case, end of maze
{
return true;
}
///////////// change here /////////////
if(!visited[x][y] && Safe(n, m, x, y))
{
///////////// change here /////////////
visited[x][y] = true;
if(Safe(n, m, x + 1, y)) // checking if it is viable to move down
{
if(Utility(n, m, x + 1, y))
{
return true;
}
}
if(Safe(n, m, x, y + 1))
{
if(Utility(n, m, x, y + 1)) // checking if it is viable to move right
{
return true;
}
}
if(Safe(n, m, x - 1, y))
{
if(Utility(n, m, x - 1, y)) // checking if it is viable to move up
{
return true;
}
}
if(Safe(n, m, x, y - 1))
{
if(Utility(n, m, x, y - 1)) // checking if it is viable to move left
{
return true;
}
}
}
return false; // returning false
}
int main()
{
int n, m;
cin >> n >> m; // input dimensions of the maze
for(int i = 0; i < n; i++) // input maze
{
for(int j = 0; j < m; j++)
{
char c;
cin >> c;
if(c == '.') //character '.' means a tile which you can go through
{
maze[i][j] = true;
}
else //character 'x' means a tile which you cannot go through
{
maze[i][j] = false;
}
///////////// change here /////////////
visited[i][j] = false;
}
}
if(Utility(n, m, 0, 0)) //printing yes or no
{
cout << "da";
}
else
{
cout << "ne";
}
return 0;
}
Here's the link where I tested it: https://ideone.com/vVqAjF
The other day, I wrote a console game of Tic-Tac-Toe in c++ for my son. He wanted me to add a computer, and I ended us using the minimax algorithm for the first time. I did some quick testing, but really just gave my laptop to my son as soon as it was printing stuff, who played with it for a couple minuets. I looked over his sholder once or twice, and noticed that it wasn't playing optimally, iv'e been trying to debug it, but I can't see where it goes wrong. I tried getting rid of alpha beta prunning, but that did not change anything.
For context, on the board the computer is -1, blank is 0, and the player is 1.
Here is the minimax function:
int minimax(int board[9], int depth, int alpha, int beta, bool isMaxizimaizingPlayer)
{
bool found = false;
for (int i = 0; i < 9; i++)
{
if (board[i] == 0)
{
found = true;
}
}
if (!found)
{
return eval(board);
}
if (depth == 0 || eval(board) != 0)
{
return eval(board);
}
if (isMaxizimaizingPlayer)
{
int maxEval = -2;
for (int spot = 0; spot < 9; spot++)
{
if (board[spot] == 0)
{
board[spot] = 1;
int e = minimax(board, depth - 1, alpha, beta, false);
if (e > maxEval)
{
maxEval = e;
}
//if (beta < alpha)
//{
// break;
//}
board[spot] = 0;
}
}
return maxEval;
}
else {
int minEval = 2;
for (int spot = 0; spot < 9; spot++)
{
if (board[spot] == 0)
{
board[spot] = -1;
int e = minimax(board, depth - 1, alpha, beta, true);
if (e < minEval)
{
minEval = e;
}
//if (beta < alpha)
//{
// break;
//}
board[spot] = 0;
}
}
return minEval;
}
}
To be compleate, here is my eval function:
int eval(int board[9])
{
/*horizontial*/
for (int i = 0; i < 3; i++)
{
if (board[i * 3] == board[i * 3 + 1] && board[i * 3 + 2] == board[i * 3] && board[i * 3] != 0)
{
return board[i * 3];
}
}
/*vertical*/
for (int i = 0; i < 3; i++)
{
if (board[i] == board[i + 3] && board[i] == board[i + 6] && board[i] != 0)
{
return board[i];
}
}
/*Both diags*/
if (board[4] != 0) {
if (board[0] == board[4] && board[0] == board[8])
{
return board[4];
}
if (board[2] == board[4] && board[4] == board[6])
{
return board[4];
}
}
return 0;
}
And here is the inital call:
int spot = 0;
int minEval = 2;
for (int i = 0; i < 9; i++)
{
if (board[i] == 0)
{
board[i] = -1;
int score = minimax(board, 3, -2, 2, false);
if (score < minEval) {
minEval = score;
spot = i;
}
board[i] = 0;
}
}
std::cout << "The computer went in spot " << spot + 1 << std::endl;
board[spot] = -1;
printBoard(board);
It looks like you only call minimax with a depth of three, so the algorithm will only look up to three moves ahead, if you want optimal play you need to set the depth to > 9, so that the agent is always looking ahead to the end of the game.
I have a program that works in VS C++ and does not work with g++. Here is the code:
#define _USE_MATH_DEFINES
#include <cmath>
#include <iostream>
#include <vector>
#include <cstdio>
#include <algorithm>
#include <set>
#define EP 1e-10
using namespace std;
typedef pair<long long, long long> ii;
typedef pair<bool, int> bi;
typedef vector<ii> vii;
// Returns the orientation of three points in 2D space
int orient2D(ii pt0, ii pt1, ii pt2)
{
long long result = (pt1.first - pt0.first)*(pt2.second - pt0.second)
- (pt1.second - pt0.second)*(pt2.first - pt0.first);
return result == 0 ? 0 : result < 0 ? -1 : 1;
}
// Returns the angle derived from law of cosines center-pt1-pt2.
// Defined to be negative if pt2 is to the right of segment pt1 to center
double angle(ii center, ii pt1, ii pt2)
{
double aS = pow(center.first - pt1.first, 2) + pow(center.second - pt1.second, 2);
double bS = pow(pt2.first - pt1.first, 2) + pow(pt2.second - pt1.second, 2);
double cS = pow(center.first - pt2.first, 2) + pow(center.second - pt2.second, 2);
/* long long aS = (center.first - pt1.first)*(center.first - pt1.first) + (center.second - pt1.second)*(center.second - pt1.second);
long long bS = (pt2.first - pt1.first)*(pt2.first - pt1.first) + (pt2.second - pt1.second)*(pt2.second - pt1.second);
long long cS = (center.first - pt2.first)*(center.first - pt2.first) + (center.second - pt2.second)*(center.second - pt2.second);*/
int sign = orient2D(pt1, center, pt2);
return sign == 0 ? 0 : sign * acos((aS + bS - cS) / ((sqrt(aS) * sqrt(bS) * 2)));
}
// Computes the average point of the set of points
ii centroid(vii &pts)
{
ii center(0, 0);
for (int i = 0; i < pts.size(); ++i)
{
center.first += pts[i].first;
center.second += pts[i].second;
}
center.first /= pts.size();
center.second /= pts.size();
return center;
}
// Uses monotone chain to convert a set of points into a convex hull, ordered counter-clockwise
vii convexHull(vii &pts)
{
sort(pts.begin(), pts.end());
vii up, dn;
for (int i = 0; i < pts.size(); ++i)
{
while (up.size() > 1 && orient2D(up[up.size()-2], up[up.size()-1], pts[i]) >= 0)
up.pop_back();
while (dn.size() > 1 && orient2D(dn[dn.size()-2], dn[dn.size()-1], pts[i]) <= 0)
dn.pop_back();
up.push_back(pts[i]);
dn.push_back(pts[i]);
}
for (int i = up.size()-2; i > 0; --i)
{
dn.push_back(up[i]);
}
return dn;
}
// Tests if a point is critical on the polygon, i.e. if angle center-qpt-polygon[i]
// is larger (smaller) than center-qpt-polygon[i-1] and center-qpt-polygon[i+1].
// This is true iff qpt-polygon[i]-polygon[i+1] and qpt-polygon[i]-polygon[i-1]
// are both left turns (min) or right turns (max)
bool isCritical(vii &polygon, bool mx, int i, ii qpt, ii center)
{
int ip1 = (i + 1) % polygon.size();
int im1 = (i + polygon.size() - 1) % polygon.size();
int p1sign = orient2D(qpt, polygon[i], polygon[ip1]);
int m1sign = orient2D(qpt, polygon[i], polygon[im1]);
if (p1sign == 0 && m1sign == 0)
{
return false;
}
if (mx)
{
return p1sign <= 0 && m1sign <= 0;
}
else
{
return p1sign >= 0 && m1sign >= 0;
}
}
// Conducts modified binary search on the polygon to find tangent lines in O(log n) time.
// This is equivalent to finding a max or min in a "parabola" that is rotated and discrete.
// Vanilla binary search does not work and neither does vanilla ternary search. However, using
// the fact that there is only a single max and min, we can use the slopes of the points at start
// and mid, as well as their values when compared to each other, to determine if the max or min is
// in the left or right section
bi find_tangent(vii &polygon, bool mx, ii qpt, int start, int end, ii center)
{
// When query is small enough, iterate the points. This avoids more complicated code dealing with the cases not possible as
// long as left and right are at least one point apart. This does not affect the asymptotic runtime.
if (end - start <= 4)
{
for (int i = start; i < end; ++i)
{
if (isCritical(polygon, mx, i, qpt, center))
{
return bi(true, i);
}
}
return bi(false, -1);
}
int mid = (start + end) / 2;
// use modulo to wrap around the polygon
int startm1 = (start + polygon.size() - 1) % polygon.size();
int midm1 = (mid + polygon.size() - 1) % polygon.size();
// left and right angles
double startA = angle(center, qpt, polygon[start]);
double midA = angle(center, qpt, polygon[mid]);
// minus 1 angles, to determine slope
double startm1A = angle(center, qpt, polygon[startm1]);
double midm1A = angle(center, qpt, polygon[midm1]);
int startSign = abs(startm1A - startA) < EP ? 0 : (startm1A < startA ? 1 : -1);
int midSign = abs(midm1A - midA) < EP ? 0 : (midm1A < midA ? 1 : -1);
bool left = true;
// naively 27 cases: left and left angles can be <, ==, or >,
// slopes can be -, 0, or +, and each left and left has slopes,
// 3 * 3 * 3 = 27. Some cases are impossible, so here are the remaining 18.
if (abs(startA - midA) < EP)
{
if (startSign == -1)
{
left = !mx;
}
else
{
left = mx;
}
}
else if (startA < midA)
{
if (startSign == 1)
{
if (midSign == 1)
{
left = false;
}
else if (midSign == -1)
{
left = mx;
}
else
{
left = false;
}
}
else if (startSign == -1)
{
if (midSign == -1)
{
left = true;
}
else if (midSign == 1)
{
left = !mx;
}
else
{
left = true;
}
}
else
{
if (midSign == -1)
{
left = false;
}
else
{
left = true;
}
}
}
else
{
if (startSign == 1)
{
if (midSign == 1)
{
left = true;
}
else if (midSign == -1)
{
left = mx;
}
else
{
left = true;
}
}
else if (startSign == -1)
{
if (midSign == -1)
{
left = false;
}
else if (midSign == 1)
{
left = !mx;
}
else
{
left = false;
}
}
else
{
if (midSign == 1)
{
left = true;
}
else
{
left = false;
}
}
}
if (left)
{
return find_tangent(polygon, mx, qpt, start, mid+1, center);
}
else
{
return find_tangent(polygon, mx, qpt, mid, end, center);
}
}
int main(){
int n, m;
cin >> n >> m;
vii rawPoints(n);
for (int i = 0; i < n; ++i)
{
cin >> rawPoints[i].first >> rawPoints[i].second;
}
vii polygon = convexHull(rawPoints);
set<ii> points(polygon.begin(), polygon.end());
ii center = centroid(polygon);
for (int i = 0; i < m; ++i)
{
ii pt;
cin >> pt.first >> pt.second;
bi top = find_tangent(polygon, true, pt, 0, polygon.size(), center);
bi bot = find_tangent(polygon, false, pt, 0, polygon.size(), center);
// a query point is inside if it is collinear with its max (top) and min (bot) angled points, it is a polygon point, or if none of the points are critical
if (!top.first || orient2D(polygon[top.second], pt, polygon[bot.second]) == 0 || points.count(pt))
{
cout << "INSIDE" << endl;
}
else
{
cout << polygon[top.second].first << " " << polygon[top.second].second << " " << polygon[bot.second].first << " " << polygon[bot.second].second << endl;
}
}
}
My suspicion is there's something wrong with the angle function. I have narrowed it down to either that or find_tangent. I also see different results in g++ when I switch from double to long long in the angle function. The double results are closer to correct, but I can't see why it should be any different. The values I'm feeding in are small and no overflow/ rounding should be causing issues. I have also seen differences in doing pow(x, 2) or x*x when I assign to a double. I don't understand why this would make a difference.
Any help would be appreciated!
EDIT: Here is the input file: https://github.com/brycesandlund/Coursework/blob/master/Java/PrintPoints/points.txt
Here is the correct result:
https://github.com/brycesandlund/Coursework/blob/master/CompGeo/CompGeo/correct.txt
Here is the incorrect result:
https://github.com/brycesandlund/Coursework/blob/master/CompGeo/CompGeo/fast.txt
The problem was with this piece of code:
// Computes the average point of the set of points
ii centroid(vii &pts)
{
ii center(0LL, 0LL);
for (int i = 0; i < pts.size(); ++i)
{
center.first += pts[i].first;
center.second += pts[i].second;
}
center.first /= pts.size(); //right here!!
center.second /= pts.size();
return center;
}
I don't know why but g++ was taking the negative center.first and turning it into a positive, overflowed long long when dividing by the unsigned integer pts.size. By converting the statements into:
center.first /= (long long)pts.size();
center.second /= (long long)pts.size();
The output from g++ and VS c++ matches.
Hi so okay put it this way.
We have 12 players well what I want to do is find the closest one.
I've written some code below; two versions of my attempt (trust me theirs been a lot more, could of written a bible by now)
/*int client::closestEnemy()
{
for(u32 i = 0; i<12; i++)
{
DbgPrint("i: %i\n", i);
u32 index = 0;
if(!p[i].exist() || !p[i].alive() || p[i].team() == 3 || i == s.index)
continue;
for(u32 o = 0; o<12; o++)
if(vec.distance(*pos(), *p[i].pos()) <= vec.distance(*pos(), *p[o].pos()) || vec.distance(*pos(), *p[i].pos()) == vec.distance(*pos(), *p[o].pos()))
index++;
DbgPrint("PLAYER %s INDEX = %i\n", p[i].readName(), index);
if(index>10)
return i;
index = 0;
}
return -1;
}*/
int client::closestEnemy()
{
float distacnes[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
u32 index = 0;
for(u32 i = 0; i<12; i++)
if(p[i].exist() || p[i].alive() || p[i].team() != 3 || i != s.index)
distacnes[i] = vec.distance(*pos(), *p[i].pos());
else
continue;
for(u32 i = 0; i<12; i++)
if(distacnes[i]<distacnes[i+1])
index++;
DbgPrint("Score = %i\n", index);
if(index>11)
return index;
return -1;
}
What I am doing is simply increment index by 1 when ever another clients distance is larger then mine.
Now the first one is best bet but sometimes does not create a high enough index which makes zero sense because at least one client has to have a smaller distance then everyone else.
First, some indentation would help, I guess.
Then, there's no need to store all distances. You can keep track of the minimum distance encountered so far, like this:
int client::closestEnemy()
{
int index = -1;
float minDistance;
for(u32 i = 0; i<12; i++) {
if(p[i].exist() || p[i].alive() || p[i].team() != 3 || i != s.index) {
float distance = vec.distance(*pos(), *p[i].pos());
if (index == -1 || distance < minDistance) {
index = i;
minDistance = distance;
}
}
}
return index;
}
I need some help. I'm writing a code in C++ that will ultimately take a random string passed in, and it will do a break at every point in the string, and it will count the number of colors to the right and left of the break (r, b, and w). Here's the catch, the w can be either r or b when it breaks or when the strong passes it ultimately making it a hybrid. My problem is when the break is implemented and there is a w immediately to the left or right I can't get the program to go find the fist b or r. Can anyone help me?
#include <stdio.h>
#include "P2Library.h"
void doubleNecklace(char neck[], char doubleNeck[], int size);
int findMaxBeads(char neck2[], int size);
#define SIZE 7
void main(void)
{
char necklace[SIZE];
char necklace2[2 * SIZE];
int brk;
int maxBeads;
int leftI, rightI, leftCount = 0, rightCount=0, totalCount, maxCount = 0;
char leftColor, rightColor;
initNecklace(necklace, SIZE);
doubleNecklace(necklace, necklace2, SIZE);
maxBeads = findMaxBeads(necklace2, SIZE * 2);
checkAnswer(necklace, SIZE, maxBeads);
printf("The max number of beads is %d\n", maxBeads);
}
int findMaxBeads(char neck2[], int size)
{
int brk;
int maxBeads;
int leftI, rightI, leftCount = 0, rightCount=0, totalCount, maxCount = 0;
char leftColor, rightColor;
for(brk = 0; brk < 2 * SIZE - 1; brk++)
{
leftCount = rightCount = 0;
rightI = brk;
rightColor = neck2[rightI];
if(rightI == 'w')
{
while(rightI == 'w')
{
rightI++;
}
rightColor = neck2[rightI];
}
rightI = brk;
while(neck2[rightI] == rightColor || neck2[rightI] == 'w')
{
rightCount++;
rightI++;
}
if(brk > 0)
{
leftI = brk - 1;
leftColor = neck2[leftI];
if(leftI == 'w')
{
while(leftI == 'w')
{
leftI--;
}
leftColor = neck2[leftI];
}
leftI = brk - 1;
while(leftI >= 0 && neck2[leftI] == leftColor || neck2[leftI] == 'w')
{
leftCount++;
leftI--;
}
}
totalCount = leftCount + rightCount;
if(totalCount > maxCount)
{
maxCount = totalCount;
}
}
return maxCount;
}
void doubleNecklace(char neck[], char doubleNeck[], int size)
{
int i;
for(i = 0; i < size; i++)
{
doubleNeck[i] = neck[i];
doubleNeck[i+size] = neck[i];
}
}
I didn't study the code in detail, but something is not symmetric: in the for loop, the "left" code has an if but the "right" code doesn't. Maybe you should remove that -1 in the for condition and add it as an if for the "right" code:
for(brk = 0; brk < 2 * SIZE; brk++)
{
leftCount = rightCount = 0;
if (brk < 2 * SIZE - 1)
{
rightI = brk;
rightColor = neck2[rightI];
//...
}
if(brk > 0)
{
leftI = brk - 1;
leftColor = neck2[leftI];
//...
}
//...
Just guessing, though... :-/
Maybe you should even change those < for <=.