sorry for bothering but I'm stuck in this, the idea is:
Insert in console numbers from 1 to 9 (it doesn't matter the order or if it repeat), and create a 2 dimensional array BUT it has to be order in SPIRAL INVERSE (starting from the center)
EXAMPLE 1:
INPUT (enter numbers without spaces):
123456789
OUTPUT:
789
612
543
EXAMPLE 2:
INPUT (enter numbers without spaces):
12345678976
OUTPUT:
7897
6126
543
I MADE THIS:
for getting the numbers and trying to put in vector of 2 dimensions but after that point I don't know how I should make the spiral...
attached my code:
#include <iostream>
using namespace std;
int main()
{
int a[] = { 1,2,3,4,5,6,7,8,9 };
int b[3][3];
int k = 0;
int i, j;
int arrSize = sizeof(a) / sizeof(a[0]);
cout << arrSize;
cout << endl;
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
b[i][j] = a[k++];
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
cout << b[i][j];
cout << endl;
}
}
With this code I be able to put into a 2D array.
Thank you in advance, for your time and patience with me!
The following program lists the (x, y) sequence for the spiral. The first list using the starting points located at (0, 0). The second moves the starting of spiral to the position of (minimum.x, minimum.y). The minimum keeps the coordinate of the left-bottom element.
You may observe the rule of spiral in the program. A position (x,y) first starts at (n, n-1) where n is the nth loop of the spiral. First, move the position downward, --y, untile y reach -n; then move x left until x = -n; then move y upward until y=n; finally, move x right until x = n. In the following program max(n) set = 4, there are 4 spiral loops. You may adjust this parameter n to fit you purpose.
The total number of each spiral loop = 8*n, except the inner most loop (0,0), the number = 1. Therefore, the number of element of spiral = 1 + 8*1 + 8*2 + 8*3 +.... You have first to determine the loops of spiral by the length of input string L, The loops number is eqaul to `n = ( (L-1) / 8 + 1 );` or `n = ( (L-1) / 8 );` if no remaider left.
#include <iostream>
#include <vector>
struct int2 {
int x, y;
int2():x(0), y(0) {}
int2(const int a, const int b):x(a), y(b) {}
int2& operator=(const int2&) = default;
void print() const {std::cout << "( " << x <<", " << y << ") "; }
int2& operator+=(const int2&a) { this->x += a.x ; this->y += a.y; return *this;}
int2& operator-() {x = -x; y = -y; return *this;}
};
int main()
{
std::vector<int2> spiral;
int2 pos, minimum;
int n;
pos = int2(0,0);
minimum = pos;
spiral.push_back(pos);
for (n=1; n<5; n++)
{
pos = int2( n, n-1); // starting point for ith loop
spiral.push_back(pos);
while (pos.y > -n) {--pos.y; spiral.push_back(pos); if (pos.y < minimum.y) minimum.y = pos.y;}
while (pos.x > -n) {--pos.x; spiral.push_back(pos); if (pos.x < minimum.x) minimum.x = pos.x; }
while (pos.y < n) {++pos.y; spiral.push_back(pos); }
while (pos.x < n) {++pos.x; spiral.push_back(pos); }
}
-minimum;
std::cout << "center at (0, 0)\n";
for (int i=0; i<spiral.size(); i++) spiral[i].print();
std::cout<<std::endl;
for (int i=0; i<spiral.size(); i++) spiral[i] += minimum;
std::cout << "center at "; minimum.print(); std::cout<<std::endl;
for (int i=0; i<spiral.size(); i++) spiral[i].print();
std::cout<<std::endl;
return 0;
}
This above (x, y) positions provide you the 2-d sequence array[x][y] to write you char forming a spiral structure.
center at (0, 0)
( 0, 0) ( 1, 0) ( 1, -1) ( 0, -1) ( -1, -1) ( -1, 0) ( -1, 1) ( 0, 1) ( 1, 1) ( 2, 1) ( 2, 0) ( 2, -1) ( 2, -2) ( 1, -2) ( 0, -2) ( -1, -2) ( -2, -2) ( -2, -1) ( -2, 0) ( -2, 1) ( -2, 2) ( -1, 2) ( 0, 2) ( 1, 2) ( 2, 2) ( 3, 2) ( 3, 1) ( 3, 0) ( 3, -1) ( 3, -2) ( 3, -3) ( 2, -3) ( 1, -3) ( 0, -3) ( -1, -3) ( -2, -3) ( -3, -3) ( -3, -2) ( -3, -1) ( -3, 0) ( -3, 1) ( -3, 2) ( -3, 3) ( -2, 3) ( -1, 3) ( 0, 3) ( 1, 3) ( 2, 3) ( 3, 3) ( 4, 3) ( 4, 2) ( 4, 1) ( 4, 0) ( 4, -1) ( 4, -2) ( 4, -3) ( 4, -4) ( 3, -4) ( 2, -4) ( 1, -4) ( 0, -4) ( -1, -4) ( -2, -4) ( -3, -4) ( -4, -4) ( -4, -3) ( -4, -2) ( -4, -1) ( -4, 0) ( -4, 1) ( -4, 2) ( -4, 3) ( -4, 4) ( -3, 4) ( -2, 4) ( -1, 4) ( 0, 4) ( 1, 4) ( 2, 4) ( 3, 4) ( 4, 4)
center at ( 4, 4)
( 4, 4) ( 5, 4) ( 5, 3) ( 4, 3) ( 3, 3) ( 3, 4) ( 3, 5) ( 4, 5) ( 5, 5) ( 6, 5) ( 6, 4) ( 6, 3) ( 6, 2) ( 5, 2) ( 4, 2) ( 3, 2) ( 2, 2) ( 2, 3) ( 2, 4) ( 2, 5) ( 2, 6) ( 3, 6) ( 4, 6) ( 5, 6) ( 6, 6) ( 7, 6) ( 7, 5) ( 7, 4) ( 7, 3) ( 7, 2) ( 7, 1) ( 6, 1) ( 5, 1) ( 4, 1) ( 3, 1) ( 2, 1) ( 1, 1) ( 1, 2) ( 1, 3) ( 1, 4) ( 1, 5) ( 1, 6) ( 1, 7) ( 2, 7) ( 3, 7) ( 4, 7) ( 5, 7) ( 6, 7) ( 7, 7) ( 8, 7) ( 8, 6) ( 8, 5) ( 8, 4) ( 8, 3) ( 8, 2) ( 8, 1) ( 8, 0) ( 7, 0) ( 6, 0) ( 5, 0) ( 4, 0) ( 3, 0) ( 2, 0) ( 1, 0) ( 0, 0) ( 0, 1) ( 0, 2) ( 0, 3) ( 0, 4) ( 0, 5) ( 0, 6) ( 0, 7) ( 0, 8) ( 1, 8) ( 2, 8) ( 3, 8) ( 4, 8) ( 5, 8) ( 6, 8) ( 7, 8) ( 8, 8)
Related
I made this segmented sieve that uses wheel factorization.
Here you find the explanation.
By setting the wheel size to 210 and using a segment vector uint8_t of size 277140 = 6 * (11 * 13 * 17 * 19 + 1) = nB*(segment_size+1) the sieve is fast enough for n=10^9.
If you want to decrease the segment memory, for example setting segment_size_min=2048 and int64_t segment_size = 4; a vector uint8_t of size 58350 = 6 * (4 * 11 * 13 * 17 + 1) is used but the execution time is longer, about double.
/// This is a implementation of the bit wheel segmented sieve
/// with max base wheel size choice 30 , 210 , 2310
#include <iostream>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <stdint.h>
const int64_t n_PB_max = 5;
const int64_t PrimesBase[n_PB_max] = {2,3,5,7,11};
const int64_t del_bit[8] =
{
~(1 << 0),~(1 << 1),~(1 << 2),~(1 << 3),
~(1 << 4),~(1 << 5),~(1 << 6),~(1 << 7)
};
const int64_t bit_count[256] =
{
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
};
int64_t Euclidean_Diophantine( int64_t coeff_a, int64_t coeff_b)
{
// return y in Diophantine equation coeff_a x + coeff_b y = 1
int64_t k=1;
std::vector<int64_t> div_t;
std::vector<int64_t> rem_t;
std::vector<int64_t> coeff_t;
div_t.push_back(coeff_a);
rem_t.push_back(coeff_b);
coeff_t.push_back((int64_t) 0);
div_t.push_back((int64_t) div_t[0] / rem_t[0]);
rem_t.push_back((int64_t) div_t[0] % rem_t[0]);
coeff_t.push_back((int64_t) 0);
while (rem_t[k] > 1)
{
k++;
div_t.push_back((int64_t) rem_t[k - 2] / rem_t[k - 1]);
rem_t.push_back((int64_t) rem_t[k - 2] % rem_t[k - 1]);
coeff_t.push_back((int64_t) 0);
}
k--;
coeff_t[k] = -div_t[k + 1];
if (k > 0)
coeff_t[k - 1] = (int64_t) 1;
while (k > 1)
{
k--;
coeff_t[k - 1] = coeff_t[k + 1];
coeff_t[k] += (int64_t) (coeff_t[k + 1] * (-div_t[k + 1]));
}
if (k == 1)
return (int64_t) (coeff_t[k - 1] + coeff_t[k] * ( -div_t[k]));
else
return (int64_t) (coeff_t[0]);
}
int64_t segmented_bit_sieve_wheel(uint64_t n,int64_t max_bW)
{
int64_t segment_size_min = 4096; //can be scaled down to have smaller segments
int64_t sqrt_n = (int64_t) std::sqrt(n);
int64_t count_p = (int64_t)0;
int64_t n_PB = (int64_t) 3;
int64_t bW = (int64_t) 30;
//get bW base wheel equal to p1*p2*...*pn <=min(max_bW,sqrt_n) with n=n_PB
while(n_PB < n_PB_max && (bW * PrimesBase[n_PB] <= std::min(max_bW , sqrt_n)))
{
bW *= PrimesBase[n_PB];
n_PB++;
}
for (int64_t i = 0; i < n_PB; i++)
if (n > (uint64_t) PrimesBase[i])
count_p++;
if (n > (uint64_t) (1 + PrimesBase[n_PB - 1])){
int64_t k_end = (n < (uint64_t)bW) ? (int64_t) 2 :(int64_t) (n / (uint64_t) bW + 1);
int64_t n_mod_bW = (int64_t) (n % (uint64_t) bW);
int64_t k_sqrt = (int64_t) std::sqrt(k_end / bW) + 1;
//find reduct residue set modulo bW
std::vector<char> Remainder_i_t(bW + 1,true);
for (int64_t i = 0; i < n_PB; i++)
for (int64_t j = PrimesBase[i]; j < bW + 1; j += PrimesBase[i])
Remainder_i_t[j] = false;
std::vector<int64_t> RW;
for (int64_t j = 2; j < bW + 1; j++)
if (Remainder_i_t[j] == true)
RW.push_back(-bW + j);
RW.push_back(1);
int64_t nR = RW.size(); //nR=phi(bW)
std::vector<int64_t> C1(nR * nR);
std::vector<int64_t> C2(nR * nR);
for (int64_t j = 0; j < nR - 2; j++)
{
int64_t rW_t , rW_t1;
rW_t1 = Euclidean_Diophantine(bW , -RW[j]);
for (int64_t i = 0; i < nR; i++)
{
if (i == j)
{
C2[nR * i + j] = 0;
C1[nR * i + j] = RW[j] + 1;
}
else if(i == nR - 3 - j)
{
C2[nR * i + j] = 1;
C1[nR * i + j] = RW[j] - 1;
}
else
{
rW_t = (int64_t) (rW_t1 * (-RW[i])) % bW;
if (rW_t > 1)
rW_t -= bW;
C1[nR * i + j] = rW_t + RW[j];
C2[nR * i + j] = (int64_t) (rW_t * RW[j]) / bW + 1;
if (i == nR - 1)
C2[nR * i + j] -= 1;
}
}
C2[nR * j + nR - 2] = (int64_t) 1;
C1[nR * j + nR - 2] = -(bW + RW[j]) - 1;
C1[nR * j + nR - 1] = RW[j] + 1;
C2[nR * j + nR - 1] = (int64_t )0;
}
for (int64_t i = nR - 2; i < nR; i++)
{
C2[nR * i + nR - 2] = (int64_t) 0;
C1[nR * i + nR - 2] = -RW[i] - 1;
C1[nR * i + nR - 1] = RW[i] + 1;
C2[nR * i + nR - 1] = (int64_t) 0;
}
int64_t segment_size = 1; //can be scaled up to have larger segments
int64_t p_mask_i = 3; //number primes for pre-sieve vector mask
for (int64_t i = 0; i < p_mask_i; i++)
segment_size *= (bW + RW[i]);
while (segment_size < std::max(k_sqrt , segment_size_min) && p_mask_i < 7 )
{
segment_size *= (bW + RW[p_mask_i]);
p_mask_i++;
}
int64_t nB = nR / 8; //nB number of byte for residue of congruence class equal to nR=8*nB
int64_t segment_size_b = nB * segment_size;
//vector used for the first segment containing prime numbers less than sqrt(n)
std::vector<uint8_t> Primes(nB + segment_size_b, 0xff);
int64_t p , pb , mb , mb_i , ib , i , jb , j , jp , k , kb;
int64_t kmax = (int64_t) std::sqrt(segment_size / bW) + 1;
//sieve for the first segment
for (k = (int64_t)1; k <= kmax; k++)
{
kb = nB * k;
mb_i = kb * k * bW; //nB * k * k * bW
for (jb = 0; jb < nB; jb++)
{
for (j = 0; j < 8; j++)
{
if(Primes[kb + jb] & (1 << j))
{
jp = j + jb * 8;
pb = nB * (bW * k + RW[jp]);
for (ib = 0; ib < nB; ib++)
{
for (i = 0; i < 8; i++)
{
mb = mb_i + nB * k * C1[(i + ib * 8) * nR + jp] + nB * C2[(i + ib * 8) * nR + jp];
for (; mb <= segment_size_b; mb += pb)
Primes[mb + ib] &= del_bit[i];
}
}
}
}
}
}
//count the prime numbers in the first segment
for (kb = nB; kb < std::min (nB + segment_size_b , nB * k_end); kb++)
count_p += bit_count[Primes[kb]];
if (kb == nB * k_end && kb <= segment_size_b && kb > 0)
for (ib = 0; ib < nB; ib++)
for (i = 0; i < 8; i++)
if(Primes[kb + ib]& (1 << i) && RW[i + ib * 8] < (n_mod_bW - bW))
count_p++;
if (k_end > segment_size)
{
// vector mask pre-sieve multiples of primes bW+RW[j] with 0<j<p_mask_i
std::vector<uint8_t> Segment_i(nB+segment_size_b , 0xff);
for (j = 0; j < p_mask_i; j++)
{
p = bW+RW[j];
pb = p * nB;
for (ib = 0; ib < nB; ib++)
{
for (i = 0; i < 8; i++)
{
mb = -segment_size + bW + C1[(i + ib * 8) * nR + j] + C2[(i + ib * 8) * nR + j];
if (mb < 0)
mb=(mb % p + p) % p;
mb *= nB;
for (; mb <= segment_size_b; mb += pb)
Segment_i[mb + ib] &= del_bit[i];
}
}
}
//vector used for subsequent segments of size (nB+segment_size_b)=nB*(1+segment_size)
std::vector<uint8_t> Segment_t(nB + segment_size_b);
int64_t k_low , kb_low;
for (k_low = segment_size; k_low < k_end; k_low += segment_size)
{
kb_low = k_low * nB;
for (kb = (int64_t)0; kb < (nB + segment_size_b); kb++)
Segment_t[kb] = Segment_i[kb];
kmax = (std::min(segment_size , (int64_t) std::sqrt((k_low + segment_size) / bW) + 2));
j = p_mask_i;
for(k = (int64_t) 1; k <= kmax; k++)
{
kb = k * nB;
mb_i = -k_low + bW * k * k;
for (jb = 0; jb < nB; jb++)
{
for (; j < 8; j++)
{
if (Primes[kb + jb] & (1 << j))
{
jp = j + jb * 8;
p = bW * k + RW[jp];
pb = p * nB;
for (ib = 0; ib < nB; ib++)
{
for (i = 0; i < 8; i++)
{
mb = mb_i + k * C1[(i + ib * 8) * nR+jp] + C2[(i + ib * 8) * nR+jp];
if (mb < 0)
mb = (mb % p + p) % p;
mb *= nB;
for (; mb <= segment_size_b; mb += pb)
Segment_t[mb + ib] &= del_bit[i];
}
}
}
}
j = (int64_t) 0;
}
}
for ( kb = nB + kb_low; kb < std::min (kb_low + segment_size_b + nB , nB * k_end); kb++)
count_p += bit_count[Segment_t[kb - kb_low]];
}
if (kb == nB * k_end && kb - kb_low <= segment_size_b && kb - kb_low > (int64_t) 0)
for (ib = 0; ib < nB; ib++)
for (i = 0; i < 8; i++)
if(Segment_t[kb - kb_low + ib]& (1 << i) && RW[i + ib * 8] < (n_mod_bW - bW))
count_p++;
}
}
return count_p;
}
int main()
{
int64_t n=1000000000;
//segmented_bit_sieve_wheel(n,max_bW) with max base wheel size choice max_bW= 30 , 210 , 2310
std::cout << " primes < " << n << ": "<< segmented_bit_sieve_wheel(n , 210) << std::endl;
return 0;
}
I was expecting the opposite behavior can someone help me understand what the size of the segment should be to optimize in terms of speed?
EDIT:
I want to clarify that the Euclidean_Diophantine function is used only in the initial phase to find the arrays C1 and C2 and can be eliminated by replacing
rW_t1 = Euclidean_Diophantine(bW , -RW[j]);
with
int64_t j1=0;
while((RW[j] * RW[j1]) % bW != bW - 1 && j1 < nR - 1)
j1++;
rW_t1 = RW[j1];
Also to get an idea about timing by compiling using rextester.com g++ with the -O3 option
you get absolute running time: 0.51s
so i tested the time spent on switching blocks by deleting in the second part
for(k = (int64_t) 1; k <= kmax; k++)
{
...
}
we therefore obtain absolute running time equal to 0.18s which does not vary much in the two configurations.
The rule is benchmark, benchmark, benchmark.
But not just overall timing. Where does time go inside of your graph? If you were using more functions, a flame graph would help. But you aren't.
So I'm going to instead recommend that you add a little instrumentation, possibly hidden behind a #ifdef. What you want to do is divide your code into sections based on different kinds of activities. Like setting up a new block to sieve versus sieving the block. Have a timer going. Every time you switch, record a new timestamp, add the elapsed for the previous activity, and save the new timestamp to time the current activity.
As for why smaller blocks would be slower, that's because you spend time sieving, and also spend time every time you switch blocks calculating where thing are. Going from blocks of size 277140 to 58350 you wind up switching blocks about 4.75 times as often. If you were spending 1/3.75 of the time on switching before (36.36%) you'll now be spending the same 2.75/3.75 on sieving plus 4.75/3.75 on switching blocks, resulting in taking 2x as long.
One idea to speed it up is that you are calling Euclidean_Diophantine with the same first parameter a lot. (I think the parameter works out to be 210.) It might be faster if you first a lookup table solving the problem mod 210, and then use that to skip most of the calculation.
I have designed a simple dual channel filter to remove some noise at a given frequency.
#include "../include/Filter.h"
void Filter(int DataIn, int* DataOut, bool Enable)
{
static coef_t Coefficients[] = {
0.0076925293, -0.039817952, 0.018740745, 0.013075141, -0.052312399,
0.052374545, 0.017044802, -0.14227364, 0.26541378, 0.68194015, 0.26541378,
-0.14227364, 0.017044802, 0.052374545, -0.052312399, 0.013075141, 0.018740745,
-0.039817952, 0.0076925293
};
static data_t ShiftRegRight[LENGTH];
static data_t ShiftRegLeft[LENGTH];
acc_t AccRight = 0x00;
acc_t AccLeft = 0x00;
if(Enable == true)
{
Shift_Accum_Loop: for(int i = (LENGTH - 1); i >= 0; i--)
{
if(i == 0)
{
ShiftRegRight[0] = DataIn & 0x0000FFFF;
ShiftRegLeft[0] = (DataIn & 0xFFFF0000) >> 0x10;
}
else
{
ShiftRegRight[i] = ShiftRegRight[i - 1];
ShiftRegLeft[i] = ShiftRegLeft[i - 1];
}
AccRight += ShiftRegRight[i] * Coefficients[i];
AccLeft += ShiftRegLeft[i] * Coefficients[i];
}
*DataOut = ((AccLeft.range() >> 0x20) << 0x10) | (AccRight.range() >> 0x20);
}
else
{
*DataOut = DataIn;
}
}
This filter produce the following output on a given test signal:
0, 0, 0
1, 28377, 218
2, 0, 64405
3, 0, 531
4, 0, 370
5, 37159, 63833
6, 0, 2616
7, 37159, 65269
8, 0, 62257
9, 0, 8484
10, 0, 17494
11, 28377, 8750
12, 0, 62919
13, 28377, 58754
14, 0, 50948
15, 0, 48035
16, 0, 52449
17, 37159, 56833
18, 0, 0
19, 37159, 8484
20, 0, 14216
21, 0, 16968
22, 0, 14216
...
The test signal is generated with a testbench:
#include <math.h>
#include <stdio.h>
#include "../include/Filter.h"
#define SAMPLES 48000
#define FREQ_RIGHT_1 8000
#define FREQ_RIGHT_2 10000
#define FREQ_LEFT_1 50
FILE* File;
int main(void)
{
int Output;
int StreamData;
uint16_t RightChannel = 0x00;
uint16_t LeftChannel = 0x00;
File = fopen("Result.log", "w");
for(int i = 0x00; i < SAMPLES; i++)
{
// Generate the input data
RightChannel = 32767 * sin(2 * M_PI * i / (SAMPLES / FREQ_RIGHT_1)) * sin(2 * M_PI * i / (SAMPLES / FREQ_RIGHT_2));
StreamData = (LeftChannel << 0x10) | RightChannel;
// Execute the function with latest input
Filter(StreamData, &Output, true);
// Write the simulation results
fprintf(File, "%i, %d, %d\n", i, StreamData, Output);
}
fclose(File);
}
So why do I get a different output, when I change the for loop in Filter from a down counting loop into a upcounting loop?
if(Enable == true)
{
Shift_Accum_Loop: for(int i = 0; i < (LENGTH - 1); i++)
{
if(i == 0)
{
...
0, 0, 0
1, 28377, 27073
2, 0, 0
3, 0, 0
4, 0, 0
5, 37159, 38462
6, 0, 0
7, 37159, 38462
8, 0, 0
9, 0, 0
10, 0, 0
11, 28377, 27073
What is the difference between this? The loops do count from 0 to (LENGTH - 1) in both cases and the filter is symetric. Why does the count direction has an impact on the result?
if(i == 0)
{
ShiftRegRight[0] = DataIn & 0x0000FFFF;
ShiftRegLeft[0] = (DataIn & 0xFFFF0000) >> 0x10;
}
else
{
ShiftRegRight[i] = ShiftRegRight[i - 1];
ShiftRegLeft[i] = ShiftRegLeft[i - 1];
}
When you count down i==0 evaluates to true last.
When you count up i==0 evaluates to true first.
in the following code, I'm able to print all the dice combinations that add up to a desired sum. I'd like some help in tweaking the code to remove the duplicate entries.
void rep(int n, string ans, int currentSum, int targetSum)
{
if(n==0)
{
if(currentSum==targetSum)
cout << "{" << ans << "}"<<endl;
}
else
{
for(int i=1 ; i<=6 ; i++)
{
if(n>1)
{
rep(n-1, ans + to_string(i) + ", ", currentSum+i, targetSum);
}
else
{
rep(n-1, ans + to_string(i), currentSum+i, targetSum);
}
}
}
}
void ManyDiceSum(int howManyDice, int targetSum)
{
if(howManyDice>0)
rep(howManyDice,"",0,targetSum);
}
int main()
{
int howManyDice, targetSum;
howManyDice=3;
targetSum=7;
ManyDiceSum(howManyDice, targetSum);
return 0;
}
Output for 3 dice and target sum of 7 should be:
{1, 1, 5}
{1, 2, 4}
{1, 3, 3}
{2, 2, 3}
But, my code is displaying all combinations:
{1, 1, 5}
{1, 2, 4}
{1, 3, 3}
{1, 4, 2}
{1, 5, 1}
{2, 1, 4}
{2, 2, 3}
{2, 3, 2}
{2, 4, 1}
{3, 1, 3}
{3, 2, 2}
{3, 3, 1}
{4, 1, 2}
{4, 2, 1}
{5, 1, 1}
Constraints are: It has to use recursion and use only 1 loop if
necessary.
First of all you do not need to pass both target and current sum to the function, only target is enough, and checking it first will speed up whole process significantly:
void rep( int n, int target, std::string ans = std::string(), int last = 1 )
{
if( n == 0 ) {
if( target == 0 )
std::cout << "{" << ans << "}" << std::endl;
return;
}
const auto limit = std::min( 6, target );
// or even following, but not sure this is quite right though
//const auto limit = std::min( 6, target - n * last );
for( int i = last ; i <= limit; ++i )
rep(n-1, target - i, ans + to_string(i) + ( n > 1 ? ", " : "" ), i );
}
void ManyDiceSum( int howManyDice, int TargetSum )
{
if (howManyDice > 0)
rep( howManyDice, TargetSum );
}
and to avoid duplicates continue from the last number you started.
A exemplary solution based on #Jarod42's comment:
void rep(int n, std::string ans, int currentSum, int TargetSum, int startFrom) {
if (n == 0) {
if (currentSum == TargetSum)
std::cout << "{" << ans << "}" << std::endl;
} else
for (int i = startFrom; i <= 6; i++)
if (n > 1)
rep(n-1, ans + to_string(i) + ", ", currentSum + i, TargetSum, i);
else
rep(n-1, ans + to_string(i), currentSum + i, TargetSum, i);
}
void ManyDiceSum(int howManyDice, int TargetSum) {
if (howManyDice > 0)
rep(howManyDice, "", 0, TargetSum, 1);
}
The task is to rotate left or rotate right a subarray of an array given number of times.
Let me explain this on an example:
lets data be an array.
data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
a sub array is determined by parameters begin and end.
if begin = 3 and end = 7, then subarray is {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
if begin = 7 and end = 3, then subarray is {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
let's rotate it right two times
if begin = 3 and end = 7, then the result is {0, 1, 2, 6, 7, 3, 4, 5, 8, 9};
if begin = 7 and end = 3, then the result is {8, 9, 0, 1,, 4, 5, 6, 2, 3, 7};
I've written code that performs this task but it's to slow.
Can someone give me a hint how to make it quicker?
Important: I'm not allowed to use other arrays than data, subprograms and build-in functions.
#include <iostream>
using namespace std;
int main(){
int dataLength;
cin >> dataLength;
int data [ dataLength ];
for (int i = 0; i < dataLength; i++){
cin >> data [ i ];
}
int begin;
int end;
int rotation;
int forLoopLength;
int tempBefore;
int tempAfter;
cin >> begin;
cin >> end;
cin >> rotation;
if (end > begin)
forLoopLength = (end - begin) + 1;
else
forLoopLength = (end - begin) + 1 + dataLength;
if (rotation < 0)
rotation = forLoopLength + (rotation % forLoopLength);
else
rotation = rotation % forLoopLength;
for (int i = 0; i < rotation; i++) {
tempBefore = data [ end ];
for (int i = 0; i < forLoopLength; i++) {
tempAfter = data [ (begin + i) % dataLength ];
data [ (begin + i) % dataLength ] = tempBefore;
tempBefore = tempAfter;
}
}
for (int i = 0; i < dataLength; i ++ ) {
cout << data [ i ] << " ";
}
return 0;
}
There's a trick to this. It's pretty weird that you'd get this for homework if the trick wasn't mentioned in class. Anyway...
To rotate a sequence of N elements left by M:
reverse the whole sequence
reverse the last M elements
reverse the first N-M elements
done
e.g. left by 2:
1234567
->
7654321
->
7654312
->
3456712
Here is my code, it makes exactly n reads and n writes, where n is subarray size.
#include<iostream>
int arr[]= { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// replacing 'addr( pos, from, size )' with just 'pos' mean rotation the whole array
int addr( int ptr, int from, int size)
{
return (ptr + from ) % size;
}
void rotate( int* arr, int shift, int from, int count, int size)
{
int i;
int pos= 0;
int cycle= 0;
int c= 0;
int c_old= 0;
// exactly count steps
for ( i=0; i< count; i++ ){
// rotation of arrays part is essentially a permutation.
// every permutation can be decomposed on cycles
// here cycle processing begins
c= arr[ addr( pos, from, size ) ];
while (1){
// one step inside the cycle
pos= (pos + shift) % count;
if ( pos == cycle )
break;
c_old= c;
c= arr[ addr( pos, from, size ) ];
arr[ addr( pos, from, size ) ]= c_old;
i++;
}
// here cycle processing ends
arr[ addr( pos, from, size ) ]= c;
pos= (pos + 1) % count;
cycle= (cycle + 1) % count;
}
}
int main()
{
rotate( arr, 4, 6, 6, 11 );
int i;
for ( i=0; i<11; i++){
std::cout << arr[i] << " ";
}
std::cout << std::endl;
return 0;
}
The following returns the number 7. My problem is that im not exactly sure why 7 is the number returned. I tried running in in debug mode to break it down but
unfortunately that did not help.
#include <iostream>
#include <list>
#include <algorithm>
using namespace std;
bool even_first( int x, int y ){
if( (x % 2 == 0) && (y % 2 != 0) ) return true;
if( (x % 2 != 0) && (y % 2 == 0) ) return false;
return x < y;
}
struct BeforeValue {
int bound;
BeforeValue( int b ) : bound( b ) { }
bool operator()( int value ) { return even_first( value, bound ); }
};
int main(){
list<int> my_list = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int count = count_if( my_list.begin( ), my_list.end( ), BeforeValue( 5) );
cout << count << "\n";
}
To function even_first you pass 2 parameters: first parameter x is equal to successive values from my_list and the second parameter y is always 5.
And in the even_first function we have 3 conditions:
if( (x % 2 == 0) && (y % 2 != 0) ) return true;
y is equal to 5 so y % 2 != 0 is always true
x % 2 == 0 is true for: 0, 2, 4, 6, 8
if( (x % 2 != 0) && (y % 2 == 0) ) return false;
It is always false because y = 5 so y % 2 == 0 is false. We go to point 3
return x < y;
To this statement we go only with values: 1, 3, 5, 7, 9
and it is true for: 1 and 3
So finally the even_first returns true for: 0, 1, 2, 3, 4, 6, 8. And the size of this set is 7