Convert fragmental dynamic allocation into continuous - c++

I should make a function that dynamically allocates two-dimensional array that looks like this (for n=3):
1
2 1 2
3 2 1 2 3
I have written code which works correct. However, I used fragmental dynamic allocation. Could you explain me how could I modify this to use continuous dynamic allocation? Dynamic allocation is new to me, and I'm confused a little bit. Could you give any explanation?
#include <cstdlib>
#include <iostream>
#include <new>
#include <stdexcept>
int **MakeTriangle(int n) {
if (n <= 0)
throw std::domain_error("Number of rows must be positive");
int **mat = nullptr;
mat = new int *[n];
for (int i = 0; i < n; i++)
mat[i] = nullptr;
try {
for (int i = 0; i < n; i++)
mat[i] = new int[2 * i + 1];
for (int i = 0; i < n; i++)
for (int j = 0; j < 2 * i + 1; j++)
mat[i][j] = abs(j - i) + 1;
}
catch (std::bad_alloc) {
for (int i = 0; i < n; i++)
delete[] mat[i];
delete[] mat;
throw std::bad_alloc();
}
return mat;
}
int main() {
std::cout << "How many rows you want: ";
int n;
std::cin >> n;
try {
int **mat = nullptr;
mat = MakeTriangle(n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < 2 * i + 1; j++)
std::cout << mat[i][j] << " ";
std::cout << std::endl;
}
for (int i = 0; i < n; i++)
delete[] mat[i];
delete[] mat;
} catch (const std::bad_alloc e) {
std::cout << "Exception: Not enough memory";
} catch (const std::domain_error e) {
std::cout << "Exception: " << e.what();
}
return 0;
}

