# Homework Help: Pascal - "nice numbers"

Tags:
1. Nov 1, 2015

### tawi

Hello,
My task is to write a program that after reading a positive integer i (from 0 to 1000) will write how many "nice numbers" are in the interval [0..i]. "Nice numbers" are numbers that are divisible by their every digit. For example 612 is a nice number becasuse it is divisible by 6,1 and 2. One the other hand 512 is not a nice number because it is not divisible by 5. And I need a little help with it.

Example of an input:
24

Corresponding output:
14

- in the interval [0,24] we can find these 14 nice numbers:
1 2 3 4 5 6 7 8 9 11 12 15 22 24

2. Nov 1, 2015

### Staff: Mentor

What do you have so far?
Where did you get stuck?

3. Nov 1, 2015

### tawi

Ok, here is what I've got:

program abcd;
var a,b,c,d,x,y,z,w,i: integer;
begin
if (x<10) then
begin
writeln (x);
if (x>10) and (x<100) then
begin
a:=x mod 10;
b:=x div 10;
y=0;
for i=x downto 10 do
begin
if (x mod a = 0) and (x mod b = 0) then
y:=y+1
else
y:=y
end;
writeln (y+9);
if (x>99) and (x<1000) then
......
......
......
end.

The following is pretty much irrelevant. The idea is the same, only the conditions are little different...

I honestly don't know where the problem is. The logic behind that seems fine to me, it compiles fine but it only works for the numbers 0-9. Once we get into longer numbers (with the conditions and cycles) it just wouldn't give me the output. As if it wasn't supposed to write anything.Thans for any help and if there's something unclear, let me know.

4. Nov 1, 2015

### Staff: Mentor

x=10 is not covered.

I would write a function that performs the check, but that's an unrelated point.
Some things look more complicated than necessary.

By the way: you can preserve the indentation by wrapping your code in [code] tags.
Code (Text):
This is a line
This is an indented line
To see what goes wrong, you can add intermediate outputs in your code (better: use a programming environment where you can follow the program flow).

5. Nov 1, 2015

### tawi

I use Borland Pascal but I am just getting to know that enviroment. Haven't gone through functions either so I would prefer some solution without it. What would you simplify?

6. Nov 1, 2015

### Staff: Mentor

For example, where is the point in this?
Why "begin" and where is the end here? What happens if x is not smaller than 10?

7. Nov 1, 2015

### tawi

The first one is unnecessary, I just thought it could be a bit more illustrative with it.

The "end" would be at the very end. But yes, I feel some of the "begin(s)" are the reason behind why it doesn't do what it should.
As to what happens when x is not <10 then there are the other conditions. One for 9<x<100 then for 99<x<1000 and last one for 999<x<10000.. Considering 10000 is the maximum input.
Basicallz what I do here is I first determine how many figures there are in the number (which determines the number of our variables - with two-figure number you have to check if it is dividable by two numbers, three-figure three numbers etc.) and then it goes through the appropriate cycle and in the end should give us how many numbers there are in the certain interval.
To give an example.. Lets say you have the number 14. You know its a two-figure number so you determine how many "nice numbers" are in the interval [10, 14]. You'll get the 2 (11,12) and that is your result for this interval. Considering we want to go down to 0 we just add 9 as all the one-figure numbers are nice numbers.

Last edited: Nov 1, 2015
8. Nov 1, 2015

### Staff: Mentor

I would start off by assuming that the number can be written with three digits; that is, a number from 1 through 999 inclusive. You can strip off the three digits by doing integer division (using the div operator) with 100 and then 10.

Code (Pascal):

hundreds := number div 100;
temp := number - hundreds * 100;
tens := temp div 10;
ones := temp mod 10;

After this code executes, hundreds, tens, and ones should be set with the values in those three places. Note that this also works if number has only one or two digits.

One problem with your code is that it skips some numbers such as 10. Another problem is in your logic, due in part to unmatched begin ... end pairs. In your logic above, you're checking to see whether x is less than 10. In the same block, you're checking to see whether x is larger than 10 and smaller than 100. If the number is smaller than 10, it can't possibly be larger than 10.

It's good that you are using indentation to show program structure, but it could use some work.
Code (Pascal):
if (x>10) and  (x<100) then
begin
a:=x mod 10;
b:=x div 10;
y=0;
for i=x downto 10 do
begin

