how to insert an element in the beginning when using recursion? - c++

I need to fill an array with the digits of a natural number using recursion. The problem is that i don't understand recursion very well.
int fill(long long number, int arr[10])
{
if(number<10)
{
arr[0]=number;
return arr[10];
}
else
{
arr[0]=number%10;
for(int i=0;i>10;i++)
{
arr[i+1]=arr[i];
}
return fill(number/10, arr);
}
}
If anyone can help in any way it would be much appreciated.

If you have a problem that must be solved with recursion, you probably should not be using for-loops.
The goal is that each iteration of fill() fills in one digit in the right position in the array, and if necessary calls itself again to fill in the remaining digits. You already have the right kind of structure in your code, but it's inefficient because of the extra for-loop. You can avoid it by using the return value of fill() to keep track of where you have to place digits. Here is a possible solution:
int fill(long long number, int arr[10])
{
if (!number)
return 0;
int pos = fill(number / 10, arr);
arr[pos] = number % 10;
return pos + 1;
}
In this implementation, we call ourselves recursively until the number is zero. When it is zero, we return 0. The return value is used to indicate where in the array we have to write a digit. So after we reach the deepest recursion level, and return for the first time, we write the most significant digit to arr[0]. Then we return 0 + 1. That means that one recursion level up, we have pos = 1, and we write the second most significant digit to arr[1], and then we return 1 + 1, and so on until we write the least significant digit, and then we are done. The return value of the initial call to fill() is then equal to the number of digits written to arr.
There are two more issue with this function. The first is when number is larger than 10 digits. In that case, it will write past the end of the array. So you will need to add some check to prevent that from happening, or ensure the array is large enough to hold the largest possible long long value (which is 20 digits if long long is 64-bits). Check LLONG_MAX from the climits.h header to get the maximum value for your platform. The second is that this function doesn't handle negative numbers very well. If you want to ensure it only handles non-negative numbers, change it to use unsigned long long. In that case, be aware that the largest number is ULLONG_MAX, and on 64-bit platforms this probably means 21 digits.

arr[i+1] iterator in for loop will have UB when i=9 and i=10

I am not going to solve it for you, here is how you should think, if you want to master the recursion (which is indeed often hard for people who encounter it for a first time).
Your function is supposed to fill first elements of array with digits, and return the number of digits.
Suppose that the number >= 10. You called fill(number/10, arr). It returned x which is the number of digits in number/10 . What should you do now? what should you return?
Suppose that the number < 10. What should you do? What should you return?

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.

Polynomial hash code results in negative numbers?

For large j in certain cases functions the hash function below returns negative values.
int hashing::hash(string a)
{
int i = 0;
int hvalue = 0;
int h =0 ;
while(a[i]!=NULL)
{
hvalue = hvalue + (int(a[i]))*pow(31,i);
i++;
}
h = hvalue%j;
return h;
}
How is that possible? How can I correct it?
In the above code, j is a prime number calculated using the size of the file. The negative values arise in certain specific cases where the string has the form " the s".
What am I doing wrong? How can I fix it?
Remember that int has a finite range and is (usually) a signed value. That means that if you exceed the maximum possible value for an int, it will wrap around and might become negative.
There are a couple of ways you could fix that. First, you could switch to using unsigned ints to hold the hash code, which are never negative and will behave nicely when wrapping around. Alternatively, if you still want to use ints, you can mask off the sign bit (the bit at the front of the number that makes the value negative) by doing this:
return (hvalue & INT_MAX) % j;
(Here, INT_MAX is defined in <climits>). This will ensure your value is positive, though you lose a bit from your hash code, which might for large data sets lead to some more clustering. The reason for doing the & before the mod is that you want to ensure the value is positive before taking the mod, since otherwise you'll overflow the number of buckets.
EDIT: You also have a serious error in your logic. This loops is incorrect:
while(a[i]!=NULL) {
...
}
C++-style strings aren't null-terminated, so this isn't guaranteed to stop once you read past the end of the string. Try changing this to read
for (int i = 0; i < a.length(); i++) {
/* ... process a[i] ... */
}
Hope this helps!

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.

Determine if a number is a runaround number

