Given input value using loops

Hello. Need help with a project im working on. Getting stuck on writing it because it must be written in a while loop without using arrays. With a user inputed pin value, there are 4 rules that must be followed in order for the pin to work.
1.The PIN must be between 5to 7digits long (assume no leading zeros are entered –for example: 002345 is only 4 digits for our purposes).
2.The PIN cannot have the same digit in two consecutive positions(e.g. 12234 would not be a valid PIN)
3.The sum of the last 4 digits of the PIN must be a multiple of 3.
4.The value of n “choose” k, where n is the largest digit and k is the left-most digit of the PIN, should be an even number. The expression n “choose” k is computed as n!/(n−k)!k! where the ! denotes a factorial. For example, for PIN645823, the largest digit n=8 and the left-most digit k=6. 8!/(8−6)!6! =8∗7∗6∗5∗4∗3∗2∗1(2∗1)∗(6∗5∗4∗3∗2∗1)=28.Therefore 645823 would be a valid pin.
here is what I have so far. Any help would be apprecaited. Also the digits must be ecstracted using a loop. No arrays. Here is my code.

#include <iostream>
#include <iomanip>
#include <cmath>

using namespace std;

int main()
{
// initialize PIN value and i
int pin=0;
int i=0;
int count=0;
int num=0;
int prevDig=0;
int rem=0;
int temp;

// initialize loop
while (pin != -1)
{
cout << "Please enter your PIN" << endl;
cin >> pin;
// use statemets to test rule one
if (pin >= 10000 && pin <=9999999)
{
// rule 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 for (i=0; i<7; i++)
            {
            rem = pin %10;
            num = num / 10;
            cout << rem << endl;
                
                if(prevDig==temp)
                {
                    temp = (pin/(int) pow(10,i))%10;
                    cout << "Invalid pin. Consecutive numbers." << endl;               
                }
                
            }
            ]pin % 10000;
            if (pin%3 !=0)
            {
                cout << "Invalid pin. Some digits sum are not divisible by 3." << endl;
            }
        }

if (pin >= 10000000)
{
cout << "Invalid pin. Too many digits." << endl;
}
if (pin <= 9999 && pin >= 0)
{
cout << "Invalid pin. Not enough digits." << endl;
}
if (pin < 0)
{
cout << "Invalid pin. Cannot be negative." << endl;
}

}


return 0;
}
Last edited on
rule 3 is abusing what you know from math things.
pin % 10000 is the last 4 digits.
if result%3 == 0, its good to go. 2 lines of code for that rule. It turns out that if the sum of digits is divisible by 3, so is the number :)

that aside, what is giving you trouble? Can you edit your post and format it, using the <> on the side-bar editor or code tags?

can you use an array somewhere else?
const unsigned int fact[] = {
1,1,2,6,24,120,720,5040,40320, 362880};
then just say fact[digit] to get the value you need for digit!
if not, you can use a switch to do the same thing.
switch(digit)
{
case 0: case 1: result = 1; break;
case 2: result = 2; break;
case 3: //.. etc up to case 9:
}
Last edited on
Whats giving me trouble is the for loop. Im trying to get it to find consecutive numbers but cannot seem to figure it out. Also rule four is giving me trouble trying to find the left most digit and the max. For the second rule, I just cannot seem to write it out properly to find consecutive digits. And I believe I edited it so you could see that. Because I do not want that loop to effect the next 2 rules. So im trying to get it to just look for consecutive numbers and then just exit the loop. I also added rule three so that should look right. And NO ARRAYS.
Last edited on
for rule 2?

rule2 might look like this:
set bool rule2 = true (passing so far).
set num = pin; //disposable copy. this is critical, you must work with a copy!
set prev = -1 or 11 or something invalid so it is ok first time.
do
get a digit. num%10.
rule2 &= digit!=prev; //if they are not equal this is true, so when 2 digits are the same it will false out.
prev = digit.
num /= 10; // 1234 becomes 123 becomes 12 1 0 and 0 ends the loop below.
while(rule2 && num); //num == 0 means false means stop.

the left most digit can be found with logs. (int)(pin/pow(10,(int)log10(pin))); //sorry I messed that up a min ago.
the max digit, you can steal it in rule2. add a max variable set to -1, then if digit> max, max = digit... save this for rule 4, but pick it off in rule 2 to be efficient (you can't exit early in 2 if you do this, remove the rule2 from the stop loop condition if you do this) or just re-loop like 2 and pick off max by itself (easier to understand but small inefficiency).

see if these make sense?
you can do ! without the array. do you know functions yet?
n!/(n−k)!k! can be done with cancels.
n!/k! where n>= k is k*k+1*k+2 .. up to k+?==n
divide that by (n-k)!
Last edited on
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
 while (pin != -1)
    {
        cout << "Please enter your PIN" << endl;
        cin >> pin;
        // use statemets to test rule one
        if (pin >= 10000 && pin <=9999999)
        {
            bool rule2 = true;
            num = pin;
            do
            {
                digit = num%10;
                rule2 &= digit != prev;
                prev = digit;
                num /= 10;
                if(digit>maxDig)
                {
                    maxDig=digit;
                }
            } while (rule2 && num);
            result = pin % 10000;
            if (result %3 !=0)
            {
                cout << "Invalid pin. Some digits sum are not divisible by 3." << endl;
            }
            leftDig = (int)(pin/pow(10,(int)log10(pin)));
            for (i=1; i<= leftDig; i++)
            {
                kVal = leftDig*i;
            }
            for (i=1; i<=maxDig; i++)
            {
                nVal = maxDig*i;
            }
            nMinusk = (maxDig -= leftDig);
            for (i=1; i<=nMinusk; i++)
            {
                nkFact = nMinusk*i;
            }
            nChoosek = (nVal/(nMinusk*kVal));


this is my code right now and cannot seem to get it to work. any fix you can see?
the factorials are not working properly and the max digit sticks onto the first pin that is entered.
the factorial is wrong, for sure. factorial is 1*2*3*4...
try
1
2
3
4
 for (int i=1; i<= leftDig; i++)
            {
                kVal *= i;  //kval is 1 initially here. 
            }


re-read my post. I said that if you move maxdigit into that loop, the loop condition exits early, and it won't work. you have to take out the early exit:
while(num); //take out the rule2 part.
though, if it stops on rule 2, it was invalid anyway. does it matter at that point?
also be sure maxdig was set to 0 initially?

make sure you understand what I am telling you, don't just slice it in.
eg above, if rule2 is false, you stop checking, because it can't get any more invalid. See how that stops the loop and taking it out forces it to go on checking all the digits anyway, and that by checking them all, it also picks up the true max even for invalid pins? Do you see all this? The only key c++ism shortcut I am really using is that 0 is false, but if you do not understand anything just ask.
Last edited on
I got it. It works now. Thank you.
Topic archived. No new replies allowed.