Trouble Sort Google CodeJam 2018 Qualifiers - c++

I am trying to improve my programming skills by solving couple of Code Jam questions. I have been stuck for a while on the "Trouble Sort" question from the Qualifier Rounds in 2018. My code produces the expected output with the example input in my console, but the online judge return "Wrong Answer".
Apparently Trouble sort is just like bubble sort, except instead of comparing the ith and i+1th elements, it compares the ith and i+2th elements and if the former is greater than the latter then the elements are swapped. The question says that this algorithm is flawed as arrays like 897 after trouble sort will return 798, which isn't sorted either. The task is to check if for a given list of integers, trouble sort is able to successfully sort the array or if it isn't then which is the index value of the first element that is out of place.
My code inputs the number of tests t and the size of integer list. Then I make a copy of it and put one copy through bubble sort and the other through trouble sort. Then I compare them element wise and if an index which has the two elements as different integers is found, it is outputted. I'm not sure what I am doing wrong here.
#include<iostream>
#include<vector>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
void swapVal(int& a, int& b)
{
int t = a;
a = b;
b = t;
}
int main()
{
int t;
cin >> t;
for (int i = 1; i <= t; i++)
{
int n;
cin >> n;
vector<int> bs(n);
vector<int> ts(n);
for (int i = 0; i < n; i++)
{
cin >> bs[i];
ts[i] = bs[i];
}
//bubbleSort(bs, n);
{
bool bsSorted = false;
while (!bsSorted)
{
bsSorted = true;
for (int i = 0; i < n - 1; i++)
{
if (bs[i] > bs[i + 1])
{
swapVal(bs[i], bs[i + 1]);
bsSorted = false;
}
}
}
}
//troubleSort(ts, n);
{
bool tsSorted = false;
while (!tsSorted)
{
tsSorted = true;
for (int i = 0; i < n - 2; i++)
{
if (ts[i] > ts[i + 2])
{
swapVal(ts[i], ts[i + 2]);
tsSorted = false;
}
}
}
}
bool same = true;
int minidx = 0;
for (int i = 0; i < n; i++)
{
if (bs[i] != ts[i])
{
same = false;
minidx = i;
break;
}
}
if (same == true)
{
cout << "Case #" << i << ": OK" << endl;
}
else if (same == false)
{
cout << "Case #" << i << ": " << minidx;
}
}
}
I am expecting the judge to give me a tick of approval, but instead it is repeatedly returning "Wrong Answer". What am I doing wrong here?

The algorithm looks correct to me. I noticed that in the false case you seem to be missing the newline. So two consecutive false statements will be on the same line.
cout << "Case #" << i << ": " << minidx<<'\n';
Might solve your problem.
Few remarks:
if (same == true) is equivalent to if(same) and if (same == false) to if(!same).
There's already std::swap.
Some people might not like nested for loops having equally named variables - the nested variable will hide the outer one.

Related

Selection Sort Implementation with C++ incorrect

