Getting the number of digits of nonnegative integers (Python) [duplicate] - python

This question already has answers here:
How to find length of digits in an integer?
(31 answers)
Closed 6 years ago.
The question asks:
<< BACKGROUND STORY:
Suppose we’re designing a point-of-sale and order-tracking system for a new burger
joint. It is a small joint and it only sells 4 options for combos: Classic Single
Combo (hamburger with one patty), Classic Double With Cheese Combo (2 patties),
and Classic Triple with Cheese Combo (3 patties), Avant-Garde Quadruple with
Guacamole Combo (4 patties). We shall encode these combos as 1, 2, 3, and 4
respectively. Each meal can be biggie sized to acquire a larger box of fries and
drink. A biggie sized combo is represented by 5, 6, 7, and 8 respectively, for the
combos 1, 2, 3, and 4 respectively. >>
Write an iterative function called order_size which takes an order and returns the number of combos in the order. For example, order_size(237) -> 3.
Whereby I should have
order_size(0) = 0
order_size(6) = 1
order_size(51) = 2
order_size(682) = 3
My code is:
def order_size(order):
# Fill in your code here
if order > 0:
size = 0
while order > 0:
size += 1
order = order // 10
return size
else:
return 0
But I don't get the order // 10 portion. I'm guessing it's wrong but I can't think of any stuff to substitute that.

No need for iterative function, you can measure the length of the number by "turning" it into a string:
num = 127
order = len(str(num))
print(order) # prints 3
But if you really want to do it iteratively:
def order(num):
res = 0
while num > 0:
num = int(num / 10)
res += 1
return res
print(order(127)) # prints 3

How about this:
from math import log
def order_size(order):
if order <= 0: return 0
return int(log(order, 10) + 1)
Some samples (left column order, right column order size):
0 0
5 1
10 2
15 2
20 2
100 3
893 3
10232 5

There are a couple errors in your suggested answer.
The else statement and both return statements should be indented a level less.
Your tester questions indicate you are supposed to count the digits for nonnegative integers, not just positive ones (i.e. you algorithm must work on 0).
Here is my suggested alternative based on yours and the criteria of the task.
def order_size(order):
# Fill in your code here
if order >= 0:
size = 0
while order > 0:
size += 1
order = order // 10
return size
else:
return 0
Notice that
By using an inclusive inequality in the if condition, I am allowing 0 to enter the while loop, as I would any other nonnegative single digit number.
By pushing the first return statement back, it executes after the while loop. Thus after the order is counted in the variable size, it is returned.
By pushing the else: back, it executes in the even the if condition is not met (i.e. when the numbers passed to order_size(n) is negative).
By pushing the second return back, it is syntactically correct, and contained in the else block, as it should be.
Now that's taken care of, let me address this:
But I don't get the order // 10 portion.
As of Python 3, the // is a floor division (a.k.a integer division) binary operation.
It effectively performs a standard division, then rounds down (towards negative infinity) to the nearest integer.
Here are some examples to help you out. Pay attention to the last one especially.
10 // 2 # Returns 5 since 10/2 = 5, rounded down is 5
2 // 2 # Returns 1 since 2/2 = 1, rounded down is 1
11 // 2 # Returns 5 since 11/2 = 5.5, rounded down is 5
4 // 10 # Returns 0 since 4/10 = 0.4, rounded down is 0
(-4) // 10 # Returns -1 since (-4)/10 = -0.4, rounded down is -1
For nonnegative numerator n, n // d can be seen as the number of times d fits into n whole.
So for a number like n = 1042, n // 10 would give you how many whole times 10 fits into 1042.
This is 104 (since 1042/10 = 104.2, and rounded down we have 104).
Notice how we've effectively knocked off a digit?
Let's have a look at your while loop.
while order > 0:
size += 1
order = order // 10
Every time a digit is "knocked off" order, the size counter is incremented, thus counting how many digits you can knock off before you hit your terminating step.
Termination occurs when you knock of the final (single) digit. For example, say you reduced order to 1 (from 1042), then 1 // 10 returns 0.
So once all the digits are "knocked off" and counted, your order will have a value of 0. The while loop will then terminate, and your size counter will be returned.
Hope this helps!
Disclaimer: Perhaps this isn't what you want to hear, but many Universities consider copying code from the Internet and passing it off as your own to be plagiarism.

