Related
Here is a question from codewars.com
Given a list and a number N, create a new list that contains each number of lst at most N times without reordering. For example if N = 2, and the input is [1,2,3,1,2,1,2,3], you take [1,2,3,1,2], drop the next [1,2] since this would lead to 1 and 2 being in the result 3 times, and then take 3, which leads to [1,2,3,1,2,3].
And here is my code:
std::vector<int> deleteNth(std::vector<int> arr, int n)
{
int counting = 0;
int counting2 = 0;
for (int i : arr)
{
for (int j : arr)
{
cout << arr.size() << " " << counting<<" "<<counting2<<endl;
if (i == j)
{
++counting;
if (counting > n) { arr.erase(arr.begin() + counting2); --counting2; }
}
counting2++;
}
counting = 0;
counting2 = 0;
}
return arr;
The basic tests are fine. But when i attemp their random test. It 's a mess.
Expected: equal to [ 8, 32, 32, 8, 8, 26, 26, 8, 19, 26, 26, 19, 26, 26, 19, 8, 8, 19, 26, 8, 8, 19, 32, 32, 26, 50, 19, 32, 32, 32, 19]
Actual: [ 8, 32, 32, 8, 8, 26, 26, 8, 19, 26, 26, 19, 26, 26, 19, 8, 8, 19, 26, 8, 8, 19, 32, 26, 50, 19, 32, 32, 19 ]
I see that you have two nested loops here. You can acheive what you want to do with a single loop. Just use a frequency array. Here I'm using std::map because the range of numbers in unknown. If the range is known, you can use an array or std::vector and have the code run in O(N).
#include <iostream>
#include <vector>
#include <map>
std::vector<int> deleteNth(std::vector<int>& arr, int n)
{
std::map<int, int> freq;
std::vector<int> result;
for (int number : arr)
{
if (freq[number] >= n)
continue;
result.push_back(number);
freq[number]++;
}
return result;
}
int main()
{
std::vector<int> v{ 1,2,3,1,2,1,2,3 };
auto result = deleteNth(v, 2);
for (int i : result)
std::cout << i << ' ';
}
Output:
1 2 3 1 2 3
I am working on a program which implements the inversion counting with merge sort algorithm.
When I test my program with given test cases. I experienced segmentation fault which I cannot find the reason.
One test case is shown in the following codes:
int inputArray[5] = {5,4,3,2,1};
inversionCount Inversion(inputArray, 5);
count = Inversion.totalinversionCount(0, 4);
The program gives the correct answer as 10.
Another test case is:
int inputArray[15] = {9, 12, 3, 1, 6, 8, 2, 5, 14, 13, 11, 7, 10, 4, 0};
inversionCount Inversion(inputArray, 15);
count = Inversion.totalinversionCount(0, 14);
The program gives an answer as 48, while the correct answer is 56. I tried to debug the program by printing the array[] elements in the class. It seems in the constructor the copied array[] is {9 12 3 1 6 8 2 5 14 13 11 7 10 4 0}. However, when the program steps into counting, the class member array[] changed to {0 12 3 1 6 8 2 5 14 13 11 7 10 4 0}. The first element changed to 0 from 9. I don't know why.
The last test case is:
int inputArray[100] = { 4, 80, 70, 23, 9, 60, 68, 27, 66, 78, 12, 40, 52, 53, 44, 8, 49, 28, 18, 46, 21, 39, 51, 7, 87, 99, 69, 62, 84, 6, 79, 67, 14, 98, 83, 0, 96, 5, 82, 10, 26, 48, 3, 2, 15, 92, 11, 55, 63, 97, 43, 45, 81, 42, 95, 20, 25, 74, 24, 72, 91, 35, 86, 19, 75, 58, 71, 47, 76, 59, 64, 93, 17, 50, 56, 94, 90, 89, 32, 37, 34, 65, 1, 73, 41, 36, 57, 77, 30, 22, 13, 29, 38, 16, 88, 61, 31, 85, 33, 54 };
inversionCount Inversion(inputArray, 100);
count = Inversion.totalinversionCount(0, 99);
The program runs into segmentation fault in the construction step. The debug shows the program pauses when copying Array[] to array[].
Signal received: SIGSEGV (Segmentation fault)
For program algorithm_design_i_week_1, pid 23,328
You may discard the signal or forward it and you may continue or pause the process
My program is given below. Please help me to find out the reason for segmentation fault. Thank you very much.
inversionCount.h
#ifndef INVERSIONCOUNT_H
#define INVERSIONCOUNT_H
#include <iostream>
using namespace std;
class inversionCount {
private:
int length;
int array[];
public:
inversionCount(int Array[], int Length);
int splitCount(int first, int mid, int last);
int totalinversionCount(int first, int last);
};
#endif /* INVERSIONCOUNT_H */
inversionCount.cpp
#include "inversionCount.h"
inversionCount::inversionCount(int Array[], int Length) {
length = Length;
for (int i = 0; i < length; i++)
array[i] = Array[i];
}
int inversionCount::splitCount(int first, int mid, int last) {
int first1 = first, last1 = mid;
int first2 = mid + 1, last2 = last;
int tempArray[length];
int i = first;
int totalSplitCount = 0;
while (i < last && first1 <= last1 && first2 <= last2) {
if (array[first1] < array[first2]) {
tempArray[i] = array[first1];
first1++;
i++;
}
else {
tempArray[i] = array[first2];
totalSplitCount += last1 + 1 - first1;
first2++;
i++;
}
}
while (first1 <= last1) {
tempArray[i] = array[first1];
first1++;
i++;
}
while (first2 <= last2) {
tempArray[i] = array[first2];
first2++;
i++;
}
for (int j = first; j < last + 1; j++)
array[j] = tempArray[j];
return totalSplitCount;
}
int inversionCount::totalinversionCount(int first, int last) {
int totalCount = 0;
if (first < last) {
int mid = (first + last) / 2;
totalCount = totalinversionCount(first, mid) + totalinversionCount(mid + 1, last) + splitCount(first, mid, last);
}
return totalCount;
}
countDriver.cpp
#include "inversionCount.h"
int main(int argc, char** argv) {
int inputArray[5] = {5,4,3,2,1};
inversionCount Inversion(inputArray, 5);
int count = 0;
count = Inversion.totalinversionCount(0, 4);
cout<<"The number of inversions is "<<count<<endl;
return 0;
}
int array[]; is not legal C++ as the definition of a member variable. Your compiler must allow it as an extension, but in that case it means "no space is allocated for the array, but we will do something like:
A* pA = static_cast<A*>(malloc(sizeof(A) + Length*sizeof(int));
You are not doing this, so when you write to the array, you overwrite some random bits of memory, so bad stuff happens.
The best bet is to use std::vector.
class inversionCount {
private:
std::vector<int> array;
public:
inversionCount(int Array[], int Length) : array(Array, Array+Length) {}
int splitCount(int first, int mid, int last);
int totalinversionCount(int first, int last);
};
One other comment: it is much better to use size_t as the type of lengths and offsets into arrays and containers - it is what the C++ library uses. size_t is an unsigned type so by using the same type as the library, you avoid difficult problems with 'signed/unsigned mismatch'. (The effects are often not what you would expect.)
I have two programs, compiled with g++ and executed on linux. Program 1 creates a 2D array and then measures how long it takes to access all of its elements 100000 times:
#include <time.h>
#include <iostream>
int main()
{
clock_t time;
int i, y, x;
int matrix[9][9]{{ 0, 1, 2, 3, 4, 5, 6, 7, 8},
{ 9, 10, 11, 12, 13, 14, 15, 16, 17},
{18, 19, 20, 21, 22, 23, 24, 25, 26},
{27, 28, 29, 30, 31, 32, 33, 34, 35},
{36, 37, 38, 39, 40, 41, 42, 43, 44},
{45, 46, 47, 48, 49, 50, 51, 52, 53},
{54, 55, 56, 57, 58, 59, 60, 61, 62},
{63, 64, 65, 66, 67, 68, 69, 70, 71},
{72, 73, 74, 75, 76, 77, 78, 79, 80}};
time = clock();
for (i = 0; i < 100000; i++)
{
for (x = 0; x < 9; x++)
{
for (y = 0; y < 9; y++)
{
matrix[x][y];
}
}
}
time = clock() - time;
std::cout << "Clicks: " << time << std::endl;
std::cout << "Time taken: " << (double) time / CLOCKS_PER_SEC << "s" << std::endl;
}
Program 2 creates a 1D array and also measures how long it takes to access all of its elements 100000 times:
#include <time.h>
#include <iostream>
int main()
{
clock_t time;
int i, j;
int vector[81] = { 0, 1, 2, 3, 4, 5, 6, 7, 8,
9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26,
27, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43, 44,
45, 46, 47, 48, 49, 50, 51, 52, 53,
54, 55, 56, 57, 58, 59, 60, 61, 62,
63, 64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79, 80};
time = clock();
for (i = 0; i < 100000; i++)
{
for (j = 0; j < 81; j++)
{
vector[j];
}
}
time = clock() - time;
std::cout << "Clicks: " << time << std::endl;
std::cout << "Time taken: " << (double) time / CLOCKS_PER_SEC << "s" << std::endl;
}
After executing program 1 my output is:
Clicks: 8106
Time taken: 0.008106s
After executing program 2 my output is:
Clicks: 15958
Time taken: 0.015958s
It is my understanding that a 1D array is stored in a continuous block of memory. Likewise the rows of a static 2D array are stored in contiguous blocks of memory. Conversely the rows of a dynamic 2d array might not be stored in contiguous blocks of memory. If this is true then program 2 should be at least similar in speed to program 1 therefore my question is why would program 1 be remarkably faster than program 2?
Here is what I found:
If you actually make use of the value then the run time is almost the same, for example, change matrix[x][y]; to matrix[x][y] += 1; and vector[j]; to vector[j] += 1;
> Clicks: 28519
> Time taken: 0.028519s
and
> Clicks: 29941
> Time taken: 0.029941s
Without the above changes, optimize while compiling, g++ -O3 <filename>.cpp, this results in same time, got the same following output for both programs:
$./a.out
> Clicks: 2
> Time taken: 2e-06s
So, what you are pointing out is compiler optimizations.
The loops are likely to be removed (kind of optimising) by compiler, because
You actually did nothing in loops.
The matrix can be treated as a const array.
program 1 is faster than program 2. ( :< )
To see whether the deletion happens to your code during compiling, you can increase the most outer loop by 100 times, and see whether the time needed for execution is increased significantly (not necessarily by exact 100 times).
If true, you can prevent this kind of optimising by doing some actual works in loop (calculate the sum, and don't forget printing it afterwards) and introduce some "unpredictable" changes to your matrix, for example:
srand(10);
for (int i=0; i<9; ++i) {
matrix[i][i] = rand()%100;
}
And further, compiler may conduct some other optimising to your code, for example, expand your loops, even the address of the element you are visiting (they are no longer calculated at run time), you can prevent this by making the executing times of loops "unpredictable" :
#include <chrono>
#include <iostream>
#include <cstdlib>
int array[100];
int array2[10][10];
int64_t Sum1D(int len) {
int64_t sum = 0;
for (int i=0; i<100000; ++i) {
for (int j=0; j<len; ++j) {
sum += array[j];
}
}
return sum;
}
int64_t Sum2D(int len1, int len2) {
int64_t sum = 0;
for (int i=0; i<100000; ++i) {
for (int j=0; j<len1; ++j) {
for (int k=0; k<len2; ++k)
sum += array2[j][k];
}
}
return sum;
}
int main()
{
for (int i=0; i<100; ++i) {
array[i] = rand();
array2[i%10][i/10] = rand();
}
auto time = std::chrono::steady_clock::now();
//int64_t sum = Sum1D(100);
int64_t sum = Sum2D(10,10);
auto duration = std::chrono::steady_clock::now()-time;
std::cout << sum << "!" << duration.count() << std::endl;
return 0;
}
which finally makes program1 slower than program2. ( :> )
I understand the array address but this code which I found in a book made me nut.I understand the recursive function too but did not get this one.Here is the code:
int main(){
const int arraySize = 5;
int a[arraySize] = { 32, 27, 64, 18, 95};
cout << "The values in reverse array are:" << endl;
someFunction(a, arraySize);
cout << endl;
cin.get();
return 0;
}
void someFunction(int b[], int size)
{
if (size > 0) {
someFunction(&b[1], size - 1);
cout << b[0] << " ";
}
}
I got this code in a exercise.My question is how it is reversing the array?I will be happy if anyone explain a bit more.thanks
Here is some pseudo-code which shows how the recusive calls to someFunction will be made, and in which order:
someFunction( { 32, 27, 64, 18, 95} , 5)
someFunction( { 27, 64, 18, 95}, 4)
someFunction( { 64, 18, 95}, 3)
someFunction( { 18, 95}, 2)
someFunction( { 95}, 1)
someFunction( { }, 0)
someFunction({ }, 0) will return without doing anything because there is nothing left in the array. Now someFunction will print the first element b[0] of the arrays as it comes out of the recursion, beginning with the array containing only one item {95}:
{ 95 }
{ 18, 95}
{ 64, 18, 95}
{ 27, 64, 18, 95}
{ 32, 27, 64, 18, 95}
So your output will be:
"The values in reverse array are:"
95 18 64 27 32
b[1] is the second element of the array. &b[1] is the address of the second element, so it is just like the original array, but 1 smaller and skipping the first element.
If you print out everything except the first element before you print the first, and do it recursively, the result is it prints out in reverse order.
Note that the actual array has not been reversed. It only gets printed in reverse order. And it's nonsense. A loop is better.
I'm currently coding a small heapify code that repeated runs bubble down but everytime it seems like nothing's happening. Not sure what's wrong here maybe I'm missing something?
template <class T>
void PriorityQueue<T>::heapify (int* arrs, int size){
int i = (size-1)/2;
while (i >= 0){
bubbleDown(arrs, i, (size));
i--;
}
}
template <class T>
void PriorityQueue<T>::bubbleDown (int* arrs, int i, int size)
{
//Each level node's are indexed at 2^(level) - 2 to 2^(level+2) - 2
//Children of these node's levels are indexed at 2i+1 and 2i+2
//The parent of node i, is indexed at (i-1)/2
int leftChildren = (2*i)+1;
int rightChildren = (2*i)+2;
int largest = i;
if (rightChildren < size)
{
if (arrs[leftChildren] < arrs[rightChildren]){
largest = rightChildren;
}
else{
largest = leftChildren;
}
if (arrs[i] > arrs[largest]){
largest = i;
}
}
else if (leftChildren < size)
{
if (arrs[i] < arrs[leftChildren]){
largest = leftChildren;
}
}
if (arrs[i] < arrs[largest])
{
int temp = arrs[i];
arrs[i] = arr[largest];
arrs[largest] = temp;
}
}
I'm calling it like this:
PriorityQueue<int> test;
int arr[] = {89, 29, 36, 48, 94, 13, 27, 70, 76, 37, 42, 58};
test.heapify(arr, 12);
for (int i = 0; i < 12; i++){
cout << arr[i] << endl;
}
Console prints out it the same way the array has been initialized.
UPDATED:
Still getting weird results
[89, -842150451, 36, 29, 94, 0, 27, 70, 48, 37, 42, 13]
The results I should be getting is
[94, 76, 89, 70, 48, 58, 13, 27, 36, 29, 37, 42, 23]
Basic typo error. Should really use more meaningful names