Related
I was learning MO's Algorithm. In that I found a question. In which we have to make a program to take input n for n nodes of a tree then n-1 pairs of u and v denoting the connection between node u and node v. After that giving the n node values.
Then we will ask q queries. For each query we take input of k and l which denote the two nodes of that tree. Now we have to find the product of all the nodes in the path of k and l (including k and l).
I want to use MO's algorithm. https://codeforces.com/blog/entry/43230
But I am unable to make the code. Can anybody help me out in this.
The basic code for that would be:
int n, q;
int nxt[ N ], to[ N ], hd[ N ];
struct Que{
int u, v, id;
} que[ N ];
void init() {
// read how many nodes and how many queries
cin >> n >> q;
// read the edge of tree
for ( int i = 1 ; i < n ; ++ i ) {
int u, v; cin >> u >> v;
// save the tree using adjacency list
nxt[ i << 1 | 0 ] = hd[ u ];
to[ i << 1 | 0 ] = v;
hd[ u ] = i << 1 | 0;
nxt[ i << 1 | 1 ] = hd[ v ];
to[ i << 1 | 1 ] = u;
hd[ v ] = i << 1 | 1;
}
for ( int i = 0 ; i < q ; ++ i ) {
// read queries
cin >> que[ i ].u >> que[ i ].v;
que[ i ].id = i;
}
}
int dfn[ N ], dfn_, block_id[ N ], block_;
int stk[ N ], stk_;
void dfs( int u, int f ) {
dfn[ u ] = dfn_++;
int saved_rbp = stk_;
for ( int v_ = hd[ u ] ; v_ ; v_ = nxt[ v_ ] ) {
if ( to[ v_ ] == f ) continue;
dfs( to[ v_ ], u );
if ( stk_ - saved_rbp < SQRT_N ) continue;
for ( ++ block_ ; stk_ != saved_rbp ; )
block_id[ stk[ -- stk_ ] ] = block_;
}
stk[ stk_ ++ ] = u;
}
bool inPath[ N ];
void SymmetricDifference( int u ) {
if ( inPath[ u ] ) {
// remove this edge
} else {
// add this edge
}
inPath[ u ] ^= 1;
}
void traverse( int& origin_u, int u ) {
for ( int g = lca( origin_u, u ) ; origin_u != g ; origin_u = parent_of[ origin_u ] )
SymmetricDifference( origin_u );
for ( int v = u ; v != origin_u ; v = parent_of[ v ] )
SymmetricDifference( v );
origin_u = u;
}
void solve() {
// construct blocks using dfs
dfs( 1, 1 );
while ( stk_ ) block_id[ stk[ -- stk_ ] ] = block_;
// re-order our queries
sort( que, que + q, [] ( const Que& x, const Que& y ) {
return tie( block_id[ x.u ], dfn[ x.v ] ) < tie( block_id[ y.u ], dfn[ y.v ] );
} );
// apply mo's algorithm on tree
int U = 1, V = 1;
for ( int i = 0 ; i < q ; ++ i ) {
pass( U, que[ i ].u );
pass( V, que[ i ].v );
// we could our answer of que[ i ].id
}
}
This problem is a slight modification of the blog that you have shared.
Problem Tags:- MO's Algorithm, Trees, LCA, Binary Lifting, Sieve, Precomputation, Prime Factors
Precomputations:- Just we need to do some precomputations with seiveOfErothenesis to store the highest prime factor of each element possible in input constraints. Then using this we will store all the prime factors and their powers for each element in input array in another matrix.
Observation:- with the constraints you can see the there can be very few such primes possible for each element. For an element (10^6) there can be a maximum of 7 prime factors possible.
Modify MO Algo Given in blog:- Now in our compute method we just need to maintain a map that will store the current count of the prime factor. While adding or subtracting each element in solving the queries we will iterate on the prime factors of that element and divide our result(storing total no. of factors) with the old count of that prime and then update the count of that prime and the multiple our result with the new count.(This will be O(7) max for each addition/subtraction).
Complexity:- O(T * ((N + Q) * sqrt(N) * F)) where F is 7 in our case. F is the complexity of your check method().
T - no of test cases in input file.
N - the size of your input array.
Q - No. of queries.
Below is an implementation of the above approach in JAVA. computePrimePowers() and check() are the methods you would be interested in.
import java.util.*;
import java.io.*;
public class Main {
static int BLOCK_SIZE;
static int ar[];
static ArrayList<Integer> graph[];
static StringBuffer sb = new StringBuffer();
static boolean notPrime[] = new boolean[1000001];
static int hpf[] = new int[1000001];
static void seive(){
notPrime[0] = true;
notPrime[1] = true;
for(int i = 2; i < 1000001; i++){
if(!notPrime[i]){
hpf[i] = i;
for(int j = 2 * i; j < 1000001; j += i){
notPrime[j] = true;
hpf[j] = i;
}
}
}
}
static long modI[] = new long[1000001];
static void computeModI() {
for(int i = 1; i < 1000001; i++) {
modI[i] = pow(i, 1000000005);
}
}
static long pow(long x, long y) {
if (y == 0)
return 1;
long p = pow(x, y / 2);
p = (p >= 1000000007) ? p % 1000000007 : p;
p = p * p;
p = (p >= 1000000007) ? p % 1000000007 : p;
if ((y & 1) == 0)
return p;
else {
long tt = x * p;
return (tt >= 1000000007) ? tt % 1000000007 : tt;
}
}
public static void main(String[] args) throws Exception {
Reader s = new Reader();
int test = s.nextInt();
seive();
computeModI();
for(int ii = 0; ii < test; ii++){
int n = s.nextInt();
lcaTable = new int[19][n + 1];
graph = new ArrayList[n + 1];
arrPrimes = new int[n + 1][7][2];
primeCnt = new int[1000001];
visited = new int[n + 1];
ar = new int[n + 1];
for(int i = 0; i < graph.length; i++) graph[i] = new ArrayList<>();
for(int i = 1; i < n; i++){
int u = s.nextInt(), v = s.nextInt();
graph[u].add(v);
graph[v].add(u);
}
int ip = 1; while(ip <= n) ar[ip++] = s.nextInt();
computePrimePowers();
int q = s.nextInt();
LVL = new int[n + 1];
dfsTime = 0;
dfs(1, -1);
BLOCK_SIZE = (int) Math.sqrt(dfsTime);
int Q[][] = new int[q][4];
int i = 0;
while(q-- > 0) {
int u = s.nextInt(), v = s.nextInt();
Q[i][0] = lca(u, v);
if (l[u] > l[v]) {
int temp = u; u = v; v = temp;
}
if (Q[i][0] == u) {
Q[i][1] = l[u];
Q[i][2] = l[v];
}
else {
Q[i][1] = r[u]; // left at col1 in query
Q[i][2] = l[v]; // right at col2
}
Q[i][3] = i;
i++;
}
Arrays.sort(Q, new Comparator<int[]>() {
#Override
public int compare(int[] x, int[] y) {
int block_x = (x[1] - 1) / (BLOCK_SIZE + 1);
int block_y = (y[1] - 1) / (BLOCK_SIZE + 1);
if(block_x != block_y)
return block_x - block_y;
return x[2] - y[2];
}
});
solveQueries(Q);
}
System.out.println(sb);
}
static long res;
private static void solveQueries(int [][] Q) {
int M = Q.length;
long results[] = new long[M];
res = 1;
int curL = Q[0][1], curR = Q[0][1] - 1;
int i = 0;
while(i < M){
while (curL < Q[i][1]) check(ID[curL++]);
while (curL > Q[i][1]) check(ID[--curL]);
while (curR < Q[i][2]) check(ID[++curR]);
while (curR > Q[i][2]) check(ID[curR--]);
int u = ID[curL], v = ID[curR];
if (Q[i][0] != u && Q[i][0] != v) check(Q[i][0]);
results[Q[i][3]] = res;
if (Q[i][0] != u && Q[i][0] != v) check(Q[i][0]);
i++;
}
i = 0;
while(i < M) sb.append(results[i++] + "\n");
}
static int visited[];
static int primeCnt[];
private static void check(int x) {
if(visited[x] == 1){
for(int i = 0; i < 7; i++) {
int c = arrPrimes[x][i][1];
int pp = arrPrimes[x][i][0];
if(pp == 0) break;
long tem = res * modI[primeCnt[pp] + 1];
res = (tem >= 1000000007) ? tem % 1000000007 : tem;
primeCnt[pp] -= c;
tem = res * (primeCnt[pp] + 1);
res = (tem >= 1000000007) ? tem % 1000000007 : tem;
}
}
else if(visited[x] == 0){
for(int i = 0; i < 7; i++) {
int c = arrPrimes[x][i][1];
int pp = arrPrimes[x][i][0];
if(pp == 0) break;
long tem = res * modI[primeCnt[pp] + 1];
res = (tem >= 1000000007) ? tem % 1000000007 : tem;
primeCnt[pp] += c;
tem = res * (primeCnt[pp] + 1);
res = (tem >= 1000000007) ? tem % 1000000007 : tem;
}
}
visited[x] ^= 1;
}
static int arrPrimes[][][];
static void computePrimePowers() {
int n = arrPrimes.length;
int i = 0;
while(i < n) {
int ele = ar[i];
int k = 0;
while(ele > 1) {
int c = 0;
int pp = hpf[ele];
while(hpf[ele] == pp) {
c++; ele /= pp;
}
arrPrimes[i][k][0] = pp;
arrPrimes[i][k][1] = c;
k++;
}
i++;
}
}
static int dfsTime;
static int l[] = new int[1000001], r[] = new int[1000001], ID[] = new int[1000001], LVL[], lcaTable[][];
static void dfs(int u, int p){
l[u] = ++dfsTime;
ID[dfsTime] = u;
int i = 1;
while(i < 19) {
lcaTable[i][u] = lcaTable[i - 1][lcaTable[i - 1][u]];
i++;
}
i = 0;
while(i < graph[u].size()){
int v = graph[u].get(i);
i++;
if (v == p) continue;
LVL[v] = LVL[u] + 1;
lcaTable[0][v] = u;
dfs(v, u);
}
r[u] = ++dfsTime;
ID[dfsTime] = u;
}
static int lca(int u, int v){
if (LVL[u] > LVL[v]) {
int temp = u;
u = v; v = temp;
}
int i = 18;
while(i >= 0) {
if (LVL[v] - (1 << i) >= LVL[u]) v = lcaTable[i][v];
i--;
}
if (u == v) return u;
i = 18;
while(i >= 0){
if (lcaTable[i][u] != lcaTable[i][v]){
u = lcaTable[i][u];
v = lcaTable[i][v];
}
i--;
}
return lcaTable[0][u];
}
}
// SIMILAR SOLUTION FOR FINDING NUMBER OF DISTINCT ELEMENTS FROM U TO V
// USING MO's ALGORITHM
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 40005;
const int MAXM = 100005;
const int LN = 19;
int N, M, K, cur, A[MAXN], LVL[MAXN], DP[LN][MAXN];
int BL[MAXN << 1], ID[MAXN << 1], VAL[MAXN], ANS[MAXM];
int d[MAXN], l[MAXN], r[MAXN];
bool VIS[MAXN];
vector < int > adjList[MAXN];
struct query{
int id, l, r, lc;
bool operator < (const query& rhs){
return (BL[l] == BL[rhs.l]) ? (r < rhs.r) : (BL[l] < BL[rhs.l]);
}
}Q[MAXM];
// Set up Stuff
void dfs(int u, int par){
l[u] = ++cur;
ID[cur] = u;
for (int i = 1; i < LN; i++) DP[i][u] = DP[i - 1][DP[i - 1][u]];
for (int i = 0; i < adjList[u].size(); i++){
int v = adjList[u][i];
if (v == par) continue;
LVL[v] = LVL[u] + 1;
DP[0][v] = u;
dfs(v, u);
}
r[u] = ++cur; ID[cur] = u;
}
// Function returns lca of (u) and (v)
inline int lca(int u, int v){
if (LVL[u] > LVL[v]) swap(u, v);
for (int i = LN - 1; i >= 0; i--)
if (LVL[v] - (1 << i) >= LVL[u]) v = DP[i][v];
if (u == v) return u;
for (int i = LN - 1; i >= 0; i--){
if (DP[i][u] != DP[i][v]){
u = DP[i][u];
v = DP[i][v];
}
}
return DP[0][u];
}
inline void check(int x, int& res){
// If (x) occurs twice, then don't consider it's value
if ( (VIS[x]) and (--VAL[A[x]] == 0) ) res--;
else if ( (!VIS[x]) and (VAL[A[x]]++ == 0) ) res++;
VIS[x] ^= 1;
}
void compute(){
// Perform standard Mo's Algorithm
int curL = Q[0].l, curR = Q[0].l - 1, res = 0;
for (int i = 0; i < M; i++){
while (curL < Q[i].l) check(ID[curL++], res);
while (curL > Q[i].l) check(ID[--curL], res);
while (curR < Q[i].r) check(ID[++curR], res);
while (curR > Q[i].r) check(ID[curR--], res);
int u = ID[curL], v = ID[curR];
// Case 2
if (Q[i].lc != u and Q[i].lc != v) check(Q[i].lc, res);
ANS[Q[i].id] = res;
if (Q[i].lc != u and Q[i].lc != v) check(Q[i].lc, res);
}
for (int i = 0; i < M; i++) printf("%d\n", ANS[i]);
}
int main(){
int u, v, x;
while (scanf("%d %d", &N, &M) != EOF){
// Cleanup
cur = 0;
memset(VIS, 0, sizeof(VIS));
memset(VAL, 0, sizeof(VAL));
for (int i = 1; i <= N; i++) adjList[i].clear();
// Inputting Values
for (int i = 1; i <= N; i++) scanf("%d", &A[i]);
memcpy(d + 1, A + 1, sizeof(int) * N);
// Compressing Coordinates
sort(d + 1, d + N + 1);
K = unique(d + 1, d + N + 1) - d - 1;
for (int i = 1; i <= N; i++) A[i] = lower_bound(d + 1, d + K + 1, A[i]) - d;
// Inputting Tree
for (int i = 1; i < N; i++){
scanf("%d %d", &u, &v);
adjList[u].push_back(v);
adjList[v].push_back(u);
}
// Preprocess
DP[0][1] = 1;
dfs(1, -1);
int size = sqrt(cur);
for (int i = 1; i <= cur; i++) BL[i] = (i - 1) / size + 1;
for (int i = 0; i < M; i++){
scanf("%d %d", &u, &v);
Q[i].lc = lca(u, v);
if (l[u] > l[v]) swap(u, v);
if (Q[i].lc == u) Q[i].l = l[u], Q[i].r = l[v];
else Q[i].l = r[u], Q[i].r = l[v];
Q[i].id = i;
}
sort(Q, Q + M);
compute();
}
}
Demo
I have this piece of code in cpp on Visual Studio
((handrule1 - maskRule1[0]) & test)
All of the variables are unsigned int.
Their values are respectively
66848250
50138096
0x80808080.
I keep getting value zero as the outcome for this line, which should not be possible.
How does this come?
I already tried working with long unsigned variables instead.
I am guessing that maybe I am doing something else wrong when choosing the data types.
Underneath you can find my full code.
Some of the variables are not defined but that's because they are already defined in another cpp-file we are not supposed to use.
void init(void) {
int aa, ab, l, x = 0;
for (int i = 4; i <= 13; i++) {
aa = 13 - i;
for (int j = (aa + 2) / 3; j <= i && j <= aa; j++) {
ab = aa - j;
for (int k = (ab + 1) / 2; k <= j && k <= ab; k++) {
adj[x] = i + j - 8;
l = ab - k; code[x++] = (((i - 4) * 7) + j) * 5 + k;
// printf("%d %d %d %d: %d\n", i, j, k, l, (((i-4)*7)+j)*5+k);
}
}
}
return;
}
char countSetBits(long long unsigned n)
{
if (n == 0)
return 0;
else
return 1 + countSetBits(n & (n - 1));
}
void init_set(void) {
long long unsigned hand = 0;
char honorPoints = 0;
char nrOfSpades = 0;
char nrOfHearts = 0;
char nrOfDiamonds = 0;
char nrOfClubs = 0;
long long unsigned maskAces = 0x8004002001;
long long unsigned maskKings = 0x10008004002;
long long unsigned maskQueens = 0x20010008004;
long long unsigned maskJacks = 0x40020010008;
long long unsigned maskSpades = 0x1FFF;
long long unsigned maskHearts = 0x3FFE000;
long long unsigned maskDiamonds = 0x7FFC000000;
long long unsigned maskClubs = 0xFFF8000000000;
char upperbound[RU][4];
char lowerbound[RU][4];
unsigned int handrule1 = 0;
unsigned int handrule2 = 0;
unsigned int handrule3 = 0;
unsigned int maskRule1[RU];
unsigned int maskRule2[RU];
unsigned int maskRule3[RU];
unsigned int maskInverse = 0x00FF00FF;
unsigned int test = 0x80808080;
unsigned int result1 = 0;
bool applicableRule = false;
unsigned int fuck = 0xFF936636;
result1 = fuck & test;
for (int r = 0; r < nrr; r++)
{
for (int i = 0; i < 4; i++)
{
upperbound[r][i] = 13;
lowerbound[r][i] = 0;
}
}
for (int r = 0; r < nrr; r++)
{
if (res[r] != 0)
{
for (int i = 0; i < res[r]; i++)
{
upperbound[r][color[r][i]] = (char) nru[r][i];
lowerbound[r][color[r][i]] = (char) nrl[r][i];
}
}
maskRule1[r] = (((char) distl[r] << 24) | ((char) distu[r] << 16) | ((char) ahpl[r] << 8) | (char) ahpu[r]) ^ maskInverse;
maskRule2[r] = ((lowerbound[r][0] << 24) | (upperbound[r][0] << 16) | (lowerbound[r][1] << 8) | upperbound[r][1]) ^ maskInverse;
maskRule3[r] = ((lowerbound[r][2] << 24) | (upperbound[r][2] << 16) | (lowerbound[r][3] << 8) | upperbound[r][3]) ^ maskInverse;
}
int x[52], y, a;
for (int i = 0; i < 52; i++) x[i] = i;
srand(1);
for (int i = 0; i < CRD; i++) {
for (int j = 52; --j > 1;) {
y = rand() % j;
a = x[y]; x[y] = x[j]; x[j] = a;
}
for (int j = 0; j < 4; j++)
{
for (int k = 13 * j; k < 13 * (j + 1); k++)
{
hand |= 1LLU << x[k];
}
//Counting honorpoints
honorPoints = (countSetBits(hand & maskAces) * 4) + (countSetBits(hand & maskKings) * 3) + (countSetBits(hand & maskQueens) * 2) + (countSetBits(hand & maskJacks) * 1);
hp[i][j] = (char) honorPoints;
honorPoints = 0;
//Counting distributions
nrOfSpades = countSetBits(hand & maskSpades);
nrOfHearts = countSetBits(hand & maskHearts);
nrOfDiamonds = countSetBits(hand & maskDiamonds);
nrOfClubs = countSetBits(hand & maskClubs);
std::array<char, 4> arrayTest = { nrOfSpades, nrOfHearts, nrOfDiamonds, nrOfClubs };
std::sort(arrayTest.begin(), arrayTest.end());
char p = arrayTest[3];
char o = arrayTest[2];
char m = arrayTest[1];
int test = (((p - 4) * 7) + o) * 5 + m;
for (int x = 0; x < 39; x++)
{
if (code[x] == test)
{
dis[i][j] = (char) x;
}
}
//Counting opening bids
ahp[i][j] = hp[i][j] + adj[dis[i][j]];
if (ahp[i][j] < 0) ahp[i][j] = 0;
handrule1 = ((dis[i][j] << 24) | (dis[i][j] << 16) | (ahp[i][j] << 8) | ahp[i][j]) ^ maskInverse;
handrule2 = ((nrOfSpades << 24) | (nrOfSpades << 16) | (nrOfHearts << 8) | nrOfHearts) ^ maskInverse;
handrule3 = ((nrOfDiamonds << 24) | (nrOfDiamonds << 16) | (nrOfClubs << 8) | nrOfClubs) ^ maskInverse;
printf("%u \n", handrule1);
printf("%u \n", maskRule1[0]);
for (int r = 0; r < nrr; r++)
{
if ((((handrule1 - maskRule1[r]) & test) == 0) && (((handrule2 - maskRule2[r]) & test) == 0) && (((handrule3 - maskRule3[r]) & test) == 0))
{
cnt[bid[r]][j]++;
applicableRule = true;
break;
}
}
if (applicableRule == false)
{
cnt[0][j]++;
}
applicableRule = false;
handrule1 = 0;
handrule2 = 0;
handrule3 = 0;
nrOfSpades = 0;
nrOfHearts = 0;
nrOfDiamonds = 0;
nrOfClubs = 0;
hand = 0;
}
}
return;
}
This script produces a fibonacci spiral which starts off in the centre and branches outward. Although the output is correct, i get an error message saying:
"Run-Time Check Failure #2 - Stack around the variable 'fibArr' was corrupted."
I've tried reducing fibCount by 1, but this caused the central number to be 0 which I dont want.
int fibFunc(int);
int main() {
//--setting variables
const int rowCount = 5, colCount = 5;
const int fibCount = rowCount * colCount - 1;
static int f;
int i, j;
//--creating grid
int grid[rowCount][colCount] = { 0 };
//Create fibArr
f = fibCount;
int fibArr[fibCount];
while (f >= 0) {
fibArr[f] = fibFunc(f);
f--;
}
//directions settings
enum direction {
DOWN, RIGHT, UP, LEFT
} d = DOWN;
//spiral loop
int R = 0, C = 0; //R for row, C for column
f = fibCount;
while (f >= 0) {
grid[R][C] = fibArr[f];
f--;
if (d == DOWN) {
if (grid[R+1][C] == 0)
R++;
else d = RIGHT;
}
if (d == RIGHT) {
if (grid[R][C+1] == 0)
C++;
else d = UP;
}
if (d == UP) {
if (grid[R-1][C] == 0)
R--;
else d = LEFT;
}
if (d == LEFT) {
if (grid[R][C-1] == 0)
C--;
else {
d = DOWN;
R++;
}
}
}
printFib(fibArr, fibCount);
for (i = 0; i < rowCount; i++) {
for (j = 0; j < colCount; j++) {
cout << setw(7) << grid[i][j];
}
cout << endl;
cout << endl;
}
system("pause>nul");
}
int fibFunc(int n) {
if (n == 0 || n == 1)
return 1;
else
return fibFunc(n - 1) + fibFunc(n - 2);
}
Output
75025 55 89 144 233
46368 34 1 2 377
28657 21 1 3 610
17711 13 8 5 987
10946 6765 4181 2584 1597
As juanchopanza pointed out, array indexing is from 0 to size - 1.
const int rowCount = 5, colCount = 5;
const int fibCount = rowCount * colCount - 1;
This would result in:
fibCount = 24 = ( 5 * 5 ) - 1;
Further down, at your while loop:
int R = 0, C = 0; //R for row, C for column
f = fibCount;
while (f >= 0) {
grid[R][C] = fibArr[f]; // f = 24; size = 24;
...
}
Here you take a value from your array fibArray with the index of 24. Last index would be 23.
Change this to:
const int fibCount = rowCount * colCount;
Then before your while loop:
f = fibCount - 1;
Besides that I would use a single dimensional array like this:
int rows = 5, cols = 5;
char* tst = new char[ rows * cols ];
int select_row = 2;
int select_col = 3;
tst[ select_row * cols + select_col ] = 65;
char c = tst[ select_row * cols + select_col ];
delete[] tst;
So I'm trying to make a Tetris game and I've come across something odd that I'm unsure about.
I have an array called bottom which stores the value of the lowest block - so, if there is no block in the first column, "bottom" will be 20.
If there's a square block occupying that first column, bottom would be 18. The weird thing is, when I set a breakpoint in my code to try to view the values for bottom, it says there is only one value in the array. In addition, my board, which is a 25 by 10 array, has the same problem, it only displays one dimension.
It seems the problem has to do with some kind of pointer issue, because it says (int (*)[10]) and (int *), where I think it should be a (int [25][10]) and (int [10]). I tried looking up array pointers and references, but the main thing I found was how to make an array of pointers and I'm not really quite sure how to word my searches.
If someone might know what's going wrong please let me know!
main.cpp
#include <chrono>
#include "makeboard.h"
int main() {
//declares and defines board
int board[24][10];
for (int y = 0; y < 24; y++) {
for (int x = 0; x < 10; x++) {
board[y][x] = 0;
}
}
makeboard(board);
}
tiles.h
#ifndef tiles_h
#define tiles_h
class O {
int board[24][10];
int x, y;
public:
void set_O (int[24][10], int, int);
};
void O::set_O (int board[24][10], int y, int x) {
board[y][x] = 1;
board[y][x+1] = 1;
board[y-1][x] = 1;
board[y-1][x+1] = 1;
}
class I {
int board[24][10];
int x, y, d;
public:
void set_I (int[24][10], int, int, int);
};
void I::set_I (int board[24][10], int d, int y, int x) {
if (d == 1 || d == 3) {
board[y-3][x] = 1;
board[y-2][x] = 1;
board[y-1][x] = 1;
board[y][x] = 1;
}
if (d == 2 || d == 4) {
board[y][x-1] = 1;
board[y][x] = 1;
board[y][x+1] = 1;
board[y][x+2] = 1;
}
}
class S {
int board[24][10];
int x, y, d;
public:
void set_S (int[24][10], int, int, int);
};
void S::set_S (int board[24][10], int d, int y, int x) {
if (d == 1 || d == 3) {
board[y-1][x] = 1;
board[y-1][x+1] = 1;
board[y][x] = 1;
board[y][x-1] = 1;
}
if (d == 2 || d == 4) {
board[y-2][x] = 1;
board[y-1][x] = 1;
board[y-1][x+1] = 1;
board[y][x+1] = 1;
}
}
class Z {
int board[24][10];
int x, y, d;
public:
void set_Z (int[24][10], int, int, int);
};
void Z::set_Z (int board[24][10], int d, int y, int x) {
if (d == 1 || d == 3) {
board[y][x] = 1;
board[y][x-1] = 1;
board[y+1][x] = 1;
board[y+1][x+1] = 1;
}
if (d == 2 || d == 4) {
board[y-1][x+1] = 1;
board[y][x+1] = 1;
board[y][x] = 1;
board[y+1][x] = 1;
}
}
class T {
int board[24][10];
int d, x, y;
public:
void set_T (int[24][10], int, int, int);
};
void T::set_T (int board[24][10], int d, int y, int x) {
if (d == 1 && (board[y+1][x-1] != 1 || board[y+1][x] != 1 || board[y+1][x+1] != 1)) {
board[y-1][x] = 1;
board[y][x-1] = 1;
board[y][x] = 1;
board[y][x+1] = 1;
}
if (d == 2 && (board[y+2][x] != 1 || board[y+1][x+1] != 1)) {
board[y-1][x] = 1;
board[y][x] = 1;
board[y][x+1] = 1;
board[y+1][x] = 1;
}
if (d == 3 && (board[y+1][x-1] != 1 || board[y+2][x] != 1 || board[y+1][x+1] != 1)) {
board[y][x-1] = 1;
board[y][x] = 1;
board[y][x+1] = 1;
board[y+1][x] = 1;
}
if (d == 4 && (board[y+1][x-1] != 1 || board[y+2][x] != 1)) {
board[y-1][x] = 1;
board[y][x-1] = 1;
board[y][x] = 1;
board[y+1][x] = 1;
}
}
class J {
int board[24][10];
int d, x, y;
public:
void set_J (int[24][10], int, int, int);
};
void J::set_J (int board[24][10], int d, int y, int x) {
if (d == 1) {
board[y-1][x-1] = 1;
board[y-1][x] = 1;
board[y-1][x+1] = 1;
board[y][x+1] = 1;
}
if (d == 2) {
board[y-2][x] = 1;
board[y-1][x] = 1;
board[y][x] = 1;
board[y][x-1] = 1;
}
if (d == 3) {
board[y][x-1] = 1;
board[y][x] = 1;
board[y][x+1] = 1;
board[y-1][x-1] = 1;
}
if (d == 4) {
board[y-2][x] = 1;
board[y-2][x+1] = 1;
board[y-1][x] = 1;
board[y][x] = 1;
}
}
class L {
int board[24][10];
int d, x, y;
public:
void set_L (int[24][10], int, int, int);
};
void L::set_L (int board[24][10], int d, int y, int x) {
if (d == 1) {
board[y-1][x-1] = 1;
board[y-1][x] = 1;
board[y-1][x+1] = 1;
board[y][x-1] = 1;
}
if (d == 2) {
board[y-2][x] = 1;
board[y-1][x] = 1;
board[y][x] = 1;
board[y][x-1] = 1;
}
if (d == 3) {
board[y-1][x-1] = 1;
board[y-1][x] = 1;
board[y-1][x+1] = 1;
board[y][x+1] = 1;
}
if (d == 4) {
board[y-2][x] = 1;
board[y-1][x] = 1;
board[y][x] = 1;
board[y][x+1] = 1;
}
}
#endif
makeboard.cpp
#include <iostream>
#include <limits>
#include <thread>
#include "makeboard.h"
#include "clearscreen.h"
#include "isBottom.h"
#include "isPressed.h"
#include "tiles.h"
using namespace std;
string icon[3] = { " ", " o ", " o " };
void makeboard(int board[24][10]) {
time_t srand( time(NULL) );
int block = srand % 7 ;
block = 3;
//declares pieces
O o;
I i;
S s;
Z z;
T t;
J j;
L l;
//declares and defines initial bottom
int bottom[10];
for (int i = 0; i < 10; i++) bottom[i] = 23;
//declares and defines initial block position
int y = 3;
int x = 4;
int d = 1;
while (!isBottom(board, block, y, x, d, bottom)) {
if (isPressed(0) && x > 0) {
x--;
}
if (isPressed(2) && x < 10) {
x++;
}
if (isPressed(1)) {
d += 1;
if (d == 4) {
d = 1;
}
}
//moves tile down
y++;
//clears screen
clearscreen();
//clears non set pieces
for (int i = 0; i < 24; i++) {
for (int j = 0; j < 10; j++) {
if (board[i][j] == 1) {
board[i][j] = 0;
}
}
}
//adds blocks to board
switch (block) {
case 1:
o.set_O(board, y, x);
break;
case 2:
i.set_I(board, d, y, x);
break;
case 3:
s.set_S(board, d, y, x);
break;
case 4:
z.set_Z(board, d, y, x);
break;
case 5:
t.set_T(board, d, y, x);
break;
case 6:
j.set_J(board, d, y, x);
break;
case 7:
l.set_L(board, d, y, x);
break;
}
//builds board
cout << "╔══════════════════════════════╗" << endl;
for (int i = 4; i < 24; i++) {
cout << "║";
for (int j = 0; j < 10; j++) {
cout << icon[board[i][j]] ;
}
cout << "║" << endl;
}
cout << "╚══════════════════════════════╝" << endl;
cout << " 0 1 2 3 4 5 6 7 8 9 " << endl;
//resets initial tile position
if (isBottom(board, block, y, x, d, bottom)) {
y = 2;
//block = srand % 7;
}
//ends game
if (isBottom(board, block, 3, x, d, bottom)) {
cout << "You lose!";
return;
}
//delay
this_thread::sleep_for (chrono::milliseconds(100));
}
return;
}
clearscreen.cpp
#include <unistd.h>
#include <term.h>
#include <stdlib.h>
#include "clearscreen.h"
void clearscreen()
{
if (!cur_term)
{
void *a;
int result;
setupterm( NULL, STDOUT_FILENO, &result );
a = malloc(sizeof(int) *result);
free (a);
if (result <= 0) free (a); return;
}
putp( tigetstr( "clear" ) );
}
isBottom.cpp
#include "isBottom.h"
bool isBottom(int board[24][10], int block, int y, int x, int d, int bottom[10]) {
switch (block) {
case 1:
if (y == bottom[x] || y == bottom[x+1]) {
board[y][x] = 2;
board[y][x+1] = 2;
board[y-1][x] = 2;
board[y-1][x+1] = 2;
bottom[x] -= 2;
bottom[x+1] -= 2;
return true;
}
return false;
break;
case 2:
if (d == 1 || d == 3) {
if (y == bottom[x]) {
board[y-3][x] = 2;
board[y-2][x] = 2;
board[y-1][x] = 2;
board[y][x] = 2;
bottom[x] -= 4;
return true;
}
return false;
break;
}
if (d == 2 || d == 4) {
if (y == bottom[x-1] || y == bottom[x] || y == bottom[x+1] || y == bottom[x+2]) {
board[y][x-1] = 2;
board[y][x] = 2;
board[y][x+1] = 2;
board[y][x+2] = 2;
bottom[x-1]--;
bottom[x]--;
bottom[x+1]--;
bottom[x+2]--;
return true;
}
return false;
break;
}
case 3:
if (d == 1 || d == 3) {
if (y == bottom[x-1] || y == bottom[x] || y == bottom[x+1]) {
board[y-1][x] = 2;
board[y-1][x+1] = 2;
board[y][x] = 2;
board[y][x-1] = 2;
bottom[x-1] = 23 - y;
bottom[x] -= 2;
bottom[x+1] -= 2;
return true;
break;
}
return false;
break;
}
if (d == 2 || d == 4) {
if (y == bottom[x-1] || y == bottom[x]) {
board[y-2][x] = 2;
board[y-1][x] = 2;
board[y-1][x+1] = 2;
board[y][x+1] = 2;
bottom[x-1]--;
bottom[x] -= 1;
return true;
break;
}
return false;
break;
}
/*
case 3:
s.set_S(board, d, y, x);
break;
case 4:
z.set_Z(board, d, y, x);
break;
case 5:
t.set_T(board, d, y, x);
break;
case 6:
j.set_J(board, d, y, x);
break;
case 7:
l.set_L(board, d, y, x);
break;
*/
}
return true;
}
isPressed.cpp
#include <Carbon/Carbon.h>
#include "isPressed.h"
bool isPressed( unsigned short inKeyCode )
{
unsigned char keyMap[16];
GetKeys((BigEndianUInt32*) &keyMap);
return (0 != ((keyMap[ inKeyCode >> 3] >> (inKeyCode & 7)) & 1));
}
It depends on the scope of your array. For example:
int GetBottom(int* bottom);
int GetBottom2(const int (&bottom)[20]);
int main()
{
int localArray1d[20] = {};
int localArray2d[10][25] = {};
// putting a breakpoint here will allow you to see the full dimensions of the array because this function KNOWS what the object is (e.g. a 1d and 2d array respectively)
int lastBrick = GetBottom(localArray1d);
// When the array is passed to GetBottom, it's passed just as a pointer. Although it IS an array, the function GetBottom doesn't know that. We could just as simply pass it a single int*
int n = 0;
GetBottom(&n); // here we are only passing a single int pointer. GetBottom has no idea that your object is an array, it only knows it has an int*
lastBrick = GetBottom2(localArray1d);
// GetBottom2 only takes an array of 20 elements, so inspecting the object in that function allows you to see all the elements.
return 0;
}
int GetBottom(int* bottom)
{
// Having a breakpoint here will not allow you to see all the elements in an array since this function doesn't even know bottom IS an array.
}
int GetBottom2(const int (&bottom)[20])
{
// A breakpoint here will allow you to fully inspect bottom.
}
It's a little tricky when you refer to arrays the way you do, but an array like int array[5] degrades to int* array when you branch outside the scope in which it is defined. It's because arrays are r-values and need to degrade into a reference or pointer l-value (which lacks that info about how many elements there are) to pass them around. The gotcha part here is that you can still write a function which accepts int parameter[5] and the compiler will accept it, but will silently treat it like int* parameter. The same goes for the debugger.
So depending on your debugger, there's different ways to look at all the elements through a pointer anyway. For example, with this code:
int* ptr = some_array;
... in MSVC, I can only see the first element pointed to by ptr in the watch window. However, if I know that some_array has 10 elements, I can type ptr,10 in the watch window and it'll show me all 10 elements.
Also, again this is debugger-specific, but some debuggers are conveniently programmed to show the contents of standard containers no matter what in a beautifully-readable format. So if you can use contaners like std::vector, it'll make your debugging life easier if you're using such a debugger.
So, I did some searching for why my compiler gives an error saying:
49 ~\C++\SHA-1\main.cpp invalid conversion from `unsigned char*' to `char*'
And I found out that you cannot convert between unsigned char to char because they are completely different types. So this lead me to the problem of needing a getline function for and unsigned char string in my code.
#include <iostream>
#include <stdint.h>
using namespace std;
uint32_t rotl( uint32_t value, int shift)
{
if ((shift &= sizeof(value)*8 - 1) == 0) return value;
return (value << shift) | (value >> (sizeof(value)*8 - shift));
}
uint32_t rotr( uint32_t value, int shift)
{
if ((shift &= sizeof(value)*8 - 1) == 0) return value;
return (value >> shift) | (value << (sizeof(value)*8 - shift));
}
int textInput();
int hexInput();
int binInput();
unsigned char message[64];
int SHA_1();
int main()
{
int selection;
cout<<"Select Input type:\n\n\t1. Text String\n\t2. Hex String\n\t3. Binary String\n";
cin>>selection;
cin.ignore();
switch(selection)
{
case 1: textInput(); break;
case 2: hexInput(); break;
case 3: binInput(); break;
}
SHA_1();
cout<<"\ndone";
cin.get();
return 0;
}
int textInput()
{
unsigned char input[63] = {0};
cout<<"Enter a text string to be hashed\n\n";
cin.getline(input, 62, '\n');
cin.ignore();
for(int x = 0; x <= 63; x++)
{
//cout<<x<<"\n";
if (input[x] == 0x00)
{
message[x] = 0x00000080;
message[63] = x; //This might be wrong.
//cout<<std::hex<<message;
break;
}
else message[x] = input[x];
}
return 0;
}
int hexInput()
{
return 0;
}
int binInput()
{
return 0;
}
int SHA_1()
{
uint32_t h0 = 0x67452301;
uint32_t h1 = 0xEFCDAB89;
uint32_t h2 = 0x98BADCFE;
uint32_t h3 = 0x10325476;
uint32_t h4 = 0xC3D2E1F0;
uint32_t a;
uint32_t b;
uint32_t c;
uint32_t d;
uint32_t e;
uint32_t f;
uint32_t k;
uint32_t temp;
uint32_t w[80];
/*for( int m = 0; m <= 63; m++)
{
cout<<"message["<<m<<"]="<<std::hex<<int(message[m])<<std::dec<<"\n";
}*/
for( int i = 0; i <= 15; i++)
{
w[i] = ((message[(i*4)] << 24) | (message[(i*4) + 1] << 16) | (message[(i*4) + 2] << 8) | (message[(i*4) + 3]));
//cout<<"W["<<i<<"]="<<std::hex<<w[i]<<std::dec<<"\n";
}
for( int i = 16; i <= 79; i++)
{
w[i] = rotl((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1);
}
a = h0;
b = h1;
c = h2;
d = h3;
e = h4;
for(int iteration = 0; iteration <= 79; iteration++)
{
if((0 <= iteration) && (iteration <= 19))
{
f = ((b & c) | ((~b) & d));
k = 0x5A827999;
}
else if((20 <= iteration) && (iteration <= 39))
{
f = (b ^ c ^ d);
k = 0x6ED9EBA1;
}
else if((40 <= iteration) && (iteration <= 59))
{
f = ((b & c) | (b & d) | (c & d));
k = 0x8F1BBCDC;
}
else if((60 <= iteration) && (iteration <= 79))
{
f = (b ^ c ^ d);
k = 0xCA62C1D6;
}
temp = (rotl( a, 5) + f + e + k + w[iteration]);
e = d;
d = c;
c = rotl( b, 30);
b = a;
a = temp;
}
h0 = h0 + a;
h1 = h1 + b;
h2 = h2 + c;
h3 = h3 + d;
h4 = h4 + e;
cout<<hex<<h0<<" "<<h1<<" "<<h2<<" "<<h3<<" "<<h4;
return 0;
}
If anyone could give me some suggestions that would be helpful.
Thanks
This is related to strict-aliasing constraints: you're not permitted to reference an unsigned char array via a char pointer.
#include <iostream>
using namespace std;
void aliasing_fun(char* arr) {
arr[0] = 42;
}
int main() {
unsigned char arr[10] = {0};
aliasing_fun(arr); // Not allowed
return 0;
}
http://ideone.com/r4OVZi
You might cast your array to char* in order to do that.
Cast your array to (char *) when calling getline:
getline((char *)input, ...);