You basically have two options. Either you allocate n * (2 * n + 1) elements and waste more or less half of them or allocate the exact number of elements you need for your triangle and be careful when accessing them:
#include <cstddef>
#include <iostream>
int** make_triangle_frag(std::size_t n) {
int** memory = new int*[n];
for (std::size_t i = 0; i < n; ++i) {
std::size_t const count = 2 * i + 1;
memory[i] = new int[count];
for (std::size_t j = 0; j < i + 1; ++j) {
int const val = i - j + 1;
memory[i][j] = val;
memory[i][count - j - 1] = val;
}
}
return memory;
}
int* make_triangle_cont_square(std::size_t n) {
auto const rowCount = 2 * n + 1;
int* memory = new int[n * (2 * n + 1)];
for (std::size_t i = 0; i < n; ++i) {
std::size_t const count = 2 * i + 1;
for (std::size_t j = 0; j < i + 1; ++j) {
int const val = i - j + 1;
memory[rowCount * i + j] = val;
memory[rowCount * i + count - j - 1] = val;
}
}
return memory;
}
std::size_t count_elems(std::size_t n) {
std::size_t count{0};
for (std::size_t i = 0; i != n; ++i) count += 2 * n + 1;
return count;
}
int* make_triangle_cont_tri(std::size_t n) {
auto const elemCount = count_elems(n);
int* memory = new int[elemCount];
std::size_t offset{0};
for (std::size_t i = 0; i < n; ++i) {
std::size_t const count = 2 * i + 1;
for (std::size_t j = 0; j < i + 1; ++j) {
int const val = i - j + 1;
memory[offset + j] = val;
memory[offset + count - j - 1] = val;
}
offset += count;
}
return memory;
}
int main() {
std::size_t const n{10};
{
int** mat = make_triangle_frag(n);
for (std::size_t i = 0; i < n; i++) {
for (std::size_t j = 0; j < 2 * i + 1; j++)
std::cout << mat[i][j] << " ";
std::cout << std::endl;
}
for (int i = 0; i < 10; ++i) delete[] mat[i];
delete[] mat;
}
{
// Cons: You waste more or less half the elements you have allocated.
// Pros: It's still easy to access the elements.
int* mat = make_triangle_cont_square(n);
for (std::size_t i = 0; i < n; i++) {
for (std::size_t j = 0; j < 2 * i + 1; j++)
std::cout << mat[i * (2 * n + 1) + j] << " ";
std::cout << std::endl;
}
delete[] mat;
}
{
// Cons: Accessing the triangle elements becomes tricky.
// Pros: You don't allocate more memory than you need.
int* mat = make_triangle_cont_tri(n);
std::size_t offset{0};
for (std::size_t i = 0; i < n; ++i) {
std::size_t const count = 2 * i + 1;
for (std::size_t j = 0; j < count; j++)
std::cout << mat[offset + j] << " ";
std::cout << '\n';
offset += count;
}
delete[] mat;
}
}
Output:
1
2 1 2
3 2 1 2 3
4 3 2 1 2 3 4
5 4 3 2 1 2 3 4 5
6 5 4 3 2 1 2 3 4 5 6
7 6 5 4 3 2 1 2 3 4 5 6 7
8 7 6 5 4 3 2 1 2 3 4 5 6 7 8
9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9
10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10
1
2 1 2
3 2 1 2 3
4 3 2 1 2 3 4
5 4 3 2 1 2 3 4 5
6 5 4 3 2 1 2 3 4 5 6
7 6 5 4 3 2 1 2 3 4 5 6 7
8 7 6 5 4 3 2 1 2 3 4 5 6 7 8
9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9
10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10
1
2 1 2
3 2 1 2 3
4 3 2 1 2 3 4
5 4 3 2 1 2 3 4 5
6 5 4 3 2 1 2 3 4 5 6
7 6 5 4 3 2 1 2 3 4 5 6 7
8 7 6 5 4 3 2 1 2 3 4 5 6 7 8
9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9
10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10
Please note that you'll have your matrix elements layed out contiguously only in the third case. Here you are what the memory layouts actually look like:
mat[0] -> { 1 }
mat[1] -> { 2, 1, 2 }
mat[2] -> { 3, 2, 1, 2, 3 }
mat { 1, ?, ?, ?, ?, 2, 1, 2, ?, ?, 3, 2, 1, 2, 3 }
mat { 1, 2, 1, 2, 3, 2, 1, 2, 3 }
Note 2: If you really need an int**, you may try this:
int* memory = make_triangle_cont_tri(n);
int** mat = new int*[n];
{
// Init mat
std::size_t offset{0};
for (std::size_t i = 0; i < n; ++i) {
std::size_t const count = 2 * i + 1;
mat[i] = memory + offset;
offset += count;
}
}
for (std::size_t i = 0; i < n; ++i) {
for (std::size_t j = 0; j < 2 * i + 1; j++)
std::cout << mat[i][j] << " ";
std::cout << '\n';
}
delete[] mat;
delete[] memory;
Output:
1
2 1 2
3 2 1 2 3
4 3 2 1 2 3 4
5 4 3 2 1 2 3 4 5
6 5 4 3 2 1 2 3 4 5 6
7 6 5 4 3 2 1 2 3 4 5 6 7
8 7 6 5 4 3 2 1 2 3 4 5 6 7 8
9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9
10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10

Related

Incorrect output in Pascal's triangle program in C++

I was creating a Pascal's triangle program in C++, but the output displayed is not as expected.
Output Expected
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
Output got
1
1 1
1 2 1
1 3 3 1
1 2 2 2 1
1 6 6 6 6 1
Till i = 4, output displayed is correct, but after that I couldn't figure out how it goes wrong. Hers is the source code to get reviewed
int main()
{ int num, a[37680], t = 0, b = 2, l;
cout<<"Enter the number of rows: ";
cin>>num;
for (int i = 1; i <= num; i++)
{
for (int j = 1; j <= (num - i); j++)
{
cout<<" ";
}
for (int k = 1; k <= i; k++)
{
l = k;
if (k == 1 || k == i)
{
a[t] = 1;
cout<<a[t]<<" ";
t+=1;
}
else
{
a[t] = a[t - b] + a[t - b - 1];
cout<<a[t]<<" ";
t+=1;
if ( l = (i - 1) )
{
b+=1;
}
}
}
cout<<endl;
}
return 0;}
Equality checking in c++ is done using == and not =, so:
if(l=(i-1))
Should be:
if(l==(i-1))