do this:
Code (Pascal):
if (x>10) and  (x<100) then
begin
a:=x mod 10;
b:=x div 10;
y=0;
for i=x downto 10 do
begin
... body of for loop
end  { end of for loop}
end { end of if }

It's also a good idea to use variable names that suggest what they're being used for. Instead of a, b, x, and y, names like tens, hundreds, and so on give a better idea to the reader what they're for.

9. Nov 1, 2015

### tawi

Ok. I see what you mean but that should be easily fixable by just moving the "end" command behind the appropriate block, right?
Thanks for the other tips, I'll look into it.

10. Nov 1, 2015

### Staff: Mentor

I think you're better off starting from scratch, rather than trying to patch what you have.

11. Nov 1, 2015

### tawi

The idea with writing any number by using three digits occured to me as well but I didn't see any way how to work with it further. At some point there's gonna have to be a condition that determines whether the number is "nice" or not. And you are gonna have to check if the x mod (hundreds), x mod (tens) and x mod (ones) are all 0 at the same time. But if, for example, your hundreds are 0 then it will not be true because division by 0 is undefined.

12. Nov 1, 2015

### Staff: Mentor

After you strip off the digits, you can have logic to see how big the number is. If the hundreds digit is 0, then you know that the number is in the interval [1..99]. If the tens digit is 0, then you know that the number is in the interval [1..9].

I'm assuming here that the number is positive, so my intervals don't include 0.

13. Nov 1, 2015

### tawi

Of course but that will lead me to pretty much the same conditions I have above, right? Just a bit simplified.. As you are saying I can set a condition whre if hundreds and tens are zero we are dealing with number 0-9, if hundreds are 0 and tens aren't we are in 0-99 and then, for the individual intervals I will need the for cycles to check whether the numbers [0,x] are divisible by its figures. Or am I wrong?

14. Nov 1, 2015

### Staff: Mentor

That's roughly the idea, but what I'm suggesting is more organized.
Strip off the digits, using the idea in the code sample I gave.
After that, work your way down, one digit at a time, from the hundreds down to the ones digit.
If the hundreds digit is zero, you have a number in the interval [1 ... 999] and you can check to see if the 3-digit number is "nice".
Otherwise, if the tens digit is not zero, you have a number in the interval [1 ... 99], and you can check to see if the 2-digit number is "nice".
Otherwise, if the ones digit is not zero, you have a number in the interval [1 ... 9], and you can check to see if the 1-digit number is "nice".

The algorithm I've laid out presumes that the number is larger than 0 and smaller than 1000.

15. Nov 1, 2015

### tawi

I understand, seems fine. Only the part with the cycle seems to be not working for me. Not sure what I am not doing right. In the example above, can you see any problems with how the for cycle is written? if we say some variable "result" is 0 at the begining and with every "nice number" going down from x to 0 increases by one, then we should get the correct result at the end, shouldn't we? It gives me outputs that aren't correct and I am wondering if the way the cycle is written is flawed.

16. Nov 1, 2015

### Staff: Mentor

Take x=14 as example input and follow the code flow line by line that gets executed. Hint: it is very short, and it is related to the begin and end I highlighted.

17. Nov 2, 2015

### tawi

The problem is that if the number has 3 digits and I start checking if that number is "nice" I also need to check how many nice numbers there are in between our x and 0.
And the problem appears when the 3-digit numbers turn to 2-digit numbers and when those turn into 1-digit numbers.. The algorithms or the conditions are different and I don't know how to connect them. The only thing that comes to mind is letting the program determine how many nice numbers there are in all 2-digit numbers and 1-digit numbers and then add those numbers to your result for 3-digit numbers...

I fell like I know exactly what I need to do but I do not know how to put that in the code so it will actually work. For example the begins and ends. I've tried to put them in places where I think they make sense but the outputs were wrong...
For example the code that should tell you how many nice numbers there are in only the 3-digit number interval [100..x]

Using the code sample from above I could write something like this:
Code (Text):

if hundreds <> 0 then
result1:=0;
for i:=x downto 100 do
if (i mod hundreds = 0) and (i mod tens = 0) and (i mod ones = 0) then
result1:=result1 + 1;
writeln (reslut1);

