I've got (binary) matrices represented by uint64_t (from C++11). And I'd like to be able to efficiently map from any column into first rank. For example
0 1 0 0 0 0 0 0
0 1 0 0 0 0 0 0
0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0
0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0
uint64_t matrice = 0x4040400040400040uLL;
uint64_t matrice_2 = map(matrice, ColumnEnum::Column2);
1 1 1 0 1 1 0 1
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
matrice_2 contains 0xED00000000000000uLL;
Great question. I really enjoyed the hacking. Here is my solution:
uint64_t map(uint64_t x, int column)
{
x = (x >> (7 - column)) & 0x0101010101010101uLL;
x = (x | (x >> 7)) & 0x00FF00FF00FF00FFuLL;
x = (x | (x >> 14))& 0x000000FF000000FFuLL;
x = (x | (x >> 28))& 0x00000000000000FFuLL;
return x << 56;
}
A working example can be found at ideone, where the call is really map(matrice, ColumnEnum::Column2).
A nice little riddle. Here is a reasonably readable version:
matrice = (matrice >> (8ull - column)) & 0x0101010101010101ull;
uint64_t result(( ((matrice >> 0ul) & 0x01ull)
| ((matrice >> 7ul) & 0x02ull)
| ((matrice >> 14ull) & 0x04ull)
| ((matrice >> 21ull) & 0x08ull)
| ((matrice >> 28ull) & 0x10ull)
| ((matrice >> 35ull) & 0x20ull)
| ((matrice >> 42ull) & 0x40ull)
| ((matrice >> 49ull) & 0x80ull)) << 56ull);
First define bitmask for every column:
uint64_t columns[8] = {
0x8080808080808080uLL,
0x4040404040404040uLL,
//...
0x0101010101010101uLL
};
by applying column bitmask to your "matrice" you get only this column:
uint64_t col1 = matrice & columns[1]; // second column - rest is empty
by shifting you can get only first column case:
uint64_t col0 = (col1 << 1); // second column - rest is empty
// ^ this number is just zero based index of column,,,
Now first bit is on right place - just set the next 7 bits:
col0 |= (col0 & (1 << 55)) << 7; // second bit...
// ....
Or just use std::bitset<64>, I would do....
Related
Suppose I have the following code.
int main(int argc, char *argv[])
{
size_t value = stoul(argv[1], 0, 16);
size_t nibble = stoul(argv[2]);
size_t replacement = stoul(argv[3]) % 16;
cout << hex << value << '\n';
}
I want to write supplementary to this code such that I can type ./a.out value nibble replacement in my terminal, and it will replace whatever digit is in the specified nibble by the replacement. So for example, I would want to type ./a.out 22334 3 11 so that the output I get is 2b334. Nibble here indicates the nibble offset. How would I make my program access the specified nibble?
value &= ~( 0xF << ( nibble * 4 ) );
value |= replacement << ( nibble * 4 );
First we create a mask.
1 1 1 1 0xF
1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0xF << ( nibble * 4 )
1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 ~( 0xF << ( nibble * 4 ) )
We use this to clear bits from the original value.
0 0 1 0 0 0 1 0 0 0 1 1 0 0 1 1 0 1 0 0 value
& 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 mask
-----------------------------------------------
0 0 1 0 0 0 0 0 0 0 1 1 0 0 1 1 0 1 0 0 value & mask
Then we prepare the value to insert.
1 0 1 1 replacement
1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 replacement << ( nibble * 4 )
Then merge it in.
0 0 1 0 0 0 0 0 0 0 1 1 0 0 1 1 0 1 0 0 value & mask
1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 replacement << ( nibble * 4 )
| -----------------------------------------------
0 0 1 0 1 0 1 1 0 0 1 1 0 0 1 1 0 1 0 0
You can use the output stream class to work with a string. This makes it much easier to replace any position.
#include <iostream>
#include <sstream>
int main (int argc, char *argv[])
{
std::ostringstream outstream_value;
outstream_value << std::hex << std::stoul(argv[1], 0, 16);
std::string hexstr = outstream_value.str();
const std::size_t length = hexstr.length();
std::ostringstream outstream_replace;
outstream_replace << std::hex << std::stoul(argv[3]) % 16;
const char replace_char = outstream_replace.str()[0];
const std::size_t nibble = std::stoul(argv[2]);
if ( length >= nibble + 1 )
hexstr[length - nibble - 1] = replace_char;
std::cout << hexstr;
return 0;
}
FAR and FRR are used to express the results of biometric devices. Below is the confusion matrix produced by biometric data produced in weka. I couldn't find any resources explaining the procedure to calculate FAR and FRR using a n*n confusion matrix. Any help explaining the procedure would be of great help. Thanks in advance!
Weka also gives these values, TP Rate, FP Rate, Precision, Recall, F-Measure and ROC Area. Please suggest if the required values can be calculated using these.
=== Confusion Matrix ===
a b c d e f g h i j k l m n o <-- classified as
1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 | a = user1
0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 | b = user2
0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 | c = user3
0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 | d = user4
0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 | e = user5
0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 | f = user6
0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 | g = user7
0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 | h = user9
1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 | i = user10
0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 | j = user11
0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 | k = user14
0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 | l = user15
0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 | m = user16
0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 | n = user17
0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 | o = user19
The accepted answer here by user "chl" has a reference to the Biometrics Literature: https://stats.stackexchange.com/questions/3489/calculating-false-acceptance-rate-for-a-gaussian-distribution-of-scores .
He says,
[the ROC curve] is a plot of (TAR=1-FRR, the false rejection rate) against false
acceptance rate (FAR).
However, commonly the ROC curve happens to be a plot of TP Rate as a function of False Positive Rate (FP Rate).
Seems you can use TP Rate and FP Rate.
I am trying to solve a n-knights problem on an 8x8 chessboard recursively. The n-knights problem is a variation of the n-queens problem, where the queens are replaced by knights. No piece can take another piece.
My code so far: http://pastebin.com/TVza3jVU.
The input consists of the number of knights that have to be placed on the chessboard. My code prints a lot of correct boards
Output looks like this (example):
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 2
0 0 0 0 0 0 0 0 3
0 0 0 0 0 0 0 0 4
0 0 0 0 0 0 0 0 5
0 0 0 0 0 0 1 0 6
1 1 0 1 0 1 0 0 7
0 1 2 3 4 5 6 7
nrBoards = 49
A '1' stands for a knight.
My problem is as follows:
0 1 1 1 1 1 0 0 0
0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 2
0 0 0 0 0 0 0 0 3
0 0 0 0 0 0 0 0 4
0 0 0 0 0 0 0 0 5
0 0 0 0 0 0 0 0 6
0 0 0 0 0 0 0 0 7
0 1 2 3 4 5 6 7
This is the last board my script will print. It will never put a knight on [0][0]. I can not figure out why. It also skips some configurations. Is there something wrong with my recursion?
From the code you have linked, it seems that one problem is in your checkplace() function. You do not check whether the bounds of x+2, x-2, y+2, y-2 etc are in or out of the interval 0 to 7.
int checkPlace(int y, int x, chessboard boards) {
if (boards.board[y - 2][x - 1] == 1) {
return 0;
}
if (boards.board[y - 1][x - 2] == 1) {
return 0;
}
if (boards.board[y - 2][x + 1] == 1) {
return 0;
}
if (boards.board[y - 1][x + 2] == 1) {
return 0;
}
if (boards.board[y + 1][x + 2] == 1) {
return 0;
}
if (boards.board[y + 1][x - 2] == 1) {
return 0;
}
if (boards.board[y + 2][x - 1] == 1) {
return 0;
}
if (boards.board[y + 2][x + 1] == 1) {
return 0;
}
return 1;
}
Instead:
if ( x-1 >= 0 && y-2 >= 0 && boards.board[y - 2][x - 1] == 1) {
Similarly for others.
So here is my issue. In the program I have below, towards the bottom of the function "SetBoardStartingConfig" I attempt to fill in the first 4 rows of an array by randomly generating numbers, checking if the square I'm attempting to place them onto is empty (0), and if the addition of the piece would make it go over the specified max values in array "MaxPieces". If it wouldn't, it should theoretically be added - but its not working as I intended, and throwing me interesting values. In main, I go on to repeat this function 10 times, but it always seems to produce a different error - below I've also pasted some of my results.
Note: I've commented out both algorithms to try this, they're separated by a bit of white space.
Sidenote: I seem to always get FlagSide = 1 (right side) the first time I run the program - any ideas on how to fix this?
Thank you all very much for your help :).
#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;
int board[10][10];
int AIPieces[11];
int PlayerPieces[11];
int MaxPieces[11];
string PieceNames[11];
//insert stuff for maximum number of things
#define NullSpace -1 // Spaces that pieces can not move to
#define Flag -5
#define Bomb 1
#define EmptySpace 0 //Empty board spaces
void SetMaxPieces()
{
MaxPieces[0] = 1;
MaxPieces[Bomb] = 6;
MaxPieces[2] = 8;
MaxPieces[3] = 5;
MaxPieces[4] = 4;
MaxPieces[5] = 4;
MaxPieces[6] = 4;
MaxPieces[7] = 3;
MaxPieces[8] = 2;
MaxPieces[9] = 1;
MaxPieces[10] = 1;
MaxPieces[11] = 1; //Spy
}
void ResetAIPieces()
{
for (int i = 0; i < 11; i++)
AIPieces[i] = 0;
}
void SetPieceNames()
{
PieceNames[0] = "Flags:";
PieceNames[1] = "Bombs:";
PieceNames[2] = "Twos:";
PieceNames[3] = "Threes:";
PieceNames[4] = "Fours:";
PieceNames[5] = "Fives:";
PieceNames[6] = "Sixes:";
PieceNames[7] = "Sevens:";
PieceNames[8] = "Eights:";
PieceNames[9] = "Nines:";
PieceNames[10] = "Tens:";
PieceNames[11] = "Spies:";
}
void PrintBoard()
{
for (int i=0; i<10; i++)
{
for (int j=0; j<10; j++)
{
cout << board[i][j] << " ";
if (board[i][j] >= 0)
{
cout << " ";
}
}
cout << endl;
}
}
void SetBoardStartingConfig()
{
for (int i=0; i<10; i++)
{
for (int j=0; j<10; j++)
{
board[i][j] = EmptySpace;
}
}
//arrays work in [row] and [column].
//below defines areas that the pieces can not move to.
board[4][2] = NullSpace;
board[4][3] = NullSpace;
board[5][2] = NullSpace;
board[5][3] = NullSpace;
board[4][6] = NullSpace;
board[4][7] = NullSpace;
board[5][6] = NullSpace;
board[5][7] = NullSpace;
int FlagSide = rand() % 2;
if (FlagSide == 0)
{
board[0][0] = Flag;
AIPieces[0]++;
AIPieces[board[2][0] = Bomb]++;
AIPieces[board[1][1] = Bomb]++;
AIPieces[board[0][2] = Bomb]++;
AIPieces[board[1][0] = rand() % 3 + 4]++;
AIPieces[board[0][1] = rand() % 3 + 4]++;
}
else if (FlagSide == 1)
{
board[0][9-0] = Flag;
AIPieces[0]++;
AIPieces[board[2][9-0] = Bomb]++;
AIPieces[board[1][9-1] = Bomb]++;
AIPieces[board[0][9-2] = Bomb]++;
AIPieces[board[1][9-0] = rand() % 3 + 4]++;
AIPieces[board[0][9-1] = rand() % 3 + 4]++;
}
//for (int i =0; i < 4; i++)
// for (int j = 0; j < 10; j++)
// {
// if (board[i][j] == 0)
// {
// int Chosen = rand() % 10+1;
// if (AIPieces[Chosen] < MaxPieces[Chosen])
// {
// board[i][j] = Chosen;
// AIPieces[Chosen]++;
// }
// else
// break;
// }
// else
// break;
// // if (AIPieces[0] < MaxPieces[0] || AIPieces[1] < MaxPieces[1] || AIPieces[2] < MaxPieces[2] || AIPieces[3] < MaxPieces[3] || AIPieces[4] < MaxPieces[4] || AIPieces[5] < MaxPieces[5] || AIPieces[5] < MaxPieces[5] || AIPieces[6] < MaxPieces[6] || AIPieces[7] < MaxPieces[7] || AIPieces[8] < MaxPieces[8] || AIPieces[9] < MaxPieces[9] || AIPieces[10] < MaxPieces[10] || AIPieces[11] < MaxPieces[11])
// //{
// // AIPieces[board[i][j] = rand() % 10+1]++;
// //}
// }
}
int main()
{
SetMaxPieces();
SetPieceNames();
int loop = 0;
do
{
SetBoardStartingConfig();
PrintBoard();
cout << endl;
for (int i = 0; i < 11; i++)
{
cout << PieceNames[i] << AIPieces[i] << endl;
}
cout << endl;
ResetAIPieces();
loop++;
} while (loop <= 10);
system("PAUSE");
}
My Results (They seem to be the same every time I run it using the first algorithm)
1 10 5 9 0 0 0 1 5 -5
3 5 6 6 2 8 2 2 1 6
6 3 8 7 2 5 3 4 3 1
3 2 7 0 0 0 0 0 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
Flags:1
Bombs:4
Twos:5
Threes:5
Fours:1
Fives:4
Sixes:4
Sevens:2
Eights:2
Nines:1
Tens:1
2 9 10 3 8 0 0 1 4 -5
6 5 4 2 3 4 4 5 1 6
2 2 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
Flags:1
Bombs:3
Twos:4
Threes:2
Fours:4
Fives:2
Sixes:2
Sevens:0
Eights:1
Nines:1
Tens:1
8 8 10 4 2 0 0 1 5 -5
9 7 6 1 3 0 0 0 1 6
7 1 3 5 0 0 0 0 0 1
7 6 1 0 0 0 0 0 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
Flags:1
Bombs:6
Twos:1
Threes:2
Fours:1
Fives:2
Sixes:3
Sevens:3
Eights:2
Nines:1
Tens:1
-5 4 1 0 0 0 0 0 0 0
6 1 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
2 4 9 10 4 5 5 7 1 7
0 0 -1 -1 0 0 -1 -1 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
Flags:1
Bombs:4
Twos:1
Threes:0
Fours:3
Fives:2
Sixes:1
Sevens:2
Eights:0
Nines:1
Tens:1
-5 5 1 0 0 0 0 0 0 0
6 1 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
5 10 7 4 8 9 0 0 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
Flags:1
Bombs:3
Twos:0
Threes:0
Fours:1
Fives:2
Sixes:1
Sevens:1
Eights:1
Nines:1
Tens:1
-5 6 1 0 0 0 0 0 0 0
4 1 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
4 6 10 9 5 1 8 7 4 7
0 0 -1 -1 0 0 -1 -1 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
Flags:1
Bombs:4
Twos:0
Threes:0
Fours:3
Fives:1
Sixes:2
Sevens:2
Eights:1
Nines:1
Tens:1
3 1 10 8 4 8 3 1 6 -5
7 1 2 7 6 0 0 0 1 6
6 5 2 3 1 0 0 0 0 1
2 5 7 0 0 0 0 0 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
Flags:1
Bombs:6
Twos:3
Threes:3
Fours:1
Fives:2
Sixes:4
Sevens:3
Eights:2
Nines:0
Tens:1
8 8 0 0 0 0 0 1 5 -5
4 4 6 10 0 0 0 0 1 6
9 2 0 0 0 0 0 0 0 1
3 7 7 1 4 0 0 0 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
Flags:1
Bombs:4
Twos:1
Threes:1
Fours:3
Fives:1
Sixes:2
Sevens:2
Eights:2
Nines:1
Tens:1
-5 4 1 0 0 0 0 0 0 0
6 1 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
6 1 10 5 8 9 4 6 2 3
0 0 -1 -1 0 0 -1 -1 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
Flags:1
Bombs:4
Twos:1
Threes:1
Fours:2
Fives:1
Sixes:3
Sevens:0
Eights:1
Nines:1
Tens:1
-5 6 1 0 0 0 0 0 0 0
5 1 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
5 1 7 2 9 10 0 0 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
Flags:1
Bombs:4
Twos:1
Threes:0
Fours:0
Fives:2
Sixes:1
Sevens:1
Eights:0
Nines:1
Tens:1
-5 4 1 0 0 0 0 0 0 0
5 1 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
4 10 9 0 0 0 0 0 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
Flags:1
Bombs:3
Twos:0
Threes:0
Fours:2
Fives:1
Sixes:0
Sevens:0
Eights:0
Nines:1
Tens:1
Press any key to continue . . .
I'm not really clear what you expect to happen or what is happening, you should try explaining why what you get is wrong, so people don't have to spend ages analysing the code and results. Is the first algorithm working and the second not? Or are both wrong? The changes below will make the program easier to reason about anyway.
Your variable and function naming is a bit unconventional. It's more usual to see variables and functions start with a lowercase letter, and classes start with an uppercase letter. Your program looks as though Everything Is Very Important.
Why are you using macros here?
#define NullSpace -1 // Spaces that pieces can not move to
#define Flag -5
#define Bomb 1
#define EmptySpace 0 //Empty board spaces
In general, macros suck, especially if you don't name them to avoid clashing with other names. The inventor of C++ recommends using ALL_CAPS for macros. Better still, don't use them:
const int NullSpace = -1; // Spaces that pieces can not move to
const int Flag -5;
const int Bomb 1;
const int EmptySpace 0; //Empty board spaces
This is a very tedious way to set arrays:
void SetMaxPieces()
{
MaxPieces[0] = 1;
MaxPieces[Bomb] = 6;
MaxPieces[2] = 8;
...
MaxPieces[10] = 1;
MaxPieces[11] = 1; //Spy
}
Just initialize the array when you define it:
int MaxPieces[11] = {
1, 6, 8, 5, 4, 4, 4, 3, 2, 1, 1, 1
};
string PieceNames[11] = {
"Flags:", "Bombs:", "Twos:", "Threes:", "Fours:", "Fives:", "Sixes:",
"Sevens:", "Eights:", "Nines:", "Tens:", "Spies:"
};
But wait! Now the compiler refuses to compile the program:
game.cc:13:1: error: too many initializers for ‘int [11]’
game.cc:17:1: error: too many initializers for ‘std::string [11] {aka std::basic_string [11]}’
You are setting twelve values in an array of eleven! The compiler didn't complain when you did MaxPieces[11] (but maybe should have done) but it definitely won't let you initialize an array with too many values. Are your arrays supposed have twelve elements? Or are you just filling them wrong?
As a commenter pointed out, you must seed rand() or the pseudo-random number generator always starts in the same initial state and produces the exact same sequence of "random" numbers.
Why are you using do-while in main? do-while is only useful in a few situations, when the condition can't be tested initially (or for some clever hacks to make its block scope act as a single statement in evil macros). In your case the condition is initially true (loop is less than 10) so just use a for or while loop. I would prefer a for because your loop variable doesn't need to exist after the for so you can initialize it there:
for (int loop = 0; loop <= 10; ++loop)
{
SetBoardStartingConfig();
PrintBoard();
cout << '\n';
for (int i = 0; i < 11; i++)
{
cout << PieceNames[i] << AIPieces[i] << '\n';
}
cout << '\n';
ResetAIPieces();
}
cout << flush;
Using endl every time you want a newline is unnecessary, endl adds a newline and flushes the stream, which doesn't need to be done on every line. The code above does it just once after the loop.
Now for the first algorithm:
for (int i =0; i < 4; i++)
for (int j = 0; j < 10; j++)
{
if (board[i][j] == 0)
{
int Chosen = rand() % 10+1;
if (AIPieces[Chosen] < MaxPieces[Chosen])
{
board[i][j] = Chosen;
AIPieces[Chosen]++;
}
else
break;
}
else
break;
Surrounding the first for in braces could help readability too. It would also help to write rand()%10 + 1 rather than the spacing you have above, so that the operator precedence is more obvious, currently it looks like you mean it to be rand() % 11 because you've grouped the addition operands.
Shouldn't the check board[i][j] == 0 be board[i][j] == EmptySpace ? Otherwise what's the point of having that constant?
Do you really want to break there? Doesn't that mean you stop filling a row as soon as you find a non-empty square or run out of a particular kind of piece? If the break should be there, where do they go for the second algo? Your code is impossible to reason about, partly because all the important logic is commented out (that's not a helpful way to read code!) and because of the inconsistent indentation.
Your second algorithm is completely unreadable, do you have a screen wide enough to see that line without wrapping? Even if you do it would be easier to read broken up.
Does the second algo check board[i][j] == EmptySpace? It doesn't seem to, but maybe that's just your formatting.
Also, all those comments make it awkward to switch between implementations to compare the results. If you do this:
for (int i =0; i < 4; i++)
{
for (int j = 0; j < 10; j++)
{
if (board[i][j] == EmptySpace)
{
#if 0
int Chosen = rand()%10 +1;
if (AIPieces[Chosen] < MaxPieces[Chosen])
{
board[i][j] = Chosen;
AIPieces[Chosen]++;
}
else
break;
#else
if (AIPieces[0] < MaxPieces[0]
|| AIPieces[1] < MaxPieces[1]
|| AIPieces[2] < MaxPieces[2]
|| AIPieces[3] < MaxPieces[3]
|| AIPieces[4] < MaxPieces[4]
|| AIPieces[5] < MaxPieces[5]
|| AIPieces[5] < MaxPieces[5]
|| AIPieces[6] < MaxPieces[6]
|| AIPieces[7] < MaxPieces[7]
|| AIPieces[8] < MaxPieces[8]
|| AIPieces[9] < MaxPieces[9]
|| AIPieces[10] < MaxPieces[10]
|| AIPieces[11] < MaxPieces[11])
{
AIPieces[board[i][j] = rand() % 10+1]++;
}
#endif
}
else
break;
}
}
Then you only need to change one character (change #if 0 to #if 1) to switch between them.
Now I can see the second algorithm properly it's obvious that if any pieces remain you will place a piece, but that could place a piece which you've run out of. e.g. if AIPieces[1] < MaxPieces[1] but AIPieces[2] == MaxPieces[2] the condition is true, but then if rand()%10 + 1 returns 2 you put a piece you aren't allowed to place. That means you place too many of some types of piece.
I think Scott has a much better idea, separate the placing of pieces into a function, which will make that loop much easier to read:
for (int i =0; i < 4; i++)
for (int j = 0; j < 10; j++)
AddPiece(rand() % 3 + 4, 1, 0);
Now you could write AddPiece2 and change the call to that to experiment with different implementations. Comparing the two algorithms could help find where it goes wrong.
I'm not sure I'm understanding the question well. But, trying to answer it. Something like this seems to be what you're asking for:
Instead of incrementing AIPieces, you need to first check that the board doesn't already have something on it and that MaxPieces haven't already been used.
AIPieces[board[1][0] = rand() % 3 + 4]++;
So try a function to do this:
void AddPiece(int pieceType, int locationX, int locationY)
{
if( board[locationX][locationY] != 0 )
return; // board already has something here, so don't add.
if( AIPieces[pieceType] >= MaxPieces[pieceType] )
return; // Can't add as all of these pieces have already been used.
board[locationX][locationY] = pieceType;
AIPieces[pieceType]++;
}
And in place of the original line, call the function like this:
AddPiece(rand() % 3 + 4, 1, 0);
Your second algorithm won't work because when you try and add a piece, the if statement checks if any type of piece has been used, instead of just checking the type of piece you're trying to add.
Could you help me find the right algorithm for image resizing? I have an image of a number. The maximum size is 200x200, I need to get an image with size 15x15 or even less. The image is monochrome (black and white) and the result should be the same. That's the info about my task.
I've already tried one algorithm, here it is
// xscale, yscale - decrease/increase rate
for (int f = 0; f<=49; f++)
{
for (int g = 0; g<=49; g++)//49+1 - final size
{
xpos = (int)f * xscale;
ypos = (int)g * yscale;
picture3[f][g]=picture4[xpos][ypos];
}
}
But it won't work with the decrease of an image, which is my prior target.
Could you help me find an algorithm, which could solve that problem (quality mustn't be perfect, the speed doesn't even matter). Some information about it would be perfect too considering the fact I'm a newbie. Of course, a short piece of c/c++ code (or a library) will be perfect too.
Edit:
I've found an algorithm. Will it be suitable for compressing from 200 to 20?
The general approach is to filter the input to generate a smaller size, and threshold to convert to monochrome. The easiest filter to implement is a simple average, and it often produces OK results. The Sinc filter is theoretically the best but it's impractical to implement and has ringing artifacts which are often undesirable. Many other filters are available, such as Lanczos or Tent (which is the generalized form of Bilinear).
Here's a version of an average filter combined with thresholding. Assuming picture4 is the input with pixel values of 0 or 1, and the output is picture3 in the same format. I also assumed that x is the least significant dimension which is opposite to the usual mathematical notation, and opposite to the coordinates in your question.
int thumbwidth = 15;
int thumbheight = 15;
double xscale = (thumbwidth+0.0) / width;
double yscale = (thumbheight+0.0) / height;
double threshold = 0.5 / (xscale * yscale);
double yend = 0.0;
for (int f = 0; f < thumbheight; f++) // y on output
{
double ystart = yend;
yend = (f + 1) / yscale;
if (yend >= height) yend = height - 0.000001;
double xend = 0.0;
for (int g = 0; g < thumbwidth; g++) // x on output
{
double xstart = xend;
xend = (g + 1) / xscale;
if (xend >= width) xend = width - 0.000001;
double sum = 0.0;
for (int y = (int)ystart; y <= (int)yend; ++y)
{
double yportion = 1.0;
if (y == (int)ystart) yportion -= ystart - y;
if (y == (int)yend) yportion -= y+1 - yend;
for (int x = (int)xstart; x <= (int)xend; ++x)
{
double xportion = 1.0;
if (x == (int)xstart) xportion -= xstart - x;
if (x == (int)xend) xportion -= x+1 - xend;
sum += picture4[y][x] * yportion * xportion;
}
}
picture3[f][g] = (sum > threshold) ? 1 : 0;
}
}
I've now tested this code. Here's the input 200x200 image, followed by a nearest-neighbor reduction to 15x15 (done in Paint Shop Pro), followed by the results of this code. I'll leave you to decide which is more faithful to the original; the difference would be much more obvious if the original had some fine detail.
To properly downscale an image, you should divide your image up into square blocks of pixels and then use something like Bilinear Interpolation in order to find the right color of the pixel that should replace the NxN block of pixels you're doing the interpolation on.
Since I'm not so good at the math involved, I'm not going to try give you an example of how the code would like. Sorry :(
Since you're fine with using a library, you could look into the imagemagick C++ bindings.
You could also output the image in a simple format like a pbm, and then call the imagemagick command to resize it:
system("convert input.pbm -resize 10x10 -compress none output.pbm");
Sample output file (note: you don't need to use a new line for each row):
P1
20 20
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0
0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0
0 0 0 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 0
0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0
0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
The output file:
P1
10 10
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 1 1 0 1 1 0
0 0 0 0 1 0 0 1 1 0 0 0 0 0 1 0 0 1 1 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 1 1 1 1
1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0
I've found an implementation of a bilinear interpolaton. C code.
Assuming that:
a - a primary array (which we need to stretch/compress) pointer.
oldw - primary width
oldh - primary height
b - a secondary array (which we get after compressing/stretching) pointer
neww - secondary width
newh - seconday height
#include <stdio.h>
#include <math.h>
#include <sys/types.h>
void resample(void *a, void *b, int oldw, int oldh, int neww, int newh)
{
int i;
int j;
int l;
int c;
float t;
float u;
float tmp;
float d1, d2, d3, d4;
u_int p1, p2, p3, p4; /* nearby pixels */
u_char red, green, blue;
for (i = 0; i < newh; i++) {
for (j = 0; j < neww; j++) {
tmp = (float) (i) / (float) (newh - 1) * (oldh - 1);
l = (int) floor(tmp);
if (l < 0) {
l = 0;
} else {
if (l >= oldh - 1) {
l = oldh - 2;
}
}
u = tmp - l;
tmp = (float) (j) / (float) (neww - 1) * (oldw - 1);
c = (int) floor(tmp);
if (c < 0) {
c = 0;
} else {
if (c >= oldw - 1) {
c = oldw - 2;
}
}
t = tmp - c;
/* coefficients */
d1 = (1 - t) * (1 - u);
d2 = t * (1 - u);
d3 = t * u;
d4 = (1 - t) * u;
/* nearby pixels: a[i][j] */
p1 = *((u_int*)a + (l * oldw) + c);
p2 = *((u_int*)a + (l * oldw) + c + 1);
p3 = *((u_int*)a + ((l + 1)* oldw) + c + 1);
p4 = *((u_int*)a + ((l + 1)* oldw) + c);
/* color components */
blue = (u_char)p1 * d1 + (u_char)p2 * d2 + (u_char)p3 * d3 + (u_char)p4 * d4;
green = (u_char)(p1 >> 8) * d1 + (u_char)(p2 >> 8) * d2 + (u_char)(p3 >> 8) * d3 + (u_char)(p4 >> 8) * d4;
red = (u_char)(p1 >> 16) * d1 + (u_char)(p2 >> 16) * d2 + (u_char)(p3 >> 16) * d3 + (u_char)(p4 >> 16) * d4;
/* new pixel R G B */
*((u_int*)b + (i * neww) + j) = (red << 16) | (green << 8) | (blue);
}
}
}
Hope it will be useful for other users. But nevertheless I still doubth whether it will work in my situation (when not stratching, but compressing an array). Any ideas?
I think, you need Interpolation. There are a lot of algorithms, for example you can use Bilinear interpolation
If you use Win32, then StretchBlt function possibly help.
The StretchBlt function copies a bitmap from a source rectangle into a destination rectangle, stretching or compressing the bitmap to fit the dimensions of the destination rectangle, if necessary. The system stretches or compresses the bitmap according to the stretching mode currently set in the destination device context.
One approach to downsizing a 200x200 image to, say 100x100, would be to take every 2nd pixel along each row and column. I'll leave you to roll your own code for downsizing to a size which is not a divisor of the original size. And I provide no warranty as to the suitability of this approach for your problem.