My problem is some kind of the Chinese postman problem.
I got a maze in which the program puts n agents and n targets. Now every agent has to visit every target at least once. Therefore I have to calculate the shortest path between all targets using the A* algorithm, maybe later the D*.
Now my problem is to calculate the permutations of the targets. I mean I have a program which calculates all possible permutations. But this doesn't mean it's clever to know them all. I mean if I have 4 targets, I got n! permutations (in this example 24). But the permutation 1234 got the same path length as 4321. So I need to upgrade my function to find symmetries in all permutations, and just use the A* for the minimum number of permutations.
So this is the code I currently use to generate all permutations. Currently I just print them out, but later i want to sore the permutations in a kind of array or vector, but that's rather simple compared to my main problem.
#include <iostream>
#include <algorithm>
#include <iterator>
int main( int argc, char *argv[] )
{
unsigned int n = atoi( argv[1] );
unsigned int f[n], *const fn = f + sizeof(f) / sizeof(*f);
for(int j=0; j<n; j++)
{
f[j]=(j+1);
}
unsigned int i = 0;
do
{
std::cout << ++i << ". Permutation: ";
copy(f, fn, std::ostream_iterator<int>(std::cout, " "));;
std::cout << std::endl;
}
while(std::next_permutation(f, fn));
return 0;
}
To skip symmetrical permutations, you may skip the one where the last node is inferior to first node:
void show_permutation(std::vector<unsigned int> v)
{
int i = 0;
do {
if (v.back() < v.front()) {
continue;
}
std::cout << ++i << ". Permutation: ";
copy(v.begin(), v.end(), std::ostream_iterator<unsigned int>(std::cout, " "));
std::cout << std::endl;
} while(std::next_permutation(v.begin(), v.end()));
}
Live example
Related
I was trying to sort the areas of a circle in an ascending order. First, the user chooses the number of circles, then he should type the coordinates and the area of his circles. In the end the program should output the radius of a circle in an ascending order.But the output of areas is not in an ascending order(It's the same as input). What is my problem?
#include<iostream>
#include <algorithm>
using namespace std;
struct circle {
int 반지름;
int coordinates;
int coordinates2;
};
bool compare(circle a, circle b){
if(a.반지름 < b.반지름)
return 1;
else
return 0;
}
int main()
{
int n = 1;
int* ptr1;
ptr1 = new int;
circle* circle1;
circle1 = new (nothrow) circle[5];
circle1[0].반지름;
circle1[0].coordinates;
circle1[0].coordinates2;
circle1[1].반지름;
circle1[1].coordinates;
circle1[1].coordinates2;
circle1[2].반지름;
circle1[2].coordinates;
circle1[2].coordinates2;
circle1[3].반지름;
circle1[3].coordinates;
circle1[3].coordinates2;
circle1[4].반지름;
circle1[4].coordinates;
circle1[4].coordinates2;
circle1[5].반지름;
circle1[5].coordinates;
circle1[5].coordinates2;
cout << "Enter the number of circles: ";
cin >> *ptr1;
cout << "중심 좌표, 반지름 : " << endl;
for (int i = 0; i < *ptr1; i++) {
cin >> circle1[i].coordinates >> circle1[i].coordinates2 >> circle1[i].반지름;
}
sort(circle1, circle1 + 1, compare);
for (int i = 0; i < *ptr1; i++) {
cout << "The result: " << circle1[i].coordinates << " " << circle1[i].coordinates2 << " " << circle1[i].반지름 << endl;
}
delete[] circle1;
delete ptr1;
return 0;
}
That's not C++, that's a strange and hybrid thing between C and C++... And this is your main problem. You're mixing up things that should not be mixed, not if you don't know PERFECLY what you do - and obviously, it's not the case, otherwise your code should have worked, and it haven't.
Corrected code, in real C++:
#include <iostream> // std::cout & co
#include <algorithm> // std::sort
#include <cstdlib> // std::rand & co
#include <vector> // std::vector
struct circle {
int area ;
int x ;
int y ;
} ;
// For printing a circle easily and not repeat code X times.
// Print as: [area#(x,y)]
std::ostream& operator<<(std::ostream& os, const circle& c) {
os << "[" << c.area << "#(" << c.x << "," << c.y << ")]" ;
return os;
}
int main() {
// Set a constant seed: each run will produce the same result, if needed to debug.
std::srand(1234) ;
// 5 circles declared within a vector, not a C array.
auto circles = std::vector<circle>(5) ;
// Fill the vector.
std::cout << "Original circles:" << std::endl ;
// Use a simpler for syntax.
for ( auto& c: circles ) {
// Random values used. The fixed seed will always give the same values on each run.
c.area = 10 + std::rand() % 50 ;
c.x = std::rand() % 1920 ;
c.y = std::rand() % 1080 ;
// Print the circle.
std::cout << "\t" << c << std::endl ;
}
// Sort the vector, use a lambda expression for the compare operator.
// No need for a "real" function, if it's used only once and only there.
// Compare function returns directly a bool, not an integer.
std::sort(circles.begin(), circles.end(), [](const circle& a, const circle& b) -> bool { return (a.area<b.area) ; });
// Display sorted vector.
std::cout << std::endl << "Sorted circles:" << std::endl ;
for ( const auto& c: circles )
std::cout << "\t" << c << std::endl ;
return 0;
}
Still strange that you use area instead of radius or diameter, but anyway... Area is for a disc, not a circle, but that's mathematical precision at this stage.
First, if you print a structure like circle at least twice, do a stream operator to do it only once. Please note that I send directly the structure to std::cout, after...
Then, I use a C++ container, not a C allocated array. You can still allocate memory for big amount of data, but for this example, that's unneeded.
Then, instead of asking for each values, I use std::rand() to fill them. Easier. Can be used in any language. Refined trick: I initialize the pseudo-random generator to a constant, fixed value, so each time the program is run, it will generate the exact same sequence of pseudo-random numbers - this can vary on each machine / OS / compiler / compiler version but it will be constant on YOUR machine during your tests, and it can be debugged easily.
Please also note that I use a compact form of for that will iterate on the whole circles container, giving me each time a circle& (reference) on each element so that I can modify it - needed for initialization.
Now, the sort itself: from begin() to end() of the container, using a lambda expression to define the compare operator. Please note that I return directly the result of the comparison, which is a bool, and that I don't cast an int to a bool implicitely...
Finally, print the result. Note that this time, I ask for a const auto& reference, to be sure to not modify data by mistake.
Nothing to delete, C++ will take care of that.
An example output, on my machine:
Original circles:
[28#(213,881)]
[18#(16,157)]
[34#(1468,816)]
[14#(745,718)]
[31#(143,818)]
Sorted circles:
[14#(745,718)]
[18#(16,157)]
[28#(213,881)]
[31#(143,818)]
[34#(1468,816)]
Doing an exercise to find the mean and mode of a list of numbers input by a user. I have written the program and it works, but I'm wondering if my function 'calcMode' is too large for this program. I've just started looking into functions which is a first attempt. Would it be better to write smaller functions? and if so what parts can I split? Im pretty new to C++ and also looking if I can improve this code. Is there any changes I can make to make this run more efficient?
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int calcMean(vector<int> numberList)
{
int originNumber = numberList[0];
int nextNumber;
int count = 0;
int highestCount = 0;
int mean = 0;
for (unsigned int i = 0; i <= numberList.size() - 1; i++)
{
nextNumber = numberList[i];
if (nextNumber == originNumber)
count++;
else
{
cout << "The Number " << originNumber << " appears " << count << " times." << endl;
count = 1;
originNumber = nextNumber;
}
}
if (count > highestCount)
{
highestCount = count;
mean = originNumber;
}
cout << "The Number " << originNumber << " appears " << count << " times." << endl;
return mean;
}
int main()
{
vector<int> v;
int userNumber;
cout << "Please type a list of numbers so we can arrange them and find the mean: "<<endl;
while (cin >> userNumber) v.push_back(userNumber);
sort(v.begin(), v.end());
for (int x : v) cout << x << " | ";
cout << endl;
cout<<calcMean(v)<<" is the mean"<<endl;
return 0;
}
One thing to watch out for is copying vectors when you don't need to.
The function signature
int calcMode(vector<int> numberList)
means the numberList will get copied.
int calcMode(const & vector<int> numberList)
will avoid the copy. Scott Meyer's Effective C++ talks about this.
As an aside, calling is a numberList is misleading - it isn't a list.
There are a couple of points that are worth being aware of in the for loop:
for (unsigned int i = 0; i <= numberList.size()-1; i++)
First, this might calculate the size() every time. An optimiser might get rid of this for you, but some people will write
for (unsigned int i = 0, size=numberList.size(); i <= size-1; i++)
The size is found once this way, instead of potentially each time.
They might even change the i++ to ++i. There used to a potential overhead here, since the post-increment might involve an extra temporary value
One question - are you *sure this gives the right answer?
The comparison nextNumber == originNumber is looking at the first number to begin with.
Try it with 1, 2, 2.
One final point. If this is general purpose, what happens if the list is empty?
Would it be better to write smaller functions?
Yes, you can make do the same job using std::map<>; which could be
a much appropriate way to count the repetition of the array elements.
Secondly, it would be much safer to know, what is the size of the
array. Therefore I suggest the following:
std::cout << "Enter the size of the array: " << std::endl;
std::cin >> arraySize;
In the calcMode(), you can easily const reference, so that array
will not be copied to the function.
Here is the updated code with above mentioned manner which you can refer:
#include <iostream>
#include <algorithm>
#include <map>
int calcMode(const std::map<int,int>& Map)
{
int currentRepetition = 0;
int mode = 0;
for(const auto& number: Map)
{
std::cout << "The Number " << number.first << " appears " << number.second << " times." << std::endl;
if(currentRepetition < number.second )
{
mode = number.first; // the number
currentRepetition = number.second; // the repetition of the that number
}
}
return mode;
}
int main()
{
int arraySize;
int userNumber;
std::map<int,int> Map;
std::cout << "Enter the size of the array: " << std::endl;
std::cin >> arraySize;
std::cout << "Please type a list of numbers so we can arrange them and find the mean: " << std::endl;
while (arraySize--)
{
std::cin >> userNumber;
Map[userNumber]++;
}
std::cout << calcMode(Map)<<" is the mode" << std::endl;
return 0;
}
Update: After posting this answer, I have found that you have edited your function with mean instead of mode. I really didn't get it.
Regarding mean & mode: I recommend you to read more. Because in general, a data set can have multiple modes and only one mean.
I personally wouldn't split this code up in smaller blocks, only if i'd want to reuse some code in other methods. But just for this method it's more readable like this.
The order of excecution is aroun O(n) for calc which is quite oke if you ask me
This program takes a word from text and puts it in a vector; after this it compares every element with the next one.
So I'm trying to compare element of a vector like this:
sort(words.begin(), words.end());
int cc = 1;
int compte = 1;
int i;
//browse the vector
for (i = 0; i <= words.size(); i++) { // comparison
if (words[i] == words[cc]) {
compte = compte + 1;
}
else { // displaying the word with comparison
cout << words[i] << " Repeated : " << compte; printf("\n");
compte = 1; cc = i;
}
}
My problem in the bounds: i+1 may exceed the vector borders. How to I handle this case?
You need to pay more attention on the initial conditions and bounds when you do iteration and comparing at the same time. It is usually a good idea to execute your code using pen and paper at first.
sort(words.begin(), words.end()); // make sure !words.empty()
int cc = 0; // index of the word we need to compare.
int compte = 1; // counting of the number of occurrence.
for( size_t i = 1; i < words.size(); ++i ){
// since you already count the first word, now we are at i=1
if( words[i] == words[cc] ){
compte += 1;
}else{
// words[i] is going to be different from words[cc].
cout << words[cc] << " Repeated : " << compte << '\n';
compte = 1;
cc = i;
}
}
// to output the last word with its repeat
cout << words[cc] << " Repeated : " << compte << '\n';
Just for some additional information.
There are better ways to count the number of word appearances.
For example, one can use unordered_map<string,int>.
Hope this help.
C++ uses zero-based indexing, e.g., an array of length 5 has indices: {0, 1, 2, 3, 4}. This means that index 5 is outside of the range.
Similarly, given an array arr of characters:
char arr[] = {'a', 'b', 'c', 'd', 'e'};
The loop for (int i = 0; i <= std::size(arr); ++i) { arr[i]; } will cause a read from outside of the range when i is equal to the length of arr, which causes undefined behaviour. To avoid this the loop must stop before i is equal to the length of the array.
for (std::size_t i = 0; i < std::size(arr); ++i) { arr[i]; }
Also note the use of std::size_t as type of the index counter. This is common practice in C++.
Now, let's finish with an example of how much easier this can be done using the standard library.
std::sort(std::begin(words), std::end(words));
std::map<std::string, std::size_t> counts;
std::for_each(std::begin(words), std::end(words), [&] (const auto& w) { ++counts[w]; });
Output using:
for (auto&& [word, count] : counts) {
std::cout << word << ": " << count << std::endl;
}
My problem in the bounds: i+1 may exceed the vector borders. How to I
handle this case?
In modern C++ coding, the problem of an index going past vector bounds can be avoided. Use the STL containers and avoid using indices. With a little effort devoted to learning how to use containers this way, you should never see these kind of 'off-by-one' errors again! As a benefit, the code becomes more easily understood and maintained.
#include <iostream>
#include <vector>
#include <map>
using namespace std;
int main() {
// a test vector of words
vector< string > words { "alpha", "gamma", "beta", "gamma" };
// map unique words to their appearance count
map< string, int > mapwordcount;
// loop over words
for( auto& w : words )
{
// insert word into map
auto ret = mapwordcount.insert( pair<string,int>( w, 1 ) );
if( ! ret.second )
{
// word already present
// so increment count
ret.first->second++;
}
}
// loop over map
for( auto& m : mapwordcount )
{
cout << "word '" << m.first << "' appears " << m.second << " times\n";
}
return 0;
}
Produces
word 'alpha' appears 1 times
word 'beta' appears 1 times
word 'gamma' appears 2 times
https://ideone.com/L9VZt6
If some book or person is teaching you to write code full of
for (i = 0; i < ...
then you should run away quickly and learn modern coding elsewhere.
Same repeated words counting using some C++ STL goodies via multiset and upper_bound:
#include <iostream>
#include <vector>
#include <string>
#include <set>
int main()
{
std::vector<std::string> words{ "one", "two", "three", "two", "one" };
std::multiset<std::string> ms(words.begin(), words.end());
for (auto it = ms.begin(), end = ms.end(); it != end; it = ms.upper_bound(*it))
std::cout << *it << " is repeated: " << ms.count(*it) << " times" << std::endl;
return 0;
}
https://ideone.com/tPYw4a
My main idea is to shrink they array from both sides . For example if the input is 1234 , wanna print 1234 and then 4321 (the reversed) .
#include <iostream>
#include <cmath>
#include <math.h>
using namespace std;
int reversedArray(int* x)
{
cout<< "*x out of while =" << *x <<endl ;
while( *x != 0 )
{
cout << "*x=" << *x << endl;
cout<< "====================== im in reversed =================" << endl ;
return reversedArray( x+1 );
}
cout<< "after return " << *x << endl;
}
int main ()
{
int Array[] = {10,2,3,4,8 ,0} ;
int* p_Array = Array;
reversedArray( Array );
}
After the "while" , why the functions that are in the stack, do not return to the next line ( " the --> cout<< "after return " <<*x <
void printReversed(int * x)
{
if (*x == 0) return;
std::cout << *x;
printReversed(x+1);
std::cout << *x;
}
The line:
return reversedArray( x+1 );
exits the function. So you never repeat the while or execute any of the code after the while if you go into the while. This makes the while effectively an if statement.
The code posted by Crazy Eddie does the job and Barmar explains the ineffectiveness of the while loop. I decided to post a non-recursive way to address the problem mentioned.
#include <iostream>
#include <vector>
using namespace std;
vector<int> reverseArray(vector<int>& arr) {
vector<int> ans;
int n = arr.size();
// insert all elements in the reverse order
for (size_t i = 0; i < n; i++) {
ans.push_back(arr[n-i-1]);
}
return ans;
}
int main ()
{
int array[] = {10, 2, 3, 4, 8, 0};
// convert into vector
vector<int> arr(array, array+6);
vector<int> rev = reverseArray(arr);
// merging the 2 arrays
arr.insert(arr.end(), rev.begin(), rev.end());
// printArray(arr) -- implement to fit your needs;
}
When you pass an int[] to a function it decays to an int* which is simply an address in memory. C++ a better plan would be to use copy_backward with an ostream_iterator:
copy_backward(Array, Array + sizeof(Array) / sizeof(*Array), ostream_iterator<int>(cout, " "))
Note that this method uses the actual size of the array, and does not depend upon a terminal element. Thus, no numbers are offlimits, and it's impossible to segfault by failing to provide the terminating element.
If you have access to C++11 you can simplify that a bit further to:
copy(crbegin(Array), crend(Array), ostream_iterator<int>(cout, " "))
Live Example
According to SGI, cplusplus.com, and every other source I've got, the sort() member function of the std::list should not invalidate iterators. However, that doesn't seem to be the case when I run this code (c++11):
#include <list>
#include <chrono>
#include <random>
#include <iostream>
#include "print.hpp"
unsigned int seed = std::chrono::system_clock::now().time_since_epoch().count();
std::default_random_engine generator(seed);
std::uniform_int_distribution<unsigned int> distribution(1, 1000000000);
auto rng = std::bind(distribution, generator);
// C++11 RNG stuff. Basically, rng() now gives some unsigned int [1, 1000000000]
int main() {
unsigned int values(0);
std::cin >> values; // Determine the size of the list
std::list<unsigned int> c;
for (unsigned int n(0); n < values; ++n) {
c.push_front(rng());
}
auto c0(c);
auto it(c.begin()), it0(c0.begin());
for (unsigned int n(0); n < 7; ++n) {
++it; // Offset these iterators so I can print 7 values
++it0;
}
std::cout << "With seed: " << seed << "\n";
std::cout << "Unsorted list: \n";
print(c.begin(), c.end()) << "\n";
print(c.begin(), it) << "\n\n";
auto t0 = std::chrono::steady_clock::now();
c0.sort();
auto d0 = std::chrono::steady_clock::now() - t0;
std::cout << "Sorted list: \n";
print(c0.begin(), c0.end()) << "\n";
print(c0.begin(), it0) << "\n"; // My own print function, given further below
std::cout << "Seconds: " << std::chrono::duration<double>(d0).count() << std::endl;
return 0;
}
In print.hpp:
#include <iostream>
template<class InputIterator>
std::ostream& print(InputIterator begin, const InputIterator& end,
std::ostream& out = std::cout) {
bool first(true);
out << "{";
for (; begin != end; ++begin) {
if (first) {
out << (*begin);
first = false;
} else {
out << ", " << (*begin);
}
}
out << "}";
return out;
}
Sample input/output:
11
With seed: 3454921017
Unsorted list:
{625860546, 672762972, 319409064, 8707580, 317964049, 762505303, 756270868, 249266563, 224065083, 843444019, 523600743}
{625860546, 672762972, 319409064, 8707580, 317964049, 762505303, 756270868}
Sorted list:
{8707580, 224065083, 249266563, 317964049, 319409064, 523600743, 625860546, 672762972, 756270868, 762505303, 843444019}
{8707580, 224065083}
Seconds: 2.7e-05
Everything works as expected, except for the printing. It is supposed to show 7 elements, but instead the actual number is fairly haphazard, provided "value" is set to more than 7. Sometimes it gives none, sometimes it gives 1, sometimes 10, sometimes 7, etc.
So, is there something observably wrong with my code, or does this indicate that g++'s std::list (and std::forward_list) is not standards conforming?
Thanks in advance!
The iterators remain valid and still refer to the same elements of the list, which have been re-ordered.
So I don't think your code does what you think it does. It prints the list from the beginning, to wherever the 7th element ended up after the list was sorted. The number of elements it prints therefore depends on the values in the list, of course.
Consider the following code:
#include <list>
#include <iostream>
int main() {
std::list<int> l;
l.push_back(1);
l.push_back(0);
std::cout << (void*)(&*l.begin()) << "\n";
l.sort();
std::cout << (void*)(&*l.begin()) << "\n";
}
The two address printed differ, showing that (unlike std::sort), std::list::sort has sorted by changing the links between the elements, not by assigning new values to the elements.
I've always assumed that this is mandated (likewise for reverse()). I can't actually find explicit text to say so, but if you look at the description of merge, and consider that the reason for list::sort to exist is presumably because mergesort works nicely with lists, then I think it's "obviously" intended. merge says, "Pointers and references to the moved elements of x now refer to those same elements but as members of *this" (23.3.5.5./23), and the start of the section that includes merge and sort says, "Since lists allow fast insertion and erasing from the middle of a list, certain operations are provided specifically for them" (23.3.5.5/1).