I'm creating Quarto, the board game. It's essentially advanced connect 4.
Each piece has four distinguishing features (WHITE VS BLACK | TALL VS SHORT | SQUARE VS CIRCLE | SOLID VS HOLLOW). If you get four of any of those features in a row, you win.
At the moment, I am current trying to write a function to check for a win. However, it is on track to be O(n^4), and I think I can improve this depending on how I structure my code.
Currently, I have this:
enum Piece
{
WTSS, WTSH, WTHS, WTHH,
WSSS, WSSH, WSHS, WSHH,
BTSS, BTSH, BTHS, BTHH,
BSSS, BSSH, BSHS, BSHH,
EMPTY
};
static const char * PieceStrings[] = {
"WTSS ", "WTSH ", "WTHS ", "WTHH ",
"WSSS ", "WSSH ", "WSHS ", "WSHH ",
"BTSS ", "BTSH ", "BTHS ", "BTHH ",
"BSSS ", "BSSH ", "BSHS ", "BSHH ",
"____ ",
};
But I don't think this is very efficient. I have thought about making them their own class, but it then makes it hard to initialize and work with all of these pieces.
This is how I am starting to go about checking for a win:
// go through all N+2 possible connections
// check if any have shared feature
bool Board::isWin() {
int i, j, k;
for (i = 0, k = BOARDSIZE-1; i < BOARDSIZE; i++, k--) {
for (j = 0; j < BOARDSIZE; j++) {
//Horizontal case
// board[i][j];
//Vertical case
// board[j][i];
}
// Diagonal cases
// board[i][i];
// board[k][i];
}
return false;
}
// Checks if pieces have a similar component
bool Board::checkPieces(list<string> & piecesInARow) {
int i, j;
list<string>::iterator it = piecesInARow.begin();
for (i = 0; i < BOARDSIZE; i++) {
for (j = 0; j < BOARDSIZE; j++) {
// check if pieces all have shared char at index
}
}
}
How can I improve this and make it easier for myself?
Each property has 2 possibilities, so you could store them in a bit-field as 0 or 1. For example:
unsigned char type = (color << 0) | (size << 1) | (shape << 2) | (thickness << 3)
where each value is a 0 or 1. Let's say:
enum Color { BLACK = 0, WHITE = 1 };
enum Size { SHORT = 0, TALL = 1 };
enum Shape { CIRCLE = 0, SQUARE = 1 };
enum Thickness { HOLLOW = 0, SOLID = 1 };
then you could compare them by checking XNOR (bit equality) to compare 2 at a time in one operation, where each comparison will return a bit-field of which types compared equally.
(piece1 XNOR piece2) AND (piece2 XNOR piece3) AND (piece3 XNOR piece4) != 0
Like this
class Piece {
public:
Piece(Color color, Size size, Shape shape, Thickness thickness) {
type = (color) | (size << 1) | (shape << 2) | (thickness << 3);
}
Color color() const {
return static_cast<Color>((type >> 0) & 1);
}
Size size() const {
return static_cast<Size>((type >> 1) & 1);
}
Shape shape() const {
return static_cast<Shape>((type >> 2) & 1);
}
Thickness thickness() const {
return static_cast<Thickness>((type >> 3) & 1);
}
static bool compare(Piece p0, Piece p1, Piece p2, Piece p3) {
unsigned char c[3];
c[0] = ~( p0.type ^ p1.type ); // XNOR
c[1] = ~( p1.type ^ p2.type ); // XNOR
c[2] = ~( p2.type ^ p3.type ); // XNOR
return (c[0] & c[1] & c[2] & 0b1111) != 0;
}
protected:
unsigned char type;
};
I tested it with this code:
int main() {
Piece p0(WHITE, SHORT, CIRCLE, HOLLOW);
Piece p1(WHITE, SHORT, CIRCLE, HOLLOW);
Piece p2(BLACK, SHORT, CIRCLE, HOLLOW);
Piece p3(BLACK, TALL, CIRCLE, SOLID);
const char* str = Piece::compare(p0, p1, p2, p3) ? "success" : "fail";
std::cout << str << '\n';
return 0;
}
I decided to manage it with a class, however, each piece is a 4-bit value, so it can be managed in an integral type just as easily.
Another consequence of doing it this way is that pieces can be randomized by picking a value between 0b0000 and 0b1111, which is [0,15] inclusive.
Related
I have 2 separate boards for 2 players: X and O. Now I'd like to make sure if an entered position (int x, int y) is valid but I've got no idea of how should I convert it to bitboard representation and compare it with given board states and it's doing me head in. Also wrote a helper function to see the board states bin(). And is there a way to merge the X and O boards into one or should I keep the separate all board to check the game state?
#include <bits/stdc++.h>
using namespace std;
bool xmove = true;
const int win[] = { 0b111000000,
0b000111000,
0b000000111,
0b100100100,
0b010010010,
0b001001001,
0b100010001,
0b001010100 };
struct Board {
int b = 0b000000000;
};
int iswin(int x) {
for (size_t i = 0; i < 8; i++) {
if (win[i] == x) return 1;
}
return 0;
};
void bin(int x){
cout << "0b" + bitset<9>(x).to_string() << endl;
};
int main() {
Board x, o, all;
x.b |= 0b000000111;
o.b |= 0b000111000;
all.b = x.b | o.b;
bin(all.b);
cout << iswin(x.b);
return 0;
}
Well you can treat your bitstring as a flattened 2d array. To convert a 2d index into a 1d one you can simply do
x * width + y
So to set the matching position in the board you can do
int move = 1 << (x * 3 + y)
since a TicTacToe board is 3 wide and 3 tall. You can then check if there already is an X or O at that position with
if(x.b & move)
{
std::cout << "there already is and x at(" << x << ", " << y << ")";
}
To then add that position to the board if there is nothing there do
x.b |= move
Same thing for o.b. This is of course based on the assumption that your x and y start at 0.
Concerning your question of whether or not you can merge the two board. How would you even do that? A bit can only be 0 or 1 so there is no way to differentiate between 3 different states (nothing, X, O).
So I have this test case and am trying to no have to make one million operator overloads or handle overload collisions or complexity. I want to be able to handle literal array constants with operator overloads. This is sort of a requirement to create ease of use for an intended library (this test case shoots in the same direction.)
I am looking for a solution to being able to add, subtract variable length carray literal constants. I have a few solutions, one that works but only if both C_COORDS and N_COORDS are more than one. I am using defines instead of Templates to simplify the test case but those defines would be replaced with Templates in the final hour.
Any suggestions welcome. Note, I'm sure I could make this more clear but can't see how at the moment. I use to do lots of C programming 30 years ago. But haven't touched CPP much since then, yes I understand CPP mostly and the differences between it and old C, but not much experience yet. I am just noting because I am sure I am missing a few OBVIOUS things. Thanks. My testcase follows....
/** Coord.cpp */
#include <iostream>
#include <cstring>
#include <initializer_list>
#include <cassert>
#define T_COORDS float // the type of coordinates
#define N_COORDS (2) // the coordinates per item
#define C_COORDS (2) // the number of coordinate items
#define L_COORDS (N_COORDS*C_COORDS) // the number of coordinate items
using namespace std;
class Coords {
public:
T_COORDS coords[L_COORDS];
Coords()
{
memset(this->coords, 0, sizeof(Coords));
}
Coords(const T_COORDS inits[L_COORDS])
{
memmove(this->coords, &inits, sizeof(Coords));
}
Coords(initializer_list<T_COORDS> inits) : coords{}
{
copy( inits.begin(), next( inits.begin(), L_COORDS ), coords );
}
friend Coords operator + (const Coords &coords0, const Coords &coords1)
{
Coords result = coords0;
for (int i=0; i < L_COORDS; i++)
result.coords[i] += coords1.coords[i];
return result;
}
/* original that complains about taking size from a temporary array. the next
* 2 UNCOMMENTED overloads accept a fixed length array, but then I have to
* have for every case and they cannot overlap.
friend Coords operator + (const Coords& coords0, const T_COORDS (& coords1)[])
{
int n = sizeof(coords1) / sizeof(T_COORDS);
if ( ! n || n > L_COORDS || n % N_COORDS )
throw "coordinate count must be a multiple and at least N_COORDS and not more then T_COORDS";
cout << "n = " << n << endl;
Coords result = coords0;
for (int i=0; i < L_COORDS; i++)
result.coords[i] += coords1[i%n];
return result;
}
*/
/* bad solution was to make to overloads that match of a fixed length array,
* however it sucks because if N_COORDS is 1, then it also won't compile
* because it ends up with duplicate overloads as L_COORDS is equal to
* C_COORDS when N_COORDS is one, and same is true is C_COORDS is one.
* WHat I hope for is a way to accept any array or at least any array with a
* length >= and on boundaries of C_COORDS and not more the L_COORDS */
friend Coords operator + (const Coords& coords0, const T_COORDS (& coords1)[C_COORDS])
{
int n = sizeof(coords1) / sizeof(T_COORDS);
if ( ! n || n > L_COORDS || n % N_COORDS )
throw "coordinate count must be a multiple and at least N_COORDS and not more then T_COORDS";
cout << "n = " << n << endl;
Coords result = coords0;
for (int i=0; i < L_COORDS; i++)
result.coords[i] += coords1[i%n];
return result;
}
/* as above, so below but for different size array */
friend Coords operator + (const Coords& coords0, const T_COORDS (& coords1)[L_COORDS])
{
int n = sizeof(coords1) / sizeof(T_COORDS);
if ( ! n || n > L_COORDS || n % N_COORDS )
throw "coordinate count must be a multiple and at least N_COORDS and not more then T_COORDS";
cout << "n = " << n << endl;
Coords result = coords0;
for (int i=0; i < L_COORDS; i++)
result.coords[i] += coords1[i%n];
return result;
}
};
void print_coords(const char* label, Coords coords)
{
cout << label << ": ( " << coords.coords[0];
for (int i=1; i < L_COORDS; i++) {
cout << ", " << coords.coords[i];
}
cout << " }" << endl;
};
int main () {
Coords coords0;
print_coords("coords0", coords0);
Coords coords1 {4,5,6,7};
print_coords("coords1", coords1);
Coords coords2 {8,9,10,11};
print_coords("coords2", coords2);
Coords coords3 = coords1 + coords2;
print_coords("coords3", coords3);
T_COORDS tmp[] = {-2,-2,-2,-2};
Coords coords4 = coords3 + tmp;
print_coords("coords4", coords4);
T_COORDS tmp2[] = {-2,-2};
Coords coords5 = coords4 + tmp2;
print_coords("coords5", coords5);
Coords coords6 = coords5 + (T_COORDS[]){10,20,30,40};
print_coords("coords6", coords6);
Coords coords7 = coords6 + (T_COORDS[]){10,20};
print_coords("coords7", coords7);
/* this won't compile with fixes length overloads because it don't match and thats ok.
try {
Coords coords8 = coords7 + (T_COORDS[]){10,20,30};
print_coords("coords8", coords8);
} catch (const char* msg) {
cout << "threw exception on 3 coordinates as expected" << endl;
}
*/
cout << "Done!" << endl;
return 0;
}
/**
* g++ Coord.cpp -o coord
* ./coord
* RESULING OUTPUT:
* coords0: ( 0, 0, 0, 0 }
* coords1: ( 4, 5, 6, 7 }
* coords2: ( 8, 9, 10, 11 }
* coords3: ( 12, 14, 16, 18 }
* n = 4
* coords4: ( 10, 12, 14, 16 }
* n = 2
* coords5: ( 8, 10, 12, 14 }
* n = 4
* coords6: ( 18, 30, 42, 54 }
* n = 2
* coords7: ( 28, 50, 52, 74 }
* Done!
*/
const T_COORDS (& coords1)[] is array of unknown bound. you know the size, so it is not what you want.
You might use template:
template <std::size_t N>
// SFINAE, instead of throw
// care, then Coords+Coords is viable and no exception in Coords(initializer_list)
// For invalid size
/*, std::enable_if_t<N != 0 && N <= L_COORDS && N % N_COORDS == 0, bool> = false*/>
friend Coords operator + (const Coords& coords0, const T_COORDS (& coords1)[N])
{
if ( ! N || N > L_COORDS || N % N_COORDS )
throw "coordinate count must be a multiple and at least N_COORDS and not more then T_COORDS";
std::cout << "n = " << N << std::endl;
Coords result = coords0;
for (int i=0; i < L_COORDS; i++)
result.coords[i] += coords1[i%N];
return result;
}
Demo
I have a vector with digits of number, vector represents big integer in system with base 2^32. For example:
vector <unsigned> vec = {453860625, 469837947, 3503557200, 40}
This vector represent this big integer:
base = 2 ^ 32
3233755723588593872632005090577 = 40 * base ^ 3 + 3503557200 * base ^ 2 + 469837947 * base + 453860625
How to get this decimal representation in string?
Here is an inefficient way to do what you want, get a decimal string from a vector of word values representing an integer of arbitrary size.
I would have preferred to implement this as a class, for better encapsulation and so math operators could be added, but to better comply with the question, this is just a bunch of free functions for manipulating std::vector<unsigned> objects. This does use a typedef BiType as an alias for std::vector<unsigned> however.
Functions for doing the binary division make up most of this code. Much of it duplicates what can be done with std::bitset, but for bitsets of arbitrary size, as vectors of unsigned words. If you want to improve efficiency, plug in a division algorithm which does per-word operations, instead of per-bit. Also, the division code is general-purpose, when it is only ever used to divide by 10, so you could replace it with special-purpose division code.
The code generally assumes a vector of unsigned words and also that the base is the maximum unsigned value, plus one. I left a comment wherever things would go wrong for smaller bases or bases which are not a power of 2 (binary division requires base to be a power of 2).
Also, I only tested for 1 case, the one you gave in the OP -- and this is new, unverified code, so you might want to do some more testing. If you find a problem case, I'll be happy to fix the bug here.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
namespace bigint {
using BiType = std::vector<unsigned>;
// cmp compares a with b, returning 1:a>b, 0:a==b, -1:a<b
int cmp(const BiType& a, const BiType& b) {
const auto max_size = std::max(a.size(), b.size());
for(auto i=max_size-1; i+1; --i) {
const auto wa = i < a.size() ? a[i] : 0;
const auto wb = i < b.size() ? b[i] : 0;
if(wa != wb) { return wa > wb ? 1 : -1; }
}
return 0;
}
bool is_zero(BiType& bi) {
for(auto w : bi) { if(w) return false; }
return true;
}
// canonize removes leading zero words
void canonize(BiType& bi) {
const auto size = bi.size();
if(!size || bi[size-1]) return;
for(auto i=size-2; i+1; --i) {
if(bi[i]) {
bi.resize(i + 1);
return;
}
}
bi.clear();
}
// subfrom subtracts b from a, modifying a
// a >= b must be guaranteed by caller
void subfrom(BiType& a, const BiType& b) {
unsigned borrow = 0;
for(std::size_t i=0; i<b.size(); ++i) {
if(b[i] || borrow) {
// TODO: handle error if i >= a.size()
const auto w = a[i] - b[i] - borrow;
// this relies on the automatic w = w (mod base),
// assuming unsigned max is base-1
// if this is not the case, w must be set to w % base here
borrow = w >= a[i];
a[i] = w;
}
}
for(auto i=b.size(); borrow; ++i) {
// TODO: handle error if i >= a.size()
borrow = !a[i];
--a[i];
// a[i] must be set modulo base here too
// (this is automatic when base is unsigned max + 1)
}
}
// binary division and its helpers: these require base to be a power of 2
// hi_bit_set is base/2
// the definition assumes CHAR_BIT == 8
const auto hi_bit_set = unsigned(1) << (sizeof(unsigned) * 8 - 1);
// shift_right_1 divides bi by 2, truncating any fraction
void shift_right_1(BiType& bi) {
unsigned carry = 0;
for(auto i=bi.size()-1; i+1; --i) {
const auto next_carry = (bi[i] & 1) ? hi_bit_set : 0;
bi[i] >>= 1;
bi[i] |= carry;
carry = next_carry;
}
// if carry is nonzero here, 1/2 was truncated from the result
canonize(bi);
}
// shift_left_1 multiplies bi by 2
void shift_left_1(BiType& bi) {
unsigned carry = 0;
for(std::size_t i=0; i<bi.size(); ++i) {
const unsigned next_carry = !!(bi[i] & hi_bit_set);
bi[i] <<= 1; // assumes high bit is lost, i.e. base is unsigned max + 1
bi[i] |= carry;
carry = next_carry;
}
if(carry) { bi.push_back(1); }
}
// sets an indexed bit in bi, growing the vector when required
void set_bit_at(BiType& bi, std::size_t index, bool set=true) {
std::size_t widx = index / (sizeof(unsigned) * 8);
std::size_t bidx = index % (sizeof(unsigned) * 8);
if(bi.size() < widx + 1) { bi.resize(widx + 1); }
if(set) { bi[widx] |= unsigned(1) << bidx; }
else { bi[widx] &= ~(unsigned(1) << bidx); }
}
// divide divides n by d, returning the result and leaving the remainder in n
// this is implemented using binary division
BiType divide(BiType& n, BiType d) {
if(is_zero(d)) {
// TODO: handle divide by zero
return {};
}
std::size_t shift = 0;
while(cmp(n, d) == 1) {
shift_left_1(d);
++shift;
}
BiType result;
do {
if(cmp(n, d) >= 0) {
set_bit_at(result, shift);
subfrom(n, d);
}
shift_right_1(d);
} while(shift--);
canonize(result);
canonize(n);
return result;
}
std::string get_decimal(BiType bi) {
std::string dec_string;
// repeat division by 10, using the remainder as a decimal digit
// this will build a string with digits in reverse order, so
// before returning, it will be reversed to correct this.
do {
const auto next_bi = divide(bi, {10});
const char digit_value = static_cast<char>(bi.size() ? bi[0] : 0);
dec_string.push_back('0' + digit_value);
bi = next_bi;
} while(!is_zero(bi));
std::reverse(dec_string.begin(), dec_string.end());
return dec_string;
}
}
int main() {
bigint::BiType my_big_int = {453860625, 469837947, 3503557200, 40};
auto dec_string = bigint::get_decimal(my_big_int);
std::cout << dec_string << '\n';
}
Output:
3233755723588593872632005090577
Lets say I have two AABB based areas, each area defined by two coordinates mins{x, y} and maxs{x, y}, I want to find the middle connection point between them.
Since my english is not good, I can't explain all with my words,
see the following picture for easier understanding:
http://i.*.com/WokivEe.png
All I need to find is the red point coordinates.
so If we move this into programming question, actual data structures would look like this:
struct Vec2D {
float x, y;
}
struct Rectangle {
Vec2D min;
Vec2D max;
}
Rectangle obj[2]
Anyone got an idea for an algorithm?
Along either the X or Y axis, sort the coordinates of the sides that touch into order. Then average the 2nd and 3rd ones in that list to find their midpoint. I hope this answers the question sufficiently.
Here is a little algorithm that first find which sides of the objects are closest, and then uses the 4 points along the common side to make a list, sorted along the common axis. The average of the 2 middle points of the sorted list are the answer. This will work for both horizontal and vertical sides. I added accessor functions to the data structures so that they can be indexed; e.g., for a Vec2D, coordinate(0) is the x value and coordinate(1) is the y value.
#include <math.h>
#include <iostream>
#include <limits>
struct Vec2D {
float x, y;
float coordinate(int axis)
{
return (axis & 1) ? y : x;
}
};
struct Rectangle {
Vec2D min;
Vec2D max;
Vec2D corner(int j)
{
return (j & 1) ? max : min;
}
// Get the other corner along the given axis
Vec2D along(int j, int ax)
{
Vec2D p = corner(j);
if (0 == ax)
{
p.x = corner(1-j).x;
}
else
{
p.y = corner(1-j).y;
}
return p;
}
};
using namespace std;
inline Vec2D* vp(const void* p)
{
return (Vec2D*) p;
}
static int compare_x(const void*a, const void*b)
{
if (vp(a)->x < vp(b)->x)
{
return -1;
}
else
if (vp(a)->x > vp(b)->x)
{
return 1;
}
return 0;
}
static int compare_y(const void*a, const void*b)
{
if (vp(a)->y < vp(b)->y)
{
return -1;
}
else
if (vp(a)->y > vp(b)->y)
{
return 1;
}
return 0;
}
int main(void) {
int ax; // axis index
int c0, c1;
float gap = numeric_limits<float>::max();
struct Rectangle obj[2] = {0,2,10,10,10,5,15,20};
struct
{
int ax,c0,c1;
} closest;
// Find out which sides are the closest to each other
for(ax = 0; 2 > ax; ++ax) // Look at x axis and y axis
{
for(c0 = 0; 2 > c0; ++c0) // Look at both corners of obj[0]
{
for(c1 = 0; 2 > c1; ++c1) // Look at both corners of obj[1]
{
float dist = fabs(obj[0].corner(c0).coordinate(ax) - obj[1].corner(c1).coordinate(ax));
if (dist < gap)
{
gap = dist;
closest.ax = ax;
closest.c0 = c0;
closest.c1 = c1;
}
}
}
}
int other = 1 - closest.ax; // The other axis
cout << "The closest gap is along the " << (closest.ax ? 'y' : 'x') << " axis\n";
cout << "The common side is along the " << (other ? 'y' : 'x') << " direction\n";
// Make a list of the 4 points along the common side
Vec2D list[4];
list[0] = obj[0].corner(closest.c0);
list[1] = obj[0].along(closest.c0, other);
list[2] = obj[1].corner(closest.c1);
list[3] = obj[1].along(closest.c1, other);
// Sort them into order along the common axis
qsort(list, 4, sizeof(Vec2D), closest.ax ? compare_x : compare_y);
// Get the average of the 2 middle points along the common axis.
Vec2D answer = {
(list[1].x + list[2].x) / 2,
(list[1].y + list[2].y) / 2
};
cout << "(" << answer.x << "," << answer.y << ")\n";
}
I'm in the process of building a free open source OpenGL3-based 3D game engine (it's not a school assignment, rather it's for personal skill development and to give something back to the open source community). I've reached the stage where I need to learn lots of related math, so I'm reading a great textbook called "Mathematics for 3D Game Programming and Computer Graphics, 3rd Edition".
I've hit a snag early on trying to do the book's exercises though, as my attempt at implementing the "Gram-Schmidt Orthogonalization algorithm" in C++ is outputting a wrong answer. I'm no math expert (although I'm trying to get better), and I have very limited experience looking at a math algorithm and translating it into code (limited to some stuff I learned from Udacity.com). Anyway, it would really help if someone could look at my incorrect code and give me a hint or a solution.
Here it is:
/*
The Gram-Schmidt Orthogonalization algorithm is as follows:
Given a set of n linearly independent vectors Beta = {e_1, e_2, ..., e_n},
the algorithm produces a set Beta' = {e_1', e_2', ..., e_n'} such that
dot(e_i', e_j') = 0 whenever i != j.
A. Set e_1' = e_1
B. Begin with the index i = 2 and k = 1
C. Subtract the projection of e, onto the vectors e_1', e_2', ..., e_(i-1)'
from e_i, and store the result in e_i', That is,
dot(e_i, e_k')
e_i' = e_i - sum_over(-------------- e_k')
e_k'^2
D. If i < n, increment i and loop back to step C.
*/
#include <iostream>
#include <glm/glm.hpp>
glm::vec3 sum_over_e(glm::vec3* e, glm::vec3* e_prime, int& i)
{
int k = 0;
glm::vec3 result;
while (k < i-2)
{
glm::vec3 e_prime_k_squared(pow(e_prime[k].x, 2), pow(e_prime[k].y, 2), pow(e_prime[k].z, 2));
result += (glm::dot(e[i], e_prime[k]) / e_prime_k_squared) * e_prime[k];
k++;
}
return result;
}
int main(int argc, char** argv)
{
int n = 2; // number of vectors we're working with
glm::vec3 e[] = {
glm::vec3(sqrt(2)/2, sqrt(2)/2, 0),
glm::vec3(-1, 1, -1),
glm::vec3(0, -2, -2)
};
glm::vec3 e_prime[n];
e_prime[0] = e[0]; // step A
int i = 0; // step B
do // step C
{
e_prime[i] = e[i] - sum_over_e(e, e_prime, i);
i++; // step D
} while (i-1 < n);
for (int loop_count = 0; loop_count <= n; loop_count++)
{
std::cout << "Vector e_prime_" << loop_count+1 << ": < "
<< e_prime[loop_count].x << ", "
<< e_prime[loop_count].y << ", "
<< e_prime[loop_count].z << " >" << std::endl;
}
return 0;
}
This code outputs:
Vector e_prime_1: < 0.707107, 0.707107, 0 >
Vector e_prime_2: < -1, 1, -1 >
Vector e_prime_3: < 0, -2, -2 >
but the correct answer is supposed to be:
Vector e_prime_1: < 0.707107, 0.707107, 0 >
Vector e_prime_2: < -1, 1, -1 >
Vector e_prime_3: < 1, -1, -2 >
Edit: Here's the code that produces the correct answer:
#include <iostream>
#include <glm/glm.hpp>
glm::vec3 sum_over_e(glm::vec3* e, glm::vec3* e_prime, int& i)
{
int k = 0;
glm::vec3 result;
while (k < i-1)
{
float e_prime_k_squared = glm::dot(e_prime[k], e_prime[k]);
result += ((glm::dot(e[i], e_prime[k]) / e_prime_k_squared) * e_prime[k]);
k++;
}
return result;
}
int main(int argc, char** argv)
{
int n = 3; // number of vectors we're working with
glm::vec3 e[] = {
glm::vec3(sqrt(2)/2, sqrt(2)/2, 0),
glm::vec3(-1, 1, -1),
glm::vec3(0, -2, -2)
};
glm::vec3 e_prime[n];
e_prime[0] = e[0]; // step A
int i = 0; // step B
do // step C
{
e_prime[i] = e[i] - sum_over_e(e, e_prime, i);
i++; // step D
} while (i < n);
for (int loop_count = 0; loop_count < n; loop_count++)
{
std::cout << "Vector e_prime_" << loop_count+1 << ": < "
<< e_prime[loop_count].x << ", "
<< e_prime[loop_count].y << ", "
<< e_prime[loop_count].z << " >" << std::endl;
}
return 0;
}
The problem is probably in the way you define e_k'^2. As far as vector math goes, the square of a vector is usually taken to be the square of its norm. Therefore,
double e_prime_k_squared = glm::dot(e_prime_k, e_prime_k);
Moreover, dividing by a vector is undefined (I wonder why GLM allows it?), so if e_k'^2 is a vector, the whole thing is undefined.