left rotation operation in c++

int main()
{
int newposition, shiftSteps;
int numbers[10], numberscopy[10];
cin >> shiftSteps;
for (int i = 0; i < 10; i++)
cin >> numbers[i];
for (int i = 0; i < 10; i++)
numberscopy[i] = numbers[i];
//------------------------------------
for (int i = 9; i >= 0; i--)
{
if (i - shiftSteps < 10 && i - shiftSteps >= 0)
newposition = i - shiftSteps;
else
newposition = i - shiftSteps + 10;
numbers[newposition] = numberscopy[i];
}
for (int i = 0; i < 10; i++)
cout << numbers[i] << " ";
}
I want to rotate 10 numbers to left and "shiftSteps" is number of moves to the left. but I have a problem, the code I wrote so far for some numbers it works properly like {0 1 2 3 4 5 6 7 8 9} and shiftSteps = 3 output is 3 4 5 6 7 8 9 0 1 2.
but if inputs are 0 1 2 3 4 5 6 7 8 9 and shiftSteps = 15, the output is 5 6 7 8 9 5 6 7 8 9 and 0 Disappears, True answer for shiftSteps = 15 is 5 6 7 8 9 0 1 2 3 4.
The problem is that newposition = i - shiftSteps + 10; results in a negative value for shiftSteps == 15 and i < 5. This results in an out-of-bounds access.
You need to ensure that the rotation amount is below the number of elements of the array, which can be achieved with a modulus operator.
shiftSteps = shiftSteps % 10;
for (int i = 9; i >= 0; i--)
{
newposition = i - shiftSteps;
if (newposition < 0)
newposition += 10;
numbers[newposition] = numberscopy[i];
}
This will work for non-negative values of shiftSteps. If you also need to handle negatives, you should adjust the condition in the loop accordingly.
PS: Also, note that in your code shiftSteps is left uninitialized.
PPS: You could also use std::rotate algorithm.

How to write this recursion with loops

