I created a C++ program through Matlab coder called implicit_enumeration.cpp which takes a matrix A and a vector b as input and returns a vector zstar and a probability value Vstar. I am now struggling to initialize the main function:
// Include Files
#include "stdafx.h"
#include "implicit_enumeration.h"
#include "main.h"
// Function Declarations
static void argInit_4x1_real_T(double result[4]);
static void argInit_4x9_real_T(double result[36]);
static void main_implicit_enumeration();
// Function Definitions
static void argInit_4x1_real_T(double result[4])
{
int idx0;
// Loop over the array to initialize each element.
for (idx0 = 0; idx0 < 4; idx0++) {
// Set the value of the array element.
// Change this value to the value that the application requires.
result[idx0] = 1;
}
}
static void argInit_4x9_real_T(double result[36])
{
int idx0;
int idx1;
// Loop over the array to initialize each element.
for (idx0 = 0; idx0 < 4; idx0++) {
for (idx1 = 0; idx1 < 9; idx1++) {
// Set the value of the array element.
// Change this value to the value that the application requires.
if (idx0 == 0) {
if (idx1 == 0) { result[idx0 + (idx1 << 2)] = 1; }
else if (idx1 == 1) { result[idx0 + (idx1 << 2)] = 1; }
else { result[idx0 + (idx1 << 2)] = 0; }
}
else if (idx0 == 1) {
if (idx1 == 2) { result[idx0 + (idx1 << 2)] = 1; }
else if (idx1 == 3) { result[idx0 + (idx1 << 2)] = 1; }
else if (idx1 == 4) { result[idx0 + (idx1 << 2)] = 1; }
else { result[idx0 + (idx1 << 2)] = 0; }
}
else if (idx0 == 2) {
if (idx1 == 5) { result[idx0 + (idx1 << 2)] = 1; }
else { result[idx0 + (idx1 << 2)] = 0; }
}
else {
if (idx1 == 6) { result[idx0 + (idx1 << 2)] = 1; }
else if (idx1 == 7) { result[idx0 + (idx1 << 2)] = 1; }
else if (idx1 == 8) { result[idx0 + (idx1 << 2)] = 1; }
else { result[idx0 + (idx1 << 2)] = 0; }
}
}
}
}
static void main_implicit_enumeration()
{
double dv0[36];
double dv1[4];
double zstar[9];
double Vstar;
// Initialize function 'implicit_enumeration' input arguments.
// Initialize function input argument 'A'.
// Initialize function input argument 'b'.
// Call the entry-point 'implicit_enumeration'.
argInit_4x9_real_T(dv0);
argInit_4x1_real_T(dv1);
implicit_enumeration(dv0, dv1, zstar, &Vstar);
}
int main(int argc, const char * const argv[])
{
// Initialize the application.
// You do not need to do this more than one time.
// Invoke the entry-point functions.
// You can call entry-point functions multiple times.
main_implicit_enumeration();
return 0;
}
Specifically, I am wondering how to initialize argv[] as a matrix A and a vector b. Is it necessary to set the command arguments even though I already initialized the matrix A and the vector b through the functions argInit_4x9_real_T() and argInit_4x1_real_T()? If yes, how to include a matrix and a vector as command arguments? The examples I checked always show single integer or real values, but not matrix or vectors.
Thank you in advance!
Actually, you are mostly done.
In main(int argc, const char * const argv[]):
argc is the number of of command line arguments, argv contains these command line arguments.
Example:
If you call test.ext something, argc is 2, argv[0] is "test.exe", argv[1] is "something".
Your initialization is done in main_implicit_enumeration()
dv0 is you matrix A (4*9 Matrix -> 36 elements), and it is
initialized in argInit_4x9_real_T()
dv1 is your vector b (4 Vector -> 4 elements), and it is initialized in argInit_4x1_real_T
zstar is the return vector
Vstar the skalar return
Question is: How do you want to pass values to your program? Load values from a file? Use a format like test.ext A=1,2,3;4,5,6 b=8,9 ?
Related
I am working on makingthis connect 4 game to be modular with different grid sizes from 3x3 up to a 10x10 as well as a modular amount of winning "pucks". The program below works by passing 3 arguments which is the grid size (grid is square), the continuous amount of pucks needed to win, and who starts first (not implemented yet). So the command to run it would be connectM 6 5 1 for example.
On the code below you will see that attempt. The program works well when you use 4 as the second argument but anything above it and I am getting a segmentation fault around line 338 and I can't put my finger on it. Does anyone have any insight on something I am obviously doing wrong?
#include <stdio.h>
#include <iostream>
#include <vector>
#include <limits.h>
#include <array>
#include <sstream>
#define min(a,b) (((a) < (b)) ? (a) : (b))
#define max(a,b) (((a) > (b)) ? (a) : (b))
using namespace std;
// function declarations
void printBoard(vector<vector<int> >&);
int userMove();
void makeMove(vector<vector<int> >&, int, unsigned int);
void errorMessage(int);
int aiMove();
vector<vector<int> > copyBoard(vector<vector<int> >);
bool winningMove(vector<vector<int> >&, unsigned int);
int scoreSet(vector<unsigned int>, unsigned int);
int tabScore(vector<vector<int> >, unsigned int);
array<int, 2> miniMax(vector<vector<int> >&, unsigned int, int, int, unsigned int);
int heurFunction(unsigned int, unsigned int, unsigned int);
// Avoid magic numbers
unsigned int NUM_COL = 7; // how wide is the board
unsigned int NUM_ROW = 7; // how tall
unsigned int PLAYER = 1; // player number
unsigned int COMPUTER = 2; // AI number
unsigned int MAX_DEPTH = 5; // the default "difficulty" of the computer controlled AI
unsigned int WINNING_PUCKS = 4; //Default winning pucks
unsigned int FIRST_PLAYER = 0;
bool gameOver = false; // flag for if game is over
unsigned int turns = 0; // count for # turns
unsigned int currentPlayer = PLAYER; // current player
vector<vector<int>> board(NUM_ROW, vector<int>(NUM_COL)); // the game board
/**
* game playing function
* loops between players while they take turns
*/
void playGame() {
printBoard(board); // print initial board
while (!gameOver) { // while no game over state
if (currentPlayer == COMPUTER) { // AI move
makeMove(board, aiMove(), COMPUTER);
}
else if (currentPlayer == PLAYER) { // player move
makeMove(board, userMove(), PLAYER);
}
else if (turns == NUM_ROW * NUM_COL) { // if max number of turns reached
gameOver = true;
}
gameOver = winningMove(board, currentPlayer); // check if player won
currentPlayer = (currentPlayer == 1) ? 2 : 1; // switch player
turns++; // iterate number of turns
cout << endl;
printBoard(board); // print board after successful move
}
if (turns == NUM_ROW * NUM_COL) { // if draw condition
cout << "Draw!" << endl;
}
else { // otherwise, someone won
cout << ((currentPlayer == PLAYER) ? "AI Wins!" : "Player Wins!") << endl;
}
}
/**
* function that makes the move for the player
* #param b - the board to make move on
* #param c - column to drop piece into
* #param p - the current player
*/
void makeMove(vector<vector<int> >& b, int c, unsigned int p) {
// start from bottom of board going up
for (unsigned int r = 0; r < NUM_ROW; r++) {
if (b[r][c] == 0) { // first available spot
b[r][c] = p; // set piece
break;
}
}
}
/**
* prompts the user for their move
* and ensures valid user input
* #return the user chosen column
*/
int userMove() {
int move = -1; // temporary
while (true) { // repeat until proper input given
cout << "Enter a column: ";
cin >> move; // init move as input
if (!cin) { // if non-integer
cin.clear();
cin.ignore(INT_MAX, '\n');
errorMessage(1); // let user know
}
else if (!((unsigned int)move < NUM_COL && move >= 0)) { // if out of bounds
errorMessage(2); // let user know
}
else if (board[NUM_ROW - 1][move] != 0) { // if full column
errorMessage(3); // let user know
}
else { // if it gets here, input valid
break;
}
cout << endl << endl;
}
return move;
}
/**
* AI "think" algorithm
* uses minimax to find ideal move
* #return - the column number for best move
*/
int aiMove() {
cout << "AI is thinking about a move..." << endl;
return miniMax(board, MAX_DEPTH, 0 - INT_MAX, INT_MAX, COMPUTER)[1];
}
/**
* Minimax implementation using alpha-beta pruning
* #param b - the board to perform MM on
* #param d - the current depth
* #param alf - alpha
* #param bet - beta
* #param p - current player
*/
array<int, 2> miniMax(vector<vector<int> > &b, unsigned int d, int alf, int bet, unsigned int p) {
/**
* if we've reached minimal depth allowed by the program
* we need to stop, so force it to return current values
* since a move will never (theoretically) get this deep,
* the column doesn't matter (-1) but we're more interested
* in the score
*
* as well, we need to take into consideration how many moves
* ie when the board is full
*/
if (d == 0 || d >= (NUM_COL * NUM_ROW) - turns) {
// get current score to return
return array<int, 2>{tabScore(b, COMPUTER), -1};
}
if (p == COMPUTER) { // if AI player
array<int, 2> moveSoFar = {INT_MIN, -1}; // since maximizing, we want lowest possible value
if (winningMove(b, PLAYER)) { // if player about to win
return moveSoFar; // force it to say it's worst possible score, so it knows to avoid move
} // otherwise, business as usual
for (unsigned int c = 0; c < NUM_COL; c++) { // for each possible move
if (b[NUM_ROW - 1][c] == 0) { // but only if that column is non-full
vector<vector<int> > newBoard = copyBoard(b); // make a copy of the board
makeMove(newBoard, c, p); // try the move
int score = miniMax(newBoard, d - 1, alf, bet, PLAYER)[0]; // find move based on that new board state
if (score > moveSoFar[0]) { // if better score, replace it, and consider that best move (for now)
moveSoFar = {score, (int)c};
}
alf = max(alf, moveSoFar[0]);
if (alf >= bet) { break; } // for pruning
}
}
return moveSoFar; // return best possible move
}
else {
array<int, 2> moveSoFar = {INT_MAX, -1}; // since PLAYER is minimized, we want moves that diminish this score
if (winningMove(b, COMPUTER)) {
return moveSoFar; // if about to win, report that move as best
}
for (unsigned int c = 0; c < NUM_COL; c++) {
if (b[NUM_ROW - 1][c] == 0) {
vector<vector<int> > newBoard = copyBoard(b);
makeMove(newBoard, c, p);
int score = miniMax(newBoard, d - 1, alf, bet, COMPUTER)[0];
if (score < moveSoFar[0]) {
moveSoFar = {score, (int)c};
}
bet = min(bet, moveSoFar[0]);
if (alf >= bet) { break; }
}
}
return moveSoFar;
}
}
/**
* function to tabulate current board "value"
* #param b - the board to evaluate
* #param p - the player to check score of
* #return - the board score
*/
int tabScore(vector<vector<int> > b, unsigned int p) {
int score = 0;
vector<unsigned int> rs(NUM_COL);
vector<unsigned int> cs(NUM_ROW);
vector<unsigned int> set(WINNING_PUCKS);
/**
* horizontal checks, we're looking for sequences of WINNING_PUCKS
* containing any combination of AI, PLAYER, and empty pieces
*/
for (unsigned int r = 0; r < NUM_ROW; r++) {
for (unsigned int c = 0; c < NUM_COL; c++) {
rs[c] = b[r][c]; // this is a distinct row alone
}
for (unsigned int c = 0; c < NUM_COL - (WINNING_PUCKS - 1); c++) {
for (int i = 0; i < WINNING_PUCKS; i++) {
set[i] = rs[c + i]; // for each possible "set" of WINNING_PUCKS spots from that row
}
score += scoreSet(set, p); // find score
}
}
// vertical
for (unsigned int c = 0; c < NUM_COL; c++) {
for (unsigned int r = 0; r < NUM_ROW; r++) {
cs[r] = b[r][c];
}
for (unsigned int r = 0; r < NUM_ROW - (WINNING_PUCKS - 1); r++) {
for (int i = 0; i < WINNING_PUCKS; i++) {
set[i] = cs[r + i];
}
score += scoreSet(set, p);
}
}
// diagonals
for (unsigned int r = 0; r < NUM_ROW - (WINNING_PUCKS - 1); r++) {
for (unsigned int c = 0; c < NUM_COL; c++) {
rs[c] = b[r][c];
}
for (unsigned int c = 0; c < NUM_COL - (WINNING_PUCKS - 1); c++) {
for (int i = 0; i < WINNING_PUCKS; i++) {
set[i] = b[r + i][c + i];
}
score += scoreSet(set, p);
}
}
for (unsigned int r = 0; r < NUM_ROW - (WINNING_PUCKS - 1); r++) {
for (unsigned int c = 0; c < NUM_COL; c++) {
rs[c] = b[r][c];
}
for (unsigned int c = 0; c < NUM_COL - (WINNING_PUCKS - 1); c++) {
for (int i = 0; i < WINNING_PUCKS; i++) {
set[i] = b[r + WINNING_PUCKS - 1 - i][c + i];
}
score += scoreSet(set, p);
}
}
return score;
}
/**
* function to find the score of a set of WINNING_PUCKS spots
* #param v - the row/column to check
* #param p - the player to check against
* #return - the score of the row/column
*/
int scoreSet(vector<unsigned int> v, unsigned int p) {
unsigned int good = 0; // points in favor of p
unsigned int bad = 0; // points against p
unsigned int empty = 0; // neutral spots
for (unsigned int i = 0; i < v.size(); i++) { // just enumerate how many of each
good += (v[i] == p) ? 1 : 0;
bad += (v[i] == PLAYER || v[i] == COMPUTER) ? 1 : 0;
empty += (v[i] == 0) ? 1 : 0;
}
// bad was calculated as (bad + good), so remove good
bad -= good;
return heurFunction(good, bad, empty);
}
/**
* """heuristic function"""
* #param g - good points
* #param b - bad points
* #param z - empty spots
* #return - the score as tabulated
*/
// int heurFunction(unsigned int g, unsigned int b, unsigned int z) {
// int score = 0;
// if (g == 4) { score += 500001; } // preference to go for winning move vs. block
// else if (g == 3 && z == 1) { score += 5000; }
// else if (g == 2 && z == 2) { score += 500; }
// else if (b == 2 && z == 2) { score -= 501; } // preference to block
// else if (b == 3 && z == 1) { score -= 5001; } // preference to block
// else if (b == 4) { score -= 500000; }
// return score;
// }
int heurFunction(unsigned int g, unsigned int b, unsigned int z) {
int score = 0;
if (g == WINNING_PUCKS) { score += 500001; } // preference to go for winning move vs. block
else if (g > z) { score += 5000; }
else if (g == z) { score += 500; }
else if (b == z) { score -= 501; } // preference to block
else if (b > z) { score -= 5001; } // preference to block
else if (b == WINNING_PUCKS) { score -= 500000; }
return score;
}
/**
* function to determine if a winning move is made
* #param b - the board to check
* #param p - the player to check against
* #return - whether that player can have a winning move
*/
bool winningMove(vector<vector<int> > &b, unsigned int p) {
unsigned int winSequence = 0; // to count adjacent pieces
// for horizontal checks
for (unsigned int c = 0; c < NUM_COL - (WINNING_PUCKS - 1); c++) { // for each column
for (unsigned int r = 0; r < NUM_ROW; r++) { // each row
for (int i = 0; i < WINNING_PUCKS; i++) { // recall you need WINNING_PUCKS to win
if ((unsigned int)b[r][c + i] == p) { // if not all pieces match
winSequence++; // add sequence count
}
if (winSequence == WINNING_PUCKS) { return true; } // if WINNING_PUCKS in row
}
winSequence = 0; // reset counter
}
}
// vertical checks
for (unsigned int c = 0; c < NUM_COL; c++) {
for (unsigned int r = 0; r < NUM_ROW - (WINNING_PUCKS - 1); r++) {
for (int i = 0; i < WINNING_PUCKS; i++) {
if ((unsigned int)b[r + i][c] == p) {
winSequence++;
}
if (winSequence == WINNING_PUCKS) { return true; }
}
winSequence = 0;
}
}
// the below two are diagonal checks
for (unsigned int c = 0; c < NUM_COL - (WINNING_PUCKS - 1); c++) {
for (unsigned int r = 3; r < NUM_ROW; r++) {
for (int i = 0; i < WINNING_PUCKS; i++) {
if ((unsigned int)b[r - i][c + i] == p) {
winSequence++;
}
if (winSequence == WINNING_PUCKS) { return true; }
}
winSequence = 0;
}
}
for (unsigned int c = 0; c < NUM_COL - (WINNING_PUCKS - 1); c++) {
for (unsigned int r = 0; r < NUM_ROW - (WINNING_PUCKS - 1); r++) {
for (int i = 0; i < WINNING_PUCKS; i++) {
if ((unsigned int)b[r + i][c + i] == p) {
winSequence++;
}
if (winSequence == WINNING_PUCKS) { return true; }
}
winSequence = 0;
}
}
return false; // otherwise no winning move
}
/**
* sets up the board to be filled with empty spaces
* also used to reset the board to this state
*/
void initBoard() {
for (unsigned int r = 0; r < NUM_ROW; r++) {
for (unsigned int c = 0; c < NUM_COL; c++) {
board[r][c] = 0; // make sure board is empty initially
}
}
}
/**
* function to copy board state to another 2D vector
* ie. make a duplicate board; used for mutating copies rather
* than the original
* #param b - the board to copy
* #return - said copy
*/
vector<vector<int> > copyBoard(vector<vector<int> > b) {
vector<vector<int>> newBoard(NUM_ROW, vector<int>(NUM_COL));
for (unsigned int r = 0; r < NUM_ROW; r++) {
for (unsigned int c = 0; c < NUM_COL; c++) {
newBoard[r][c] = b[r][c]; // just straight copy
}
}
return newBoard;
}
/**
* prints the board to console out
* #param b - the board to print
*/
void printBoard(vector<vector<int> > &b) {
for (unsigned int i = 0; i < NUM_COL; i++) {
cout << " " << i;
}
cout << endl << "---------------" << endl;
for (unsigned int r = 0; r < NUM_ROW; r++) {
for (unsigned int c = 0; c < NUM_COL; c++) {
cout << "|";
switch (b[NUM_ROW - r - 1][c]) {
case 0: cout << " "; break; // no piece
case 1: cout << "O"; break; // one player's piece
case 2: cout << "X"; break; // other player's piece
}
if (c + 1 == NUM_COL) { cout << "|"; }
}
cout << endl;
}
cout << "---------------" << endl;
cout << endl;
}
/**
* handler for displaying error messages
* #param t - the type of error to display
*/
void errorMessage(int t) {
if (t == 1) { // non-int input
cout << "Use a value 0.." << NUM_COL - 1 << endl;
}
else if (t == 2) { // out of bounds
cout << "That is not a valid column." << endl;
}
else if (t == 3) { // full column
cout << "That column is full." << endl;
}
cout << endl;
}
/**
* main driver
*/
int main(int argc, char** argv) {
// int i = -1; bool flag = false;
// if (argc == 2) {
// istringstream in(argv[1]);
// if (!(in >> i)) { flag = true; }
// if (i > (int)(NUM_ROW * NUM_COL) || i <= -1) { flag = true; }
// if (flag) { cout << "Invalid command line argument, using default depth = 5." << endl; }
// else { MAX_DEPTH = i; }
// }
if(argc <= 1){
cout << "No arguments fed. Terminating";
return 0;
}
if(argc == 4){
int gridSize = atoi(argv[1]);
int diskAmount = atoi(argv[2]);
bool firstTurn = (bool)argv[3];
if(gridSize < 3 || gridSize > 10){
cout << "Incorrect Grid size";
return 0;
}
if(diskAmount < 1 || diskAmount > gridSize){
cout << "Incorrect disk amount";
return 0;
}
NUM_COL = gridSize;
NUM_ROW = gridSize;
WINNING_PUCKS = diskAmount;
FIRST_PLAYER = firstTurn;
}
else{
cout << "Incorrect amount of arguments. Terminating";
return 0;
}
//cout << NUM_COL << endl << WINNING_PUCKS << endl << FIRST_PLAYER << endl;
initBoard(); // initial setup
playGame(); // begin the game
return 0; // exit state
}
It looks to me that you didn't change one of the hard-coded values from your earlier version of the game. On line 336, you have
for (unsigned int r = 3; r < NUM_ROW; r++) {
This is only correct when WINNING_PUCKS is set to 4. The general case should be:
for (unsigned int r = (WINNING_PUCKS - 1); r < NUM_ROW; r++) {
Note that while this part should now work correctly, when I ran it, it still crashes when an end-game is reached with the error message:
double free or corruption (out)
Aborted (core dumped)
I haven't determined what caused this yet.
I've been trying to solve this problem (from school) for just about a week now. We're given two numbers, from -(10^100000) to +that.
Of course the simplest solution is to implement written addition, so that's what I did. I decided, that I would store the numbers as strings, using two functions:
int ti(char a) { // changes char to int
int output = a - 48;
return output;
}
char tc(int a) { // changes int to char
char output = a + 48;
return output;
}
This way I can store negative digits, like -2. With that in mind I implemented a toMinus function:
void toMinus(std::string &a) { // 123 -> -1 -2 -3
for (auto &x : a) {
x = tc(-ti(x));
}
}
I also created a changeSize function, which adds 0 to the beginning of the number until they are both their max size + 1 and removeZeros, which removes leading zeros:
void changeSize(std::string &a, std::string &b) {
size_t exp_size = std::max(a.size(), b.size()) + 2;
while (a.size() != exp_size) {
a = '0' + a;
}
while (b.size() != exp_size) {
b = '0' + b;
}
}
void removeZeros(std::string &a) {
int i = 0;
for (; i < a.size(); i++) {
if (a[i] != '0') {
break;
}
}
a.erase(0, i);
if (a.size() == 0) {
a = "0";
}
}
After all that, I created the main add() function:
std::string add(std::string &a, std::string &b) {
bool neg[2] = {false, false};
bool out_negative = false;
if (a[0] == '-') {
neg[0] = true;
a.erase(0, 1);
}
if (b[0] == '-') {
neg[1] = true;
b.erase(0, 1);
}
changeSize(a, b);
if (neg[0] && !(neg[1] && neg[0])) {
toMinus(a);
}
if(neg[1] && !(neg[1] && neg[0])) {
toMinus(b);
}
if (neg[1] && neg[0]) {
out_negative = true;
}
// Addition
for (int i = a.size() - 1; i > 0; i--) {
int _a = ti(a[i]);
int _b = ti(b[i]);
int out = _a + _b;
if (out >= 10) {
a[i - 1] += out / 10;
} else if (out < 0) {
if (abs(out) < 10) {
a[i - 1]--;
} else {
a[i - 1] += abs(out) / 10;
}
if (i != 1)
out += 10;
}
a[i] = tc(abs(out % 10));
}
if (ti(a[0]) == -1) { // Overflow
out_negative = true;
a[0] = '0';
a[1]--;
for (int i = 2; i < a.size(); i++) {
if (i == a.size() - 1) {
a[i] = tc(10 - ti(a[i]));
} else {
a[i] = tc(9 - ti(a[i]));
}
}
}
if (neg[0] && neg[1]) {
out_negative = true;
}
removeZeros(a);
if (out_negative) {
a = '-' + a;
}
return a;
}
This program works in most cases, although our school checker found that it doesn't - like instead of
-4400547114413430129608370706728634555709161366260921095898099024156859909714382493551072616612065064
it returned
-4400547114413430129608370706728634555709161366260921095698099024156859909714382493551072616612065064
I can't find what the problem is. Please help and thank you in advance.
Full code on pastebin
While I think your overall approach is totally reasonable for this problem, your implementation seems a bit too complicated. Trying to solve this myself, I came up with this:
#include <iostream>
#include <limits>
#include <random>
#include <string>
bool greater(const std::string& a, const std::string& b)
{
if (a.length() == b.length()) return a > b;
return a.length() > b.length();
}
std::string add(std::string a, std::string b)
{
std::string out;
bool aNeg = a[0] == '-';
if (aNeg) a.erase(0, 1);
bool bNeg = b[0] == '-';
if (bNeg) b.erase(0, 1);
bool resNeg = aNeg && bNeg;
if (aNeg ^ bNeg && (aNeg && greater(a, b) || bNeg && greater(b, a)))
{
resNeg = true;
std::swap(a, b);
}
int i = a.length() - 1;
int j = b.length() - 1;
int carry = 0;
while (i >= 0 || j >= 0)
{
const int digitA = (i >= 0) ? a[i] - '0' : 0;
const int digitB = (j >= 0) ? b[j] - '0' : 0;
const int sum = (aNeg == bNeg ? digitA + digitB : (bNeg ? digitA - digitB : digitB - digitA)) + carry;
carry = 0;
if (sum >= 10) carry = 1;
else if (sum < 0) carry = -1;
out = std::to_string((sum + 20) % 10) + out;
i--;
j--;
}
if (carry) out = '1' + out;
while (out[0] == '0') out.erase(0, 1);
if (resNeg) out = '-' + out;
return out;
}
void test()
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(-std::numeric_limits<int32_t>::max(), std::numeric_limits<int32_t>::max());
for (int i = 0; i < 1000000; ++i)
{
const int64_t a = dis(gen);
const int64_t b = dis(gen);
const auto expected = std::to_string(a + b);
const auto actual = add(std::to_string(a), std::to_string(b));
if (actual != expected) {
std::cout << "mismatch expected: " << expected << std::endl;
std::cout << "mismatch actual : " << actual << std::endl;
std::cout << " a: " << a << std::endl;
std::cout << " b: " << b << std::endl;
}
}
}
int main()
{
test();
}
It can potentially be further optimized, but the main points are:
If the sign of both numbers is the same, we can do simple written addition. If both are negative, we simply prepend - at the end.
If the signs are different, we do written subtraction. If the minuend is greater than the subtrahend, there's no issue, we know that the result will be positive. If, however, the subtrahend is greater, we have to reformulate the problem. For example, 123 - 234 we would formulate as -(234 - 123). The inner part we can solve using regular written subtraction, after which we prepend -.
I test this with random numbers for which we can calculate the correct result using regular integer arithmetic. Since it doesn't fail for those, I'm pretty confident it also works correctly for larger inputs. An approach like this could also help you uncover cases where your implementation fails.
Other than that, I think you should use a known failing case with a debugger or simply print statements for the intermediate steps to see where it fails. The only small differences in the failing example you posted could point at some issue with handling a carry-over.
The goal of this program is for the knight to move around the chest board and only touching each spot once.
Each spot is initialized and set to zero by default.
As the knight moves, each spot the knight touches should correspond with the number of moves taken to reach that point.
However, I am having quite a few problems
1) My Knight is moving around the board and going either out of bound of the multidimensional chess board array or manipulates the movement arrays (horizontal[] and vertical[])
2) The conditions of my boolean functions MoveOnBoard && MoveHasNotBeenMade are that if the next possible move is between the exisiting rows and columns also if the spot being moved to has a value of 0(meaning it has yet to be moved to). However, both of these conditions
seem to be ignored.
How would I go about fixing this?
Thank you in advance!
Here's the code below
using namespace std;
#include <iostream>
#include <array>
void DefinedMoveSet();
void RenderBoard();
void MoveKnight(int& moveChoice, int& numberOfMovesMade);
void PossibleMoves();
bool MoveOnBoard(int& moveChoice);
bool MoveHasNotBeenMade(int& moveChoice);
// Two single dimenisional arrays to store move positions for the Knight
// Arrays have yet to be assigned values
int vertical[8], horizontal[8];
int currentRow = 4, currentColumn = 3;
// Initializing an array with the dimension 8 * 8
int chestBoard[8][8] = { 0 };
int main()
{
DefinedMoveSet();
PossibleMoves();
RenderBoard();
cin.ignore();
return 0;
}
void RenderBoard()
{
// The outer loop goes through each row until it reaches 8
for (int boardRow = 0; boardRow < 8; boardRow++)
{
// The inner loop takes in the specific row
for (int boardColumn = 0; boardColumn < 8; boardColumn++)
{
// Then iterates through the columns of that row until it reaches 8
// Each index is seperated by a tab escape key shortcut
cout << chestBoard[boardRow][boardColumn] << "\t";
}
// Back to the inner array a new line is printed for the next row
cout << "\n";
}
}
void DefinedMoveSet()
{
// Values for the horizontal array at each index
horizontal[0] = 2;
horizontal[1] = 1;
horizontal[2] = -1;
horizontal[3] = -2;
horizontal[4] = -2;
horizontal[5] = -1;
horizontal[6] = 1;
horizontal[7] = 2;
// Values for the vertical array at each index
vertical[0] = -1;
vertical[1] = -2;
vertical[2] = -2;
vertical[3] = -1;
vertical[4] = 1;
vertical[5] = 2;
vertical[6] = 2;
vertical[7] = 1;
}
bool MoveOnBoard(int& moveChoice)
{
int futureRow = currentRow + vertical[moveChoice];
int futureColumn = currentColumn + horizontal[moveChoice];
if ((0 < futureRow) && (0 < futureColumn) && (futureRow < 8) && (futureColumn < 8))
return true;
}
bool MoveHasNotBeenMade(int& moveChoice)
{
int futureRow = currentRow + vertical[moveChoice];
int futureColumn = currentColumn + horizontal[moveChoice];
if (chestBoard[futureRow][futureColumn] == 0)
return true;
}
void PossibleMoves()
{
bool movesStillExist = true;
int numberOfMovesMade = 1;
while (numberOfMovesMade < 65 && movesStillExist)
{
for (int i = 0; i < 8; i++)
{
if (i == 8)
movesStillExist = false;
if (MoveOnBoard(i) && MoveHasNotBeenMade(i))
{
numberOfMovesMade++;
MoveKnight(i, numberOfMovesMade);
}
}
}
}
void MoveKnight(int &moveChoice, int &numberOfMovesMade)
{
// Takes in the int moveNumber as a parameter
// MoveNumber(or case) must be between 0 and 7
// if there is not a case for the value then the knight will not move
//chestBoard[currentRow][currentColumn] = numberOfMovesMade;
currentRow += vertical[moveChoice];
currentColumn += horizontal[moveChoice];
chestBoard[currentRow][currentColumn] = numberOfMovesMade;
}
in MoveOnBoardand and in MoveHasNotBeenMade instead of
if(...)
return true;
should be
if(...)
return true;
return false;
if condtion == false, function returning not void reach end without return statement.
With the advice from the comments I received, I was able to fix the index issues as well as the return value of the boolean functions.
My main problem was that I was not breaking out of the previous loop after moving.
Easily solved by this if statement
if (MoveOnBoard(i) && MoveHasNotBeenMade(i))
{
MoveKnight(i);
break;
}
I was trying to achieve this by telling the compiler
if (i == 8)
movesStillExist = false;
As pointed out by #Aziuth this condition will never be met because a move at that index does not exist.
So instead for my purposes I changed that condition to be
if (i == 7)
movesStillExist = false;
Also for the index issues my logic was a little off
if (((0 <= futureRow) && (0 <= futureColumn)) && ((futureRow < 8) && (futureColumn < 8)))
return true; // if the future row and column are in bounds then return true
return false; // else the default is false
Also, my code is not idealistic for c++.
Having so many global variables and not enough commenting.
Please understand that the use of single and multidimensional arrays are required due to this being a challenge for my c++ course.
bool MoveOnBoard(int& moveChoice)
{
int futureRow = currentRow + vertical[moveChoice];
int futureColumn = currentColumn + horizontal[moveChoice];
if (((0 <= futureRow) && (0 <= futureColumn)) && ((futureRow < 8) && (futureColumn < 8)))
return true;
return false;
}
bool MoveHasNotBeenMade(int& moveChoice)
{
int futureRow = currentRow + vertical[moveChoice];
int futureColumn = currentColumn + horizontal[moveChoice];
if (chestBoard[futureRow][futureColumn] == 0)
return true;
return false;
}
void PossibleMoves()
{
bool movesStillExist = true;
while (numberOfMovesMade < 65 && movesStillExist)
{
for (int i = 0; i < 8; i++)
{
if (MoveOnBoard(i) && MoveHasNotBeenMade(i))
{
MoveKnight(i);
break;
}
if (i == 7)
movesStillExist = false;
}
}
}
void MoveKnight(int &moveChoice)
{
// Takes in the int moveNumber as a parameter
// MoveNumber(or case) must be between 0 and 7
// if there is not a case for the value then the knight will not move
chestBoard[currentRow][currentColumn] = numberOfMovesMade;
numberOfMovesMade++;
currentRow += vertical[moveChoice];
currentColumn += horizontal[moveChoice];
chestBoard[currentRow][currentColumn] = numberOfMovesMade;
}
I'm trying to create a simple minesweeper game, and have some issues with creating the board. I am using a 2d vector in lieu of a 2d array and am having trouble incrementing the tiles value to see how many mines are adjacent to the tile.
int Boardsize::createBoard() const {
// vector < vector<Tile> > board;
impl->board.resize(getLength(), vector<Tile>(getWidth(), Tile()));
for (int i = 0; i < getMines(); i++) {
int v1 = rand() % getLength();
int v2 = rand() % getWidth();
if (impl->board[v1][v2].getMine() == true) i--;
else {impl->board[v1][v2].setMine(true);
if (v1 - 1 > -1) impl->board[v1-1][v2]++;
if (v1 + 1 < getLength()) impl->board[v1+1][v2]++;
if (v2 - 1 > -1) impl->board[v1][v2-1]++;
if (v2 + 1 < getWidth()) impl->board[v1][v2+1]++;
if ((v1 - 1 > -1) && (v2 - 1 > -1)) impl->board[v1-1][v2-1]++;
if ((v1 - 1 > -1) && (v2 + 1 < getWidth())) impl->board[v1-1][v2+1]++;
if ((v1 + 1 < getLength()) && (v2 - 1 > -1)) impl->board[v1+1][v2-1]++;
if ((v1 + 1 < getLength()) && (v2 + 1 < getWidth())) impl->board[v1+1][v2+1]++;
}
}
}
Values length, width and mines are set ahead of time. The way I intend it to work is "Check if getMine = true, if yes then game over. If no, isRevealed is set to true and the tile shows how many mines are adjacent to the tile. However, I'm getting the error:
error: no 'operator++(int)' declared for postfix '++' [-fpermissive]|
Do I need to set a seperate function to increment the content? I am assuming that the board.resize fills the vector full of 0's.
I appreciate the help.
Here is the "Tile" file's contents:
namespace Minesweeper {
using namespace std;
class Tile::Tilement {
int status;
bool mine;
int Adjmines;
friend class Tile;
public:
Tilement ()
: status(0), mine(false), Adjmines(0)
{
}
};
Tile::Tile() {
cout << "Tile is being created" << endl;
}
Tile::~Tile() {
cout << "Tile is being deleted" << endl;
}
void Tile::setMine(int a) {
tint->mine = true;
}
void Tile::setStatus(int a) {
if ((a == 0) || (a == 1) || (a == 2)) {
tint->status = a;
}
else {
#ifdef DEBUG
cout << "Tile status invalid" << endl;
#endif // DEBUG
throw invalid_argument("Invalid tile status");
}
}
//void Tile::setContent(char r) {
// tint->content = r;
//}
int Tile::getStatus() const {
return tint->status;
}
char Tile::getAdjcount() const {
return tint->Adjmines;
}
char Tile::getMine() const {
return tint->mine;
}
int Tile::setAdjmines(int a) {
a = a++;
}
char Tile::getContent() const {
if (Tile::getMine() == true) {
return tint->mine;
}
else return tint->Adjmines;
}
EDIT: I've changed the incrementations a bit so that they're now like this:
if (v1 - 1 > -1) impl->board[v1-1][v2].incAdjmines; (etc).
And the incAdjmines function looks like this:
int Tile::incAdjmines() {
Adjmines = Adjmines + 1;
}
And...well, the code compiled, if nothing else, but due to some errors in another fragment of code, I can't tell if it works correctly. Thank you all for your help so far.
You are calling ++ on Tile object which seems with no overload for this operator.
You can solve your problem by overloading this operator for Tile class. Or by directly telling which variable you want to increase for example:
impl->board[v1-1][v2].cout_of_things++
for an intro program, we were asked to build a program that could find every single possible working magic square of a given size. I am having trouble modifying a class variable from within a recursive function. I am trying to increment the number of magic squares found every time the combination of numbers I am trying yields a magic square.
More specifically, I am trying to modify numSquares within the function recursiveMagic(). After setting a breakpoint at that specific line, the variable, numSquares does not change, even though I am incrementing it. I think it has something to do with the recursion, however, I am not sure. If you want to lend some advice, I appreciate it.
//============================================================================
// Name : magicSquare.cpp
// Author :
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================
#include <iostream>
using namespace std;
/**
* MagicSquare
*/
class MagicSquare {
private:
int magicSquare[9];
int usedNumbers[9];
int numSquares;
int N;
int magicInt;
public:
MagicSquare() {
numSquares = 0;
for (int i = 0; i < 9; i++)
usedNumbers[i] = 0;
N = 3; //default is 3
magicInt = N * (N * N + 1) / 2;
}
MagicSquare(int n) {
numSquares = 0;
for (int i = 0; i < 9; i++)
usedNumbers[i] = 0;
N = n;
magicInt = N * (N * N + 1) / 2;
}
void recursiveMagic(int n) {
for (int i = 1; i <= N * N + 1; i++) {
if (usedNumbers[i - 1] == 0) {
usedNumbers[i - 1] = 1;
magicSquare[n] = i;
if (n < N * N)
recursiveMagic(n + 1);
else {
if (isMagicSquare()) {
numSquares++; //this is the line that is not working correctly
printSquare();
}
}
usedNumbers[i - 1] = 0;
}
}
}
//To efficiently check all rows and collumns, we must convert the one dimensional array into a 2d array
//since the sudo 2d array looks like this:
// 0 1 2
// 3 4 5
// 6 7 8
//the following for-if loops convert the i to the appropriate location.
bool isMagicSquare() {
for (int i = 0; i < 3; i++) {
if ((magicSquare[i * 3] + magicSquare[i * 3 + 1] + magicSquare[i * 3 + 2]) != magicInt) //check horizontal
return false;
else if ((magicSquare[i] + magicSquare[i + 3] + magicSquare[i + 6]) != magicInt) // check vertical
return false;
}
if ((magicSquare[0] + magicSquare[4] + magicSquare[8]) != magicInt)
return false;
if ((magicSquare[6] + magicSquare[4] + magicSquare[2]) != magicInt)
return false;
return true;
}
/**
* printSquare: prints the current magic square combination
*/
void printSquare() {
for (int i = 0; i < 3; i++)
cout << magicSquare[i * 3] << " " << magicSquare[i * 3 + 1]
<< " " << magicSquare[i * 3 + 2] << endl;
cout << "------------------" << endl;
}
/**
* checkRow: checks to see if the current row will complete the magic square
* #param i - used to determine what row is being analyzed
* #return true if it is a working row, and false if it is not
*/
bool checkRow(int i) {
i = (i + 1) % 3 - 1;
return (magicSquare[i * 3] + magicSquare[i * 3 + 1] + magicSquare[i * 3 + 2]) == magicInt;
}
int getnumSquares() {
return numSquares;
}
}; //------End of MagicSquare Class-----
int main() {
MagicSquare square;
cout << "Begin Magic Square recursion:" << endl << "------------------"
<< endl;
square.recursiveMagic(0);
cout << "Done with routine, returned combinations: " << square.getnumSquares() << endl;
return 0;
}
The array is being overwritten leading to overwriting the numSquares field.
class MagicSquare {
private:
int magicSquare[9];
int usedNumbers[9];
Changes to
class MagicSquare {
private:
int magicSquare[10];
int usedNumbers[10];
Also in your initializer the loop says < 9 but what you want to say is < 10. Or just use memset is better for that purpose.