I decide 2D Dinamic Coding on C++, i'm decide task about count of ways to bottom-right field in table, and my program return %. Why?
Program:
#include <iostream>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
int arr[n][m];
for (int i = 0; i < n; i++)
arr[i][0] = 1;
for (int i = 0; i < m; i++)
arr[0][i] = 1;
for (int i = 1; i < n; i++) {
for (int j = 1; j < m; j++)
arr[i][j] = arr[i-1][j] + arr[i][j-1];
}
cout << arr[n-1][m-1];
}
I would like answer
Request:
1 10
Response:
1
Your program has undefined behavior for any other sizes than n = 1 and m = 1 because you leave the non-standard VLA (variable length array) arr's positions outside arr[0][0] uninitialized and later read from those positions. If you want to continue using these non-standard VLA:s, you need to initialize them after constructing them. Example:
#include <cstring> // std::memset
// ...
int arr[n][m];
std::memset(arr, 0, sizeof arr); // zero out the memory
// ...
Another approach that would both make it initialized and be compliant with standard C++ would be to use std::vectors instead:
#include <vector>
// ...
std::vector<std::vector<int>> arr(n, std::vector<int>(m));
// ...
A slightly more cumbersome approach is to store the data in a 1D vector inside a class and provide methods of accessing the data as if it was stored in a 2D matrix. A class letting you store arbitrary number of dimensions could look something like below:
#include <utility>
#include <vector>
template <class T, size_t Dim> // number of dimensions as a template parameter
class matrix {
public:
template <class... Args>
matrix(size_t s, Args&&... sizes) // sizes of all dimensions
: m_data(s * (... * sizes)), // allocate the total amount of data
m_sizes{s, static_cast<size_t>(sizes)...}, // store sizes
m_muls{static_cast<size_t>(sizes)..., 1} // and multipliers
{
static_assert(sizeof...(Args) + 1 == Dim);
for (size_t i = Dim - 1; i--;)
m_muls[i] *= m_muls[i + 1]; // calculate dimensional multipliers
}
template <size_t D> size_t size() const { return m_sizes[D]; }
size_t size(size_t D) const { return m_sizes[D]; }
// access the data using (y,z) instead of [y][x]
template <class... Args>
T& operator()(Args&&... indices) {
static_assert(sizeof...(Args) == Dim);
return op_impl(std::make_index_sequence<Dim>{}, indices...);
}
private:
template <std::size_t... I, class... Args>
T& op_impl(std::index_sequence<I...>, Args&&... indices) {
return m_data[(... + (indices * m_muls[I]))];
}
std::vector<T> m_data;
size_t m_sizes[Dim];
size_t m_muls[Dim];
};
With such a wrapper, you'd only need to change the implementation slightly:
#include <iostream>
int main() {
int n, m;
if(!(std::cin >> n >> m && n > 0 && m > 0)) return 1;
matrix<int, 2> arr(n, m);
for (int i = 0; i < arr.size<0>(); i++)
arr(i, 0) = 1;
for (int i = 0; i < arr.size<1>(); i++)
arr(0, i) = 1;
for (int i = 1; i < n; i++) {
for (int j = 1; j < m; j++)
arr(i, j) = arr(i - 1, j) + arr(i, j - 1);
}
std::cout << arr(n - 1, m - 1) << '\n';
}
Related
I have a template that uses a three-dimensional array to find the maximum. The crux of the problem is that this template must find the maximum in a one-dimensional array. We add a question with a char variable, if question = '1' = three-dimensional, if 2, then one-dimensional.
l need use template T2 for one dimensional and thee dimensional it depends of question(char)
T2 maxShablon2(T2 ***arr, const int n) {
int max = arr[0][0][0];
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
for (int k = 0; k < n; ++k) {
if (arr[i][j][k] > max) {
max = arr[i][j][k];
}
}
}
}
cout << " Our max: " << max;
}
template<std::size_t N>
using count = std::integral_constant<std::size_t, N>;
template<class T>
constexpr T maxOver( count<0> unused, T t, int n ) {
return t;
}
template<std::size_t depth, class Ptr>
constexpr auto maxOver( count<depth>, Ptr* t, int n ) {
auto max = maxOver( count<depth-1>{}, t[0], n );
for (int i = 1; i < n; ++i) {
auto candidate = maxOver( count<depth-1>{}, t[i], n );
if (candidate > max)
max = candidate;
}
return max;
}
now,
constexpr int arr[100] = {1,2,3,0};
constexpr int arr_max = maxOver( count<1>{}, arr, 100 );
static_assert(arr_max == 3);
constexpr int arr3[5][5][5] = {{{1,-1,7},{2,3,4}},{{3},{4,5,9}}};
constexpr int arr3_max = maxOver( count<3>{}, arr3, 5 );
static_assert(arr3_max == 9);
passes (Live example).
I have a piece of code as follows, and the number of for loops is determined by n which is known at compile time. Each for loop iterates over the values 0 and 1. Currently, my code looks something like this
for(int in=0;in<2;in++){
for(int in_1=0;in_1<2;in_1++){
for(int in_2=0;in_2<2;in_2++){
// ... n times
for(int i2=0;i2<2;i2++){
for(int i1=0;i1<2;i1++){
d[in][in_1][in_2]...[i2][i1] =updown(in)+updown(in_1)+...+updown(i1);
}
}
// ...
}
}
}
Now my question is whether one can write it in a more compact form.
The n bits in_k can be interpreted as the representation of one integer less than 2^n.
This allows easily to work with a 1-D array (vector) d[.].
In practice, an interger j corresponds to
j = in[0] + 2*in[1] + ... + 2^n-1*in[n-1]
Moreover, a direct implementation is O(NlogN). (N = 2^n)
A recursive solution is possible, for example using
f(val, n) = updown(val%2) + f(val/2, n-1) and f(val, 0) = 0.
This would correspond to a O(N) complexity, at the condition to introduce memoization, not implemented here.
Result:
0 : 0
1 : 1
2 : 1
3 : 2
4 : 1
5 : 2
6 : 2
7 : 3
8 : 1
9 : 2
10 : 2
11 : 3
12 : 2
13 : 3
14 : 3
15 : 4
#include <iostream>
#include <vector>
int up_down (int b) {
if (b) return 1;
return 0;
}
int f(int val, int n) {
if (n < 0) return 0;
return up_down (val%2) + f(val/2, n-1);
}
int main() {
const int n = 4;
int size = 1;
for (int i = 0; i < n; ++i) size *= 2;
std::vector<int> d(size, 0);
for (int i = 0; i < size; ++i) {
d[i] = f(i, n);
}
for (int i = 0; i < size; ++i) {
std::cout << i << " : " << d[i] << '\n';
}
return 0;
}
As mentioned above, the recursive approach allows a O(N) complexity, at the condition to implement memoization.
Another possibility is to use a simple iterative approach, in order to get this O(N) complexity.
(here N represents to total number of data)
#include <iostream>
#include <vector>
int up_down (int b) {
if (b) return 1;
return 0;
}
int main() {
const int n = 4;
int size = 1;
for (int i = 0; i < n; ++i) size *= 2;
std::vector<int> d(size, 0);
int size_block = 1;
for (int i = 0; i < n; ++i) {
for (int j = size_block-1; j >= 0; --j) {
d[2*j+1] = d[j] + up_down(1);
d[2*j] = d[j] + up_down(0);
}
size_block *= 2;
}
for (int i = 0; i < size; ++i) {
std::cout << i << " : " << d[i] << '\n';
}
return 0;
}
You can refactor your code slightly like this:
for(int in=0;in<2;in++) {
auto& dn = d[in];
auto updown_n = updown(in);
for(int in_1=0;in_1<2;in_1++) {
// dn_1 == d[in][in_1]
auto& dn_1 = dn[in_1];
// updown_n_1 == updown(in)+updown(in_1)
auto updown_n_1 = updown_n + updown(in_1);
for(int in_2=0;in_2<2;in_2++) {
// dn_2 == d[in][in_1][in_2]
auto& dn_2 = dn_1[in_2];
// updown_n_2 == updown(in)+updown(in_1)+updown(in_2)
auto updown_n_2 = updown_n_1 + updown(in_2);
.
.
.
for(int i2=0;i2<2;i1++) {
// d2 == d[in][in_1][in_2]...[i2]
auto& d2 = d3[i2];
// updown_2 = updown(in)+updown(in_1)+updown(in_2)+...+updown(i2)
auto updown_2 = updown_3 + updown(i2);
for(int i1=0;i1<2;i1++) {
// d1 == d[in][in_1][in_2]...[i2][i1]
auto& d1 = d2[i1];
// updown_1 = updown(in)+updown(in_1)+updown(in_2)+...+updown(i2)+updown(i1)
auto updown_1 = updown_2 + updown(i1);
// d[in][in_1][in_2]...[i2][i1] = updown(in)+updown(in_1)+...+updown(i1);
d1 = updown_1;
}
}
}
}
}
And make this into a recursive function now:
template<std::size_t N, typename T>
void loop(T& d) {
for (int i = 0; i < 2; ++i) {
loop<N-1>(d[i], updown(i));
}
}
template<std::size_t N, typename T, typename U>
typename std::enable_if<N != 0>::type loop(T& d, U updown_result) {
for (int i = 0; i < 2; ++i) {
loop<N-1>(d[i], updown_result + updown(i));
}
}
template<std::size_t N, typename T, typename U>
typename std::enable_if<N == 0>::type loop(T& d, U updown_result) {
d = updown_result;
}
If your type is int d[2][2][2]...[2][2]; or int*****... d;, you can also stop when the type isn't an array or pointer instead of manually specifying N (or change for whatever the type of d[0][0][0]...[0][0] is)
Here's a version that does that with a recursive lambda:
auto loop = [](auto& self, auto& d, auto updown_result) -> void {
using d_t = typename std::remove_cv<typename std::remove_reference<decltype(d)>::type>::type;
if constexpr (!std::is_array<d_t>::value && !std::is_pointer<d_t>::value) {
// Last level of nesting
d = updown_result;
} else {
for (int i = 0; i < 2; ++i) {
self(self, d[i], updown_result + updown(i));
}
}
};
for (int i = 0; i < 2; ++i) {
loop(loop, d[i], updown(i));
}
I am assuming that it is a multi-dimensional matrix. You may have to solve it mathematically first and then write the respective equations in the program.
Minutes ago, I was pracitise trival algorithm problem. The codes below(concrete logic of the algorithm problem is not importnant, so all we need to know is codes above main function are just TMP):
#include <array>
#include <algorithm>
#include <iterator>
#include <iostream>
constexpr int digit_in_ones[10] = { 6, 2, 5, 5, 4, 5, 6, 3, 7, 6 };
constexpr int createOneD(int index);
template<int ...>
struct seq
{
};
template<int A, int ...B>
struct gens : gens<A - 1, A - 1, B...>
{
};
template<int ...S>
struct gens<0, S ...>
{
typedef seq<S...> type;
};
template<int N>
class oneDArrayMaker
{
private:
typedef typename gens<N>::type sequence;
template<int ...S>
static constexpr std::array<int, N> make(seq<S ...>)
{
return std::array<int, N>{ {createOneD(S)...}};
}
public:
static constexpr std::array<int, N> oneDArr = make(sequence());
};
template<int N>
constexpr std::array<int, N> oneDArrayMaker<N>::oneDArr;
constexpr int createOneD(int index)
{
return index < 10 ?
digit_in_ones[index] :
digit_in_ones[(index % 100) / 10] + digit_in_ones[index % 10] +
(index >= 100 ? digit_in_ones[index / 100] : 0);
}
int main()
{
int n{}, ans{};
scanf("%d", &n);
for (int i = 0; i < 800; i++)
{
for (int j = 0; j < 800; j++)
{
auto temp = oneDArrayMaker<800>::oneDArr[i] + oneDArrayMaker<800>::oneDArr[j] + (i+j < 800 ? oneDArrayMaker<800>::oneDArr[i+j] : 100) + 4;
if (temp == n)
{
ans++;
}
}
}
printf("%d", ans);
}
I knew loop and if(exclude constexpr function and if constexpr) are run-time, not compile time. So tricks like template specialization are substations for if and loop. I learned a lesson about silly usage of if in template programming from this article-
Compile Time Loops with C++11 - Creating a Generalized static_for Implementation, here the codes:
#include <iostream>
template<int index> void do_stuff()
{
std::cout << index << std::endl;
}
template<int max_index, int index = 0> void stuff_helper()
{
if (index <= max_index)
{
do_stuff<index>();
stuff_helper<max_index, index + 1>();
}
}
int main()
{
stuff_helper<100>();
return 0;
}
author's explanation:
On the surface, it could look like the if statement would be responsible for terminating the recursion, like how this would work with a "normal" run-time based recursion algorithm. But that's the problem. What works at runtime doesn't work at compile time.
This is an infinite loop, and only stops because compilers limit themselves to a certain recursion depth. In clang, I get an error fatal error: recursive template instantiation exceeded maximum depth of 256. You can expect a similar error with your compiler of choice.
Oops..., I just state what I have known...
Finally, it comes to my question:
Now that templates's instantiation(specifically, two-parses) is at compile time. So all templates instantiation in the toppest codes should be at compile time:
for (int i = 0; i < 800; i++)
{
for (int j = 0; j < 800; j++)
{
auto temp = oneDArrayMaker<800>::oneDArr[i] + ... // 800 * 800 instantiations should be deternimated at compile time
...
}
...
}
As we known
1. the two for loop here is runtime ahthough it is out of template function/class's definition and just in main function.
2. every auto temp = oneDArrayMaker<800>::oneDArr[i] + ... should be initializated at compile time, so 800 * 800 instantiations should be deternimated at compile time.
Q1: Is runtime loop in main function confliced with 799*799 compile-time template initializations?
My assumption: At compile time, compiler know the depth of the loop, so just unroll the loops, which there is no loop at runtime.
But I maintain that the two loops(i and j) can also not be deternimated at runtime, I change main function to:
int main()
{
int n{}, ans{}, i{}, j{};
scanf("%d", &n);
scanf("%d %d", &i, &j);
std::cout << n << " " << i << " " << j << std::endl;
for (; i < 800; i++)
{
for (; j < 800; j++)
{
auto temp = oneDArrayMaker<800>::oneDArr[i] + oneDArrayMaker<800>::oneDArr[j] + (i+j < 800 ? oneDArrayMaker<800>::oneDArr[i+j] : 100) + 4;
if (temp == n)
{
ans++;
}
}
}
printf("%d", ans);
}
Now i and j have to be deternimated at runtime because of scanf. I just pass extra two 0 to stdin.
Here is live example after alter main function, and output is 12(the right answer is 128)
It compile successfully and no warning is generated. What confuses me is the output is different from the original codes(live code, whose output is 128(equal to the rigth answer).
After dubug, I find the key is after altering codes, for (; i < 800; i++) is only excuate once i = 0, whereas it should have excauted 1~799, that's the reason for 12, not 128.
Q2: If depth of for loop cannot be deternimated at runtime and TMP codes live in loops, what will happen?
Q3: How to explain the output 12
Update:
Q3 has been resolved by #Scott Brown, I'm so careless.
Q1 and Q2 still confuses me
You forget to reset j before 'for (; j < 800; j++)'.
int main()
{
int n{}, ans{}, i{}, j{};
scanf("%d", &n);
scanf("%d %d", &i, &j);
std::cout << n << " " << i << " " << j << std::endl;
int j_orig = j;// here
for (; i < 800; i++)
{
j = j_orig;// and here
for (; j < 800; j++)
{
auto temp = oneDArrayMaker<800>::oneDArr[i] + oneDArrayMaker<800>::oneDArr[j] + (i+j < 800 ? oneDArrayMaker<800>::oneDArr[i+j] : 100) + 4;
if (temp == n)
{
ans++;
}
}
}
printf("%d", ans);
}
I have a Matrix template class and I need a function to set it's elements with variable number of args.
I should be able to call it like this:
aghMatrix<string> matrix;
matrix.setItems(2, 3, "torzmiae", "jestdnaci", "tablickore", "wyrazobed", "oelmntai", "rozmiaecy");
Where first integer is rows number, second is columns and rest (R * C) arguments are elements that I should put into matrix.
It should work with any data types, not only primitive ones.
For now, my function looks like this:
template<typename T>
template<typename... ARGS>
void aghMatrix<T>::setItems(const int rows, const int cols, ARGS... args) {
array<T, sizeof...(args)>unpacked_args {args...};
int row = 0;
int col = 0;
for (T arg : unpacked_args)
{
this->matrixPtr[row][col] = arg;
col++;
if (col == this->cols) {
row++;
col = 0;
}
}
return;
}
I assumed my matrix object is able to hold all elements. It does compile with many warnings about casting everything to unsigned int, but the program doesn't work anyway (it freezes on start).
Class declaration:
template<typename T>
class aghMatrix {
public:
[...]
template<typename... ARGS> void setItems(const int rows, const int cols, ARGS... args);
[...]
private:
T **matrixPtr;
int rows;
int cols;
void createMatrix(const int row, const int col);
bool checkRowCol(const int row, const int col) const;
};
Github project
EDIT: Oops! I just noticed you said "non recursive," so I presume the following pattern doesn't work for you. I'll still leave it hanging here for now, but I have provided also a non recursive solution below (which is based on va_list and hence only works with POD types)
If I understand correctly what you want to do, then you probably want the recursive variadic argument unpacking pattern; something like this seems to do the trick...
#include <iostream>
using namespace std;
// Helper for build_matrix, taking zero variadic arguments.
// This serves as the termination in the recursive unpacking of the args.
template<typename T>
void build_matrix_helper(T**, size_t, size_t, size_t, size_t) { return; }
// Helper for build_matrix, taking at least one variadic argument.
template <typename T, typename ...ARGS>
void build_matrix_helper(T** matrix, size_t curr_row, size_t curr_col,
size_t row, size_t col, const T& first, ARGS...rest) {
if (curr_col < col) {
matrix[curr_row][curr_col] = first;
++curr_col;
return build_matrix_helper<T>(matrix, curr_row, curr_col, row, col, rest...);
}
else {
++curr_row;
curr_col = 0;
return build_matrix_helper<T>(matrix, curr_row, curr_col, row, col, first, rest...);
}
return;
}
// Bare bones implementation.
template<typename T, typename ...ARGS>
T **build_matrix(size_t row, size_t col, ARGS...elements) {
T **new_mat = new T*[row];
for (size_t j = 0; j < row; ++j)
new_mat[j] = new T[col];
build_matrix_helper<T>(new_mat, 0, 0, row, col, elements...);
return new_mat;
}
int main() {
int **nm = build_matrix<int>(2, 3, 1, 2, 3, 4, 5, 6);
for (size_t i = 0; i < 2; ++i) {
cout << "[" << i + 1 << "]: ";
for (size_t j = 0; j < 3; ++j)
cout << nm[i][j] << " ";
cout << endl;
}
delete[] nm;
return 0;
}
In general, you want to avoid any direct manipulation of memory as much as possible. Also avoid as much as possible any casting voodoo unless you absolutely need it (which also ties in with direct memory manipulation).
Anyway, can use a non recursive solution below, using std::va_list.
NOTE Since this uses va_list, it does not work with non POD types.
#include <iostream>
#include <cstdarg>
using namespace std;
template <typename T>
T **build_matrix(size_t row, size_t col, ...) {
va_list args;
T **matrix = new T*[row];
va_start(args, col);
for (size_t i = 0; i < row; ++i) {
matrix[i] = new T[col];
for (size_t j = 0; j < col; ++j)
matrix[i][j] = va_arg(args, T);
}
va_end(args);
return matrix;
}
int main() {
int **nm = build_matrix<int>(2, 3, 1, 2, 3, 4, 5, 6);
for (size_t i = 0; i < 2; ++i) {
cout << "[" << i + 1 << "]: ";
for (size_t j = 0; j < 3; ++j)
cout << nm[i][j] << " ";
cout << endl;
}
delete[] nm;
return 0;
}
EDIT Initializer lists
As has been suggested in the comments to your OP, it is better to use initializer lists. I know this isn't what you asked for originally, but maybe it's worth considering:
#include <iostream>
#include <stdexcept>
using namespace std;
template <typename T>
T **build_matrix(size_t row, size_t col, initializer_list<T> il) {
if (il.size() != row*col)
throw out_of_range("Number of elements does not match matrix dimensions!");
size_t curr_row = 0;
size_t curr_col = 0;
T **nm = new T*[row];
nm[0] = new T[col];
for (T elm : il) {
if (curr_col == col) {
++curr_row;
nm[curr_row] = new T[col];
curr_col = 0;
}
nm[curr_row][curr_col] = elm;
++curr_col;
}
return nm;
}
int main() {
int **nm = build_matrix<int>(2, 3, {1, 2, 3, 4, 5, 6});
for (size_t i = 0; i < 2; ++i) {
cout << "[" << i + 1 << "]: ";
for (size_t j = 0; j < 3; ++j)
cout << nm[i][j] << " ";
cout << endl;
}
delete[] nm;
return 0;
}
There are two files:
Matrix.hpp:
template <typename T>
class Matrix {
private:
size_t rows = 0;
size_t cols = 0;
T* data = nullptr;
public:
Matrix() = default;
~Matrix();
Matrix(size_t n, size_t m);
T& operator() (size_t i, size_t j);
};
template <typename T>
Matrix<T>::Matrix(size_t n, size_t m) : rows(n), cols(m) {
try {
data = new T[rows*cols];
} catch (const std::bad_alloc& e) {
std::exit(EXIT_FAILURE);
}
};
template <typename T>
Matrix<T>::~Matrix() {
delete[] data;
}
template <typename T>
T& Matrix<T>::operator()(size_t i, size_t j) {
if (i < rows && i >= 0 && j < cols && j >= 0) {
return data[(i+1)*cols + (j+1)];
} else {
throw std::logic_error("matrix indices out of range");
}
}
and
Main.cpp:
#include <iostream>
#include "Matrix.hpp"
int main() {
size_t n, k;
std::cin >> n >> k;
Matrix<long double> m = {n, k};
for (size_t i = 0; i < m.getNumRows(); ++i) {
for (size_t j = 0; j < m.getNumCols(); ++j) {
std::cin >> m(i,j);
}
}
for (size_t i = 0; i < m.getNumRows(); ++i) {
std::cout << "\n";
for (size_t j = 0; j < m.getNumCols(); ++j) {
std::cout << m(i, j) << " ";
}
}
return 0;
}
When I'm entering something like:
1 2 3 4
I can get
3 4
as answer but sometimes the same input causes Segmentation fault 11 moreover when I'm changing template argument from long double to int, error disappears. How can I fix it?
Your operator function is accessing data outside its bounds.
Passing (0,0) to the function should return data[0]. Currently it returns data[2].
Change line
return data[(i+1)*cols+(j+1)];
to
return data[i*cols+j];