I saw the following as an exercise in a website. It basically says write the following function without using recursion and without using structures like vector, stack, etc:
void rec(int n) {
if (n != 0) {
cout << n << " ";
rec(n-1);
rec(n-1);
}
}
At first I thought it was going to be easy, but I'm suprisingly struggling to accomplish it.
To understand it better, I defined it like a math function as the following:
f(x) = {1 if x = 0, f(x-1) + f(x-1) otherwise} (where + operator means concatenation and - is the normal minus)
However, Unrolling this made it harder, and I'm stuck. Is there any direct way to write it as a loop? And also, more generally, is there an algorithm to solve this type of problems?
If you fiddle with it enough, you can get at least one way that will output the ordered sequence without revisiting it :)
let n = 5
// Recursive
let rec_str = ''
function rec(n) {
if (n != 0) {
rec_str += n
rec(n-1);
rec(n-1);
}
}
rec(n)
console.log(rec_str)
// Iterative
function f(n){
let str = ''
for (let i=1; i<1<<n; i++){
let t = i
let p = n
let k = (1 << n) - 1
while (k > 2){
if (t < 2){
break
} else if (t <= k){
t = t - 1
p = p - 1
k = k >> 1
} else {
t = t - k
}
}
str += p
}
console.log(str)
}
f(n)
(The code is building a string, which I think should be disallowed according to the rules, but only for demonstration; we could just output the number instead.)
void loop(int n)
{
int j = 0;
int m = n - 1;
for (int i = 0; i < int(pow(2, n)) - 1; i++)
{
j = i;
if (j == 0)
{
std::cout << n << " ";
continue;
}
m = n - 1;
while (true)
{
if (m == 1)
{
std::cout << m << " ";
m = n - 1;
break;
}
if (j >= int(pow(2, m)))
{
j = j - int(pow(2, m)) + 1;
}
if (j == 1)
{
std::cout << m << " ";
m = n - 1;
break;
}
else
{
j--;
}
m--;
}
}
std::cout << std::endl;
}
For n = 3 for instance
out = [3 2 1 1 2 1 1]
indexes = [0 1 2 3 4 5 6]
Consider the list of indexes; for i > 0 and i <= 2^(m) the index i has the same value as the index i + 2^(m)-1 where m = n - 1. This is true for every n. If you are in the second half of the list, find its correspondent index in the first half by this formula. If the resulting number is 1, the value is m. If not, you are in a lower level of the tree. m = m - 1 and repeat until the index is 1 or m =1, in which case you've reached the end of the tree, print 1.
For instance, with n = 4, this is what happens with all the indexes, at every while step. p(x) means the value x gets printed at that index. A / means that index has already been printed.:
n = 4,m = 3
[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14]
m = 3
[p(n=4) 1 2 3 4 5 6 7 8 9 10 11 12 13 14]
if(i >=2^3) -> i = i -2^3 + 1)
[/ 1 2 3 4 5 6 7 1 2 3 4 5 6 7]
if(i == 1) -> print m, else i = i -1
[/ p(3) 1 2 3 4 5 6 p(3)1 2 3 4 5 6]
m = 2
if (i >=2^2) -> i = i - 2^2 +1
[/ / 1 2 3 1 2 3 / 1 2 3 1 2 3]
if(i == 1) -> print m, else i = i -1
[ / / p(2) 1 2 p(2) 1 2 / p(2) 1 2 p(2) 1 2]
m = 1
if (m == 1) -> print(m)
[ / / / p(1) p(1) / p(1) p(1) / / p(1) p(1) / p(1) p(1)]
Therefore the result is:
[4 3 2 1 1 2 1 1 3 2 1 1 2 1 1]
void via_loop(int n) {
string prev = "1 ", ans = "1 ";
for (int i = 2; i <= n; i++) {
ans = to_string(i) + " " + prev + prev;
prev = ans;
}
cout << ans;
}
Idea is to save result from the previous computation of each number. Full code:
void rec(int n) {
if (n != 0) {
cout << n << " ";
rec(n-1);
rec(n-1);
}
}
void via_loop(int n) {
string prev = "1 ", ans = "1 ";
for (int i = 2; i <= n; i++) {
ans = to_string(i) + " " + prev + prev;
prev = ans;
}
cout << ans;
}
int main() {
int n = 5;
cout << "Rec : ";
rec(n);
cout << endl;
cout << "Loop: ";
via_loop(n);
cout << endl;
}
Output:
Rec : 5 4 3 2 1 1 2 1 1 3 2 1 1 2 1 1 4 3 2 1 1 2 1 1 3 2 1 1 2 1 1
Loop: 5 4 3 2 1 1 2 1 1 3 2 1 1 2 1 1 4 3 2 1 1 2 1 1 3 2 1 1 2 1 1

Eigen indexing, update all column of a specific row