Definition of a runaround #:
It is an integer with exactly N digits, each of which is between 1 and 9, inclusively.
The digits form a sequence with each digit telling where the next digit in the sequence occurs. This is done by giving the number of digits to the right of the digit where the next digit in the sequence occurs. If necessary, counting wraps around from the rightmost digit back to the leftmost.
The leftmost digit in the number is the first digit in the sequence, and the sequence must return to this digit after all digits in the number have been used exactly once.
No digit will appear more than once in the number.
Checking for repeat digits isn't a problem, but I can't seem to come up with a good way to check for the "runaround" part. I'm looking more for suggestions/pseudo code than actual c++.
if you convert the integer into a string it shouldn't be any difficult: all you need is an operator[] (that the std::string class provides) and an array of boolean for recording which element has already been checked:
string value = input_integer;
vector<bool> checked;
int index = value[0];
checked[0] = true;
bool done = false;
while (!done) {
index = get_wrapped_index(value, index);
if (!checked[index])
checked[index] = true;
else
return false; // not a roundaround
if allTrue(checked) && index == 0
done = true;
}
return true;
You have to code get_wrapped_index(string s, index i), that must return the integer specified by s[i] given the right-wrapping costraint specified by the problem.
You have 4 rules laid out so just write code to check each rule.
The number is N digits. Determine what N is. Could be done by converting to a string or a vector for each digit. You may need to use division by 10 and mod (%) 10 a few times.
A method to move from one digit to the next. So if you are at digit position x with value y, you move to x+y mod N that is (x+y)%N. The first position is considered position 0, of course.
You need to check that you touch every position, and also that you do not have a duplicate. This could be one check. If you reach a digit you have seen before you know you have the correct solution if and only if this is the Nth iteration and you are at index 0.
12 is failure. Because although it is after 2 iterations you do not reach index 0 but revisit index 1 (2 takes you from index 1 back to index 1)
11 is failure because you see another 1 when you have not had all your iterations yet.
123 is failure because you get back to 1 an iteration too early. You don't need to know you didn't see the 3, or that you got back to index 0, just that you saw another 1 too early.
285 works though. You see 2 then 5 then 8 then 2. You are at index 0 and have had 3 iterations.
You need to store a collection of seen digits. vector is slightly controversial, so you could use std::bitset or even just a bool[10] will do for this example, or vector. You could also use std::set, the latter case of which would allow you to check its size to see your iteration count.

How can I remove the leading zeroes from an integer generated by a loop and store it as an array?

I have a for loop generating integers.
For instance:
for (int i=300; i>200; i--)
{(somefunction)*i=n;
cout<<n;
}
This produces an output on the screen like this:
f=00000000000100023;
I want to store the 100023 part of this number (i.e just ignore all the zeros before the non zero numbers start but then keeping the zeros which follow) as an array.
Like this:
array[0]=1;
array[1]=0;
array[2]=0;
array[3]=0;
array[4]=2;
array[5]=3;
How would I go about achieving this?
This is a mish-mash of answers, because they are all there, I just don't think you're seeing the solution.
First off, if they are integers Bill's answer along with the other answers are great, save some of them skip out on the "store in array" part. Also, as pointed out in a comment on your question, this part is a duplicate.
But with your new code, the solution I had in mind was John's solution. You just need to figure out how to ignore leading zero's, which is easy:
std::vector<int> digits;
bool inNumber = false;
for (int i=300; i>200; i--)
{
int value = (somefunction) * i;
if (value != 0)
{
inNumber = true; // its not zero, so we have entered the number
}
if (inNumber)
{
// this code cannot execute until we hit the first non-zero number
digits.push_back(value);
}
}
Basically, just don't start pushing until you've reached the actual number.
In light of the edited question, my original answer (below) isn't the best. If you absolutely have to have the output in an array instead of a vector, you can start with GMan's answer then transfer the resulting bytes to an array. You could do the same with JohnFx's answer once you find the first non-zero digit in his result.
I'm assuming f is of type int, in which case it doesn't store the leading zeroes.
int f = 100023;
To start you need to find the required length of the array. You can do that by taking the log (base 10) of f. You can import the cmath library to use the log10 function.
int length = log10(f);
int array[length];
length should now be 6.
Next you can strip each digit from f and store it in the array using a loop and the modulus (%) operator.
for(int i=length-1; i >= 0; --i)
{
array[i] = f % 10;
f = f / 10;
}
Each time through the loop, the modulus takes the last digit by returning the remainder from division by 10. The next line divides f by 10 to get ready for the next iteration of the loop.
The straightforward way would be
std::vector<int> vec;
while(MyInt > 0)
{
vec.push_back(MyInt%10);
MyInt /= 10;
}
which stores the decimals in reverse order (vector used to simplify my code).
Hang on a second. If you wrote the code generating the integers, why bother parsing it back into an array?
Why not just jam the integers into an array in your loop?
int array[100];
for (int i=300; i>200; i--)
{
array[i]= (somefunction)*i;
}
Since the leading zeros are not kept because it represents the same number
See: convert an integer number into an array