What I am trying to achieve is this:
I have an image and I need to split it into sub blocks of 16x16 and I am working on the algorithm for this. For testing purposes though, I am using a small matrix:
A = {1, 2, 3, 4}
Now what I want to end up is this: 2 blocks containing:
A[1] = {1 2};
A[2] = {3, 4};
I have tried to use the following:
double matrix[4] = {1, 2, 3, 4};
for(int i = 0; (i < 4); i++)
{
for(unsigned j=i; (j < 2); j +=2)
{
std::cout << j << ' ';
}
std::cout << std::endl;
}
My thought process was to loop through the entire array (4) and then increment by 2 each time to create the 1x2 block. This did not work however.
Where am I going wrong here?
Something like that? (Does both output and assignment)
int LEN = 4;
int INNER = 2;
int OUTER_LEN = LEN/INNER_LEN;
double matrix[LEN] = {1, 2, 3, 4};
double* matrix2[OUTER_LEN];
for(int i = 0; i < OUTER_LEN; i++)
{
matrix2[i] = &matrix[i*INNER_LEN];
for(unsigned j=0; j < INNER_LEN; j++)
{
std::cout << matrix[i*INNER_LEN+j] << ' ';
}
std::cout << std::endl;
}
Just for output you could do something like that:
#include <iostream>
int main(){
const size_t SIZE = 4;
const size_t PART_SIZE = 2;
double matrix[4] = {1, 2, 3, 4};
for(int i = 0; (i < SIZE); i += PART_SIZE)
{
for(size_t j = i; (j < i + PART_SIZE) && j < SIZE; j += 1)
{
std::cout << matrix[j] << ' ';
}
std::cout << std::endl;
}
}
To add another matrix:
#include <iostream>
int main(){
const size_t SIZE = 4;
const size_t PART_SIZE = 2;
size_t partsNumber = SIZE / PART_SIZE; // Beware of SIZE that is not divisible by PART_SIZE - partsNumber will be too small
double matrix[4] = { 1, 2, 3, 4 };
// To do it properly I should make it dynamic array with size of partsNumber instead of the 2 literals
double parts_matrix[2][PART_SIZE];
for (int i = 0; (i < SIZE); i += PART_SIZE) {
for (size_t j = i; (j < i + PART_SIZE) && j < SIZE; j += 1) {
std::cout << matrix[j] << ' ';
parts_matrix[j / partsNumber][j % PART_SIZE] = matrix[j];
}
std::cout << std::endl;
}
std::cout << parts_matrix[0][0] << " " << parts_matrix[0][1] << std::endl << parts_matrix[1][0] << " " << parts_matrix[1][1]; // Check if it works
}
The following is a demo of how to do the splitting for custom block size (rough cut though, corner cases and input verification are ommited) using boost range and the boost::slice functionality (here "output creation" is presented)
#include <iterator>
#include <iostream>
#include <boost/range/adaptor/sliced.hpp>
#include <boost/range/algorithm/copy.hpp>
using namespace std;
using namespace boost::adaptors;
template<typename T, size_t N>
void split(T (&input)[N], size_t block_size)
{
for (size_t i(0); i <= N-block_size; i += block_size)
{
cout << "{ ";
boost::copy(input | sliced(i, i+block_size),
std::ostream_iterator<int>(std::cout, " "));
cout << "}\n";
}
}
int main()
{
int A[] = {1, 2, 3, 4};
split(A, 2);
}
Demo
Output
{ 1 2 }
{ 3 4 }
What if I don't want to do output
To some the following may look more readable
template<typename T, size_t N>
void split(T (&input)[N], size_t block_size)
{
for (size_t i(0); i <= N-block_size; i += block_size)
{
cout << "{ ";
// do whatever with the i slice (again I'm showing output)
for (auto k : (input | sliced(i, i+block_size))) cout << k << " ";
cout << "}\n";
}
}
Related
Normally I would use other methods to fix this program but I am not allowed to use advanced techniques for this project, and so what I have is more or less as far as I'm allowed to go.
So my program is meant to take in an array with 10 numbers and then output how many of each value is in the array. For example, {1, 1, 1, 1, 1, 2, 2, 2, 2, 2} is meant to return
5 1
5 2
However, it returns
6 1
4 2
I've made sure that the finalData and Data arrays are holding the proper values.
cout << count(data, data + MAX_VALUE, finalData[i+1]) << " " << data[i] << "\n";
seems to be outputting the wrong value.
for some reason. I believe the error is in my last function, getResults, more specifically the last for loop. Here is that function.
void getResults(int finalData[], int data[])
{
int temp[MAX_VALUE];
int j = 0;
for (int i = 0; i < MAX_VALUE - 1; i++)
if (finalData[i] != finalData[i + 1])
temp[j++] = finalData[i];
temp[j++] = finalData[MAX_VALUE - 1];
for (int i = 0; i < j; i++)
{
finalData[i] = temp[i];
}
for (int i = 0; i < j; i++)
{
cout << count(data, data + MAX_VALUE, finalData[i+1]) << " " << data[i] << "\n";
}
}
This is my complete code.
#include<iostream>
#include<iomanip>
#include<string>
#include<cmath>
#include <algorithm>
using namespace std;
void printHeader();
int getData(string);
void getResults(int finalData[], int data[]);
const int MAX_VALUE = 10;
int main(void)
{
int countValue = 0;
int freq = 0;
printHeader();
int data[MAX_VALUE] = {};
int frequency[MAX_VALUE] = {};
for (int i = 0; i < MAX_VALUE; i++)
{
cout << "Please enter data position " << i + 1 << "\n";
data[i] = getData("\nPlease enter a valid integer.\n");
}
sort(data, data + MAX_VALUE);
int values[MAX_VALUE] = {};
int secondData[MAX_VALUE] = {};
for (int i = 0; i < MAX_VALUE; i++)
{
secondData[i] = data[i];
}
getResults(data, secondData);
return 0;
}
void printHeader()
{
}
int getData(string error)
{
int userInput = 0;
do
{
cin >> userInput;
if (cin.fail())
{
cout << error;
}
} while (cin.fail());
return userInput;
}
void getResults(int finalData[], int data[])
{
int temp[MAX_VALUE];
int j = 0;
for (int i = 0; i < MAX_VALUE - 1; i++)
if (finalData[i] != finalData[i + 1])
temp[j++] = finalData[i];
temp[j++] = finalData[MAX_VALUE - 1];
for (int i = 0; i < j; i++)
{
finalData[i] = temp[i];
}
for (int i = 0; i < j; i++)
{
cout << count(data, data + MAX_VALUE, finalData[i+1]) << " " << data[i] << "\n";
}
}
Got the right answer. Made the changes I listed at the top as well as the following change to the count function.
cout << count(data, data + MAX_VALUE, finalData[i]) << " " << finalData[i] << "\n";
You have done a simple error. When you call getResults you pass the same array(pointer) to 2 different parameters. Now when you update finalData the unwanted side effect update also data(they are the same pointer(with different name). So when you call count will not return the expected result.
To solve this problem you can do a copy of the input array and give it as second parameter of getResults(...) function.
I have a row of ten numbers for example:
5 5 6 7 5 9 4 2 2 7
Now I want a program that finds all duplicates and gives them out in the console like 3 times 5, 2 times 2, 2 times 7.
While I did code an algorithm that finds duplicates in a row of numbers I can't give them out in the console as described. My program will output:
3 times 5
2 times 5
2 times 7
2 times 2
How can I solve this problem?
#include <iostream>
using namespace std;
int main()
{
int arr[10];
int i,j;
int z = 1;
for(i = 0; i < 10; i++) {
cin >> arr[i];
}
for(i = 0; i < 10; i++){
for(j = i+1; j < 10; j++){
if(arr[i] == arr[j]){
z++;
}
}
if(z >= 2){
cout << z << " times " << arr[i] << endl;
z = 1;
}
}
return 0;
}
You can use the STL here (C++11):
int arr[10];
std::map<int, int> counters;
for (auto item : arr)
{
cin >> item;
++counters[item];
}
std::for_each(counters.begin(), counters.end(), [](const std::pair<int,int>& item)
{
if(item.second > 1) std::cout << item.second << " times " << item.first << std::endl;
});
You need to check that arr[i] is not already found before, like this for example:
if(z >= 2) {
int found_before = 0;
for(j = 0; j < i; ++j)
if(arr[i] == arr[j])
found_before = 1;
if(!found_before)
cout << z << " times " << arr[i] << endl;
z = 1;
}
which will print:
3 times 5
2 times 7
2 times 2
That way you don't print 5 again.
With your code it would print that it found 5 three times (for the first 5 in your array), and then when it would move to he second 5 in your array, it would forgot about the first 5 in your array, and report that it found 5 twice (itself and the 5th number of the array).
Why not use STL?
std::map<int, int> counter;
for (i = 0; i < 10; i++)
counter[arr[i]] ++;
for (i = 0; i < 10; i++) {
if (counter.count(arr[i]) > 0){
std::cout << counter[arr[i]] << " times "<< arr[i] << std::endl;
counter.erase(arr[i]);
}
}
std::map is a convenient tool for this job. You can easily count up occurrences of a specific number. After counting, you can print the count of each array element. With counter.erase, it's guaranteed that you won't print the same element for multiple times.
Why keeping your algorithm idea, I suggest to create sub method:
std::size_t count(const int* arr, std::size_t start, std::size_t end, int value)
{
std::size_t res = 0;
for (std::size_t i = start; i != end; ++i) {
if (arr[i] == value) {
++res;
}
}
return res;
}
then your fixed algorithm would be:
for (std::size_t i = 0; i != 10; ++i) {
if (count(arr, 0, i, arr[i]) != 0) {
continue; // Already visited
}
auto total = count(arr, i, 10, arr[i]);
if(total >= 2){
std::cout << z << " times " << arr[i] << std::endl;
}
}
An easy way is to make another array for it, especially if the numbers are not that big.
Lets say you have initialized your array like so: int nums[10] = { 5, 5, 6, 7, 5, 9, 4, 2, 2, 7 }
int result[max(nums)]; //Fill with zeroes, max(nums) is the highest number in the array
for(int i = 0; i < 10; i++) {
result[nums[i]]++;
}
for(int i = 0; i < max(nums); i++) {
if (result[i] > 1) cout << result[i];
}
Mind you this isn't optimized for memory. For larger number contents you might want to consider hashmaps.
If you don't need performance but rather compact code, then std::multiset with std::upper_bound is an alternative:
#include<set>
#include<iostream>
#include<algorithm>
int main(int a, char** b)
{
int array[] = {5, 5, 6, 7, 5, 9, 4, 2, 2, 7};
std::multiset<int> a(std::begin(array), std::end(array));
for(auto it = a.begin(); it != a.end(); it = std::upper_bound(a.begin(), a.end(), *it))
{
if(a.count(*it) > 1)
std::cout << *it << " times " << a.count(*it) << std::endl;
}
return 0;
}
I have to write a functioncalled moveAndSortInt() that will receive an array of integers as an argument, and move all the even values down to the second half of the array and sort them from largest to smallest, while all the odd values will be sorted from smallest to largest. How can I improve my code?
#include <iostream>
using namespace std;
void moveAndSortInt(int[], int);
void displayName();
int main() {
int ary1[] = { -19, 270, 76, -61, 54 };
int size = 5;
int i;
int ary2[] = {9, 8, -103, -73, 74, 53};
int size2 = 6;
int j;
displayName();
cout << endl;
cout << "Original ary1[]" << endl;
for (i = 0; i < size; i++) {
cout << " " << ary1[i] << " ";
}
cout << endl;
cout << "\nCallingMoveAndSortInt() --\n " << endl;
moveAndSortInt(ary1, size);
cout << "Updated ary1[]" << endl;
for (i = 0; i < size; i++) {
cout << " " << ary1[i] << " ";
}
cout << endl;
cout << "\nOriginal ary2[]" << endl;
for (j = 0; j < size2; j++) {
cout << " " << ary2[j] << " ";
}
cout << endl;
cout << "\nCallingMoveAndSortInt() --\n" << endl;
moveAndSortInt(ary2, size2);
cout << "Updated ary2[]" << endl;
for (j = 0; j < size2; j++) {
cout << " " << ary2[j] << " ";
}
}
void moveAndSortInt(int ary[], int size) {
int i, j;
int temp;
for (i = 0; i < 1 + size / 2; i++) {
if (ary[i] % 2 == 0) {
for (j = size - 1; j > size / 2; j--) {
if (ary[j] % 2 != 0) {
temp = ary[i];
ary[i] = ary[j];
ary[j] = temp;
j = 0;
}
}
}
}
return;
I would suggest using std::sort, the standard algorithm for sorting, which is often implemented with a Quicksort. It is very fast, and also supports custom comparison. Here's some code to get you started:
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> data = { 2, 213, 2, 2, 3 ,123, 4, 213, 2132, 123 };
std::sort(data.begin(), data.end(), [](int lhs, int rhs)
{
if (lhs % 2) // if lhs is odd
if (rhs % 2) // and rhs is odd then just use comparision
return lhs < rhs;
else // and if rhs is even then rhs is "bigger"
return false;
else // if lhs is even
if (rhs % 2)
return true; // and rhs is odd then lhs is "bigger"
else // and if they are both even just use comparision.
return lhs < rhs;
});
}
I'm sorry if that code is a little hard to read, but it does the trick.
This of course would work with C-style arrays too, just replace data.begin() with data and data.end() with data + size.
Alright, so I looked at it a bit. Let's start with conventions.
int i;
for (i = 1; i < 10; i++)
Can be shortened to:
for (int i = 1; i < 10; i++)
Which looks better and is more readable. It would also be nice to have a few more comments, but that's something everyone needs to get better at, no matter how good they are.
So it seems that your code does correctly sort the array into even and odd halves. That's all you need to do yourself as long as you know where they end because sorting them largest to smallest is something that std::sort can do for you.
Edit: It was pointed out to me that my previous example is not exactly the same, as with the second one i can only be used in the loop. For your purposes, they work the same.
You can just reorder it
#include <algorithm>
#include <climits>
#include <iostream>
#include <vector>
int main()
{
auto const shuffle = [] (int input)
{
if ( input % 2 )
{
unsigned const dist_from_min = (unsigned)input - INT_MIN;
return dist_from_min >> 1;
}
else
{
unsigned const dist_from_max = INT_MAX - (unsigned)input;
return INT_MIN + (dist_from_max >> 1);
}
};
auto const ordering = [shuffle] (int left, int right)
{ return shuffle (left) < shuffle (right); };
std::vector <int> data =
{ 5, 2, 3, 0, -1, -3, 1, 100
, INT_MIN, INT_MIN + 1, INT_MAX, INT_MAX - 1
, -567, -765, 765, 567, -234, -432, 234, 432
};
std::sort ( data.begin ( ), data.end ( ), ordering );
for ( auto item : data )
std::cout << item << "\n";
}
For an array, say, size 5,
I'm trying to find a random position between 0 and the current last element of the array.
(This last position is 4 the first time, will be 3 the second time, and so on.)
Delete whatever element is in that array position, shifting all elements above it down so that there are no empty spots in the array.
I am trying to be as time-efficient as possible, so I want to avoid setting said random position to 0 or something like that.
So if my array looked something like int n[] = {1,3,5,7,9}; and my random position finder chose position 2, how would I move 5(position 2) to the end and shift everything down so that my resulting array looks like {1,3,7,9,5} ?
So far I have:
for (int j = 0; j < 5; j++)
{
printf ("before removal:\n");
printarray (array, 5);
int randompos = ( rand() % (5-j) ); //selects random number from 0 to active last pos.
/* ?????? */ = array[randompos]; // What position will hold my random position?
//Also, what goes in place of the 'deleted' element?
insertion_sort (array, 5-j); //sort only the active elements
printf ("after removal:\n");
printarray (array, 5);
}
desired output:
before removal:
1,3,5,7,9
(say random position was array position 2, storing number 5)
after removal:
1,3,7,9,5
Given the array {1,3,5,7,9} and pos = 2, you can do the following:
int main()
{
int pos = 2;
int arr[] = {1, 3, 5, 7,9};
int length =sizeof(arr)/sizeof(arr[0]);
int val = arr[pos];
for (int i = pos; i < length; i++){
int j = i + 1;
arr[i] = arr[j];
}
arr[length - 1] = val;
return 0;
}
#include <iostream>
#include <algorithm>
#include <random>
int main() {
int n[] = {1, 3, 5, 7, 9};
std::size_t n_size = sizeof(n) / sizeof(int);
std::default_random_engine generator;
for(std::size_t i(0), sz(n_size); i < sz; ++i) {
std::cout << "before removal:" << std::endl;
std::cout << " ";
for(std::size_t j(0); j < n_size; ++j) std::cout << n[j] << " ";
std::cout << std::endl;
--n_size;
std::uniform_int_distribution<int> distribution(0, n_size);
std::size_t idx = distribution(generator);
std::cout << " Removing index: " << idx << std::endl;
std::swap(n[idx], n[n_size]);
std::sort(std::begin(n), std::begin(n) + n_size); // use your sorting here
std::cout << "after removal:" << std::endl;
std::cout << " ";
for(std::size_t j(0); j < n_size; ++j) std::cout << n[j] << " ";
std::cout << "\n" << std::endl;
}
}
LIVE DEMO
So I've been trying to implement an algorithm to output a heap array in tree format. For
instance if I have an array like A[10,6,8,2,4,3,6,0,1,3,2,2,1,0,2] I would like the output to be:
10-----6-----2-----0
| | |--1
| |--4-----3
| |--2
|--8-----3-----2
| |--1
|--6-----0
|--2
Update: Solved my question, I made an answer with the code for those interested.
A possible solution is to insert placeholders into the array and thus form a MxN matrix out if it. Then you can simply loop over it, insert a line feed after every row and indent cells having a placeholder.
This C++11 program outputs heap in a little bit different format:
// 10
// ||--------------||
// 6 8
// ||------|| ||------||
// 2 4 3 6
//||--|| ||--|| ||--|| ||--||
// 0 1 3 2 2 1 0 2
#include<iostream>
#include<vector>
#include<sstream>
#include<string>
#include<cmath>
#include<iomanip>
// http://stackoverflow.com/questions/994593/how-to-do-an-integer-log2-in-c
// will be used to compute height of the heap
size_t IntegerLogarithm2(size_t arg) {
size_t logarithm = 0;
while (arg >>= 1) ++logarithm;
return logarithm;
}
// will be used to compute number of elements at the level i
size_t IntegerPower2(size_t arg) {
if(arg)
return (size_t)2 << (arg-1);
else
return 1;
}
// returns total line length for the level
size_t LineLength(size_t level, size_t item_width, size_t spaces_between) {
return IntegerPower2(level) * (item_width + spaces_between) - spaces_between;
}
int main()
{
// The input heap array
std::vector<int> A = {10, 6, 8, 2, 4, 3, 6, 0, 1, 3, 2, 2, 1, 0, 2};
// The heap array split by levels
std::vector<std::vector<int> > levels;
// Height of the heap
size_t levels_number = IntegerLogarithm2(A.size() + 1);
levels.resize(levels_number);
// Now fill the levels
for (size_t i = 0; i < levels.size(); ++i) {
size_t elements_number = IntegerPower2(i);
levels[i].resize(elements_number);
for (size_t j = elements_number - 1, p = 0; p < elements_number; ++j, ++p)
levels[i][p] = A[j];
}
if (levels_number < 1) return 0;
int magnitude = (abs(A[0]) <= 1 ? 1 : abs(A[0]));
size_t tab_width = (size_t)floor(log(double(magnitude)) / log(10.0)) + 1;
// size_t longest_line = LineLength(levels_number - 1, tab_width, tab_width);
std::vector<std::string> text;
text.reserve(levels_number * 2 - 1);
// Do the aligned output to the strings array
for (size_t i = 0; i < levels_number; ++i) {
size_t outer_space_width = IntegerPower2(levels_number - 1 - i) - 1;
size_t inner_space_width = outer_space_width * 2 + 1;
std::string outer_space(outer_space_width * tab_width, ' ');
std::string inner_space(inner_space_width * tab_width, ' ');
std::ostringstream line;
line << outer_space;
if (i > 0) {
std::ostringstream branchline;
std::string joint(tab_width, '|');
std::string branch(inner_space_width * tab_width, '-');
branchline << outer_space;
if (levels[i].size() > 0) {
branchline << joint;
}
bool isline = true;
for (size_t j = 1; j < levels[i].size(); ++j, isline = !isline) {
if(isline)
branchline << branch << joint;
else
branchline << inner_space << std::setfill(' ') <<
std::setw(tab_width) << joint;
}
branchline << outer_space;
text.push_back(branchline.str());
}
if (levels[i].size() > 0) {
line << std::setfill(' ') << std::setw(tab_width) << levels[i][0];
}
for (size_t j = 1; j < levels[i].size(); ++j) {
line << inner_space << std::setfill(' ') <<
std::setw(tab_width) << levels[i][j];
}
line << outer_space;
text.push_back(line.str());
}
// Output the text
for (auto& i : text)
std::cout << i << std::endl;
return 0;
}
Yap, harder than it initially seemed. Effectively does what Sebastian Dressler proposed.
Here is the final implementation. Formatting scales with number length.
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
std::string do_padding (unsigned index, unsigned mlength){
std::string padding;
if (int((index-1)/2) != 0){
return (int((index-1)/2) % 2 == 0) ?
(do_padding(int((index-1)/2),mlength) + std::string(mlength+4,' ') + " ") :
(do_padding(int((index-1)/2),mlength) + std::string(mlength+3,' ') + " |") ;
}
return padding;
}
void printer (std::vector<int> const & tree, unsigned index, unsigned mlength){
auto last = tree.size() - 1 ;
auto left = 2 * index + 1 ;
auto right = 2 * index + 2 ;
std::cout << " " << tree[index] << " ";
if (left <= last){
auto llength = std::to_string(tree[left]).size();
std::cout << "---" << std::string(mlength - llength,'-');
printer(tree,left,mlength);
if (right <= last) {
auto rlength = std::to_string(tree[right]).size();
std::cout << "\n" << do_padding(right,mlength) << std::string(mlength+ 3,' ') << " | ";
std::cout << "\n" << do_padding(right,mlength) << std::string(mlength+ 3,' ') << " └" <<
std::string(mlength - rlength,'-');
printer(tree,right,mlength);
}
}
}
void print_tree (std::vector<int> & tree){
unsigned mlength = 0;
for (int & element : tree){
auto clength = std::to_string(element).size();
if (clength > mlength) {
mlength = std::to_string(element).size();
}
}
std::cout << std::string(mlength- std::to_string(tree[0]).size(),' ');
printer(tree,0,mlength);
}
int main() {
std::vector<int> test;
for(auto i =0; i<50; ++i){
test.push_back(rand() % 1000 + 1);
}
std::make_heap(test.begin(),test.end());
std::cout << "\n";
print_tree(test);
}