Now I have left all the "begins" and "ends" out.. Where will they go considering there will be other blocks behind this determining the same thing for numbers from different intervals? Whatever I tried the for cycle just wouldn't work. The output would be just wrong.
I tried writing a simple program that would determine whether just the input is a nice number, that is without problem using the same method, just no cycle, which leads me to the conclusion the mistake is somewhere there. Only one more thing I noticed. Everytime the input is a number ending with a 0 the program gives and dividing by 0 error.. How to work around that in this case?
I really want to understand this so all the help is appreciated:)

Last edited: Nov 2, 2015
18. Nov 2, 2015

### Staff: Mentor

You are looking at the wrong place. Did you follow my suggestion? What was the result?

19. Nov 2, 2015

### tawi

Yes, the end was missing before the second if. Tried to fix it that way but the results would be bad whatever I did.
I ended up defining a function that pretty much does the same thing I did in all those intervals and then I send it through one for cycle at the end. Works perfectly.

20. Nov 2, 2015

### Staff: Mentor

I missed the part in your first post that you have to check all of the numbers from the input number on down. Here's how I would do this problem:

Prompt user to enter an integer in the range 1 through 999, inclusive.
Determine the digits of the input number, as already discussed.
Use a for loop to iterate from 1 through number, checking each
Good. Yes, writing a function to do the check makes sense.

In my earlier posts I misunderstood the requirements of the problem, thinking that you only had to check one input number to see if it was "nice."

Does your code correctly handle numbers such as 403 and 510? Your code should have logic in it to eliminate numbers such as these from consideration.

21. Nov 3, 2015

### tawi

Yes, I actually extended all the conditions and made sure it handles every number correctly. I am not quite sure what you mean by eliminating them. I just made another condition that checks if any of the digits is 0 and if it is, it automatically considers the number not "nice".
Here's my version, I am sure lots of it can be simplified but it still seems pretty straightforward and clear. And most importantnyl, it works..

Code (Text):

function nNumb (x: integer): integer;

begin

{here I define my variables for individual digits such as:}

thousands := x div 1000;
hundreds := ...
....
ones:= ...

if (x > 0) and (x < 10) then
result:=1;

if (x > 9) and (x < 100) then
if (ones <> 0) then
if (x mod ones = 0) and (x mod tens = 0) then
result:=1;

if (x > 99) and (x < 1000) then
if (ones <> 0) and (tens<> 0) then
if (x mod ones= 0) and (x mod tens= 0) and (x mod hundreds= 0) then
result:=1;

nNumb:=result;

begin

for i:=input downto 0 do
begin
y:=y+nNumb(i);
end;

writeln (y);
end.

Sorry for the indentation, it pasted strangely.. This is just a shorter version (I actually made it for all integers up to 32767) but you get the idea.

Last edited: Nov 3, 2015
22. Nov 3, 2015

### Staff: Mentor

Here's some Python code I wrote for your original problem.
Code (Python):

# nice.py - from input value N, of at most three digits, determine all "nice" numbers in the interval 1..N
# A "nice" number is one for which all of its digits divide the number

import string

# Determine whether number is "nice"
def checkNice(number):
global count

# All numbers in interval [1 .. 9] are nice
if number >= 1 and number < 10:
outstr = '{0:d} is nice'.format(number)
print(outstr)
count += 1

# number has two digits
elif number < 100:
ones = number % 10
tens = number // 10
# Skip over numbers whose ones' digit is 0,
#  and check that each digit divides number
if ones is not 0 and number % ones == 0 and number % tens == 0:
outstr = '{0:d} is nice'.format(int(number))
print(outstr)
count += 1

# number has three digits
else:
ones = number % 10
tens = (number // 10) % 10
hundreds = number // 100

# Skip over numbers whose tens' digit is 0, or whose ones' digit is 0,
#  then check that all three digits divide number
if ones is not 0 and tens is not 0:
if number % ones == 0 and number % tens == 0 and number % hundreds == 0:
outstr = '{0:d} is nice'.format(int(number))
print(outstr)
count += 1

# Prompt for an input value
N = int(input('Enter a positive integer N of at most 3 digits: '))

# Global variable for keeping track of how many nice numbers were found
count = 0
# Exit early if input value is nonpositive or larger than 999
if N <= 0 or N > 999:
print('Input value out of range')
exit

else:
for i in range(N + 1):
checkNice(i)

outstr = 'Found {0:d} nice numbers'.format(count)
print(outstr)