really new to C++, trying to instantiate some basic algorithms with it. Having trouble returning the correct result for selection sort. Here is my code
#include <iostream>
#include <array>
#include <vector>
using namespace std;
// Selection Sort :
int findMin(vector<int> &arr, int a)
{
int m = a;
for (int i = a + 1; i < arr.size(); i++)
{
if (arr[i] < arr[m])
{
m = i;
}
return m;
}
}
void swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
void selectionSort(vector<int> &arr)
{
if (!arr.empty())
{
for (int i = 0; i < arr.size(); ++i)
{
int min = findMin(arr, i);
swap(arr[i], arr[min]); // Assume a correct swap function
}
}
}
void print(vector<int> &arr)
{
if (!arr.empty())
{
for (int i = 0; i < arr.size(); i++)
{
cout << arr[i] << "";
cout << endl;
}
}
}
int main()
{
vector<int> sort;
sort.push_back(2);
sort.push_back(1);
sort.push_back(7);
sort.push_back(4);
sort.push_back(5);
sort.push_back(3);
print(sort);
cout << "this was unsorted array";
cout << endl;
cout << findMin(sort, 0);
cout << "this was minimum";
cout << endl;
selectionSort(sort);
print(sort);
}
I am getting the following results:
comparison_sort.cpp:20:1: warning: non-void function does not return a value in all control paths [-Wreturn-type]
}
^
1 warning generated.
2
1
7
4
5
3
this was unsorted array
1
this was minimum
1
2
4
5
3
0
My question is: What is causing this control path error? Why is the "7" here being replaced with a "0"?
Thanks in advance! Sorry for the noob question.
I have reviewed all my current functions and nothing seems to explain why the 7 is replaced with a 0. I have tried multiple integers and it looks like the maximum number is always replaced.
The warning is very real, and it alludes to the problem that's breaking your sort as well.
You are currently returning m inside your loop body. What that means is that if the loop is entered, then the function will return m on the very first time around the loop. It only has a chance to check the first element.
And of course, if a is the last index of the array, then the loop will never execute, and you will never explicitly return a value. This is the "control path" which does not return a value.
It's quite clear that you've accidentally put return m; in the wrong place, and even though you have good code indentation, some inexplicable force is preventing you from seeing this. To fix both the warning and the sorting issue, move return m; outside the loop:
int findMin(vector<int> &arr, int a)
{
int m = a;
for (int i = a + 1; i < arr.size(); i++)
{
if (arr[i] < arr[m])
{
m = i;
}
}
return m;
}

Want to print next biggest number

