Counting Sort in C++ - c++

I am trying to implement the Counting Sort in C++ without creating a function. This is the code that I've written so far, but the program doesn't return me any values. It doesn't give me any errors either. Therefore, what is wrong?
#include <iostream>
using namespace std;
int main()
{
int A[100], B[100], C[100], i, j, k = 0, n;
cin >> n;
for (i = 0; i < n; ++i)
{
cin >> A[i];
}
for (i = 0; i < n; ++i)
{
if (A[i] > k)
{
k = A[i];
}
}
for (i = 0; i < k + 1; ++i)
{
C[i] = 0;
}
for (j = 0; j < n; ++j)
{
C[A[j]]++;
}
for (i = 0; i < k; ++i)
{
C[i] += C[i - 1];
}
for (j = n; j > 0; --j)
{
B[C[A[j]]] = A[j];
C[A[j]] -= 1;
}
for (i = 0; i < n; ++i)
{
cout << B[i] << " ";
}
return 0;
}

It looks like you're on the right track. You take input into A, find the largest value you'll be dealing with and then make sure you zero out that many values in your C array. But that's when things start to go wrong. You then do:
for (i = 0; i < k; ++i)
{
C[i] += C[i - 1];
}
for (j = n; j > 0; --j)
{
B[C[A[j]]] = A[j];
C[A[j]] -= 1;
}
That first loop will always go out of bounds on the first iteration (C[i-1] when i=0 will be undefined behavior), but even if it didn't I'm not sure what you have in mind here. Or in the loop after that for that matter.
Instead, if I were you, I'd create an indx variable to keep track of which index I'm next going to insert a number to (how many numbers I've inserted so far), and then I'd loop over C and for each value in C, I'd loop that many times and insert that many values of that index. My explanation may sound a little wordy, but that'd look like:
int indx = 0;
for(int x = 0; x <= k; x++) {
for(int y = 0; y < C[x]; y++) {
B[indx++] = x;
}
}
If you replace the two loops above with this one, then everything should work as expected.
See a live example here: ideone

Related

unable to sort an array, wrong output

#include<bits/stdc++.h>
using namespace std;
int
main ()
{
int a[3] = { 3, 2, 1 }, i, j, t = 0, k = 0;
int m;
for (int i = 0; i < 2; i++)
{
m = a[i];
for (int j = i++; j < 3; j++)
{
if (m > a[j])
{
m = a[j];
k = j;
}
}
t = a[i];
a[i] = m;
a[k] = t;
}
for (int i = 0; i < 3; i++)
{
cout << a[i];
}
return 0;
}
You seem to want to implement an insertion sort algorithm by hand. For this task, you should consider using std::sort. I refactored your code such that it basically does the same thing as you wanted and included some tips to make the code more readable and easier to debug for you and others:
#include <algorithm> //only include necessary headers
#include <iostream>
//do not use "using namespace std"
int main ()
{
int a[3] = { 3, 2, 1 };
/*
Declare local variables at the first point they are used an as local as possible.
It is much easier to read, if a no longer necessary variables leaves scope.
*/
for (int i = 0; i < 2; i++) {
int min = a[i]; //use names that tell something about what you are doing
int bestIndex = i;
for (int j = i+1; j<3; j++) { //here was your major bug: i++ also increcments i
if (a[j] < min){
min = a[j];
bestIndex = j;
}
}
std::swap(a[i], a[bestIndex]);
//try to use standard algorithms as often as possible. They document your code, are optimized and easier to read.
}
for (int i = 0; i < 3; i++){
std::cout << a[i];
}
return 0;
}
Look at this:
for (int i = 0; i < 2; i++)
{
for (int j = i++; j < 3; j++)
{
}
}
On the first iteration of the outer loop:
i is 0.
Then the inner loop increments it to 1.
Then the outer loop increments it to 2.
Then the outer loop is done, after just one iteration.
You want i+1 in the inner loop, not i++.
#include<bits/stdc++.h>
using namespace std;
int main ()
{
int a[3] = { 3,2,1}, t = 0, k = 0;
int m=0;
bool flag_change =false;
for (int i = 0; i < 2; i++)
{
m = a[i];
for (int j = i+1; j < 3; j++)
{
if (m < a[j]) //changing sing (<>) sort by ascending/sort by descending order
{
m = a[j];
k = j;
flag_change = true;
}
}
if(flag_change)
{
t = a[i];
a[i] = m;
a[k] = t;
flag_change = false;
}
}
for (int i = 0; i < 3; i++)
{
cout << a[i];
}
return 0;
}
I'm done correct you code. Code is working.But it is not good implementation.

Displaying first element user input in an Array

We can define the term 'value of a name' as the average position of
the letters in the name, calculating 'A' as 1, 'B' as 2, 'C' as 3, and
so on. The value of "BOB" would be (2 + 15 + 2)/ 3 = 6. According to
this value, the names will be arranged from the smallest towards the
biggest in the output. When two or more names have the same value,
the name which is in the first position in the original list (the
first one the user inputs) should show up first in the sorted list
(the output).
Input In the first line we have an integer N (1 <= N <= 100), which is
the number of names. In every of the N lines we have one name ([A-Z],
no empty spaces). Names contain 1 - 200 letters.
Output Print out the sorted list (one name in a line).
Test-case
Input: 3 BOB AAAAAAA TOM Output: AAAAAAA BOB TOM
I tried something, and the code seemed to work, I just had a problem with the output. I couldn't find a way to arrange the names with the same value, according to their position in the original list. Here's the other test-case I tried, but didn't figure out:
Input:
10
COSOPYILSPKNKZSTUZVMEERQDL
RRPPNG
PQUPOGTJETGXDQDEMGPNMJEBI
TQJZMOLQ
BKNGFEJZWMJNJLSTUBHCFHXWMYUPZM
YNWEPZKNBOOXNZVWKIUS
LV
CJDFYDMYZVOEW
TMHEJLIDEHT
KGTGFIFWYTKPWTYQQPGKRRYFXN
Output:
TMHEJLIDEHT
PQUPOGTJETGXDQDEMGPNMJEBI
BKNGFEJZWMJNJLSTUBHCFHXWMYUPZM
CJDFYDMYZVOEW
RRPPNG
COSOPYILSPKNKZSTUZVMEERQDL
KGTGFIFWYTKPWTYQQPGKRRYFXN
TQJZMOLQ
YNWEPZKNBOOXNZVWKIUS
LV
My output:
TMHEJLIDEHT
PQUPOGTJETGXDQDEMGPNMJEBI
CJDFYDMYZVOEW // these two
BKNGFEJZWMJNJLSTUBHCFHXWMYUPZM // should be arranged with their places switched
RRPPNG
COSOPYILSPKNKZSTUZVMEERQDL
KGTGFIFWYTKPWTYQQPGKRRYFXN
TQJZMOLQ
YNWEPZKNBOOXNZVWKIUS
LV
#include <iostream>
#include <string>
using namespace std;
int main() {
int N;
cin >> N;
string words[N];
int res[N];
for (int i = 0; i < N; i++) {
int sum = 0;
int value = 0;
int temp = 0;
string word;
cin >> words[i];
word = words[i];
for (int j = 0; j < word.length(); j++) {
sum += (int)word[j] - 64;
}
value = sum / word.length();
res[i] = value;
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (res[i] < res[j]) {
swap(res[i], res[j]);
swap(words[i], words[j]);
}
}
}
for (int i = 0; i < N; i++) {
cout << words[i] << endl;
}
return 0;
}
string words[N];
int res[N];
This here is not valid C++, you can not size a stack array using a runtime variable, although some compilers might support such a feature. You might use say std::vector instead, which behaves much like an array.
vector<string> words;
vector<int> res;
for (int i = 0; i < N; i++) {
int sum = 0;
int value = 0;
int temp = 0;
string word;
cin >> word;
words.push_back(word);
for (int j = 0; j < word.length(); j++) {
sum += (int)word[j] - 64;
}
value = sum / word.length();
res.push_back(value);
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (res[i] < res[j]) {
swap(res[i], res[j]);
swap(words[i], words[j]);
}
}
}
The ordering is because your sorting algorithm is not stable. Stable means that items with equal values will maintain the same order relative to each other.
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (res[i] < res[j]) {
swap(res[i], res[j]);
swap(words[i], words[j]);
}
}
}
What you have is very close to bubble sort, which is stable.
for (int i = 0; i < N; i++) {
for (int j = 0; j < N - i - 1; j++) { // i elements sorted so far
if (res[j] > res[j + 1]) {
swap(res[j], res[j + 1]);
swap(words[j], words[j + 1]);
}
}
}
C++ also provides a stable sort in <algorithm>, but it can't function directly on two arrays like this unfortunately, one option is to compute the value on the fly, another could be to make a class holding both items and sort that, or another to sort the indices.
std::stable_sort(words.begin(), words.end(), [&](auto &a, auto &b)
{
int suma = 0, sumb = 0; // better yet, make a "int value(const string &str)" function.
for (int j = 0; j < a.length(); j++) {
suma += (int)a[j] - 64;
}
for (int j = 0; j < b.length(); j++) {
sumb += (int)b[j] - 64;
}
int valuea = suma / a.length();
int valueb = sumb / b.length();
return valuea < valueb;
});
A class containing both items is pretty straight forward, for indices, make a 3rd array and sort that.
vector<size_t> indices;
...
string word;
cin >> word;
indices.push_back(words.size());
words.push_back(word);
...
std::stable_sort(indices.begin(), indices.end(), [&](auto a, auto b){ return res[a] < res[n]; });
for (int i = 0; i < N; i++) {
cout << words[indices[i]] << endl;
}
A possible solution could be order the result array during construction.
When you add the words in the result array, use the result obtained to add the word in the right place. In this way you can check if exist already the same value and add the new word after the previous with the same value.
After reading the next word use insertion sort (wiki) which is stable
read word
calculate value
insert in a right place in the array
go to 1 until i < N otherwise print out
Doesn't require additional sorting procedure.
in python:
def sort_list(list1, list2):
zipped_pairs = zip(list2, list1)
z = [x for _, x in sorted(zipped_pairs)]
return z
times = int(input())
entries = []
ordered = []
for x in range(times):
entries.append(input())
for x in entries:
chars = []
for y in x:
chars.append(ord(y) - 96)
ordered.append(sum(chars))
print(sort_list(entries,ordered))
If you use a std::multimap<int, std::string>, there would be no need to sort, as the key would already serve as the sorting criteria.
Here is a solution using std::multimap:
#include <string>
#include <numeric>
#include <iostream>
#include <sstream>
#include <map>
// Test data
std::string test = "10\n"
"COSOPYILSPKNKZSTUZVMEERQDL\n"
"RRPPNG\n"
"PQUPOGTJETGXDQDEMGPNMJEBI\n"
"TQJZMOLQ\n"
"BKNGFEJZWMJNJLSTUBHCFHXWMYUPZM\n"
"YNWEPZKNBOOXNZVWKIUS\n"
"LV\n"
"CJDFYDMYZVOEW\n"
"TMHEJLIDEHT\n"
"KGTGFIFWYTKPWTYQQPGKRRYFXN\n";
int main()
{
std::istringstream strm(test);
// Read in the data
std::multimap<int, std::string> strmap;
int N;
strm >> N;
std::string word;
for (int i = 0; i < N; ++i)
{
strm >> word;
// get the average using std::accumulate and divide by the length of the word
int avg = std::accumulate(word.begin(), word.end(), 0,
[&](int total, char val) { return total + val - 'A' + 1; }) / word.length();
// insert this value in the map
strmap.insert({ avg, word });
}
// output results
for (auto& w : strmap)
std::cout << w.second << "\n";
}
Output:
TMHEJLIDEHT
PQUPOGTJETGXDQDEMGPNMJEBI
BKNGFEJZWMJNJLSTUBHCFHXWMYUPZM
CJDFYDMYZVOEW
RRPPNG
COSOPYILSPKNKZSTUZVMEERQDL
KGTGFIFWYTKPWTYQQPGKRRYFXN
TQJZMOLQ
YNWEPZKNBOOXNZVWKIUS
LV
The std::accumulate is used to add up the values to get the average.
Or just order them in the end (You won't need the 2nd array):
for (int i = 0; i < N; i++) {
for (int j = i + 1; j < N; j++) {
int sumA = 0, sumB = 0;
for (int k = 0; k < words[i].size(); k++)
sumA += words[i][k] - 'A' + 1;
for (int k = 0; k < words[j].size(); k++)
sumB += words[j][k] - 'A' + 1;
if (sumA / words[i].size() > sumB / words[j].size())
swap(words[i], words[j]);
}
}
As they shown above, it's way better to use a vector to store your data.

Partial Pivoting/Gaussian elimination- swapping columns instead of rows producing wrong output

I'm trying to implement a quick program to solve a system of linear equations. The program reads the input from a file and then writes the upper-triangular system and solutions to a file. It is working with no pivoting, but when I try to implement the pivoting it produces incorrect results.
As example input, here is the following system of equations:
w+2x-3y+4z=12
2w+2x-2y+3z=10
x+y=-1
w-x+y-2z=-4
I expect the results to be w=1, x=0, y=-1 and z=2. When I don't pivot, I get this answer (with some rounding error on x). When I add in the pivoting, I get the same numbers but in the wrong order: w=2,x=1,y=-1 and z=0.
What do I need to do to get these in the correct order? Am I missing a step somewhere? I need to do column swapping instead of rows because I need to adapt this to a parallel algorithm later that requires that. Here is the code that does the elimination and back substitution:
void gaussian_elimination(double** A, double* b, double* x, int n)
{
int maxIndex;
double temp;
int i;
for (int k = 0; k < n; k++)
{
i = k;
for (int j = k+1; j < n; j++)
{
if (abs(A[k][j]) > abs(A[k][i]))
{
i = j;
}
}
if (i != k)
{
for (int j = 0; j < n; j++)
{
temp = A[j][k];
A[j][k] = A[j][i];
A[j][i] = temp;
}
}
for (int j = k + 1; j < n; j++)
{
A[k][j] = A[k][j] / A[k][k];
}
b[k] = b[k] / A[k][k];
A[k][k] = 1;
for (i = k + 1; i < n; i++)
{
for (int j = k + 1; j < n; j++)
{
A[i][j] = A[i][j] - A[i][k] * A[k][j];
}
b[i] = b[i] - A[i][k] * b[k];
A[i][k] = 0;
}
}
}
void back_substitution(double**U, double*x, double*y, int n)
{
for (int k = n - 1; k >= 0; k--)
{
x[k] = y[k];
for (int i = k - 1; i >= 0; i--)
{
y[i] = y[i] - x[k]*U[i][k];
}
}
}
I believe what you implemented is actually complete pivoting.
With complete pivoting, you must keep track of the permutation of columns, and apply the same permutation to your answer.
You can do this with an array {0, 1, ..., n}, where you swap the i'th and k'th values in the second loop. Then, rearange the solution using this array.
If what you were trying to do is partial pivoting, you need to look for the maximum in the respective row, and swap the rows and the values of 'b' accordingly.

Finalize the magic square generator

This code that runs only for odd N. The problem is that there are no ideas how to add support for even values N
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
setlocale(0, "");
int n;
cout << "Enter the size of the magic square - ";
cin >> n;
int **matrix = new int *[n];
for (int i = 0; i < n; ++i)
{
matrix[i] = new int[n];
}
int nsqr = n * n;
int i = 0, j = n / 2;
for (int k = 1; k <= nsqr; ++k)
{
matrix[i][j] = k;
i--;
j++;
if (k % n == 0)
{
i += 2;
--j;
}
else
{
if (j == n)
{
j -= n;
}
else if (i < 0)
{
i += n;
}
}
}
cout << "\n\nMagic square size - " << n << "\n\n";
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cout << matrix[i][j] << "\t";
}
cout << endl;
}
for (i = 0; i < n; i++)
delete[] matrix[i];
delete[] matrix;
system("pause >> null");
return 0;
}
I would be grateful for tips on troubleshooting.
If i'm not mistaken, the problem is in this line:
int i = 0, j = n / 2;
But i don't know how to change the code to support even values
I would assume that you meant normal magic square (where the number are restricted to 1,2..n^2)
First of all, it's impposible to construct such magic square for n=2.
2nd, you would need an whole new algorithm for it, which is much more complicated. The problem (constructing magic square for any even number) is solved in this paper and while there isn't any psaudo code there, the implementation from the explenation is quite straightforward (long one though).
the problem is here:
i = 0;
int j = n / 2;
for (int k = 1; k <= nsqr; ++k)
{
matrix[i][j] = k;
i--;
}
look how you decrement i inside the loop and making it as an index of the array so:
matrix[-3][j] = k; // will be in your code
you are messing deliberately with the indexes of the array
I found answer on my question in this artcile
I made full revision my algorithm based on this article. Later posted listing the resulting program

