Solving the Josephus Problem using a vector - c++

EDIT: I seem to have sorted out the errors, at the very least, and have updated the code. However, the math still doesn't seem to be working out. Any ideas?
In short, I'm trying to write a program in C++ that will prompt the user for the number of people in the initial circle, and then tell them in which position they should stand in order to survive if k (the number of people counted to before being executed) = 3.
I've got what I think is the right idea, but I get the error "Debug Assertion Failed" and "Expression: vector erase iterator outside range" if I input k as anything other than 1, 2, or 5.
// ConsoleApplication2.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int n;//size of the circle
vector <int> circle; //the circle itself
//ask for how many people are in the circle
cin >> n;
//fill the circle with 1,2,3...n
for (int idx = 0; idx < n; idx++)
{
circle.push_back (idx+1);
}
//cout << "The size of the circle is " << circle.size() << ".\nThe highest number is " << circle[n-1] << "."; //test to make sure numbers are being assigned properly to each vector element
for (int count = 0, idx = 0; circle.size() > 1; idx++,count++)
{
//if the position (idx) is greater than the size of the circle, go back to the beginning of the circle and start counting again
if (idx >= circle.size())
{
idx = 0;
}
//every time the counter reaches three, that person is executed
if (count == 3)
{
circle.erase (circle.begin()+(idx));
count = 0;
}
}
cout << "The place to stand to win the hand is position #" << circle.front() << ".\n";
return 0;
}

You only check for if (idx > circle.size()) and then go ahead and call circle.erase (circle.begin()+(idx));. This call isn't safe when idx == circle.size().

#Pradhan already gave you the solution to your original error (idx >= circle.size() instead of idx >= circle.size().
For why the result is still not correct:
When you erase an element, you have to adjust your index to compensate for it (subtract 1). Otherwise the index corresponds to the next element in the vector, so effectively you are always executing every 4th person not every 3rd.
Here is my version of the code:
#include <iostream>
#include <vector>
#include <numeric>
using namespace std;
int main(){
int n;
cin >> n;
//fill the circle with 1,2,3...n
vector <int> circle(n);
std::iota(std::begin(circle), std::end(circle),1);
int idx = -1;
while (circle.size() > 1) {
//advance by threee
idx = (idx + 3) % circle.size();
//execute Person
circle.erase(circle.begin() + (idx));
//readjust to compensate for missing element
--idx;
}
cout << "The place to stand to win the hand is position #" << circle.front() << ".\n";
}
of course, you can rewrite the loop to
int idx = 0;
while (circle.size() > 1) {
//advance by three
idx = (idx + 2) % circle.size();
//execute Person
circle.erase(circle.begin() + (idx));
}

Related

Where is the origin of the Segmentation fault

