C++ - Trouble Understanding a Divide and Conquer Function - c++

I'm having trouble understanding how this divide and conquer function compares data elements:
int main()
{
int arr[] = { -5, -10, -16, -3, -7 };
int largest;
largest = largest_element(arr, 0, sizeof(arr) / sizeof(int));
cout << "Largest element in arr is " << largest << ".\n";
return 0;
}
int largest_element(const int *a, int begin, int past_end)
{
int result;
int mid;
int left_large;
int right_large;
assert(begin >= 0);
assert(begin < past_end);
if (past_end - begin == 1)
result = a[begin];
else {
mid = (begin + past_end) / 2;
left_large = largest_element(a, begin, mid);
right_large = largest_element(a, mid, past_end);
if (left_large >= right_large)
result = left_large;
else
result = right_large;
}
//STOP! draw tree here when begin == 1, and past_end == 2.
return result;
}
I understand that the array is simply divided into smaller sub arrays, and that once the base case is reached, it'll return a[begin]. However, based on my diagram, I don't understand how the values are truly compared if when we have an array of two elements, it simply returns the first value. For example, how will the right most element in an array be compared if it has nothing else to compare with?
Here is my diagram. I have no other diagrams to compare mine with.

I don't understand how the values are truly compared if when we have
an array of two elements, it simply returns the first value.
I am unable to reproduce that finding. When arr has only 2 elements, the function still returns the larger of the two.
Your debugger is an appropriate way to evaluate your code and identify what you are misunderstanding.
However, it might be fun to add diagnostics and allow the code to report it's progress. Here is one technique:
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <cassert>
class T548_t
{
int depth;
public:
T548_t() = default;
~T548_t() = default;
int exec()
{
{
depth = 0; // 0 1 2 3 4
int arr[] = { -5, -10, -16, -3, -7 }; // -3 is largest
uint sz = sizeof(arr) / sizeof(int);
std::cout << hdr(sz);
std::cout << "\n\n Largest element in arr is "
<< largest_element(arr, 0, sz)
<< ".\n" << std::endl;
}
{
depth = 0;
int arr[] = { -10, -5 }; // -5 is largest
uint sz = sizeof(arr) / sizeof(int);
std::cout << hdr(sz);
std::cout << "\n\n Largest element in arr is "
<< largest_element(arr, 0, sz)
<< ".\n" << std::endl;
}
return 0;
}
private: // methods
int largest_element(const int* a, int begin, int past_end)
{
int result;
int mid;
int left_large;
int right_large;
assert(begin >= 0);
assert(begin < past_end);
std::cout << show(a, begin, past_end) << std::flush;
if (past_end - begin == 1)
result = a[begin];
else {
mid = (begin + past_end) / 2;
left_large = largest_element(a, begin, mid);
right_large = largest_element(a, mid, past_end);
if (left_large >= right_large)
result = left_large;
else
result = right_large;
}
//STOP! draw tree here when begin == 1, and past_end == 2.
depth -= 1;
return result;
}
std::string show(const int* a, int b, int e)
{
std::stringstream ss;
depth += 1;
ss << "\n a[" << b << " .. " << e-1 << "] "
<< depth << " ";
if(b > 0)
ss << std::setw(4*b) << " ";
for (int i = b; i < e; ++i)
ss << std::setw(4) << a[i];
return ss.str();
}
std::string hdr(uint sz)
{
std::stringstream ss;
ss << "\n "
<< " b .. e"
<< std::setw(8) << "depth"
<< std::setw(4) << " ";
for (uint i=0; i<sz; ++i)
ss << i << " ";
return ss.str();
}
}; // class T548_t
int main(int, char**)
{
T548_t t548;
return t548.exec();
}
Here is the output:
b .. e depth 0 1 2 3 4
a[0 .. 4] 1 -5 -10 -16 -3 -7
a[0 .. 1] 2 -5 -10
a[0 .. 0] 3 -5
a[1 .. 1] 3 -10
a[2 .. 4] 2 -16 -3 -7
a[2 .. 2] 3 -16
a[3 .. 4] 3 -3 -7
a[3 .. 3] 4 -3
a[4 .. 4] 4 -7
Largest element in arr is -3.
b .. e depth 0 1
a[0 .. 1] 1 -10 -5
a[0 .. 0] 2 -10
a[1 .. 1] 2 -5
Largest element in arr is -5.