So Here is the question:
Consider a class named Job that has deadline as a data member and relevant getter/setter
method(s). Assume you have to schedule two most earliest jobs on the basis of their deadlines. That is,
if there are three jobs in the system with deadlines (deadline1, deadline2, and deadline3, respectively)
then the system should report the top two earliest jobs (with smallest deadline value). You might need
to find the deadline with smallest and second most smallest value.
Here is my code:
#include<iostream>
using namespace std;
class job
{
private:
int Deadline;
public:
static int i;
void setDeadline(int a);
int getDeadline();
};
void job::setDeadline(int a)
{
Deadline = a;
cout << "Job " << i << " Has Deadline " << Deadline << endl;
}
int job::getDeadline()
{
return Deadline;
}
int job::i = 1;
int main()
{
job job1, job2, job3, job4, job5, job6, job7, job8, job9, job10, count;
job1.setDeadline(5);
count.i++;
job2.setDeadline(3);
count.i++;
job3.setDeadline(6);
count.i++;
job4.setDeadline(12);
count.i++;
job5.setDeadline(31);
count.i++;
job6.setDeadline(20);
count.i++;
job7.setDeadline(19);
count.i++;
job8.setDeadline(2);
count.i++;
job9.setDeadline(8);
count.i++;
job10.setDeadline(7);
int array[10] = { job1.getDeadline(), job2.getDeadline(),job3.getDeadline(),job4.getDeadline(),job5.getDeadline(),job6.getDeadline(),job7.getDeadline(),job8.getDeadline(),job9.getDeadline(),job10.getDeadline() };
int temp = array[0], store = 0, first = 0, second = 0;
for (int i = 0; i <= 9; i++)
{
if (temp > array[i])
{
temp = array[i];
}
}
for (int i = 0; i <= 9; i++)
{
if (temp == array[i])
{
first = i + 1;
break;
}
}
temp = array[0];
for (int i = 0; i <= 9; i++)
{
if (temp > array[i])
{
temp = array[i];
}
}
for (int i = 0; i <= 9; i++)
{
if (temp == array[i])
{
second = i + 1;
}
}
cout << "\nJob " << first << " and Job " << second << " are earliest";
return 0;
}
the problem I am facing is that both times it print the first smallest value. I want to print first 2 smallest value. How can I do that?
When you look for the first value, you go through the array and find the job with the lowest deadline and fill "first" with the job id (by the way, if you want to relate the "job id" to the index, personally I would make the variables zero-based, so job0, job1 and so on up to job9)
When you look for the second value, you do the exact same operations so the job you find is again the job with the lowest deadline and use that info to fill "second".
So, as you do the exact same thing both times, you are getting the exact same value for both. When you search for the second value you should take "first" into account so that you ignore the job that has already been used for "first" and not update "temp" in that case (this is a little bit easier if you name the jobs starting with zero because you don't have to constantly add one to the index).
the problem I am facing is that both times it print the first smallest value. I want to print first 2 smallest value. How can I do that?
With your solution: By creating another temp array with the first element removed you already discovered.
I wrote you as a minimal executable example using a vector of pairs since you didn't mention restrictions or anything - that is the most elegant solution I am able to come up with:
#include <iostream>
#include <vector>
#include <string>
bool sortVecBySec(const std::pair<std::string, int> &a,
const std::pair<std::string, int> &b)
{
return (a.second < b.second);
}
int main()
{
//Driver function to sort the vector elements by
//the second element of pairs
std::vector<std::pair <std::string,int>> v;
std::string job[10];
int deadline[10] = {5,3,6,12,31,20,19,2,8,7};
int n = sizeof(job)/sizeof(job[0]);
//Propagate string array
for(int i{}; i < 10;++i){
job[i] = "Job " + (std::to_string(i+1));
}
//Enter values in vector of pairs
for(int i{}; i<n; ++i){
v.push_back(make_pair(job[i],deadline[i]));
}
//Printing the vector of pairs
std::cout << "Vector of pairs as it is before\n";
for(int i{}; i< n; i++){
std::cout << v[i].first << " = " <<v[i].second << '\n';
}
//Using sort() function to sort by 2nd element of pairs
sort(v.begin(), v.end(),sortVecBySec);
//Printing the vector of pairs
std::cout << "\nVector of pairs from shortest to longest\n";
for(int i{}; i< 2; i++){
std::cout << v[i].first << " = " <<v[i].second << '\n';
}
std::cin.get();
return 0;
}
If you want to print all jobs, just use the n variable in the last print section instead of 2.
I think that should help you and shouldn't be to hard to parse it in a class.
First, you can save an extra round by saving the index right there, when you locate the earliest deadline
for (int i = 0; i <= 9; i++)
{
if (temp > array[i])
{
temp = array[i];
first = i + 1;
}
}
When searching for the next higher deadline value, you must take first into account. Both for the start value, and later when comparing with other values
temp = first > 1 ? array[0] : array[1];
for (int i = 0; i <= 9; i++)
{
if (temp > array[i] && array[i] > array[first])
{
temp = array[i];
second = i + 1;
}
}
Be aware, that this does not work properly, when you have multiple equal values.
For this case, compare the index values instead, e.g.
if (temp > array[i] && i != first)
{
temp = array[i];
second = i + 1;
}

Run-time check: stack around variable was corrupted

I am creating a program that rewrites an array with values from a file. I have linked the code below. When running the file I get the error "Run-time check failure, stack around 'arr' variable was corrupted.
Also, the output of the program returns all the array locations with the same number,
arr[0] = -858993460
The numbers in the file, separated by a line are:
12
13
15
#include<iostream>;
#include<fstream>;
using namespace std;
template <class T>
void init(T * a, int size, T v)//done
{
for (int i = 0; i < size; i++)
{
a[size] = v;
}
}
bool getNumbers(char * file, int * a, int & size)//not done
{
int count = 0;
ifstream f(file);
while (f.good() == true && count < 1)
{
f >> a[count];
count++;
}
if (size > count)
{
return true;
}
else if (size < count)
{
return false;
}
}
void testGetNumbers()
{
int arr[5];
int size = 5;
cout << "Testing init and getNumbers." << endl;
init(arr, 5, -1);
cout << "Before getNumbers: " << endl;
for (int i = 0; i < size; i++)
{
cout << "arr[" << i << "] = " << arr[i] << endl;
}
if (getNumbers("nums.txt", arr, size))
{
cout << size << " numbers read from file" << endl;
}
else
{
cout << "Array not large enough" << endl;
}
cout << "After getNumbers: " << endl;
for (int i = 0; i < size; i++)
{
cout << "arr[" << i << "] = " << arr[i] << endl;
}
cout << endl;
}
int main()
{
testGetNumbers();
return 0;
}
This line in the first loop looks like having error.
a[size] = v;
It causes out of array bound access and memory/stack corruption. It should be
a[i] = v;
Starting with the main function, the line
return 0;
... is not necessary because that's the default return value for main. I would remove it, some people insist on having it, I think most people don't care. But it's always a good idea to be fully aware of what the code expresses, implicitly or explicitly, so: returning 0 expresses that the program succeeded.
For an explicit main return value I recommend using the names EXIT_SUCCESS and EXIT_FAILURE from the <stdlib.h> header.
Then it's much more clear.
main calls testGetNumbers, which, except for an output statement, starts like this:
int arr[5];
int size = 5;
init(arr, 5, -1);
As it happens the init function is has Undefined Behavior and doesn't fill the array with -1 values as intended, but disregard. For now, look only at the verbosity above. Consider writing this instead:
vector<int> arr( 5, -1 );
Using std::vector from the <vector> header.
Following the call chain down into init, one finds
a[size] = v;
That attempts to assign value v to the item just beyond the end of the array.
That has Undefined Behavior.
Should probably be
a[i] = v;
But as noted, this whole function is redundant when you use std::vector, as you should unless strictly forbidden by your teacher.
Back up in testGetNumbers it proceeds to call getNumbers, in that function we find
ifstream f(file);
while (f.good() == true && count < 1)
{
f >> a[count];
count++;
}
Generally one should never use f.good() or f.eof() in a loop condition: use f.fail(). Also, ~never compare a boolean to true or false, just use it directly. Then the loop can look like this:
ifstream f(file);
while (!f.fail() && count < 1)
{
f >> a[count];
count++;
}
Tip: in standard C++ you can write ! as not and && as and. With the Visual C++ compiler you have to include the <iso646.h> header to do that.
Disclaimer: the fixes noted here do not guarantee that the loop is correct for your intended purpose. Indeed the increment of count also when the input operation fails, looks probably unintended. Ditto for the loop limit.
The function continues (or rather, ends) with
if (size > count)
{
return true;
}
else if (size < count)
{
return false;
}
This has a big problem: what if size == count? Then the execution continues to fall off the end of the function without returning a value. This is again Undefined Behavior.
I leave it to you to decide what you want the function to return in that case, and ensure that it does that.
In your init function...
template <class T>
void init(T * a, int size, T v)//done
{
for (int i = 0; i < size; i++)
{
a[size] = v;
}
}
Nope:
a[size] = v;
Yup:
a[i] = v;

C++ Bubble Sort (Ascending) function not returning results

I'm trying to use a bubble sort in a function instead of inline, and I seem to be having an issue with it returning results. As in currently, it's giving me no results at all. Here is my code that I have written up so far...
Basically, the user tells the program how many numbers they want to enter (up to 20 allowed) then it inputs those into an array in the order entered. Then it prints the values entered, sorts, and prints the sorted values. Or at least that's what is supposed to happen.
Thanks for the help in advance!
#include <iostream>
using namespace std;
int vault[20] = {}; // array to store the 20 values
int val = 0; // variable to pass values to the array
int amt = 0; // variable to get the amount of numbers the user is going to enter
int i = 0; // loop counter
// Bubble Sort Function Prototype
void bubble (int (&vault)[20], int val);
// Bubble Sort Function
void bubble (int (&vault)[20], int val)
{
int swap = 1; // flag used to indicate swaps occuring
int temp = 0; // holder variable
int x = 0; // loop counter
int y = 0; // second loop counter
for (x = 0; (x < val) && (swap = 1); x++)
{
swap = 0;
for (y = x+1; y < val; y++)
{
if (vault[x] > vault[y])
{
temp = vault[x];
vault[x] = vault[y];
vault[y] = temp;
swap = 1;
}
}
}
return;
}
int main()
{
cout << "Welcome to the Bubble Sort exe\n\n" << endl;
cout << "Please enter in the amount of numbers you would like to enter: ";
cin >> amt;
cout << "Please enter the values you wish to enter: ";
for(i = 0; i < amt; i++)
{
cin >> vault[i];
}
cout << "The values you entered in order are: ";
for (i = 0; i < amt; i++)
{
cout << vault[i] << ' ';
}
cout << "\n\nLet me just sort that for you!" << endl;
bubble(vault, val);
cout << "\n\nHere are the values in ascending order:\n" << endl;
for (i = 0; i < val; i++)
{
cout << vault[i] << ' ';
}
system("pause");
return 0;
}
What you've written isn't a classic bubble-sort algorithm. Bubble-sort iterates through the entire array each time, swapping elements with their immediate successor, doing this over-and-over until no more swaps occur.
In the traditional implementation, there are no "nested for-loops." There's one for-loop nested in a while or repeat-until structure.
The algorithm is called "bubble" because the lowest value "bubbles up" to the top ... with roughly the speed of a bubble trapped in very viscous oil.
(Compare with, say, the Shell sort, which is a slight-seeming alteration to Bubble that makes a tremendous difference. And to the quintessential and definitive Quicksort.)
Mathias pointed me in the correct direction. I had forgotten to initialize the variable 'val'. When I corrected that, it works perfectly.
As for everybody saying that this is not a classic bubble sort, I have seen this exact form on multiple sites and on slides from my prof., what is wrong with this way of writing it?
I'm trying this now instead, and it's completely failing on me (sigh):
void bubble (int (&vault)[20], int val)
{
bool swap = true; // flag used to indicate swaps occuring
int temp = 0; // holder variable
int x = 0; // loop counter
int y = 0; // second loop counter
while (swap = true)
{
swap = false;
x++;
for (y = 0; y < val - x; y++)
{
if (vault[y] > vault[y+1])
{
temp = vault[y];
vault[y] = vault[y+1];
vault[y+1] = temp;
swap = true;
}
}
}
}

How to solve 8 queens 1D array with brute force?

I was given an assignment to modify an 8 Queens program to use a 1D array and to use brute force (already did backtracking). I've come up with the following code:
#include <cmath>
#include <iostream>
using namespace std;
bool ok(int board[8]){
for(int j = 0; j <= 7; j++){ //check for repeating digits
cout << "ok loop 1"<<endl;
for (int k = 0; k <= 7; k++)
{
cout << "ok loop 2"<<endl;
if (board[k] = board[j]){ return false; }
}
}
for(int c = 7; c >= 0; c--){ //check if position is safe
cout << "ok loop 3"<<endl;
//int r = 0;
for(int i = 1; i <= c; i++){
cout << "ok loop 4"<<endl;
if(board[c-i] == c)
return false;
else if ((board[c]-i)>0 && board[c-i]-i == 1)
return false;
else if ((board[c]+i)<=7 && board[c-i]+i == 1)
return false;
} // for loop
} // for loop
return true;
} // ok
void print(int board[8], int c){
cout << "Solution " << c << ": " << endl;
for(int i = 0; i < 8; i++){
{
cout << board[i] <<" ";
}
}
cout << endl;
}
int main ()
{
int b[8]={0}; //initialize the array
int count = 0;
for(b[0]=0; b[0]<8; b[0]++)
for(b[1]=0; b[1]<8; b[1]++)
for(b[2]=0; b[2]<8; b[2]++)
for(b[3]=0 ; b[3]<8; b[3]++)
for(b[4]=0; b[4]<8; b[4]++)
for(b[5]=0; b[5]<8; b[5]++)
for(b[6]=0; b[6]<8; b[6]++)
for(b[7]=0; b[7]<8; b[7]++)
if(ok(b))
{
count++;
print(b, count);
}
system("PAUSE");
return 0;
}
It keeps looping forever and I am not sure why. Would anyone mind helping me?
There's a few things that could be improved:
If you passed a reference to a constant array of eight chars to ok() instead of just a pointer to non-const ints, the compiler could have told you about one of the issues.
How many different positions can a queen have? I'd say 64, though your code suggests eight. I'd start with documenting the actual meaning of variables and constants throughout your code, because you seem to be confused there yourself.
You check if board[x] is board[y], but with x and y being equal, and from that you claim that there are repeating digits.
You make a difference between the different queens. In other words, your program will find all permutations of how the queens could be positioned on the same eight positions. This is not incorrect, but inefficient. If you fix the number of positions, that will make a noticeable difference.