I have written the following program intended on comparing float's in C++. Originally this was written trying to compare double's but I soon realized how bad a problem that is. In general what is supposed to happen is that the program is to compare the two numbers of the given slot array and swap them as necessary.
#include<iostream>
using namespace std;
int swap(float[] , int, int);
int main() {
float slot[10] = {8.25, 3.26, 1.20, 5.15, 7.99, 10.59, 4.36, 9.76, 6.29, 2.09};
int n=10, i;
int lower, upper, sortflag, sml, scan;
lower = 0;
upper = n-1;
sortflag = 1;
float temp;
while( (lower < upper) && (sortflag == 1)) {
sml = lower;
sortflag = 0;
scan = lower + 1;
while(scan <= upper - lower) {
if (slot[scan] > slot[scan + 1]) {
swap(slot, scan, scan + 1);
sortflag = 1;
if(slot[scan] < slot[sml]) sml = scan;
}
scan++;
}
swap(slot, lower, sml);
upper = upper - 1;
lower = lower + 1;
}
cout << "AFTER SORT: " << endl;
for (i= 0; i < n; i++) cout << slot[i] << " ";
cout << endl;
return 0;
}
void swap(float data[], int i, int j) {
float temp;
temp = data[i];
data[j] = data[i];
data[j] = temp;
}
When I ran this program with double instead of float, the program ran infinitely until I had to invoke Ctrl+C to break it. After switching to float I instead get the following output:
AFTER SORT:
8.25 8.25 3.26 5.15 7.99 10.59 10.59 10.59 10.59 10.59
0 0 1 3 4 5 5 5 5 5
--------------------------------
Process exited after 0.06651 seconds with return value 0
Press any key to continue . . .
Where is the logic going wrong?
EDIT: So after some consideration, I went ahead and rewrote the program to make it compare int array values instead.
int slot[10] = {8, 3, 1, 5, 7, 10, 4, 9, 6, 2};
And adjusted all the appropriate functions as necessary:
// Declaration of function:
void swap(int[] , int, int);
void swap(int data[], int i, int j) {
int temp;
temp = data[i];
data[i] = data[j];
data[j] = temp;
}
And the function is now coming up correct with the correct input. There is no problems with going out of bounds here.
AFTER SORT:
1 2 3 4 5 6 7 8 9 10
--------------------------------
Process exited after 0.05111 seconds with return value 0
Press any key to continue . . .
Here's the new modified program:
int main() {
int slot[10] = {8, 3, 1, 5, 7, 10, 4, 9, 6, 2};
int n=10, i;
int lower, upper, sortflag, sml, scan;
lower = 0;
upper = n-1;
sortflag = 1;
while( (lower < upper) && (sortflag == 1)) {
sml = lower;
sortflag = 0;
scan = lower + 1;
while(scan <= (upper-lower)) {
if (slot[scan] > slot[scan + 1]) {
swap(slot, scan, scan + 1);
sortflag = 1;
if(slot[scan] < slot[sml]) sml = scan;
}
scan++;
}
swap(slot, lower, sml);
upper = upper - 1;
lower = lower + 1;
}
cout << "AFTER SORT: " << endl;
for (i= 0; i < n; i++) cout << slot[i] << " ";
cout << endl;
//for (i= 0; i < n; i++) cout << index[i] << " ";
cout << endl;
return 0;
}
void swap(int data[], int i, int j) {
int temp;
temp = data[i];
data[i] = data[j];
data[j] = temp;
}
So now the question is why does the int version work without problem but neither the double nor float versions do?
Your swap function is wrong. data[j] = data[i]; is useless when followed by another write data[j] = temp;. It should be like this
int swap(float data[], int i, int j) {
float temp;
temp = data[i];
data[i] = data[j]; // reverse this line
data[j] = temp;
return 0;
}
And there's no point making the function returning int if you don't use the result. Just declare it void
Related
I'm very new to C++ or even coding. I was trying to make a simple array sorter, where the I first input the number of elements that will be in the array and then input the elements. My outcome should be the array sorted in ascending order. I have not thought about the case if elements inserted are same. So I would love to get some help from you folks.
The main error that I'm facing is that only the first unsorted element is sorted while the rest are either interchanged or left the same.
int main(){
int x;
cout<<"Enter no. of elements"<<endl;
cin>>x;
int A[x];
for (int i = 0;i<x;i++){
cin>>A[i];
}
for(int i=0;i<x;i++)
cout<<A[i]<<",";
int count=0;
if(count <= (x-1)){
for (int i=0;i<(x-1);i++){
if(A[i]>A[i+1]){
int a;
a = A[i];
A[i] = A[(i+1)];
A[i+1] = a;
}
else if(A[i]<A[i+1])
count++;
}
}
cout<<"Sorted array:";
for(int i=0;i<x;i++)
cout<<A[i]<<",";
return 0;
}
You declared a variable length array
int x;
cout<<"Enter no. of elements"<<endl;
cin>>x;
int A[x];
because its size is not a compile-time constant.
However variable length arrays are not a standard C++ feature though some compilers have their own language extensions that support variable length arrays,
It is better to use the class template std::vector.
Another problem is that it seems you are trying to use the bubble sort method to sort the array. But this method requires two loops.
Here is a demonstration program that shows how the bubble sort algorithm can be implemented.
#include <iostream>
int main()
{
int a[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
const size_t N = sizeof( a ) / sizeof( *a );
for (const auto &item : a)
{
std::cout << item << ' ';
}
std::cout << '\n';
for (size_t last = N, sorted = N; not ( last < 2 ); last = sorted)
{
for (size_t i = sorted = 1; i < last; i++)
{
if (a[i] < a[i - 1])
{
// std::swap( a[i-1], a[i] );
int tmp = a[i - 1];
a[i - 1] = a[i];
a[i] = tmp;
sorted = i;
}
}
}
for (const auto &item : a)
{
std::cout << item << ' ';
}
std::cout << '\n';
}
The program output is
9 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 9
Let us try the following method:
find the largest element in the array and move it to the end, by swapping with the last element;
repeat with the array but the last element, and so on.
To find the largest element in A[0..m-1], scan the array and keep an index to the largest so far, let l. This index can be initialized to 0.
// Move the largest to the end
int l= 0;
for (int i= 1; i < m; i++)
{
if (A[i] > A[l]) l= i;
}
// A[l] is the largest in A[0..m-1]
Swap(A[l], A[m-1]);
// A[m-1] is the largest in A[0..m-1]
To sort, repeat with decreasing m. You can stop when the subarray just holds one element:
// Sort
for (int m= n-1; m > 1; m--)
{
// Move the largest to the end
....
}
Writing the Swap operation and assembling the whole code is your task. Also check
correctness of the Move for the limit cases m= 0, 1, 2.
correctness of the Sort for the limit cases n= 1, 2, 3.
how you could instrument the code to verify that the Move does its job.
how you could instrument the code to verify that the Sort does its job.
what happens in case of equal keys.
Your code can be fixed a bit to make it working.
Just replace if (count <= (x - 1)) with while (count < (x - 1)) and also set count = 0; at start of loop, plus replace else if (A[i] < A[i + 1]) with just else. And your code becomes working!
Necessary fixes I did in code below. Also I did formatting (indents and spaces) to make code looks nicer. Rest remains same.
As I see you have a kind of Bubble Sort.
Try it online!
#include <iostream>
using namespace std;
int main() {
int x;
cout << "Enter no. of elements" << endl;
cin >> x;
int A[x];
for (int i = 0; i < x; i++) {
cin >> A[i];
}
for (int i = 0; i < x; i++)
cout << A[i] << ",";
int count = 0;
while (count < (x - 1)) {
count = 0;
for (int i = 0; i < (x - 1); i++) {
if (A[i] > A[i + 1]) {
int a;
a = A[i];
A[i] = A[(i + 1)];
A[i + 1] = a;
} else
count++;
}
}
cout << "Sorted array:";
for (int i = 0; i < x; i++)
cout << A[i] << ",";
return 0;
}
Input:
10
7 3 5 9 1 8 6 0 2 4
Output:
7,3,5,9,1,8,6,0,2,4,Sorted array:0,1,2,3,4,5,6,7,8,9,
If you are taking the size of array as input from user you have to create your array dynamically in c++ like
int *array=new int(x)
and after taking the inputs of the elements just run a nested loop from 0 to size and
the inner loop from 0 to size-1 and check if(A[i]>A[i+1]) if true then swap the values else continue
I have to display the records based on the integer value in an array. For instance, if I have an array i.e.
2, 3, 5, 3, 6, 8, 10, 1, 9, 7
I would need to display 3 and 5 based on the integer 2. Then it should display 6,8 and 10 based on integer 3 and then 9 based on 1. So my display array would be:
3,5
6,8,10
9
So far, I haven't been able to form any algorithm/code.. How to proceed on this one?
tested it with your given array...
void display_records(std::vector<int> vi) {
int tmp = 0;
int index = 0;
for(int i=0;i<vi.size(); i++){
for(int j=1;j<=vi[i];j++){
index = i + j;
tmp = vi[index];
if((i+j) < vi.size()) { //to prevent it going out of range
std::cout << tmp << " " ;
}
}
i = i + vi[i];
std::cout << std::endl;
}
}
Try something like this: (i am not sure if i understood your question) (not tested)
void displayRecords(int* vect, int size, int val)
{
for(int i=0; i<size; i++)
{
if(vect[i]==val)
{
int tmp = val;
int j = i + 1;
while(tmp && j != size)
{
std::cout<<vect[j]<<" ";
j++;
tmp--;
}
break;
}
}
}
I'm trying to get the longest(largest) sequence of consecutive prime numbers from an array..
On first test with 10 elements in the array works , but when i tried with 15 elements like: 3, 5, 7, 8, 9, 11, 13, 17, 19, 20, 23, 29, 31, 37, 41 it spit out 4, which is incorrect.
#include <iostream>
using namespace std;
int main()
{
int bar[100];
int x, j = 0;
int maxseq = 0;
int longestseqstart = 0;
cout << "How big is the array? =";
cin >> x;
for (int i = 0; i < x; i++) {
cout << "bar[" << i << "]=";
cin >> bar[i];
}
for (int i = 1; i < x - 1; i = j) {
int startseq = i;
int seq = 0;
j = i + 1;
bool prim = true;
int a = bar[i];
for (int d = 2; d <= a / 2; d++) {
if (a % d == 0) {
prim = false;
}
}
while (j < x && prim) {
seq++;
if (seq > maxseq) {
maxseq = seq;
longestseqstart = i;
}
int a = bar[j];
for (int d = 2; d <= a / 2; d++) {
if (a % d == 0) {
prim = false;
}
}
j++;
}
}
cout << "The longest sequence is: ";
cout << maxseq;
return 0;
}
I would write the program the following way
#include <iostream>
#include <iterator>
#include <algorithm>
bool is_prime( unsigned int n )
{
bool prime = n % 2 == 0 ? n == 2 : n != 1;
for ( unsigned int i = 3; prime && i <= n / i; i += 2 )
{
prime = n % i != 0;
}
return prime;
}
int main()
{
unsigned int a[] = { 3, 5, 7, 8, 9, 11, 13, 17, 19, 20, 23, 29, 31, 37, 41 };
const size_t N = sizeof( a ) / sizeof( *a );
size_t maxseq = 0;
for ( auto current = std::find_if( a, a + N, is_prime );
current != a + N;
current = std::find_if( current, a + N, is_prime ) )
{
auto first = current;
current = std::find_if_not( current, a + N, is_prime );
size_t n = std::distance( first, current );
if ( maxseq < n ) maxseq = n;
}
std::cout << "The longest sequence is: " << maxseq << '\n';
return 0;
}
The program output is
The longest sequence is: 5
I did not use generic functions std::begin( a ) and std::end( a ) because in your program the array can contain less actual elements than the array dimension.
If you do not know yet standard C++ algorithms then the program can be defined the following way
#include <iostream>
bool is_prime( unsigned int n )
{
bool prime = n % 2 == 0 ? n == 2 : n != 1;
for ( unsigned int i = 3; prime && i <= n / i; i += 2 )
{
prime = n % i != 0;
}
return prime;
}
int main()
{
unsigned int a[] = { 3, 5, 7, 8, 9, 11, 13, 17, 19, 20, 23, 29, 31, 37, 41 };
const size_t N = sizeof( a ) / sizeof( *a );
size_t maxseq = 0;
size_t n = 0;
for ( size_t i = 0; i < N; i++ )
{
bool prime = a[i] % 2 == 0 ? a[i] == 2 : a[i] != 1;
for ( unsigned int j = 3; prime && j <= a[i] / j; j += 2 )
{
prime = a[i] % j != 0;
}
if ( prime )
{
if ( maxseq < ++n ) maxseq = n;
}
else
{
n = 0;
}
}
std::cout << "The longest sequence is: " << maxseq << '\n';
return 0;
}
The program output is the same as above
The longest sequence is: 5
As for your program then this loop
for (int i = 1; i < x - 1; i = j) {
skips the first element of the array that is bar[0].
And due to this statement
j = i + 1;
the calculated value of seq one less than it should be because you do not take into account that bar[i] is already prime.
Set initially seq equal to 1.
int seq = 1;
Moreover you incorrectly are determining prime numbers. For example according to your algorithm 1 is prime.
You are checking twice for prime numbers and you are using a nested loop. That's not necessary. It's enough to read all numbers, check each number, increment the count if it's a prime number and store the maximum sequence length.
#include <iostream>
#include <vector>
using namespace std;
bool isPrime(int a) {
bool prim = true;
for (int d = 2; d*d <= a; ++d) {
if (a % d == 0) {
prim = false;
}
}
return prim;
}
int main()
{
int x;
int longestseqstart = 0;
cout << "How big is the array? =";
cin >> x;
std::vector<int> bar(x);
for (int i = 0; i < x; i++) {
cout << "bar[" << i << "]=";
cin >> bar[i];
}
unsigned int count = 0;
unsigned int maxseq = 0;
for (const auto &el : bar) {
if (isPrime(el)) {
++count;
if (count > maxseq) maxseq = count;
} else count = 0;
}
cout << "The longest sequence is: ";
cout << maxseq;
return 0;
}
Of course you can avoid the usage of std::vector and functions with
#include <iostream>
using namespace std;
int main()
{
int x;
int longestseqstart = 0;
cout << "How big is the array? =";
cin >> x;
int bar[100];
for (int i = 0; i < x; i++) {
cout << "bar[" << i << "]=";
cin >> bar[i];
}
unsigned int count = 0;
unsigned int maxseq = 0;
for (unsigned int i = 0; i < x; ++i) {
int a = bar[i];
bool prim = true;
for (int d = 2; d*d <= a; ++d) {
if (a % d == 0) {
prim = false;
}
}
if (prim) {
++count;
if (count > maxseq) maxseq = count;
} else count = 0;
}
cout << "The longest sequence is: ";
cout << maxseq;
return 0;
}
The algorithm looks basically OK. The issue is mostly one of organization: the way the inner loop block is set up means that a run of primes will be short by 1 because the longest sequence is only updated at the beginning of the inner loop, missing the final prime.
A couple of minimal failing examples are:
How big is the array? =1
bar[0]=13
The longest sequence is: 0
How big is the array? =2
bar[0]=5
bar[1]=6
The longest sequence is: 0
Note that there's a repeated prime check in two places. This should not be. If we move all of the prime logic into the loop and test for a new longest sequence only after finishing the entire run, we'll have a clear, accurate algorithm:
#include <iostream>
int is_prime(int n) {
for (int i = 2; i <= n / 2; i++) {
if (n % i == 0) {
return false;
}
}
return true;
}
int main() {
int nums[100];
int n;
std::cout << "How big is the array? =";
std::cin >> n;
for (int i = 0; i < n; i++) {
std::cout << "nums[" << i << "]=";
std::cin >> nums[i];
}
int longest = 0;
for (int i = 0, start = 0; i < n; i++) {
for (start = i; i < n && is_prime(nums[i]); i++);
longest = std::max(longest, i - start);
}
std::cout << "The longest sequence is: " << longest;
return 0;
}
In this rewrite I...
avoided using namespace std;.
removed unnecessary/confusing variables.
used clear variable names (bar should only be used in example code when the name doesn't matter).
moved is_prime to its own function.
But there are outstanding issues with this code. It should...
use a vector instead of an array. As it stands, it's vulnerable to a buffer overflow attack should the user specify an array length > 100.
use a faster method of finding primes. We only need to check up to the square root of the number and can skip a lot of numbers such as even numbers after 2. I suspect this is incidental to this exercise but it's worth mentioning.
move the longest_prime_sequence to a separate function (and possibly user input gathering as well).
Convert the array to a Boolean array and find longest length. Try this snippet(not optimized):
bool is_prime(int n) {
for (int i = 2; i < n; i++) {
if (n%i == 0) return false;
}
return true;
}
int main() {
//Input
unsigned int bar[15] = { 3, 5, 7, 8, 9, 11, 13, 17, 19, 20, 23, 29, 31, 37, 41 };
// Convert input to boolean array
bool boo[15];
for (int i = 0; i < 15; i++) {
boo[i] = is_prime(bar[i]);
}
//Check the longest boolean array
int longest = 0;
for (int i = 0; i < 15; i++) {
int count = 0;
while (boo[i + count] && (i+ count) <15) {
count++;
}
if (longest < count) longest = count;
}
//Output
cout << longest;
return 0;
}
When using the bubble sort method to sort my array from smallest to largest its outputting an unexpected value of: -858993460.
Within the debugger i'm being prompted with "Stack around variable 'numb was corrupted'.
I'm currently using Visual studios to run the code.
I have also ran the same code within a new project with no results.
#include <iostream>
int main()
{
int length = 6;
int temp = 0;
int end = 6;
int numb[] = { 6, 5, 4, 3, 2, 1 };
for (int counter = length - 1; counter > 0; counter--)
{
for (int i = 0; i < end; i++)
{
if (numb[i] > numb[i + 1])
{
temp = numb[i + 1];
numb[i + 1] = numb[i];
numb[i] = temp;
}
}
for (int i = 0; i <= 5; i++)
{
std::cout << numb[i] << " ";
}
std::cout << "\n";
end--;
}
system("pause");
}
In you inner for loop where int i = 0; i < end; i++, you need to set the condition to be i < end - 1. This is because you are already going to be at the end of the array with i + 1 when swapping the indexes around.
I'm trying to find all possible solutions to the 3X3 magic square.
There should be exactly 8 solutions.
My code gets them all but there are a lot of repeats. I'm having a hard time tracking the recursive steps to see why I'm getting all the repeats.
// This program finds all solutions to the magic square for a 3X3
// square where each column, row and diagonal sum is equal
#include <iostream>
using namespace std;
#define SQUARE_SIZE 9
int anyLine = 0;
int currLine = 0;
int numSolutions = 0;
// swap two values in the square.
void swap(int arr[], int idxa, int idxb)
{
int tmp = arr[idxa];
arr[idxa] = arr[idxb];
arr[idxb] = tmp;
}
void printArray(int arr[])
{
for (int i = 0; i < SQUARE_SIZE; i++)
{
cout << arr[i] << " ";
if ((i + 1) % 3 == 0)
cout << endl;
}
cout << endl;
}
// this function tests to see if we have a "good" arrangement of numbers
// i.e the sum of each row, column and diagonal is equal
bool checkArr(int arr[])
{
anyLine = arr[0] + arr[1] + arr[2];
currLine = 0;
for (int i = 0; i < SQUARE_SIZE; i++)
{
currLine += arr[i];
if ((i + 1) % 3 == 0)
{
if (currLine != anyLine)
return false;
currLine = 0;
}
}
// check vertically
for (int col = 0; col <3; col++)
{
for (int row = 0; row <3; row++)
{
currLine += arr[col + 3 * row];
}
if (currLine != anyLine)
return false;
currLine = 0;
}
// check the diagonals
if ((arr[2] + arr[4] + arr[6]) != anyLine)
return false;
if ((arr[0] + arr[4] + arr[8]) != anyLine)
return false;
return true;
}
void solve(int arr[], int pos)
{
if (pos == 8)
{
if (checkArr(arr))
{
printArray(arr);
numSolutions++;
}
} else
{
for (int i = 0; i < 9; i++)
{
if (i == pos) continue;
if (checkArr(arr))
{
printArray(arr);
numSolutions++;
}
swap(arr, pos, i);
solve(arr, pos + 1);
}
}
}
int main()
{
int arr[SQUARE_SIZE] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
solve(arr, 0);
cout << "number of solutions is: " << numSolutions << endl;
return 0;
}
Basically, you are finding all permutations of the array using a recursive permutation algorithm.
There are 4 things you need to change:
First, start your loop from pos, not 0
Second, swap elements back after recursing (backtracking)
Third, only test once you have generated each complete permutation (when pos = 8), or else you will be testing the same permutations more than once.
Fourth, swapping an element with itself (i.e. not swapping it) is a valid permutation, because the elements are allowed to stay in their original positions.
void solve(int arr[], int pos)
{
if (pos == 8)
{
if (checkArr(arr))
{
printArray(arr);
numSolutions++;
}
}
else
{
for (int i = pos ; i < 9; i++)
{
swap(arr,pos,i);
solve(arr,pos +1);
swap(arr,pos,i);
}
}
}
Demo
Your code calls printArray from two places - the base case of the recursion (i.e. when pos == 8) and in the loop before calling swap. The second call is unnecessary: you would get the same square when you reach the pos == 8 state.
This brings the number of duplicates down, but it does not eliminate them because of the way in which you generate your squares. You need to keep track of what has been printed. One way to do it is to make a set of solutions that you have found, and check it before printing the newly found solution:
set<int> seen;
int key(int arr[]) {
return arr[0]
+ 10 * arr[1]
+ 100 * arr[2]
+ 1000 * arr[3]
+ 10000 * arr[4]
+ 100000 * arr[5]
+ 1000000 * arr[6]
+ 10000000 * arr[7]
+ 100000000 * arr[8];
}
void printArray(int arr[]) {
if (!seen.insert(key(arr)).second) {
// second is set to false when a duplicate is found
return;
}
numSolutions++;
for (int i = 0; i < SQUARE_SIZE; i++) {
cout << arr[i] << " ";
if((i+1) % 3 == 0)
cout << endl;
}
cout << endl;
}
Demo.
A few things to note about the solution above:
key(int[]) converts the square to a single decimal number, so this approach is going to work only for squares composed of decimal digits. You would need a different strategy for arbitrary numbers - for example, using a set of comma-separated strings.
Counting of solutions is moved to printArray(int[]). You could drop numSolutions altogether, and use seen.size() instead; it provides the same answer.
If you don't want to actually solve this recursively for exercise purposes, I'd recommend using std::next_permutation:
void solve(int(&arr)[SQUARE_SIZE], int pos)
{
sort(std::begin(arr), std::end(arr));
do {
if (checkArr(arr)) {
numSolutions++;
printArray(arr);
}
} while (next_permutation(begin(arr), end(arr)));
}