Related

Python: What does 'and not' mean in this code [duplicate]

This question already has answers here:
What is Truthy and Falsy? How is it different from True and False?
(8 answers)
Closed 3 years ago.
This is the entire code. What does 'and not' mean in the code. I understand it to mean that only a number that will equal to 0 when the number modulus 2 is carried out.
That is if 10 is entered by the user, 2,4,6,8 will be sum to get 20.
the_max = int(input("Enter the upper limit:"))
the_sum = 0
extra = 0
for number in range(1,the_max):
if number%2 and not number%3:
the_sum = the_sum + number
else:
extra = extra + 1 # Line 1
print(the_sum) # Line 2
print(extra) # Line 3
It means that the number is not a multiple of 2 but a multiple of 3;
the if statement has two conditions:
number % 2
since the % returns the remainder of a a number divided by 2, it will return 0 on a multiple of 2 and will result in rejection of if condition.
and not number % 3
This means that we need both condition to be good. But with this one the not operand reverses it.
So this time any number % 3 in which number is a multiple of 3 will result in 0 and will be reversed to 1;
You're parsing it wrong. The correct interpretation is
if (number % 2 != 0) and (number % 3 == 0):
This code is taking shortcuts by omitting the explicit comparison to zero, since 0 evaluates to False in a boolean expression like this one, whereas any other integer value evaluates to True.
The second clause, thus, is given a not to flip its polarity. not (number % 3) is equivalent to (number % 3 == 0).

How do I count how many times I've divided in a recursion?

