C++ Finding the last occurrence of an int in a linear search - c++

This week for homework I've been tasked with loading in a text file of 1,000 numbers and to do a linear search of a number entered in by a user. I have the linear search part done, but I have to find and print the last occurrence of that integer. I figured it would be easiest to run the array from the end and print the last occurrence and break the loop. I've started the code, but am having some trouble at finding the last occurrence.
I know my second for loop to run the array backwards is wrong, I'm just not sure what about it is wrong. Any help is appreciated! Thank you!
#include <iostream>
#include <fstream>
#include <conio.h>
using namespace std;
int main()
{
ifstream input("A1.txt");
int find;
cout << "Enter a number to search for: ";
cin >> find;
if (input.is_open())
{
int linSearch[1000];
for (int i = 0; i < 1000; i++)
{
input >> linSearch[i];
for (i = 1000; i > 0; i--)
{
if (find == linSearch[i])
{
cout << find << " is at position " << i << ". " << endl;
}
}
}
}
_getch();
return 0;
}

for (int i = 0; i < 1000; i++)
{
input >> linSearch[i];
This is a good start. You started a loop to read the 1000 numbers into your array.
for (i = 1000; i > 0; i--)
Don't you think this is a bit premature? You haven't yet finished the loop to read the 1000 numbers in the file, yet, and you're already searching the array, that hasn't been fully read yet. There's a very technical term for this logical mistake: "putting the cart before the horse". You need to finish the loop to read the 1000 numbers, first. And only then you can execute this second loop.
{
if (find == linSearch[i])
Ok, now let's back up a bit. You started the loop with i=1000. Now, right here, what is the very first value if i? It is 1000. Don't you see a problem here? The 1000 element array, "linSearch", as you know, contains values numbered 0 through 999. That's a 1000 elements total. With i starting off with a value of 1000, accessing the non-existent linSearch[1000] is undefined behavior, and a bug.
You could tweak the logic here, to get it right. But it's not even necessary to do that. You already have a perfectly working loop that reads the 1000 numbers from the file. And you know which number you want to search.
So, each time you read the next number from the file, if it's the number you're looking for, you just store its position. So, when all is said and done, the last position that's stored in that variable will be the position of the last occurrence of the number you're searching for. Simple logic. All you have to do is also set a flag indicating that the number you were searching for has been found.
And once you come to the decision to do that, you will find that it's no longer even needed to have any kind of an array in the first place. All you have to do is read the 1000 numbers from the file, one number at a time, check if each number is the one you're searching for, and if so, save its position. Then, at the end of the loop, compare notes.

Since it's homework, I should probably be at least a little vague, and I definitely shouldn't use code.
You should not be nesting the 2nd loop within the first loop. It should be at the same indentation level as, and after the closing bracket for, the first loop.
Also, you shouldn't be searching back to 0 in almost all cases, but instead back to where you found the element in your linear search, or where you find it, and no further.
And yes, pay attention to what Beta wrote.
Also, shouldn't you break out of the loop each time you find what you're looking for?

Related

Go through the array from left to right and collect as many numbers as possible

CSES problem (https://cses.fi/problemset/task/2216/).
You are given an array that contains each number between 1…n exactly once. Your task is to collect the numbers from 1 to n in increasing order.
On each round, you go through the array from left to right and collect as many numbers as possible. What will be the total number of rounds?
Constraints: 1≤n≤2⋅10^5
This is my code on c++:
int n, res=0;
cin>>n;
int arr[n];
set <int, greater <int>> lastEl;
for(int i=0; i<n; i++) {
cin>>arr[i];
auto it=lastEl.lower_bound(arr[i]);
if(it==lastEl.end()) res++;
else lastEl.erase(*it);
lastEl.insert(arr[i]);
}
cout<<res;
I go through the array once. If the element arr[i] is smaller than all the previous ones, then I "open" a new sequence, and save the element as the last element in this sequence. I store the last elements of already opened sequences in set. If arr[i] is smaller than some of the previous elements, then I take already existing sequence with the largest last element (but less than arr[i]), and replace the last element of this sequence with arr[i].
Alas, it works only on two tests of three given, and for the third one the output is much less than it shoud be. What am I doing wrong?
Let me explain my thought process in detail so that it will be easier for you next time when you face the same type of problem.
First of all, a mistake I often made when faced with this kind of problem is the urge to simulate the process. What do I mean by "simulating the process" mentioned in the problem statement? The problem mentions that a round takes place to maximize the collection of increasing numbers in a certain order. So, you start with 1, find it and see that the next number 2 is not beyond it, i.e., 2 cannot be in the same round as 1 and form an increasing sequence. So, we need another round for 2. Now we find that, 2 and 3 both can be collected in the same round, as we're moving from left to right and taking numbers in an increasing order. But we cannot take 4 because it starts before 2. Finally, for 4 and 5 we need another round. That's makes a total of three rounds.
Now, the problem becomes very easy to solve if you simulate the process in this way. In the first round, you look for numbers that form an increasing sequence starting with 1. You remove these numbers before starting the second round. You continue this way until you've exhausted all the numbers.
But simulating this process will result in a time complexity that won't pass the constraints mentioned in the problem statement. So, we need to figure out another way that gives the same output without simulating the whole process.
Notice that the position of numbers is crucial here. Why do we need another round for 2? Because it comes before 1. We don't need another round for 3 because it comes after 2. Similarly, we need another round for 4 because it comes before 2.
So, when considering each number, we only need to be concerned with the position of the number that comes before it in the order. When considering 2, we look at the position of 1? Does 1 come before or after 2? It it comes after, we don't need another round. But if it comes before, we'll need an extra round. For each number, we look at this condition and increment the round count if necessary. This way, we can figure out the total number of rounds without simulating the whole process.
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char const *argv[])
{
int n;
cin >> n;
vector <int> v(n + 1), pos(n + 1);
for(int i = 1; i <= n; ++i){
cin >> v[i];
pos[v[i]] = i;
}
int total_rounds = 1; // we'll always need at least one round because the input sequence will never be empty
for(int i = 2; i <= n; ++i){
if(pos[i] < pos[i - 1]) total_rounds++;
}
cout << total_rounds << '\n';
return 0;
}
Next time when you're faced with this type of problem, pause for a while and try to control your urge to simulate the process in code. Almost certainly, there will be some clever observation that will allow you to achieve optimal solution.

getting infinte amount of inputs from the user than printing the biggest 3 , without using arrays

First time around, first time learning to code anything. Sorry for my ignorance.
So I've been asked to code a program that gets infinite amount of number from the users until he submits the number I manage to do so very well, but I also need to print the biggest sum of a following three inputs, for example, the user inputs 4,20,2,4,11,9,8,1 the program should print 11,9,8 because the sum of those 3 is greater than all other 3.
I must tell you I cannot use arrays, I know its a bummber but I know it is possible to do so without.
I was trying to build a function that tries to act like an array but I can't really call her back since its a two-variable function and one of them is the input, which I obviously don't know. was working on this question for 5 hours now and thought ill ask for your wisdom
cout << " enter numbers as long as you wish" << endl;
cout << "when you wish to stop enter the number 1" << endl;
int n;
int sum;
int i = 1;
while (n != 1) {
cin >> n;
remember(i, n);
if (n == 1) {
cout << "you choosed to stop " << endl;
break;
}
i++;
}
And the function I was trying to build is really simple but I can't call any specific value for example remember(1, n) when I want to sum them up and see who is bigger.
int remember(int i, int n){
return n;
}
*** Please note that the sums that are being tested are the sums of the numbers in the exact order that the user-submitted therefor 11,9,8 is the output and NOT 20,11,9
You need seven variables: Three which is the "window" you're currently reading, and which you check your sum with; Three which is the "biggest sum" triple; And one which is the current input.
For each input you read into the "current input" variable, you shift the window down one value and set the top variable to the just read input.
Then you take the sum of all three values in the window, and check if it's bigger than the sum of the current "biggest sum" triple. If it is, then you make the "biggest sum" triple equal to the current window values.
Iterate until there is no more input, and then print the "biggest" values.
Regarding the shifting of the three window values, lets say you have three variables named window1, window2 and window3 then you could shift like this:
window1 = window2;
window2 = window3;
window3 = current;
Checking the sum is as easy as
if ((window1 + window2 + window3) > (biggest1 + biggest2 + biggest3))
All window and biggest variables need to be initialized to the lowest possibly value for the type (for int that would be std::numeric_limits<int>::min()).
Since you initialize all values, there's no need to have special cases for the first and second input.
Iterating while there's input could be done by doing
while (std::cin >> current)
First of all, n is uninitialized, so it's undefined behavior when you do while (n != 1){. So technically, there's no guarantee that anything works past that. You should initialize it, for example by setting it to 0 (or any other value that's not 1, in this case):
int n = 0;
But the issue that you observe is because you have another int n; in your loop, which shadows the outer n (the one that is checked in the while condition). So the cin >> n; only ever modifies that inner n. The outer one will stay at the same uninitialized value. So if that value made it enter the loop, it will never exit the loop, because n != 1 is always true.
Remove the int n; inside the loop to solve the problem.
Basically, what you need is 4 variables to account the actual list and its sums (3 for the list and 1 for the sum of it)
You need 3 more variables to account the actual list.
At each interaction, you have two things to do:
Compare the sum of actual list with the stored one. If the sum the actual list is greater than that stored, actualize it
For each new number, rotate you variables that account for the actual list.
In pseudo code:
v3 = v2;
v2 = v1;
v1 = new_number;

Would this method be efficient at finding string permuations

#include <iostream>
#include <string>
using namespace std;
int main()
{
string word;
cin>>word;
int s = word.size();
string original_word = word;
do
{
for(decltype(s) i =1; i!= s;++i){
auto temp =word[i-1];
word[i-1] = word[i];
word[i] = temp;
cout<<word<<endl;
}
}while(word!=original_word);
}
Is this solution efficient and how does it compare by doing this recursively?
Edit: When I tested the program it displayed all permutations
i.e cat produced:
cat
act
atc
tac
tca
cta
Let's imagine tracing this code on the input 12345. On the first pass through the do ... while loop, your code steps the array through these configurations:
21345
23145
23415
23451
Notice that after this iteration of the loop finishes, you've cyclically shifted the array one step. This means that at the end of the next do ... while loop, you'll have cyclically shifted the array twice, then three times, then four times, etc. After n iterations, this will reset the array back to its original configuration. Since each pass of bubbling the character to the end goes through n intermediary steps, this means that your approach will generate at most n2 different permutations of the input string. However, there are n! possible permutations of the input string, and n! greatly exceeds n2 for all n ≥ 4. As a result, this approach can't generate all possible permutations, since it doesn't produce enough unique combinations before returning back to the start.
If you're interested in learning about a ton of different ways to enumerate permutations by individual swaps, you may want to pick up a copy of The Art of Computer Programming or search online for different methods. This is a really interesting topic and in the course of working through these algorithms I think you'll learn a ton of ways to analyze different algorithms and prove correctness.

I have n spaces, in each space, I can place a number 0 through m. Writing a program to output all possible results. Need help :)

The idea is, given an n number of spaces, empty fields, or what have you, I can place in either a number from 0 to m. So if I have two spaces and just 01 , the outcome would be:
(0 1)
(1 0)
(0 0)
(1 1)
if i had two spaces and three numbers (0 1 2) the outcome would be
(0 1)
(1 1)
(0 2)
(2 0)
(2 2)
(2 1)
and so on until I got all 9 (3^2) possible outcomes.
So i'm trying to write a program that will give me all possible outcomes if I have n spaces and can place in any number from 0 to m in any one of those spaces.
Originally I thought to use for loops but that was quickly shotdown when I realzed I'd have to make one for every number up through n, and that it wouldn't work for cases where n is bigger.
I had the idea to use a random number generator and generate a number from 0 to m but that won't guarantee I'll actually get all the possible outcomes.
I am stuck :(
Ideas?
Any help is much appreciated :)
Basically what you will need is a starting point, ending point, and a way to convert from each state to the next state. For example, a recursive function that is able to add one number to the smallest pace value that you need, and when it is larger than the maximum, to increment the next larger number and set the current one back to zero.
Take this for example:
#include <iostream>
#include <vector>
using namespace std;
// This is just a function to print out a vector.
template<typename T>
inline ostream &operator<< (ostream &os, const vector<T> &v) {
bool first = true;
os << "(";
for (int i = 0; i < v.size (); i++) {
if (first) first = false;
else os << " ";
os << v[i];
}
return os << ")";
}
bool addOne (vector<int> &nums, int pos, int maxNum) {
// If our position has moved off of bounds, so we're done
if (pos < 0)
return false;
// If we have reached the maximum number in one column, we will
// set it back to the base number and increment the next smallest number.
if (nums[pos] == maxNum) {
nums[pos] = 0;
return addOne (nums, pos-1, maxNum);
}
// Otherwise we simply increment this numbers.
else {
nums[pos]++;
return true;
}
}
int main () {
vector<int> nums;
int spaces = 3;
int numbers = 3;
// populate all spaces with 0
nums.resize (spaces, 0);
// Continue looping until the recursive addOne() function returns false (which means we
// have reached the end up all of the numbers)
do {
cout << nums << endl;
} while (addOne (nums, nums.size()-1, numbers));
return 0;
}
Whenever a task requires finding "all of" something, you should first try to do it in these three steps: Can I put them in some kind of order? Can I find the next one given one? Can I find the first?
So if I asked you to give me all the numbers from 1 to 10 inclusive, how would you do it? Well, it's easy because: You know a simple way to put them in order. You can give me the next one given any one of them. You know which is first. So you start with the first, then keep going to the next until you're done.
This same method applies to this problem. You need three algorithms:
An algorithm that orders the outputs such that each output is either greater than or less than every other possible output. (You don't need to code this, just understand it.)
An algorithm to convert any output into the next output and fail if given the last output. (You do need to code this.)
An algorithm to generate the first output, one less (according to the first algorithm) than every other possible output. (You do need to code this.)
Then it's simple:
Generate the first output (using algorithm 3). Output it.
Use the increment algorithm (algorithm 2) to generate the next output. If there is no next output, stop. Otherwise, output it.
Repeat step 2.
Update: Here are some possible algorithms:
Algorithm 1:
Compare the first digits of the two outputs. If one is greater than the other, that output is greater. If they are equal, continue
Repeat step on moving to successive digits until we find a mismatch.
Algorithm 2:
Start with the rightmost digit.
If this digit is not the maximum it can be, increment it and stop.
Are we at the leftmost digit? If so, stop with error.
Move the digit pointer left one digit.
Algorithm 3:
Set all digits to zero.
“i'm trying to write a program that will give me all possible outcomes if I have n spaces and can place in any number from 0 to m in any one of those spaces.”
Assuming an inclusive “to”, let R = m + 1.
Then this is isomorphic to outputting every number in the range 0 through Rn-1 presented in the base R numeral system.
Which means one outer loop to count (for this you can use the C++ ++ increment operator), and an inner loop to extract and present the digits. For the inner loop you can use C++’ / division operator, and depending on what you find most clear, also the % remainder operator. Unless you restrict yourself to the three choices of R directly supported by the C++ standard library, in which case use the standard formatters.
Note that Rn can get large fast.
So don't redirect the output to your printer, and be prepared to wait for a while for the program to complete.
I think you need to look up recursion. http://www.danzig.us/cpp/recursion.html
Basically it is a function that calls itself. This allows you to perform an N number of nested for loops.

Getting a memory address in my array?

I'm writing a C++ application that has a user enter a 0 (zero) or a one (1) as input, then stores the numbers as an array and sorts them so that the zeros come first and the ones come last.
However, I think I'm getting a memory address in my array that's messing up the sorting operation.
The function that accepts input looks like this:
cout << "Please enter number " << i+1 << ":\n";
cin >> ar[i];
Then there's a function that's called that sorts the input and displays the sorted list:
sort_elements(ar, number);
... and that function looks like this:
void sort_elements(int ar[], long int num_elements) {
int temp_num;
num_elements -= 1; //since the array starts at 0
cout << "num_elements is " << num_elements << "\n";
for (int i=0; i < (num_elements/2); i++ ) {
if (ar[i] > ar[num_elements-i]) {
temp_num = ar[i];
ar[i] = ar[num_elements-i];
ar[num_elements-i] = temp_num;
}
}
cout << "Here's your neatly sorted list of numbers: \n";
for (int j=0; j <= num_elements; j++) {
cout << ar[j] << ", ";
}
cout << "\n";
}
For a five number input, starting with three "1"s, and ending with two "0"s, this results in an output that looks like this:
1, 0, 1, 1, 1892218304,
I'm assuming the 1892218304 is a memory address, that's messing up the input. Though I don't really know.
Can anyone figure out why my sort operation is getting messed up?
Thanks in advance.
Suggestion
Use vector and sort in standard library
#include <algorithm>
#include <vector>
#include <iostream>
#include <iterator>
int main()
{
std::vector<int> v;
for(int i=0; i < 10; i++)
{
v.push_back(i);
}
std::sort(v.begin(), v.end());
return 0;
}
The number you are seeing is not a memory address, but the value of the 4 bytes either immediately before or immediately after your array, interpreted as an int. Your code has an off-by-one error that causes an access to just outside the array. That much I suspect even though I don't have proof.
However, I can't find anything wrong with the code you posted that would cause it to access outside the array bounds.
Are you sure that num_elements has the correct value when this function is called?
Update to address the pastebin code
Things are going wrong already from the start:
int number;
int ar[number]
This is called a variable-length array and it's not legal in C90 or any flavor of C++. That your program compiles is probably "thanks to" a compiler extension... which helpfully raises a bug: the value of number is not initialized before the array is allocated.
You need to do one of the following:
declare ar as an array of constant size (a hard limit on the number of inputs you can accept)
dynamically allocate ar with new[] after number is entered from the user
(by far preferable) use an std::vector instead of an array
It looks to me like you're just getting an uninitialized value in your output.
Under the circumstances, the simplest "sorting" method is probably a counting sort -- i.e., count the number of 0's and the number of 1's the user enters, and then print out the appropriate number of 0's followed by the appropriate number of 1's.
As Tony said, your sorting algorithm is incorrect.
If we assume the following values:
ar[0] = 0
ar[1] = 1
ar[2] = 0
ar[3] = 1
ar[4] = 0
that gives us num_elements equal to 5.
Running this through your function as written, we get the following sorting behavior:
First pass, i = 0
ar[0] > ar[4] -> not true, so no switch
Secon pass, i = 1
ar[1] > ar[3] -> not true, so no switch
There is no third pass, as your for loop condition is met
i = 2
num_elements/2 = 2
2 is not less than 2
So based on your code, you didn't sort anything. This is the first issue.
Your print problem is interesting, based on what you have shown num_elements has been decremented by 1 at the top of your code snippet in your function - therefore the <= condition is correct and you should not be outside the bounds of your 'ar' array. Are you sure this is the exact code, or perhaps you did not copy it properly here and you are actually having a scoping issue?
(EDIT: Although the other answers suggesting using a built in sorting method via vectors, I'd suggest you still work your current implementation out to figure out WHY this is wrong, and what you need to do to fix it. You will not always have an available type that has built in sorting, so understanding the fundamentals is important for any young programmer.)
EDIT2: Based on the link you provided, you aren't properly defining your integer array. You are defining the array based on an uninitialized integer (int ar[number]) when number has not yet been initialized. You then read a value from the standard input to set number, and assume your array has been dynamically adjusted to be of the size read from cin. It does not work this way. Your entire loop is reading/writing outside the bounds of your array which is a big no-no. You want to read the number first, and then define your array based on the size read. - Looks like Jon beat me again.. BAH! :P
The last element being read and printed to the screen has never been written to. I think it's likely your function which accepts input has a fault, like maybe you have a line like you have here
num_elements -= 1; //since the array starts at 0
at the input function so that the first element you write to is at address 1. Then when you're reading them you read from address zero.
I kind of agree with Jim's point: Use the facilities in the C++ standard library to finish your task as much as possible.
Besides, I suggest you go through the algorithm all by yourself, manually, instead of letting the computer run it for you. Ever heard of the "Rubber Duck Debugging Method"? :-) Have a try.