something like this is only going to help you if the array is sorted and you can ignore half of the results on every recursion.
just loop through the elements to find the largest number. you have to check every value

Related

Prime-checking every element of a 10^6 array

My goal is to figure out whether each element of an array is a prime or not.
Example:
Input: int A[5]={1,2,3,4,5}
Output: bool P[5]={0,1,1,0,1}
The problem is the array size is up to 10^6. I tried the most efficient prime-checking algorithm
(code: http://cpp.sh/9ewxa) but just the "cin" and "prime_checking" take really long time. How should I solve this problem, Thanks.
Your "most efficient" prime test is actually horribly inefficient. Something like the Miller-Rabin primality test is much faster on a one by one basis. If your input are below 4.3 billion (i.e. uint32_t) then you only need to do 3 tests: a = 2, 7, and 61. For numbers in the uint64_t range it's 12 tests.
If you have a large array of integers then computing all primes up to some maximum might be faster than repeated tests. See Sieve of Eratosthenes for a good way to compute all primes fast. But it's impractical if your input numbers can be larger than 4 billion due to the memory required.
Here is some code that computes a Sieve up to UINT32_MAX+1 and then checks Miller-Rabin has the same results as the sieve: https://gist.github.com/mrvn/137fb0c8a5c78dbf92108b696ff82d92
#include <iostream>
#include <cstdint>
#include <array>
#include <ranges>
#include <cassert>
#include <bitset>
uint32_t pow_n(uint32_t a, uint32_t d, uint32_t n) {
if (d == 0) return 1;
if (d == 1) return a;
uint32_t t = pow_n(a, d / 2, n);
t = ((uint64_t)t * t) % n;
if (d % 2 == 0) {
return t;
} else {
return ((uint64_t)t * a) % n;
}
};
bool test(uint32_t n, unsigned s, uint32_t d, uint32_t a) {
//std::cout << "test(n = " << n << ", s = " << s << ", d = " << d << ", a = " << a << ")\n";
uint32_t x = pow_n(a ,d ,n);
//std::cout << " x = " << x << std::endl;
if (x == 1 || x == n - 1) return true;
for (unsigned i = 1; i < s; ++i) {
x = ((uint64_t)x * x) % n;
if (x == n - 1) return true;
}
return false;
}
bool is_prime(uint32_t n) {
static const std::array witnesses{2u, 3u, 5u, 7u, 11u, 13u, 17u, 19u, 23u, 29u, 31u, 37u};
static const std::array bounds{
2'047llu, 1'373'653llu, 25'326'001llu, 3'215'031'751llu,
2'152'302'898'747llu, 3'474'749'660'383llu,
341'550'071'728'321llu, 341'550'071'728'321llu /* no bounds for 19 */,
3'825'123'056'546'413'051llu,
3'825'123'056'546'413'051llu /* no bound for 29 */,
3'825'123'056'546'413'051llu /* no bound for 31 */,
(unsigned long long)UINT64_MAX /* off by a bit but it's the last bounds */,
};
static_assert(witnesses.size() == bounds.size());
if (n == 2) return true; // 2 is prime
if (n % 2 == 0) return false; // other even numbers are not
if (n <= witnesses.back()) { // I know the first few primes
return (std::ranges::find(witnesses, n) != std::end(witnesses));
}
// write n = 2^s * d + 1 with d odd
unsigned s = 0;
uint32_t d = n - 1;
while (d % 2 == 0) {
++s;
d /= 2;
}
// test widtnesses until the bounds say it's a sure thing
auto it = bounds.cbegin();
for (auto a : witnesses) {
//std::cout << a << " ";
if (!test(n, s, d, a)) return false;
if (n < *it++) return true;
}
return true;
}
template<std::size_t N>
auto composite() {
std::bitset<N / 2 + 1> is_composite;
for (uint32_t i = 3; (uint64_t)i * i < N; i += 2) {
if (is_composite[i / 2]) continue;
for (uint64_t j = i * i; j < N; j += 2 * i) is_composite[j / 2] = true;
}
return is_composite;
}
bool slow_prime(uint32_t n) {
static const auto is_composite = composite<UINT32_MAX + 1llu>();
if (n < 2) return false;
if (n == 2) return true;
if (n % 2 == 0) return false;
return !is_composite.test(n / 2);
}
int main() {
/*
std::cout << "2047: ";
bool fast = is_prime(2047);
bool slow = slow_prime(2047);
std::cout << (fast ? "fast prime" : "");
std::cout << (slow ? "slow prime" : "");
std::cout << std::endl;
*/
//std::cout << "2: prime\n";
for (uint64_t i = 0; i <= UINT32_MAX; ++i) {
if (i % 1000000 == 1) { std::cout << "\r" << i << " "; std::cout.flush(); }
bool fast = is_prime(i);
bool slow = slow_prime(i);
if (fast != slow) std::cout << i << std::endl;
assert(fast == slow);
//std::cout << i << ": " << (is_prime(i) ? "prime" : "") << std::endl;
}
}
The sieve takes ~15s to compute and uses 256MB of memory, verifying Miller-Rabin takes ~12m45s or 765 times slower than the sieve. Which tells me that if you are testing more than 85 million 32bit numbers for primes then just compute them all with a sieve. Since the sieve is O(n^2) it only gets better if your maximum input is smaller.

Is this how you add the digits of multiple numbers? (units, tens, hundreds)

I just wanna make sure whether this code is good or it needs improvement. What do you all think?
#include <iostream>
using namespace std;
u = (a%10+b%10+c%10+d%10+e%10+f%10);
t = (a / 10 % 10 + b / 10 %10 + c / 10 % 10 + d / 10 %10 + e / 10 % 10 + f / 10 %10);
h = (a / 100 % 10 + b / 100 % 10 + c / 100 % 10 + d / 100 % 10 + e / 100 % 10 + f / 100 % 10);
cout << "The sum of the first digit is: " << u << "\n";
cout << "The sum of the second digit is: " << t << "\n";
cout << "The sum of the third digit is: " << h ;
You could make it a bit more generic in at least two ways:
Write your code for just one number.
Then loop for any input numbers.
Write your code for adding any ith digit.
So, in this case, you could just focus on how to extract the ith digit of a given number n.
What, as shown in your code, could be done with (n / divisor) % 10, where divisor would be exp(10, i), i starting from 0.
Demo
#include <algorithm> // for_each
#include <iostream> // cout
#include <numeric> // accumulate
#include <vector>
int main()
{
std::vector<int> v{123'456, 99'999, 100};
auto sum_of_ith_digit = [](const std::vector<int>& v, size_t i) {
auto divisor{1};
while (i != 0) { divisor *= 10; i--; } // 1 for digit 0, 10 for digit 1, 100 for digit 2...
return std::accumulate(std::cbegin(v), std::cend(v), 0, // for each number in v
[&divisor](auto& total, const auto& n){ // get ith digit
return total + (n / divisor) % 10; // and add it to a total,
}); // then return the total
};
auto units = sum_of_ith_digit(v, 0);
auto tens = sum_of_ith_digit(v, 1);
auto hundreds = sum_of_ith_digit(v, 2);
std::for_each(std::cbegin(v), std::cend(v), [first=true](const int n) mutable {
std::cout << (first ? "v = " : ", ") << n; first = false; });
std::cout << "\n\tunits = " << units << ", tens = " << tens << ", hundreds = " << hundreds << "\n";
}
// Outputs:
// v = 123456, 99999, 100
// units = 15, tens = 14, hundreds = 14
The code below should do exactly the same, although it could be a little easier to understand. Demo
#include <iostream> // cout
#include <vector>
int sum_of_ith_digit(const std::vector<int>& v, size_t i)
{
// 1 for digit 0, 10 for digit 1, 100 for digit 2...
int divisor{1};
while (i != 0) { divisor *= 10; i--; }
// For each number in v, get ith digit, and add it to a total, then return the total
int total{0};
for (int n : v) { total += (n / divisor) % 10; }
return total;
};
int main()
{
std::vector<int> v{123'456, 99'999, 100};
int units = sum_of_ith_digit(v, 0);
int tens = sum_of_ith_digit(v, 1);
int hundreds = sum_of_ith_digit(v, 2);
std::cout << "v = ";
bool first{true};
for (int n : v)
{
if (not first) { std::cout << ", "; }
else { first = false; }
std::cout << n;
}
std::cout << "\n\tunits = " << units << ", tens = " << tens << ", hundreds = " << hundreds << "\n";
}
// Outputs:
// v = 123456, 99999, 100
// units = 15, tens = 14, hundreds = 14

C++ Knight moves path

I am working on the knight moves problem and managed to print the number of moves but still need to print the path e.g. "3 moves: path is: [3,3] [4,5] [2,4] [4,3]". I tried to print the Queue but got instead all visited paths. I tried also to work backward to the previous points (function minStepToReachTarget) but i think my novice skill did not help.
i already got the number of moves but is there a function or piece of code that help me print the path?
Best,
James.
#include <bits/stdc++.h>
#include <iostream>
#include <queue>
using namespace std;
// structure for storing a cell's data
class cell {
public:
int x, y;
int dis;
cell() {}
cell(int x, int y, int dis) : x(x), y(y), dis(dis) { }
};
// Utility method returns true if (x, y) lies
// inside Board
bool isInside(int x, int y, int N)
{
if (x >= 1 && x <= N && y >= 1 && y <= N)
return true;
return false;
}
// Method returns minimum step
// to reach target position
int minStepToReachTarget( int knightPos[], int targetPos[], int N)
{
// x and y direction, where a knight can move
int dx[] = { -2, -1, 1, 2, -2, -1, 1, 2 };
int dy[] = { -1, -2, -2, -1, 1, 2, 2, 1 };
// queue for storing states of knight in board
queue<cell> q;
// push starting position of knight with 0 distance
q.push(cell(knightPos[0], knightPos[1], 0));
cell t;
int x, y;
bool visit[N + 1][N + 1];
// make all cell unvisited
for (int i = 1; i <= N; i++)
for (int j = 1; j <= N; j++)
visit[i][j] = false;
// visit starting state
visit[knightPos[0]][knightPos[1]] = true;
// loop until we have one element in queue
while (!q.empty()) {
t = q.front();
q.pop();
// cout << "[" << t.x << " "<< t.y<<"]\n";
// if current cell is equal to target cell,
// return its distance
if (t.x == targetPos[0] && t.y == targetPos[1]) {
// cout << "[" << targetPos[0] << " " << targetPos[1] << "]\n";
return t.dis;
}
// loop for all reachable states
for (int i = 0; i < 8; i++) {
x = t.x + dx[i];
y = t.y + dy[i];
// If reachable state is not yet visited and
// inside board, push that state into queue
if (isInside(x, y, N) && !visit[x][y]) {
visit[x][y] = true;
//** cout << "[" << x << " " << y << "]\n";
q.push(cell(x, y, t.dis + 1));
}
}
}
return t.dis;
}
int main(){
int N = 8, knightPos[2], targetPos[2];
cout <<"=> Enter the current Knight’s location: ";
for (int i = 0; i < 2; i++) std::cin>> knightPos[i];
cout <<"=> Enter the destination location: ";
for (int i = 0; i < 2; i++) std::cin>> targetPos[i];
cout <<"=> You made it in " << minStepToReachTarget(knightPos, targetPos, N) <<
" moves from [" << knightPos[0] <<"," << knightPos[1] << "] "
"to [" << targetPos[0] <<"," << targetPos[1] <<"]! Here is your path: ";
return 0;
/*
=> Enter the current Knight’s location: 3 3
=> Enter the destination location: 4 3
=> You made it in 3 moves from [3,3] to [4,3]! Here is your path:
[3,3] [4,5] [2,4] [4,3]
*/
}
You're doing a breadth-first search on your board. Once your reach your destination, the function minStepToReachTarget has no idea how it got there. What you can do is, for each cell in the queue, keep track of its 'parent', i.e. from which cell it was visited first. Once you've found the target, instead of returning t.dis, you could trace the parents of t and return an array representing the path. t.dis would then be equal to the length of the array minus one, since you include both the starting point and target point in the path.

Tracing the output, could not figure it out even when debugging it?

When calling the function f4 how is the function returning 6? i really cant figure out how the function operates shouldnt it just return 1? because of (n-1)
#include <iostream>
#include<cmath>
#include<fstream>
using namespace std;
int x = 3;
void f1(int, int &);
int f4(int);
int main()
{
int x = 5; int y = 10;
f1(x, y);
cout << x << "\t" << y << endl;
x = 15; y = 20;
f1(x++, x);
cout << x << "\t" << y << endl;
x = 3;
cout << f4(x) << endl;
system("pause");
return 0;
}
void f1(int a, int &b)
{
a *= 2; b += x;
cout << a << "\t" << b << endl;
}
int f4(int n) {
if (n == 1 || n == 0)
return n;
else
return n + f4(n - 1);
}
The f4 function is recursive. This calling with a number other than 1 or 0 will make it recurse. You call it with 3, so the compiler (simplified) sees
f4(3) => 3 + f4(2) => 3 + 2 + f4(1) => 3 + 2 + 1 => 5 + 1 => 6
recursion in a nutshell..
int f4(int n) {
if (n == 1 || n == 0)
return n;
else
return n + f4(n - 1);
}
Your code states that when n is 1 or 0 just return n, otherwise add n to the result of the function.
that sets up a recursive stack where the first call n = 3 and it recurses.
on the next call n = 2 and it recurses.
on the next call n = 1 and it returns as well as the rest of the stack leading to 1 + 2 + 3 which is 6.

feeding hex characters to stringstream

I'm trying to set bits in a binary string. I initially have an empty string which needs to set the give bit(i) in the string(s).
for the given example, the output should be 0x3001 as:
pos: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
bit: 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1
^ ^
MSB LSB
Which, in hex is 3001.
#include<iostream>
#include<string>
#include<sstream>
#include<iomanip>
using namespace std;
void generate_string(string& s,int i){
int sl = s.length();
int x = i/8;
std::stringstream m(s, ios_base::app);
if(sl<x){
for(int j = x-sl;j>=0;j--){
m<<'\x00';
}
}
s = m.str();
s[x] |= 1 << i%8;
}
int main(){
string s = "";
generate_string(s,15);
generate_string(s,2);
generate_string(s,3);
for(int i=0;i<s.length();i++)
cout<<hex<<(int)s[i];
return 0;
}
But this program is not showing any output.
It's actually much more simpler than you think. The only complicated part is to calculate the bit number to be set in the byte.
Oh, and why use a string for this? Why not a vector?
Here's my solution, using std::vector instead:
void set_bit(std::vector<uint8_t>& bits, unsigned bit)
{
static unsigned const bit_count = 8; // Should really use std::numeric_limits<uint8_t>::digits
unsigned index = bit / bit_count;
while (index + 1 > bits.size())
bits.push_back(0);
// Since the bit-numbers are reversed from what's "common",
// we need a little more complex calculation here.
// bit % bit_count to get the "normal" bit number
// bit_count - bit % bit_count to reverse the bit numbering
// Then -1 to get a number between 0 and 7
bits[index] |= 1 << (bit_count - bit % bit_count - 1);
}
You can use a similar solution using std::string too, but I don't see why.
Maybe like this?
#include<iostream>
#include<string>
using namespace std;
void set_bit(string& s,int i){
auto bits = ((i + 7) / 8) * 8;
if (bits > s.length())
{
auto diff = bits - s.length();
s += std::string(diff, '0');
}
s[i] = '1';
}
int main(){
string s;
set_bit(s, 2);
set_bit(s, 3);
set_bit(s, 15);
cout << s << endl;
return 0;
}
expected output:
0011000000000001
update: attempt 2 :-)
#include<iostream>
#include<iomanip>
#include<string>
using namespace std;
void set_bit(string& s,int i){
auto bytes = (i + 7) / 8;
if (bytes > s.length())
{
auto diff = bytes - s.length();
s += std::string(diff, 0);
}
s[i / 8] |= char(1 << (7-(i%8)));
}
int main(){
string s;
set_bit(s, 2);
set_bit(s, 3);
set_bit(s, 15);
std::cout << "as hex: ";
for (auto c : s) {
cout << hex << setfill('0') << setw(2) << (int(c) & 0xff);
}
cout << endl;
std::cout << "as binary: ";
auto sep = "";
for (auto c : s) {
unsigned char bits = c;
for (unsigned char mask = 0x80 ; mask ; mask >>= 1)
{
cout << sep << ((bits & mask) ? '1' : '0');
sep = " ";
}
}
cout << endl;
return 0;
}
expected output:
as hex: 3001
as binary: 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1
I don't quite understand what the output should be in Your problem, because You are mixing most/least signifanct bits with nibbles order in sample input/output, but I You would like to print number in hex as a string You can do sth like this:
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
void feed(std::string& s, int x){
unsigned int mask = 15;
int nibblesInWord = sizeof(void*)*16;
std::stringstream ss;
while(nibblesInWord--){
std::cout << int(x & mask) <<std::endl;
ss << int(x & mask);
x >>= 4;
}
s = ss.str();
std::reverse(s.begin(), s.end());
}
int main(){
std::string s;
feed(s, 99);
std::cout << s <<std::endl;
}