This piece of code is supposed to go through a column of a vector of this format: -23 ##.###(where '-' is the beginning of the column and the last # is the end), if you're not aware of the concept of a nanogram, the first number says there are 2 hashes, and the second says there are 3 hashes, there is a minimum requirement of at least one dot(.) or one "whitespace" between each set of hashes(blackspaces). All i want this code to do is to check if the hashes correspond to the numbers for the columns first, but for some reason the input vector;
\[\["-","-","-","-","-","-","-","-"\],\["-","-","-","2","2","1","-","1"\],\["-","-","-","2","1","1","3","
3"\],\["-","3","1","#","#","#",".","#"\],\["-","-","2","#","#",".",".","."\],\["-","-","2",".",".",".","#","#"\],\["-","1","2","#",".",".","#","#"\],\["-","-","5","#","#","#","#","#"\]\]
gives the "segmentation fault" error and codesignal's IDE doesn't much more detail than that.
#include <iostream>
#include <vector>
using namespace std;
bool countSharpsVertically(vector<vector<string>> & referenceVectorOfVectorStrings, int column, int distance) {
for (int i{}, j{distance}; j<referenceVectorOfVectorStrings.size()/*i < distance*/; i++) {
while (referenceVectorOfVectorStrings[i][column]=="-") // might want to check if there are no numbers idk how annoying these edge cases are going to be
i++;
// cout << (referenceVectorOfVectorStrings[j][column])<< " ";j++;
while (referenceVectorOfVectorStrings[j][column]==".")j++;
for ( int spaces{}; spaces<stoi(referenceVectorOfVectorStrings[i][column]); j++, spaces++){
if (referenceVectorOfVectorStrings[j][column]!="#")return false;
}
if (referenceVectorOfVectorStrings[j][column]!=".")return false;
if (i<distance-1&&j>=referenceVectorOfVectorStrings.size())return 0;
// cout << referenceVectorOfVectorStrings[j++][column] << " ";
}
cout << endl;
return true;
}
bool solution(int size, vector<vector<string>> nonogramField) {
int distance=(size + 1) / 2;
//check down
// cout << distance;
for (int i{distance}; i < nonogramField.size(); i++ ) {
if (!countSharpsVertically(nonogramField, i, distance)) return 0;
}
//check left
return true;
}
int main() {
vector<vector<string>> nonogramField = {{"-","-","-","-","-","-","-","-"},
{"-","-","-","2","2","1","-","1"},
{"-","-","-","2","1","1","3","3"},
{"-","3","1","#","#","#",".","#"},
{"-","-","2","#","#",".",".","."},
{"-","-","2",".",".",".","#","#"},
{"-","1","2","#",".",".","#","#"},
{"-","-","5","#","#","#","#","#"}};
cout << solution(5, nonogramField);
return 0;
}
All my initial suspicions for the origin of the segmentation fault were wrong, please where is the error coming from.

Locating a Segmentation Fault

I have the fallowing code. I read the guide for what a segmentation fault is, but I'm not 100% sure where its actually happening within my code. It works until I start working with the dynamic array (histogram), more specifically at the //set all initial values to be zero. Within that mess after I'm not sure. Thanks!
The instructor asked to "Use a dynamic array to store the histogram.", Which I think is my issue here.
-Solved-
thanks for the help, the error was in how I initialized the array pointer
rather than
const int hSize = 10;
IntArrayPtr histogram;
histogram = new int[hSize];
I used
const int hSize = 10;
int hValues[hSize] = { 0 };
IntArrayPtr histogram;
histogram = hValues;
Which worked as the instructor wanted.
#include <iostream>
#include <vector>
using namespace std;
typedef int* IntArrayPtr;
int main() {
vector<int>grades;
int newGrade;
cout << "Input grades between 0 and 100. Input -1 to calculate histogram: " << endl;
cin >> newGrade;
grades.push_back(newGrade);
while (newGrade > 0) {
cin >> newGrade;
while (newGrade > 100) {
cout << "less than 100 plz: ";
cin >> newGrade;
}
grades.push_back(newGrade);
}
grades.pop_back();
int size = grades.size();
cout << "Calculating histogram with " << size << " grades." << endl;
//Create dynamic array for the histogram of 10 sections.
const int hSize = 10;
IntArrayPtr histogram;
histogram = new int[hSize];
}
//Make the historgram
int stackValue = 0;
for (int j = 0; j < hSize; j++) {
//Loop through the grade vector slots
for (int i = 0; i < size; i++) {
int testValue = grades[i];
//If the grade at the index is between the stack values of the histogram add one to the value of the slot
if (testValue > stackValue && testValue < stackValue + 10) {
histogram[j]++;
}
}
//After looping through the vector jump up to the next histogram slot and corresponding stack value.
stackValue += 10;
}
//Histogram output. Only output the stacks with values
for (int i = 0; i < 10; i++) {
if (histogram[i] != 0) {
cout << "Number of " << (i + 1) * 10 << "'s: " << histogram[i];
}
}
return 0;
}
Working Code:
#include <iostream>
#include <vector>
using namespace std;
typedef int* IntArrayPtr;
int main() {
vector<int>grades;
int newGrade;
cout << "Input grades between 0 and 100. Input -1 to calculate histogram: " << endl;
cin >> newGrade;
grades.push_back(newGrade);
while (newGrade > 0) {
cin >> newGrade;
while (newGrade > 100) {
cout << "less than 100 plz: ";
cin >> newGrade;
}
grades.push_back(newGrade);
}
grades.pop_back();
int size = grades.size();
cout << "Calculating histogram with " << size << " grades." << endl;
//Create dynamic array for the histogram of 10 sections.
const int hSize = 10;
int hValues[hSize] = { 0 };
IntArrayPtr histogram;
histogram = hValues;
//Make the historgram
int stackValue = 0;
for (int j = 0; j < hSize; j++) {
//Loop through the grade vector slots
for (int i = 0; i < size; i++) {
int testValue = grades[i];
//If the grade at the index is between the stack values of the histogram add one to the value of the slot
if (testValue > stackValue && testValue < stackValue + 10) {
histogram[j]++;
}
}
//After looping through the vector jump up to the next histogram slot and corresponding stack value.
stackValue += 10;
}
//Histogram output. Only output the stacks with values
for (int i = 0; i < 10; i++) {
if (histogram[i] != 0) {
cout << "Number of " << (i + 1) * 10 << "'s: " << histogram[i] << endl;
}
}
return 0;
}
histogram is a pointer, not an array.
While
int histogram[hSize] = {0};
would create a zero-initialised array, your
histogram = { 0 };
does not set any elements to zero (it couldn't, because histogram points to one int, not many).
The braces are ignored – a pretty confusing behaviour inherited from C – and it is equivalent to
histogram = 0;
that is,
histogram = nullptr;
You want
int* histogram = new int[hSize]();
The parentheses value-initialises the array, and in turn its elements.
Value-initialising integers sets them to zero.
(By the way: the habit of typedeffing away asterisks causes more problems than it solves. Don't do it.)
Seg faults are problems with accessing regions of memory you don't have access to, so you need to look at your use of pointers. It often means you have a pointer with a bad value that you just dereferenced.
In this case, the problem is this line:
histogram = { 0 };
This is not setting the histogram values to zero as you think: it's resetting the historgram pointer to zero. Then you later dereference that pointer causing your SegFault (note that this line doesn't even compile with clang, so your compiler isn't helping you any on this one).
Changing that line to:
memset(histogram, 0, hSize);
Will sort the problem in this case.
More generally, to diagnose a segfault there are two tricks I use regularly (though avoidance is better than cure):
Run the program under a debugger: the debugger will likely stop the program at the point of the fault and you can see exactly where it failed
Run the program under Valgrind or similar - that will also tell you where the error surfaced but in more complex failures can also tell you where it was caused (often not the same place).

C++ Variable not properly receiving new value from vector?

I'm trying to write a program that creates and fills a vector with int values, then searches through it and returns the minimum value, recursively. I have the code written out and building, but it returns a weirdly large value for minimum every time- I have a feeling it's not properly assigning the smallest value to int minimum, but I'm not sure. Any thoughts?
#include <iostream>
#include <conio.h>
#include <vector>
using namespace std;
int vectorSize;
int minimum;
int result = -1;
int start;
int ending;
int answer;
int test;
int recursiveMinimum(vector<int>, int, int);
void main() {
cout << "How many values do you want your vector to be? ";
cin >> vectorSize;
cout << endl;
vector<int> searchVector(vectorSize);
start = 0;
ending = searchVector.size() - 1;
for (int i = 0; i < vectorSize; i++) {
cout << "Enter value for position " << i << " " << endl;
cin >> searchVector[i];
}
for (int x = 0; x < vectorSize; x++) {
cout << searchVector[x] << " ";
}
int answer = recursiveMinimum(searchVector, start, ending);
cout << "The smallest value in the vector is: " << answer;
_getch();
}
int recursiveMinimum(vector<int> searchVector, int start, int end) {
if (start < end) {
if (searchVector[start] < minimum) {
minimum = searchVector[start]; //this part seems to not work
}
start++;
recursiveMinimum(searchVector, start, end);
}
else {
return minimum;
}
}
`
Your minimum variable is not initialised, which leads to undefined behaviour. It should be set to the first value in the vector:
minimum = searchVector[0];
int answer = recursiveMinimum(searchVector, start, ending);
Additionally, ending is off by one, which makes it pick 6 as the smallest value out of [6, 9, 8, 4].
So, ultimately, your code should look like this:
minimum = searchVector[0];
int answer = recursiveMinimum(searchVector, start, ending + 1); // note the + 1
While irrelevant to the question, I advise you to use a tail call in recursiveMinimum, as explained here:
start++;
return recursiveMinimum(searchVector, start, end);
The main issue is that you do not initialise minimum. Hence, comparison searchVector[start] < minimum might never become true, and minimum remains uninitialized.
As a quick fix, write int minimum = MAX_INT; instead of int minimum;. MAX_INT is the maximum positive integer value (defined in limits.h). So the values in your array will never be greater that this value, and your minimum search loop will work (unless there are other issues; but for that, please consult the debugger :-) )

Function returning simple hashcode in C++

I'm trying to handle following programming exercise from my C++ book: "Write a function which takes a string as argument and returns a primitve hash-code, which is calculated by adding the values of all characters in the string."
My solution to this is:
#include <iostream>
#include <string>
#define clrscr() system("cls")
#define pause() system("pause")
using namespace std;
int hashc(char string[]);
int main()
{
char phrase[256];
cout << "This program converts any string into primitve hash-code." << "\n";
cout << "Input phrase: "; cin.getline(phrase, sizeof(phrase));
cout << "\n";
cout << "Hash-code for your phrase is: " << hashc(phrase) << "\n\n";
pause();
return(0);
}
int hashc(char string[])
{
int index;
int length;
int hash_value = 0;
length = strlen(string);
for(index = 0; index >= length; ++index)
{
hash_value = hash_value + string[index];
}
return(hash_value);
}
The problem is: the function always returns hash_value = 0 as it seems that it is skipping the for-loop. When I return length in the function it gives back the correct length of a given string (which is index >= length for index = 0). Therefore it should normally trigger the for-loop, shouldn't it? A little hint right here is greatly appreciated!
Cheers!
An idiomatic for-loop should look like this:
for(index = 0; index < length; ++index)
{
hash_value += string[index];
}
The key features are that the index starts at 0 (index = 0), the index is compared to the length with 'less-than' (index < length) and, as you have it, the index is incremented using pre-increment (++index).
for(index = 0; index < length; ++index)
You're never entering the loop at the moment, and no characters caused a segmentation fault on my system. It enters the loop in the only situation that it passes the condition (length >= index, i.e. 0 >= 0) and then loops until it attempts to access an illegal location, at which point the seg fault occurs.

Getting odd results when trying to solve Collatz p‌r‌o‌b‌l‌e‌m

I'm trying to solving Project Euler Problem 14. It asks to find the number under 1 million that generates the longest sequence. What I did was create a vector, v, and populate its elements with the length of the sequence for a particular number. Thus, the element that resides in position 13 will correspond to the length of the sequence generated by the number 13, and so on. However, some seemingly random elements take very large numbers and I can't figure out what's wrong with the code. Also, when I test it with 1,000,000, I get a completely wrong answer, but I know the program is working for some small numbers after testing them by hand and verifying.
#include <iostream>
#include <vector>
using namespace std;
void find_longest(int n)
{
int count = 1;
int max = 0;
int position;
vector<int> v;
v.push_back(0);
v.push_back(0);
for(int i = 1; i < n; i++)
{
long long int trainer = i;
count = 1;
while(trainer != 1)
{
if(trainer%2 == 0)
{
trainer /= 2;
count++;
}
else
{
trainer = 3*trainer + 1;
count++;
}
}
v.push_back(count);
}
vector<int>::iterator it;
for(it = v.begin(); it < v.end(); it++)
{
cout << v[*it] << endl;
//if(v[*it] > max)
//{
// max = v[*it];
// position = *it;
//}
}
//cout << "The longest sequence is " << max << " terms long and is ";
//cout << "generated by the number " << position << "." << endl;
}
int main()
{
find_longest(100);
//find_longest(1000000);
}
//removing change for type mismatch
You don't need to remember all N numbers in a vector.
All you need is current sequence length. Then you calculate sequence length for the next number and if it is bigger than what you have already, you just keep the biggest one.