Let say I have an ArrayXXf (or MatrixXf) m. In each iteration of a for loop, I want to fill m row-wise with a VectorXf.
Eigen::ArrayXXf m(5, 5);
for (int i = 0; i < 5; i++)
{
Eigen::VectorXf vec(5);
vec << i, i + 1, i + 2, i+3, i+4;
//fill m row wise
// in matlab I will do something like m(i,:) = vec;
// in numpy this will looks like m[i:] = vec;
// that means when i is 0 m looks like
// [ 0 1 2 3 4 5
// - - - - - -
// - - - - - -
// - - - - - -
// - - - - - -]
}
How can I achieve that in Eigen?
To simplify #Kunal's answer, you can directly modify rows (or columns) of an Array (or Matrix) without creating a temporary vector. In your example you can use .setLinSpaced():
Eigen::ArrayXXf m(5, 5);
for (int i = 0; i < 5; i++) {
m.row(i).setLinSpaced(i,i+4); //.col(i) would be slightly more efficient
}
or use the comma initializer:
for (int i = 0; i < 5; i++) {
m.row(i) << i, i+1, i+2, i+3, i+4;
}
Use block() function.
#include <iostream>
#include <Eigen/Dense>
using namespace std;
int main()
{
Eigen::ArrayXXf m(5, 5);
for (int i = 0; i < 5; i++) {
Eigen::VectorXf vec(5);
vec << i, i + 1, i + 2, i+3, i+4;
m.block(i, 0, 1, 5) << vec.transpose();
}
std::cout << m << std::endl;
return 0;
}
Output:
0 1 2 3 4
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
Edit:
There is one simpler alternative also: row() function.
#include <iostream>
#include <Eigen/Dense>
using namespace std;
int main()
{
Eigen::ArrayXXf m(5, 5);
for (int i = 0; i < 5; i++) {
Eigen::VectorXf vec(5);
vec << i, i + 1, i + 2, i+3, i+4;
m.row(i) = vec.transpose();
}
std::cout << m << std::endl;
return 0;
}
Output:
0 1 2 3 4
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
P.S. transpose() is required because Eigen::VectorXf by default is a column vector, not a row vector.

I can't figure out a sum and numbers solution