I'm currently taking a course in Computer Science, I got an assignment to use either Python or pseudocode to ask the user to enter a digit, then divide it by 2, and then count how many divisions it takes to reach 1 (and add 1 more as it reaches 1). I've never coded before but I came up with this; but it only returns a 1 no matter what I input.
def divTime (t):
if d <= 1:
return t + 1
else:
return t + 1, divTime(d / 2)
d = input("Enter a number:")
t = 0
print (divTime)(t)
You can add 1 to the recursive call with the input number floor-divided by 2, until the input number becomes 1, at which point return 1:
def divTime(d):
if d == 1:
return 1
return 1 + divTime(d // 2)
so that:
print(divTime(1))
print(divTime(3))
print(divTime(9))
outputs:
1
2
4
This works:
def div_time(d, t=0):
if d < 1:
return t
else:
return div_time(d/2, t+1)
d = input("Enter a number:")
print(f"t = {div_time(int(d))}")
It always returns 1 because you're always passing it 0.
It looks like you're "thinking in loops" – you don't need a separate counter variable.
How many times does it take to divide:
k smaller than 2? None.
k greater than or equal to 2? One more than it takes to divide k // 2.
That is,
def divTime(x):
if x < 2:
return 0
return 1 + divTime(x // 2)
or
def divTime(x):
return 0 if x < 2 else 1 + divTime(x //2)
Instead of providing a straight forward answer, I'll break the problem out into a few steps for students:
Ignore the input and edge cases for now, let's focus on writing a function that solves the problem at hand, then we may come back to providing an input to this function.
Problem statement confusion - You will often divide an odd number with a remainder, skipping the exact number 1 due to remainders. There is ambiguity with your problem from dealing with remainders - we will reword the problem statement:
Write a function that returns the number of times it takes to divide an input integer to become less than or equal to 1.
The next part is identifying the type of algorithm that can solve this type of problem. Since we want to run the function an unknown amount of times using the same function, this seems to be a perfect use case of recursion.
Say I provide 10 as an input. We then want to say 10/2=5 (count 1), 5/2=2.5 (count 2), 2.5/2=1.25 (count 3), 1.25/2=0.625 (count 4), return [4] counts.
Now we know we need a counter (x = x+1), recursion, and a return/print statement.
class solution:
''' this class will print the number of times it takes to divide an integer by 2 to become less than or equal to 1 '''
def __init__(self):
#this global counter will help us keep track of how many times we divide by two. we can use it in functions inside of this class.
self.counter=0
def counter_2(self, input_integer):
#if the input number is less than or equal to 1 (our goal), then we finish by printing the counter.
if input_integer<=1:
print(self.counter, input_integer)
#if the input is greater than 1, we need to keep dividing by 2.
else:
input_integer=input_integer/2
#we divided by two, so make our counter increase by +1.
self.counter=self.counter+1
#use recursion to call our function again, using our current inputer_integer that we just divided by 2 and reassigned the value.
self.counter_2(input_integer)
s=solution()
s.counter_2(10)

Euler Project problem #12 Python code gives weird results

I was trying to solve problem number 12 of Project Euler. This is the problem:
The sequence of triangle numbers is generated by adding the natural
numbers. So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7
= 28. The first ten terms would be:
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
Let us list the factors of the first seven triangle numbers:
1: 1
3: 1,3
6: 1,2,3,6
10: 1,2,5,10
15: 1,3,5,15
21: 1,3,7,21
28: 1,2,4,7,14,28
We can see that 28 is the first triangle number to have over five
divisors.
What is the value of the first triangle number to have over five
hundred divisors?
I defined two functions to do the job:
1) allfactor(x): This gives us all the factors of a given number in a list form. Example: allfactor(10) gives us [1, 2, 5, 10]
2)TriangularNo(x): This gives us the nth Triangular number. Example TriangularNo(5) gives us 5
Here is the complete code which I wrote:
facs=[]
def allfacof(x):
for i in range(1,int(x/2)+1):
if x%i==0:
facs.append(i)
else:
pass
facs.append(x)
return(facs)
def TriangularNo(x):
no=0
for i in range(1,x+1):
no=no+i
return(no)
a=0 # a will tell us the number of iterations
while True:
a+=1
N=TriangularNo(a)
length=(len(allfacof(N)))
if int(length)>=500:
print(N)
break
else:
pass
When I run this code I get 1378 as the output which is clearly wrong because len(allfacof(1378)) turns out to be 8 and not 500 as demanded in the question.
Notice in the while loop, I use if int(length)>=500: So this means that when my code runs, length somehow gets the value = 500 but when I run the function separately it says that it's length is 8.
I am just not able to find out the error. Please help me
The problem is you are using facs as a global variable and you are only appending to the item. You should make it a member of allfacof() so that it clears out after each value.
If you look into facs then you will find it equals
1, 1, 3, 1, 2, 3, 6, 1, 2, 5, 10 ...
Although moving facs into all_factors_of() solves your immediate problem, the next problem with this code is performance. Let's consider triangle number generation first. The optimization that #Voo suggests:
def TriangularNo(n):
return n * (n + 1) / 2
is fine if we're looking for arbitrary triangle numbers -- but we're not. We're looking for sequential triangle numbers, so in this case the formula slows down our code! When going sequentially, you only need do a couple of additions to get the next triangle number -- but using the formula, you need to do an addition, a multiplication and a division! More expensive if you're going sequentially. Since we are going sequentially, this seems a perfect use of a Python generator:
def triangular_number_generator():
triangle = number = 1
while True:
yield triangle
number += 1
triangle += number
Which makes clear the two additions needed to get to the next triangle number. Now let's consider your factorization function:
Your factorization function loses performance in the way that it produces factors in order. But we're only concerned with the number of factors, order doesn't matter. So when we factor 28, we can add 1 and 28 to the factors list at the same time. Ditto 2 and 14 -- making 14 our new upper limit. Similarly 4 and 7 where 7 becomes the new upper limit. So we collect factors faster and quickly reduce the upper limit that we need to check. Here's the rest of the code:
def factors_of(number):
divisor = 1
limit = number
factors = []
while divisor <= limit:
if number % divisor == 0:
factors.append(divisor)
remainder = number // divisor
if remainder != divisor:
factors.append(remainder)
limit = remainder - 1
divisor += 1
return factors
triangular = triangular_number_generator()
number = next(triangular)
factors = factors_of(number)
while len(factors) <= 200:
number = next(triangular)
factors = factors_of(number)
print(number)
How does it compare? If we run your fixed code with a lower limit of > 200 factors, it takes about a minute to come up with the answer (2031120). The above code takes about 1/3 of a second. Now consider how long it'll take both to reach > 500 factors. Finally, to meet the stated goal:
What is the value of the first triangle number to have over five
hundred divisors?
this comparison in your original code:
if int(length)>=500:
would instead need to be:
if length > 500:
Though the way the count of factors jumps, it makes no difference for 500. But for smaller limits, for testing, it can make a difference.

Need explanation of how function works printing digits in reverse

I cheated after giving up of how to figure out how to print digits backwards making a function for it but I still do not quite understand how it works. For instance why does it print the digits backwards and not in order?
def print_digits(n):
"""
>>> print_digits(13789)
9 8 7 3 1
>>> print_digits(39874613)
3 1 6 4 7 8 9 3
>>> print_digits(213141)
1 4 1 3 1 2
"""
while n > 0:
print n % 10
n = n / 10
I would appreciate a line by line explanation starting with the while loop. I've tried tracing it in my head and on paper but just can't grasp the code in the function.
In the first line in the loop the '%' operator devides the number given by 10 and returns the rest only, means the fraction of the division (25 : 10 = 2.5, so it returns the 5 only!).
The line 'n/10' then does exactly the other way around and stores part left of the comma into the variable itself, as the '/' operator returns only the left part of the comma.
In short you can say:
n%10 returns only the rest of the divison
n/10 "throws" the rest of the division away
the code repeats
% operator returns the remainder of division. (20%3=2,24%5=4).
When you divide a number by 10 remainder is always the last digit.
For example 123/10=12 & remainder is 3. So 123%10=3.
Inside the while loop while n is greater than 0 the last digit of n is printed.
And because of the line n=n/10, n becomes n/10. Here integer division has used so finally value of n will become 0 and then the loop will stop.( if n is initially 123 value of n will change as 123,12,1,0 and then loop will stop.)

Checking to see if a number ends in 5?

I'm trying to define a function that takes 2 parameters, adds them up, and if the sum of the two parameters ends in 5, it reports a 2. If it doesn't end in 5, it returns 8.
Any ideas?
I was thinking of doing an if statement, but I'm confused as to how I would check if a number ends in 5( or is 5).
Thanks for your help, trying to teach myself how to program is so difficult yet so rewarding :)
Solution
My answer assumes you are checking integers (which seems pretty reasonable judging from your question):
def sum_ends_with_5(a, b):
"""
Checks if sum ends with "5" digit.
"""
result = a + b
return 2 if result % 10 == 5 else 8
or more flexible (with any number of arguments):
def sum_ends_with_5(*args):
"""
Checks if sum ends with "5" digit.
"""
result = sum(args)
return 2 if result % 10 == 5 else 8
How it works (aka tests)
The function behaves like that:
>>> sum_ends_with_5(5)
2
>>> sum_ends_with_5(3)
8
>>> sum_ends_with_5(2, 8)
8
>>> sum_ends_with_5(7, 8)
2
>>> sum_ends_with_5(10, 20, 3, 2)
2
Shorter version
So, if you want to write it in shorter and more flexible way, you can do this:
def sum_ends_with_5(*args):
return 2 if sum(args) % 10 == 5 else 8
Take the modulus by 10 and check if it's 5.
print num % 10 == 5
Numbers end in 5 if and only if they are are divisible by 5 but are not divisible by 10. You can easily check for these conditions with modulo arithmetic. More generally, you can check if a number ends with a digit by comparing the mod 10 value of that number to the digit.
num = 1234
isDivisibleByFive = num % 10 == 5
One easy approach is to take the number and convert it to a string and check the last digit using indexing to see if it is 5:
E.g.,
n = 153
str(n)[-1] == '5':
False
and
n = 155
str(155)[-1] == '5'
True
So as part of an if-statement:
if str(n)[-1] == `5`:
print "number ends in 5"
else:
print "number did not end in 5"
If you just wanted to check for divisibility by 5 (which is different than ending with 5) you could use the mod operation.
But you also could mod by 10 and check for a remainder of 5 to determine if the number (int) ends with 5. My solution checks for the last digit of any number (including floats)
I like the solution from Tadeck best but there is another way, not as good in my opinion for this specific use case, but still may be useful if your return values ever need to follow more complex rules than is available from a simple modulo operation.
def xlatVal (*nums):
# 0 1 2 3 4 5 6 7 8 9
lookupTbl = [8,8,8,8,8,2,8,8,8,8]
return lookupTbl[sum(nums) % 10]
While the values are still reduced to a range using modulo, this allows arbitrary translations across that range.
Convert it to a string and check the last character:
str(num)[-1] == "5"

Categories