Why doesn't this C++ insertion sort work?

I'm learning C++ and this is one of my first programs that is going to sort a list of numbers, I found the algorithm in Kenneth H. Rosen book and wrote it in C++. when I check it on the paper it seems to be correct, but in practice it has some error. For example I enter 3(enter)2(enter)1(enter)4(enter)5(enter) and it returns 3 1 1 4 5 as the answer. I don't know what is the problem, please help.
int main()
{
int i, j, s, n, k, a[50];
cout << "Enter number of numbers:\n";
cin >> n;
cout << "Enter the numbers:\n";
for (i = 0; i < n; i++) {
cin >> a[i];
}
for (j = 2; j < n; j++) {
i = 1;
while (a[j] > a[i]) {
i = i + 1; // Here we find the proper place to(if needed) directly insert our number into the sorted part.
}
s = a[j];
for (k = 0; k < j - i - 1; k++) {
a[j - k] = a[j - k - 1];
}
a[i] = s;
}
for (i = 0; i < n; i++) {
cout << a[i] << " ";
}
_getch();
return 0;
}
I've also included the header files and namespace, not written here though. And in the case you think I have used so many variables, sorry about that, I needed them :)
Your index i should start from the first element which is 0 instead of 1.
Fixing line 11 should do the job:
for (j = 2; j < n; j++) {
i = 0;
while (a[j] > a[i]) {
Edit:
Oh, and also, your variable j should start from the second element which is index 1 instead of 2:
for (j = 1; j < n; j++) {