I am not that skilled or advanced in C++ and I have trouble solving a problem.
I know how to do it mathematically but I can't write the source code, my algorithm is wrong and messy.
So, the problem is that I have to write a code that reads a number ( n ) from the keyboard and then it has to find a sum that is equal to n squared ( n ^ 2 ) and the number of sum's elements has to be equal to n.
For example 3^2 = 9, 3^2 = 2 + 3 + 4, 3 elements and 3^2 is 9 = 2 + 3 + 4.
I had several attempts but none of them were successful.
I know I'm borderline stupid but at least I tried.
If anyone has the time to look over this problem and is willing to help me I'd be very thankful.
1
#include <iostream>
#include <list>
#include <algorithm>
using namespace std;
int main()
{
//1,3,5,7,9,11,13,15,17,19,21,23,25,27..
int n;
list<int> l;
cin >> n;
if ( n % 2 == 0 ){
cout << "Wrong." << endl;
}
for ( int i = 1; i <= 99;i+=2){
l.push_back(i);
}
//List is full with 1,3,5,7,9,11,13,15,17,19,21,23,25,27..
list<int>::iterator it = find(begin(l),end(l), n);
}
2
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int main()
{
// 3^2 = 2 + 3 + 4
// 7^2 = 4 + 5 + 6 + 7 + 8 + 9 + 10
int n;
int numbers[100];
for (int i = 0; i <= 100; i++){
numbers[i] = i;
}
cin >> n;
int requiredSum;
requiredSum = n * n;
//while(sum < requiredSum){
// for(int i = 1; i < requiredSum; i++){
// sum += i;
// sumnums.push_back(sum);
// }
//}
int sum = 0;
std::vector<int> sumnums;
while(sum < requiredSum){
for(int i = 1; i < requiredSum; i++){
sum += i;
sumnums.push_back(sum);
}
}
for(int i=0; i<sumnums.size(); ++i)
std::cout << sumnums[i] << ' ';
}
Update:
The numbers of the sum have to be consecutive numbers.Like 3 * 3 has to be equal to 2 + 3 + 4 not 3 + 3 + 3.
So, my first try was that I found a rule for each sum.
Like 3 * 3 = 2 + 3 + 4, 5 * 5 = 3 + 4 + 5 + 6 + 7, 7 * 7 = 4 + 5 + 6 + 7 + 8 + 9 + 10.
Every sum starts with the second element of the previous sum and continues for a number of elements equal to n - 1, like 3 * 3 = 2 + 3 + 4, 5 * 5 , the sum for 5 * 5 starts with 3 + another 4 elements.
And another algorithm would be #molbdnilo 's, like 3 * 3 = 3 + 3 + 3 = 3 + 3 + 3 - 1 + 1, 3 * 3 = ( 3 - 1 ) + 3 + ( 3 + 1 ), but then 5 * 5 = (5 - 2) + ( 5 - 1 ) + 5 + 5 + 1 + 5 + 2
Let's do a few special cases by hand.
(The division here is integer division.)
3^2: 9
2 + 3 + 4 = 9
x-1 x x+1
1 is 3/2
5: 25
3 + 4 + 5 + 6 + 7 = 25
x-2 x-1 x x+1 x+2
2 is 5/2
7: 49
4 + 5 + 6 + 7 + 8 + 9 + 10
x-3 x-2 x-1 x x+1 x+2 x+3
3 is 7/2
It appears that we're looking for the sequence from n - n / 2 to n + n / 2.
(Or, equivalently, n / 2 + 1 to n / 2 + n, but I like symmetry.)
Assuming that this is correct (the proof left as an exercise ;-):
int main()
{
int n = 0;
std::cin >> n;
if (n % 2 == 0)
{
std::cout << "Must be odd\n";
return -1;
}
int delta = n / 2;
for (int i = n - delta; i <= n + delta; i++)
{
std::cout << i << " ";
}
std::cout << std::endl;
}
If there is not constraints on what are the elements forming the sum, the simplest solution is just to sum up the number n, n times, which is always n^2.
int main()
{
int n;
cout<<"Enter n: ";
cin >> n;
for(int i=0; i<n-1; i++){
cout<<n<<"+";
}
cout<<n<<"="<<(n*n);
return 0;
}
Firstly, better use std::vector<> than std::list<>, at least while you have less than ~million elements (it will be faster, because of inside structure of the containers).
Secondly, prefer ++i usage, instead of, i++. Specially in situation like that
...for(int i = 1; i < requiredSum; i++)...
Take a look over here
Finally,
the only error you had that you were simply pushing new numbers inside container (std::list, std::vector, etc.) instead of summing them, so
while(sum < requiredSum){
for(int i = 1; i < requiredSum; i++){
sum += i;
sumnums.push_back(sum);
}
change to
// will count our numbers
amountOfNumbers = 1;
while(sum < requiredSum && amountOfNumber < n)
{
sum += amountOfNumbers;
++amountOfNumbers;
}
// we should make -1 to our amount
--amountOfNumber;
// now let's check our requirements...
if(sum == requiredSum && amountOfNumbers == n)
{
cout << "Got it!";
// you can easily cout them, if you wish, because you have amountOfNumbers.
// implementation of that I am leaving for you, because it is not hard ;)
}
else
{
cout << "Damn it!;
}
I assumed that you need sequential sum of numbers that starts from 1 and equals to n*n and their amount equils to n.
If something wrong or need explanation, please, do not hesitate to contact me.
Upd. amountOfNumber < n intead <=
Also, regarding "not starting from 1". You said that you know how do it on paper, than could you provide your algorithm, then we can better understand your problem.
Upd.#2: Correct and simple answer.
Sorry for such a long answer. I came up with a great and simple solution.
Your condition requires this equation x+(x+1)+(x+2)+... = n*n to be true then we can easily find a solution.
nx+ArPrg = nn, where is
ArPrg - Arithmetic progression (ArPrg = ((n-1)*(1+n-1))/2)
After some manipulation with only unknown variable x, our final equation will be
#include <iostream>
int main()
{
int n;
std::cout << "Enter x: ";
std::cin >> n;
auto squareOfN = n * n;
if (n % 2 == 0)
{
std::cout << "Can't count this.\n";
}
auto x = n - (n - 1) / 2;
std::cout << "Our numbers: ";
for (int i = 0; i < n; ++i)
std::cout << x + i << " ";
return 0;
}
Math is cool :)