I'm given n sets and need to make sure that atleast m sets are selected. I'm planning to deal with bits.
My approach is:
for i in [0,(2^n)-1]
convert i to binary
if number of 1s are greater than or equal to m
{ Some calculations requiring which bits are on }
Now, is there any other way I can make sure that number of on bits are atleast m ? In my above approach, I'll be wasting time in converting numbers to binary and then checking if no. of on bits are >=m. Is there a way to cut short the loop ? (I'm dealing in C++)
I guess you need to generate bitmasks to select a subset of atleast "m" elements from a set of "n" elements.
This can be easily done if we have an algorithm to generate all the bitmasks having exactly "m" bits set.
#include <iostream>
#include <vector>
#include <cassert>
using namespace std;
// Given "n" and "r", generate all the possible nCr subsets of an array of size "n"
typedef unsigned long long ULL;
// Generate the lowest number bigger than "num" having exactly "r" set bits
// Algorithm (From Cracking The Coding Interview, 5th Edition) -:
// 1. Find the position of the rightmost "non-trailing" zero (such that there is atleast one '1' on its right).
// Let this position be 'p'
// If there does not exist such a zero, the input is already the largest number possible.
// 2. Flip the bit at 'p' to 1 from 0.
// 3. Count the number of zeroes and ones to the right of 'p'.
// Let that number be c0 and c1 respectively.
// 4. Set all the bits to the right of 'p' to 0.
// 5. Set the first (c1-1) bits (starting from the right) to 1.
ULL NextBigger( ULL num )
{
ULL numBak = num;
// Compute c0 and c1
// c0 = Number of zeroes to the right of the rightmost non-trailing zero
size_t c0 = 0;
// c1 = Number of ones to the right of the rightmost non-trailing zero
size_t c1 = 0;
while ( numBak && ( ( numBak & 1 ) == 0 ) )
{
c0++;
numBak >>= 1;
}
while ( ( numBak & 1 ) == 1 )
{
c1++;
numBak >>= 1;
}
// If the input is either 0,
// or of the form "1111..00000",
// then there is no bigger number possible
// Note that for this to work, num should be unsigned
if ( c0 + c1 == 0 || c0 + c1 == ( sizeof( num ) * 8 ) )
{
return 0;
}
// Position of the rightmost non-trailing zero ( starting from the right )
const size_t p = c0 + c1;
// Flip the rightmost non-trailing zero
num |= 1 << p;
// Clear all bits to the right of p
num &= ~( ( 1 << p ) - 1 );
// Insert (c1-1) ones on the right of p
num |= ( 1 << ( c1 - 1 ) ) - 1;
return num;
}
vector<ULL> GenerateSubsets( const size_t& n, const size_t& r )
{
assert( n > 0 );
assert( r > 0 );
assert( n >= r );
vector<ULL> subsets;
// The smallest number having exactly "r" bits set
ULL lowest = ( 1ULL << r ) - 1;
// The biggest number having exactly "r" bits set
ULL highest = lowest << ( n - r );
// The set bits in the binary of "bitMask" denote the positions of the set included in the subset
// This loop should run exactly nCr times
for ( ULL bitMask = lowest; bitMask <= highest; bitMask = NextBigger( bitMask ) )
{
subsets.push_back( bitMask );
}
return subsets;
}
// Extracts the subset indices from the bitmask
vector<size_t> DecodeMask( ULL bitMask )
{
vector<size_t> positions;
size_t i = 0;
while ( bitMask )
{
if ( bitMask & 1 )
{
positions.push_back( i );
}
bitMask >>= 1;
i++;
}
return positions;
}
int main()
{
size_t n = 5;
size_t r = 2;
cout << "Generating subsets of size " << r << "\n";
auto vec = GenerateSubsets( n, r );
cout << "Number of subsets = " << vec.size() << "\n";
// Print the subset indices
for ( size_t i = 0; i < vec.size(); i++ )
{
auto decode = DecodeMask( vec[i] );
for ( size_t j = 0; j < decode.size(); j++ )
{
cout << decode[j] << " ";
}
cout << "\n";
}
}
Now we can easily modify this to generate all the bitmasks having at least "m" bits set by applying the above algo while incrementing "m" upto "n".
// Rest of the code same as above
int main()
{
size_t n = 5;
size_t m = 2;
for ( size_t r = m; r <= n; r++ )
{
cout << "Generating subsets of size " << r << "\n";
auto vec = GenerateSubsets( n, r );
cout << "Number of subsets = " << vec.size() << "\n";
// Print the subset indices
for ( size_t i = 0; i < vec.size(); i++ )
{
auto decode = DecodeMask( vec[i] );
for ( size_t j = 0; j < decode.size(); j++ )
{
cout << decode[j] << " ";
}
cout << "\n";
}
cout << "\n";
}
}
Related
I have the following problem : I have a hex number (datatype : std::uint64_t) in C++, and the hex number contains all the digits from 1 to a given n. The question is now to rotate the first k digits of the hex number, for example :
hex = 0x436512, k = 3 --> 0x634512
I have already tried splitting the hex number into two parts, e.g
std::uint64_t left = hex >> ((n - k) * 4);
std::uint64_t right = ((1UL << ((n - k) * 4)) - 1) & hex;
and then rotating left and merging left and right together. Is there a possibility to do this in-place and by only using bit-manipulation and/or mathematical operators?
As a baseline you can use this which is basically converting to digits and back.
#include <cstdio>
#include <cstdint>
#include <array>
uint64_t rotate( uint64_t value, int k ) {
// decompose
std::array<uint8_t,16> digits;
int numdigits = 0;
while ( value > 0 ) {
digits[numdigits] = value % 16;
value = value / 16;
numdigits += 1;
}
if ( k>numdigits ) return 0;
// revert digits
int p1 = numdigits - 1;
int p2 = numdigits - k;
for ( ; p1>p2; p1--,p2++ ) {
uint8_t tmp = digits[p1];
digits[p1] = digits[p2];
digits[p2] = tmp;
}
// reconstruct
for ( int j=0; j<numdigits; ++j ) {
value = (value*16) + digits[numdigits-1-j];
}
return value;
}
int main() {
uint64_t value = 0x123ffffff;
for ( int j=0; j<8; ++j ) {
value = value >> 4;
printf( "%lx %lx\n", value, rotate(value,3) );
}
}
Godbolt: https://godbolt.org/z/77qWEo9vE
It produces:
Program stdout
123fffff 321fffff
123ffff 321ffff
123fff 321fff
123ff 321ff
123f 321f
123 321
12 0
1 0
You actually do not need to decompose the entire number, you can strictly decompose only the left digits.
#include <cstdio>
#include <cstdint>
#include <array>
uint64_t rotate( uint64_t value, int k ) {
// sanity check
if ( value == 0 ) return 0;
// fast find number of digits
int numdigits = (63-__builtin_clzl(value))/4 + 1;
if ( k>numdigits ) return 0;
// Decompose left and right
int rightbits = 4*(numdigits-k);
uint64_t left = value >> rightbits;
uint64_t right = rightbits==0 ? 0 : value & (uint64_t(-1)>>(64-rightbits));
// decompose left
uint64_t rot = 0;
for ( int j=0; j<k; ++j ) {
uint64_t digit = left % 16;
left = left / 16;
rot = (rot*16) + digit;
}
// rejoin
return right | (rot<<rightbits);
}
int main() {
uint64_t value = 0x123ffffff;
for ( int j=0; j<8; ++j ) {
value = value >> 4;
printf( "%lx %lx\n", value, rotate(value,3) );
}
}
Produces the same output.
Godbolt: https://godbolt.org/z/P3z6W8b3M
Running under Google benchmark:
#include <benchmark/benchmark.h>
#include <vector>
#include <iostream>
uint64_t rotate1(uint64_t value, int k);
uint64_t rotate2(uint64_t value, int k);
struct RotateTrivial {
uint64_t operator()(uint64_t value, int k) {
return rotate1(value, k);
}
};
struct RotateLeftOnly {
uint64_t operator()(uint64_t value, int k) {
return rotate2(value, k);
}
};
template <typename Fn>
static void Benchmark(benchmark::State& state) {
Fn fn;
for (auto _ : state) {
uint64_t value = uint64_t(-1);
for (int j = 0; j < 16; ++j) {
for (int k = 1; k < j; ++k) {
uint64_t result = fn(value, k);
benchmark::DoNotOptimize(result);
}
value = value >> 4;
}
}
}
BENCHMARK(Benchmark<RotateTrivial>);
BENCHMARK(Benchmark<RotateLeftOnly>);
BENCHMARK_MAIN();
Produces on an AMD Threadripper 3960x 3.5GHz
--------------------------------------------------------------------
Benchmark Time CPU Iterations
--------------------------------------------------------------------
Benchmark<RotateTrivial> 619 ns 619 ns 1158174
Benchmark<RotateLeftOnly> 320 ns 320 ns 2222098
Each iteration has 105 calls so it's about 6.3 ns/call or 20 cycles for the trivial version and 3.1ns/call or 10 cycles for the optimized version.
I'm currently studying for an exam and I'm trying to deal with dynamical matrix. I've come across a problem regarding calculating the sum of every diagonal of a matrix whose values and size are chosen by the user.
The intent of my program is to print, thanks to a function, whose parameters are the matrix and its size, the value of every diagonal sum. I'll show you the code and describe it in depth.
----------------
| 52 | 35 | 5 | Example of matrix.
---------------- Imagine the first diagonal to be the one which goes right-to-left
| 2 | 71 | 1 | and only consists in the number "47".
---------------- The second diagonal would be the one which goes right-to-left and
| 3 | 60 | 25 | consists in the number "15" and "79".
---------------- So to get the sum of the second diagonal it would be:
| 79 | 55 | 98 |
---------------- sum = m[n_rows - 1][diag - 2] + m[n_rows - 2][diag - 1]
| 47 | 15 | 66 |
---------------- When diag > columns, in order to avoid error regarding matrix size,
I should lower the quantity "n_rows - 1" by the quantity "diag - n_columns".
This is what I thought to do, according to my description:
void diag_matrix(int** m, int righe, int colonne){//righe = rows, colonne = columns.
//M is the matrix.
// diag is the number of the diagonal I'm considering.
for(int diag = 1; diag < (righe + colonne); diag++){
int sum = 0;// the sum
int i = 0;// the counter of the cicle
int l = 0;// this is the value to riallign the row in case diag > column
int temp = diag;//I use this variable not to modify the value of diag.
// What I want is: when the column-index/row-index of the matrix reaches 0, the cicle will interrupt (after final iteration);
while(righe - i - l - 1 > 0 || diag - 1 - i > 0){
if (diag > colonne){//this condition changes l-value only if diag value is greater than column. Explanation outside the code
l = diag - colonne;//this is the value to subtract to row-index
temp = colonne;//this position is necessary to set column-index to its maxium.
}
sum = sum + m[righe - 1 - l - i][temp -1 - i];//pretty clear I think.
i++;//the i is incremented by one.
}// end of while-statement
cout << "Somma Diagonale " << diag << " = " << sum << ".\n";
}// end of for-statement
}//end of function declaration
Obviously it does not work, but I can't figure out the problem.
(There used to be a paragraph here, but on a second look, you didn’t make the mistake it was talking about.)
Since you didn’t post to Code Reviews, here’s a solution instead of a detailed code review. (If you want to make the original approach work, I’d suggest single-stepping through it in a debugger and checking where your variables first get the wrong value.) It’s got a lot of boilerplate to make it compile and run, but the part you’ll be most interested in is diag_sums() and its comments.
One idea here is to use OOP to automatically check the bounds of your array accesses. The latter is very important for catching off-by-one errors and the like. You can turn it off in production if you want, but you really don’t want to silence warnings when your program has a buffer overrun. Other optimizations here include locality of access for the data, and strength reduction on the operations: rather than check on each iteration whether we’ve hit the right edge and the bottom edge, we can simply calculate the length of each diagonal in advance.
Since the definition of diagonal number k of matrix a with M rows is equivalent to: all elements a[i][j] such that such that M - k = i - j, the algorithm ensures correctness by maintaining the invariant, which holds whenever we add 1 to both i and j, starting when either i or j is 0, and stopping whenever i = M or j = N, that is, traversing each step of the diagonal from the left or top edge to the right or bottom edge, whichever comes first.
#include <assert.h>
#include <iostream>
#include <stddef.h>
#include <stdlib.h>
#include <utility>
#include <vector>
using std::cin;
using std::cout;
template <typename T>
class matrix {
public:
matrix( const ptrdiff_t rows,
const ptrdiff_t cols,
std::vector<T>&& elems )
: rows_(rows), cols_(cols), elems_(elems)
{
assert( rows_ > 0 );
assert( cols_ > 0 );
assert( elems_.size() == static_cast<size_t>(rows_*cols_) );
}
matrix( const ptrdiff_t rows,
const ptrdiff_t cols,
const std::vector<T>& elems )
: matrix( rows, cols, std::move(std::vector<T>(elems)) )
{}
matrix( const matrix<T>& ) = default;
matrix( matrix<T>&& ) = default;
matrix& operator= ( const matrix<T>& ) = default;
matrix& operator= ( matrix<T>&& ) = default;
T& operator() ( const ptrdiff_t m, const ptrdiff_t n )
{
assert( m >= 0 && m < rows_ );
assert( n >= 0 && n < cols_ );
return elems_[static_cast<size_t>(m*cols_ + n)];
}
const T& operator() ( const ptrdiff_t m, const ptrdiff_t n ) const
{
/* Because this call does not modify any data, and the only reason the
* member function above cannot be const is that it returns a non-const
* reference to an element of elems, casting away the const qualifier
* internally and then returning a const reference is a safe way to
* re-use the code.
*/
matrix<T>& nonconst = *const_cast<matrix<T>*>(this);
return nonconst(m,n);
}
ptrdiff_t rows() const { return rows_; }
ptrdiff_t cols() const { return cols_; }
private:
ptrdiff_t rows_;
ptrdiff_t cols_;
std::vector<T> elems_;
};
template<typename T>
std::ostream& operator<< ( std::ostream& out, const matrix<T>& x )
/* Boilerplate to print a matrix. */
{
const ptrdiff_t m = x.rows(), n = x.cols();
for ( ptrdiff_t i = 0; i < m; ++i ) {
out << x(i,0);
for ( ptrdiff_t j = 1; j < n; ++j )
out << ' ' << x(i,j);
out << '\n';
} // end for
return out;
}
using elem_t = int;
std::vector<elem_t> diag_sums( const matrix<elem_t>& a )
/* Return a vector of all the diagonal sums of a.
*
* The first diagonal sum is a(rows-1,0)
* The second is a(rows-2,0) + a(rows-1,1)
* The third is a(rows-3,0) + a(rows-2,1) + a(rows-1,2)
* And so on. I.e., the kth diagonal is the sum of all elements a(i,j) such
* that i - j == rows - k.
*
* If a is a M×N matrix, there are M diagonals starting in column zero, and
* N-1 diagonals (excluding the one containing a(0,0) so we don't count it
* twice) starting in row 0. We process them bottom to top, then left to
* right.
*
* The number of elements in a diagonal starting at a(i,0) is min{M-i, N}. The
* number of elements in a diagonal starting at a(0,j) is min{M, N-j}. This is
* because a diagonal stops at either the bottom edge or the left edge of a.
*/
{
const ptrdiff_t m = a.rows(), n = a.cols();
std::vector<elem_t> result;
result.reserve( static_cast<size_t>(m + n - 1) );
for ( ptrdiff_t i = m-1; i > 0; --i ) {
elem_t sum = 0;
const ptrdiff_t nk = (m-i) < n ? (m-i) : n;
for ( ptrdiff_t k = 0; k < nk; ++k )
sum += a(i+k, k);
result.emplace_back(sum);
} // end for i
for ( ptrdiff_t j = 0; j < n; ++j ) {
elem_t sum = 0;
const ptrdiff_t nk = m < (n-j) ? m : (n-j);
for ( ptrdiff_t k = 0; k < nk; ++k )
sum += a(k, j+k);
result.emplace_back(sum);
} // end for j
return result;
}
matrix<elem_t> read_input_matrix( const int row, const int column )
/* Reads in row*column consecutive elements from cin and packs them into a
* matrix<elem_t>.
*/
{
assert(row > 0);
assert(column > 0);
const ptrdiff_t nelements = row*column;
assert(nelements > 0); // Check for overflow.
std::vector<elem_t> result;
result.reserve(static_cast<size_t>(nelements));
for ( ptrdiff_t i = nelements; i > 0; --i ) {
int x;
cin >> x;
assert(cin.good());
result.push_back(x);
}
return matrix<elem_t>( row,
column,
std::move(result) );
}
template<typename T>
bool print_sequence( const T& container )
/* Prints the contents of a container in the format
* "{47, 94, 124, 160, 148, 36, 5}".
*/
{
cout << "{";
if ( container.begin() != container.end() )
cout << *container.begin();
for ( auto it = container.begin() + 1; it < container.end(); ++it )
cout << ", " << *it;
cout << "}\n";
return cout.good();
}
/* A simple test driver that reads in the number of rows, the number of
* columns, and then row*columns int values, from standard input. It
* then passes the result to diag_matrix(), E.g.:
*
* 5 3
* 52 35 5
* 2 71 1
* 3 60 25
* 79 55 98
* 47 15 66
*/
int main()
{
int rows, columns;
cin >> rows;
cin >> columns;
assert(cin.good());
const matrix<elem_t> input_matrix = read_input_matrix( rows, columns );
// cout << input_matrix; // Instrumentation.
const std::vector<elem_t> sums = diag_sums(input_matrix);
print_sequence(sums);
return EXIT_SUCCESS;
}
You could also just do print_sequence(diag_sums(read_input_matrix( rows, columns ))).
You can simplify your code finding the starting position of each diagonal and then stepping through the matrix as long as the coordinates stay inside the matrix.
Something like this:
#include <iostream>
using namespace std;
void diag_matrix(int** m, int rows, int cols)
{
for (int diag = 1; diag < rows + cols; diag++)
{
int x, y;
if (diag < rows)
{
y = rows - diag;
x = 0;
}
else
{
y = 0;
x = diag - rows;
}
int sum = 0;
cout << "Summing diagonal #" << diag << ":";
while ((x < cols) && (y < rows))
{
sum += m[y][x];
cout << " " << m[y][x];
x++;
y++;
}
cout << " result: " << sum << "." << endl;
}
}
int main(int argc, char* argv[])
{
int rows = 5, cols = 3;
int **m = new int*[rows];
for (int i = 0; i < rows; i++)
m[i] = new int[cols];
m[0][0] = 52; m[0][1] = 35; m[0][2] = 5;
m[1][0] = 2; m[1][1] = 71; m[1][2] = 1;
m[2][0] = 3; m[2][1] = 60; m[2][2] = 25;
m[3][0] = 79; m[3][1] = 55; m[3][2] = 98;
m[4][0] = 47; m[4][1] = 15; m[4][2] = 66;
diag_matrix(m, rows, cols);
for (int i = 0; i < rows; i++)
delete[] m[i];
delete[] m;
return 0;
}
I am attempting to solve Project Euler problem 10 where the user is asked to calculate the sum of all the primes less than two million. I've written the following by studying the pseudocode on Wikipedia but the answer it generates seems to be incorrect, at least according to the website whenever I try to enter it:
int main()
{
int limit = 2000000;
int answer = 5;
std::vector<bool> isPrime;
for( int i = 0; i < limit; ++i ){
isPrime.push_back( false );
}
int n = 0;
for( int x = 1; x <= ceil( sqrt( limit ) ); ++x ){
for( int y = 1; y <= ceil( sqrt( limit ) ); ++y ){
n = 4*x*x + y*y;
if( (n <= limit) && ( n%12 == 1 || n%12 == 5 ) ){
isPrime.at(n) = ! isPrime.at(n);
}
n = 3*x*x + y*y;
if( (n <= limit) && ( n%12 == 7 ) ){
isPrime.at(n) = ! isPrime.at(n);
}
n = 3*x*x - y*y;
if( (x > y) && (n <= limit) && (n%12 == 11) ){
isPrime.at(n) = ! isPrime.at(n);
}
}
}
for( n = 6; n <= ceil( sqrt( limit ) ); n += 2 ){
if( isPrime.at(n) ){
for( int m = n*n; m < limit; m += n*n ){
isPrime.at(m) = false;
}
}
}
for( int i = 5; i < limit; i += 2 ){
if( isPrime.at(i) ){
answer += i;
}
}
std::cout << "The sum of the primes below " << limit << " is " << answer << std::endl;
return 0;
}
The following output is generated:
The sum of all the primes below 2000000 is 1179908154
I've tested it with smaller limits that I'm able to verify by hand and the code is indeed functioning correctly for those numbers. I've found other peoples implementation which indicate that the answer should be 142913828922, but I can't figure out where their code differs from mine.
Can anyone see what it is I'm doing wrong here?
You only have a signed 32-bit integer for the answer. The actual answer is much higher than can fit in 32 bits, so you have to go over to using 64 bit integers. Try using unsigned long long instead.
You can create your own class to store big numbers.Or u can use an array of integer to store your answer and storing each digit at each index. (Even if unsigned long long not working) :)
I wrote a program to calculate (adding) 2 positive big integer using vector to store the numbers.
#include <cstdlib>
#include <cstdio> // sd sprintf()
#include <iostream>
#include <vector>// sd vector
typedef short TYPE;// alias
void input();
void makeArray();
void display(const std::vector<TYPE> Ar);
TYPE convertChar2T( char * ch);
void add();
static std::string num1;//store big integer as string
static std::string num2;
static std::vector<TYPE> Arr1;//store as vector
static std::vector<TYPE> Arr2;
static std::vector<TYPE> result;
int main(int argc, char** argv) {
input();
makeArray();
display(Arr1);
display(Arr2);
add();
display(result);
return 0;
}
//input 2 big integer number
void input(){
std::cout << "Enter 1st number : " ;
if (! std::getline(std::cin , num1) )
std::cerr << "Not OK\n";
std::cout << "Enter 2nd number : ";
if (! std::getline(std::cin , num2) )
std::cerr << "Not OK\n";
}
//grab into 2 arrays
void makeArray(){
for (std::size_t i = 0; i < num1.size(); i++){
char temp1[2] = { num1[i], '\0'}; //use array-of-char as it need '\0'
Arr1.push_back( convertChar2T(temp1) ); //push what is converted
}
for (std::size_t i = 0; i < num2.size(); i++){
char temp2[2] = { num2[i], '\0'};
Arr2.push_back( convertChar2T(temp2) );
}
}
//convert char -> TYPE by using sscanf()
TYPE convertChar2T( char * ch){
TYPE numb ;
sscanf( ch, "%d", &numb );//NGUOC LAI SPRINTF
return numb;
}
//display array
void display(const std::vector<TYPE> Ar){
for (std::size_t i = 0; i < Ar.size(); i++)
std::cout << Ar.at(i) << '\t';
std::cout << '\n';
}
void add(){
std::size_t i = Arr1.size(); // NEVER COMES TO ZERO ( 1 AT LEAST )
std::size_t j = Arr2.size();
//check original one and later one
//3 cases : 1 - original one , not yet processed
// 2 - original # one, not yet processed
// -1 - original # one or one, processed
//NOTE: at first only value 1 or 2 ( not process )
short check_one[2] = {
( i == 1 ) ? 1 : 2,
( j == 1 ) ? 1 : 2,
};
bool boost = 0;
bool Arr1_isgood = true;// whether count to 1 or not
bool Arr2_isgood = true;// good -> not yet 1
short temp_result = 0;//temporary result to push into vector
while ( Arr1_isgood || Arr2_isgood ){// while not all comes to 1
// i == j : 2 cases
// 1st: both 1 now - 3 cases
// 1.1 #1+not process original and processed
// 1.2 processed and #1+not processed
// 1.3 both 1 original + not processed
// 2nd: both # 1
if ( i == j ) {
if ( check_one[0] == 2 && check_one[1] == -1 ){//#1+not process original and processed
temp_result = Arr1[i-1] + boost;
check_one[0] == -1;
}
else if ( check_one[0] == -1 && check_one[1] == 2 ){//processed and #1+not processed
temp_result = Arr2[j-1] + boost;
check_one[1] = -1;
}
else//both 1 original + not processed OR both # 1
temp_result = Arr1[i-1] + Arr2[j-1] + boost;
//check result >= 10 or < 10
if ( temp_result >= 10 ){
temp_result = temp_result - 10 ;
boost = 1;
}
else
boost = 0;
//result.begin() return iterator at beginning
result.insert( result.begin() ,temp_result );
//update info
if ( i == j && i == 1){ // NOTE : NEU SD i==j==1 -> sai (vi luon true)
Arr1_isgood = Arr2_isgood = false;
continue;
}
else if ( i == j && i != 1){ // i == j # 1
i--;
j--;
}
}
if (i != j){
//check to set flag ( if one of two die )
if ( i == 1 && j > 1 )
Arr1_isgood = false;
else if ( i > 1 && j == 1 )
Arr2_isgood = false;
// i die && j live OR vice versa
if ( (!Arr1_isgood && Arr2_isgood) ||
(Arr1_isgood && !Arr2_isgood ) ){
if (!Arr1_isgood && Arr2_isgood ){ //1st case
if ( check_one[0] == 1 || check_one[0] == 2){//not yet processed as SET FLAG ABOVE first
temp_result = Arr1[i-1] + Arr2[j-1] + boost;
check_one[0] = -1 ;
}
else
temp_result = Arr2[j-1] + boost;
j--;
}
else if ( Arr1_isgood && !Arr2_isgood ){ //2nd case
if ( check_one[1] == 1 || check_one[1] == 2 ){//not yet processed as SET FLAG ABOVE first
temp_result = Arr1[i-1] + Arr2[j-1] + boost;
check_one[1] = -1 ;
}
else
temp_result = Arr1[i-1] + boost;
i--;
}
}
else {// both is good
temp_result = Arr1[i-1] + Arr2[j-1] + boost;
i--;
j--;
}
//check result >= 10 or < 10
if (temp_result >= 10) {
temp_result -= 10;
boost = 1;
} else
boost = 0;
result.insert( result.begin() ,temp_result );
}
}
//insert boost (if any exists)
if (boost == 1)
result.insert( result.begin(), boost);
}
I'm torn between the use of "Arr1_isgood" bool variable and the check_one variable, it seems that they can be combined into one variable ? I tried to do it and it takes a lot of time without correct result.
Can the digit be store in some kind of smaller data structure rather than "short" type ? as "short" takes more than needed bits.
Another thing is : it seems that std::size_t only reach up to 4 billion in size, as when size_t reach 1, I decreased it several times and it comes to 4 billion ? Isn't it?
I wonder if these codes somehow can be optimized more?
If you want to manipulate big integers, you should use a big-integer library, e.g. GMP.
In your machine has 32-bit ints, suppose you represent each number (unsigned) as an array of 31-bit signed ints, starting from the least significant.
Then maybe you could do something like this:
// do c = a + b
int a[n], b[n], c[n];
int carry = 0;
for (i = 0; i < n; i++){
// do the addition with carry
c[i] = a[i] + b[i] + carry;
// if the addition carried into the sign bit
carry = (c[i] < 0);
// detect it and remove it from the sum
if (carry){
c[i] &= 0x7fffffff;
}
}
Then you could figure out how to handle negatives.
I got a bit stuck with my algorithm and I need some help to solve my problem. I think an example would explain better my problem.
Assuming:
d = 4 (maximum number of allowed bits in a number, 2^4-1=15).
m_max = 1 (maximum number of allowed bits mismatches).
kappa = (maximum number of elements to find for a given d and m, where m in m_max)
The main idea is for a given number, x, to compute its complement number (in binary base) and all the possible combinations for up to m_max mismatches from x complement's number.
Now the program start to scan from i = 0 till 15.
for i = 0 and m = 0, kappa = \binom{d}{0} = 1 (this called a perfect match)
possible combinations in bits, is only 1111 (for 0: 0000).
for i = 0 and m = 1, kappa = \binom{d}{1} = 4 (one mismatch)
possible combinations in bits are: 1000, 0100, 0010 and 0001
My problem was to generalize it to general d and m. I wrote the following code:
#include <stdlib.h>
#include <iomanip>
#include <boost/math/special_functions/binomial.hpp>
#include <iostream>
#include <stdint.h>
#include <vector>
namespace vec {
typedef std::vector<unsigned int> uint_1d_vec_t;
}
int main( int argc, char* argv[] ) {
int counter, d, m;
unsigned num_combination, bits_mask, bit_mask, max_num_mismatch;
uint_1d_vec_t kappa;
d = 4;
m = 2;
bits_mask = 2^num_bits - 1;
for ( unsigned i = 0 ; i < num_elemets ; i++ ) {
counter = 0;
for ( unsigned m = 0 ; m < max_num_mismatch ; m++ ) {
// maximum number of allowed combinations
num_combination = boost::math::binomial_coefficient<double>( static_cast<unsigned>( d ), static_cast<unsigned>(m) );
kappa.push_back( num_combination );
for ( unsigned j = 0 ; j < kappa.at(m) ; j++ ) {
if ( m == 0 )
v[i][counter++] = i^bits_mask; // M_0
else {
bit_mask = 1 << ( num_bits - j );
v[i][counter++] = v[i][0] ^ bits_mask
}
}
}
}
return 0;
}
I got stuck in the line v[i][counter++] = v[i][0] ^ bits_mask since I was unable to generalize my algorithm to m_max>1, since I needed for m_max mismatches m_max loops and in my original problem, m is unknown until runtime.
i wrote a code that do what i want, but since i am newbie, it is a bit ugly.
i fixed m and d although this code would work fine for genral m and d.
the main idea is simple, assuming we would like to compute the complement of 0 up to two failure (d= 4,m=2), we will see that max number of possibilities is given by \sum_{i = 0)^2\binom{4}{i} = 11.
The complement to 0 (at 4 bits) is 15
With 1 bit possible mismatch (from 15): 7 11 13 14
with 2 bits possible mismatches (from 15): 3 5 6 9 10 12
i wanted that the output of this program will be a vector with the numbers 15 7 11 13 14 3 5 6 9 10 12 inside it.
i hope that this time i am more clear with presenting my question (although i also supplied the solution). I would appreachiate if someone could point out, in my code, ways to improve it and make it faster.
regards
#include <boost/math/special_functions/binomial.hpp>
#include <iostream>
#include <vector>
#define USE_VECTOR
namespace vec {
#if defined(USE_VECTOR) || !defined(USE_DEQUE)
typedef std::vector<unsigned int> uint_1d_vec_t;
typedef std::vector<uint_1d_vec_t> uint_2d_vec_t;
#else
typedef std::deque<unsigned int> uint_1d_vec_t;
typedef std::deque<uint_1d_vec_t> uint_2d_vec_t;
#endif
}
using namespace std;
void get_pointers_vec( vec::uint_2d_vec_t &v , unsigned num_elemets , unsigned max_num_unmatch , unsigned num_bits );
double get_kappa( int m , int d );
int main( ) {
unsigned int num_elements , m , num_bits;
num_elements = 16;
num_bits = 4; // 2^4 = 16
m = 2;
double kappa = 0;
for ( unsigned int i = 0 ; i <= m ; i++ )
kappa += get_kappa( num_bits , i );
vec::uint_2d_vec_t Pointer( num_elements , vec::uint_1d_vec_t (kappa ,0 ) );
get_pointers_vec( Pointer , num_elements , m , num_bits );
for ( unsigned int i = 0 ; i < num_elements ; i++ ) {
std::cout << setw(2) << i << ":";
for ( unsigned int j = 0 ; j < kappa ; j++ )
std::cout << setw(3) << Pointer[i][j];
std::cout << std::endl;
}
return EXIT_SUCCESS;
}
double get_kappa( int n , int k ) {
double kappa = boost::math::binomial_coefficient<double>( static_cast<unsigned>( n ), static_cast<unsigned>(k) );
return kappa;
}
void get_pointers_vec( vec::uint_2d_vec_t &v , unsigned num_elemets , unsigned max_num_unmatch , unsigned num_bits ) {
int counter;
unsigned num_combination, ref_index, bits_mask, bit_mask;
vec::uint_1d_vec_t kappa;
bits_mask = pow( 2 , num_bits ) - 1;
for ( unsigned i = 0 ; i < num_elemets ; i++ ) {
counter = 0;
kappa.clear();
ref_index = 0;
for ( unsigned m = 0 ; m <= max_num_unmatch ; m++ ) {
num_combination = get_kappa( num_bits , m ); // maximum number of allowed combinations
kappa.push_back( num_combination );
if ( m == 0 ) {
v[i][counter++] = i^bits_mask; // M_0
}
else if ( num_bits == kappa.at(m) ) {
for ( unsigned k = m ; k <= num_bits ; k++ ) {
bit_mask = 1 << ( num_bits - k );
v[i][counter++] = v[i][ref_index] ^ bit_mask;
}
}
else {
// Find first element's index
ref_index += kappa.at( m - 2 );
for( unsigned j = 0 ; j < ( kappa.at(m - 1) - 1 ) ; j++ ) {
for ( unsigned k = m + j ; k <= num_bits ; k++ ) {
bit_mask = 1 << ( num_bits - k );
v[i][counter++] = v[i][ref_index] ^ bit_mask;
}
ref_index++;
}
}
}
}
}