I'm looking to write a function that receives two four-digit numbers (m, n) that counts how many digits are the same between m and n, including duplicates and zeroes on the left. The thing is, my professor only taught us how to use loops, and don't want us to use lists and intersections, and I'm no able to do it.
For example, if m = 331 and n = 3, it should return 2 as the amount of equal digits, bit if n = 33, it should return 3 same digits.
>>> compare_digits(331, 3)
2
>>> compare_digits(332, 33)
3
Edit: This is the code I created before, and it counts same digits more than it should, but the central idea is the usage of % and // to read each digit, but it's not working...
def compare_digits(m, n):
read_ndigits = 0
same_digits = 0
while read_ndigits < 4: #number of digits
current_n = n % 10
read_mdigits = 0
while read_mdigits < 4:
current_m = m % 10
if current_n == current_m:
same_digits += 1
m //= 10
read_mdigits += 1
n //= 10
read_ndigits += 1
return same_digits
The output is very messy and I can't even recognize any pattern.
You can use collections.Counter() with set intersection:
from collections import Counter
def compare_digits(m, n):
m_counts = Counter(str(m).zfill(4))
n_counts = Counter(str(n).zfill(4))
return sum(min(m_counts[k], n_counts[k]) for k in m_counts.keys() & n_counts.keys())
print(compare_digits(331, 3)) # 2
print(compare_digits(332, 33)) # 3
print(compare_digits(3, 331)) # 2
Well, I decided to limit the number of digits to 4 and not be generic about it, so I wrote this and it worked perfectly:
def compare_digits(m, n):
a = m % 10
m //= 10
b = m % 10
m //= 10
c = m % 10
m //= 10
d = m % 10
read_ndigits = 0
same_digits = 0
while read_ndigits < 4:
current = n % 10
if current == a:
same_digits += 1
a = None
elif current == b:
same_digits += 1
b = None
elif current == c:
same_digits += 1
c = None
elif current == d:
same_digits += 1
d = None
n //= 10
read_ndigits += 1
return same_digits
Thank you all for your help :)
Related
My code should verify if a number is even, if it is, it prints the number multiplied by 2, if it isn't, it should print the number multiplied by 3, but just doesn't work.
m = int(input())
for i in range(m):
n = int(input())
n*=2 if n%2==0 else n*3
print(n)
When i try this input:
3
1
2
3
It returns:
3
4
**27** <- ?
n *= 2 if n % 2 == 0 else n * 3
means
n *= (2 if n % 2 == 0 else n * 3)
which means
if n % 2 == 0:
n = n * 2
else:
n = n * n * 3
You meant to write
n *= 2 if n % 2 == 0 else 3
n*=2 if n%2==0 else n*3
Operator precedence.
This statement is interpreted as
n *= (2 if n%2==0 else n*3)
And for input 3, n%2==0 is not true, so the statement becomes
n *= 9
Which is 27.
Why the program count one more value? For example, I give him N = 50. It gives out:
1
4
9
16
25
36
49
64
Code:
N = int(input())
n = 1
k = 1
while n < N:
n = k ** 2
print(n)
k = k + 1
As explained, you're checking n then changing n, you want to change n then check before continuing.
You can use the walrus operator to assign n and check it's value all in the while statement. (requires Python 3.8+)
N = int(input())
n = 1
k = 1
while (n := k**2) < N:
print(n)
k += 1
This essentially assigns n to k**2 then checks if that result is <N before continuing.
1
4
9
16
25
36
49
Your program outputs 1 4 9 16 25 36 49 64 if your input is 50 because the `while`` loop is checking the value before you increase it. Once in the loop, you increase it, calculate the square and then print.
If you want it to terminate, try setting calculating n as the last step in the loop:
N = int(input())
n = 1
k = 1
while n < N:
print(n)
k = k + 1
n = k ** 2
You're checking whether you reached the limit before you calculate the square and print it. So you're checking the previous value of n, not the one that's about to be printed.
Move the check inside the loop.
while True:
n = k ** 2
if n >= N:
break
print(n)
k += 1
The n < N is evaluated after you've changed (and printed) n.
n = 1
k = 1
N=50
while 1:
n = k ** 2
if n > N:
break
print(n)
k = k + 1
To fix this, break before you print, moving the evaluation inside the loop rather than after the last update of n
1
4
9
16
25
36
49
With the condition of your code, for example, when n = 49, The condition is fulfilled because 49 < 50 therefore it will continue to process the value and print the new one. But once n = 64 which is > 50, it stops. This is a possible solution:
N = int(input())
n = 1
k = 1
while True:
if n >= N:
break
n = k ** 2
print(n)
k = k + 1
This will continuously execute the code but once the condition is met that n >= N, it will stop executing.
I want to create a dict with lists as values, where the content on the lists depends on whether or not the key (numbers 1 to 100) is dividable by 3,5 and/or 7
The output would be like this:
{
1: ['nodiv3', 'nodiv5', 'nodiv7'],
3: ['div3', 'nodiv5', 'nodiv7'],
15: ['div3', 'div5', 'nodiv7'],
}
Similar questions where about filtering the list/values, not creating them.
dict_divider = {}
for x in range(0,101):
div_list= []
if x % 3 == 0:
div_list.append('div3')
else:
div_list.append('nodiv3')
if x % 5 == 0:
div_list.append('div5')
else:
div_list.append('nodiv5')
if x % 7 == 0:
div_list.append('div7')
else:
div_list.append('nodiv7')
dict_divider[x] = div_list
This works just fine, but is there a way to do this with a pythonic one-/twoliner?
Something along like this: d = dict((val, range(int(val), int(val) + 2)) for val in ['1', '2', '3'])
Pythonic is not about one or two liners. In my opinion is (mainly) about readability, perhaps this could be considered more pythonic:
def label(n, divisor):
return f"{'' if n % divisor == 0 else 'no'}div{divisor}"
def find_divisors(n, divisors=[3, 5, 7]):
return [label(n, divisor) for divisor in divisors]
dict_divider = {x: find_divisors(x) for x in range(1, 101)}
print(dict_divider)
You don't actually need to do all these brute-force divisions. Every third number is divisible by three, every seventh number is divisible by seven, etc:
0 1 2 3 4 5 6 7 8 9 ... <-- range(10)
0 1 2 0 1 2 0 1 2 0 ... <-- mod 3
0 1 2 3 4 5 6 7 8 9 ... <-- range(10)
0 1 2 3 4 5 6 0 1 2 ... <-- mod 7
So the best approach should take advantage of that fact, using the repeating patterns of modulo. Then, we can just zip the range with however many iterators you want to use.
import itertools
def divs(n):
L = [f"div{n}"] + [f"nodiv{n}"] * (n - 1)
return itertools.cycle(L)
repeaters = [divs(n) for n in (3, 5, 7)]
d = {x: s for x, *s in zip(range(101), *repeaters)}
There is actually a one liner that isnt even that complicated :)
my_dict = {}
for i in range(100):
my_dict[i] = ['div' + str(n) if i % n == 0 else 'nodiv' + str(n) for n in [3,5,7]]
you could write a second loop so that you only have to write if...else only once
dict_divider = {}
div_check_lst = [3, 5, 7]
for x in range(0,101):
div_list= []
for div_check in div_check_lst:
if x % div_check == 0:
div_list.append(f'div{str(div_check)}')
else:
div_list.append(f'nodiv{str(div_check)}')
dict_divider[x] = div_list
or
dict_divider = {x:[f'{'no' * x % div_check != 0}div{str(div_check)}' for x in range(0,101) for div_check in div_check_lst]}
I'm a beginner and I tried this code to list the sum of all the multiples of 3 or 5 below 100, but it gives a wrong answer and I don't know why.
result = 0
result2 = 0
som = 0
sum2 = 0
below_1000 = True
while below_1000:
result = result+3
if result < 1000:
som += result
else:
below_1000 = False
below_1000 = True
while below_1000:
result2 = result2+5
if result2 < 1000:
sum2 += result2
else:
below_1000 = False
final_result = som+sum2
print(final_result)
Since you first loop over multiples of 3, then again over multiples of 5, you are double-counting a lot of values, specifically values that are multiples of both 3 and 5 (for example 15 or 60).
To write this manually, you can use a for loop over range
total = 0
for i in range(1000):
if i % 3 == 0 or i % 5 == 0:
total += i
>>> total
233168
A more concise way to do this same thing is using a generator expression within the sum function
>>> sum(i for i in range(1000) if i % 3 == 0 or i % 5 == 0)
233168
Can you help me in how to print this on the right way? I've tried many ways but none work'd
while True:
m = int(input())
mlen = m
sm = 1
aux = 1
matriz = []
if m == 0:
print()
break
for i in range(m):
linha = []
for j in range(m):
linha.append(sm)
matriz.append(linha)
while m - 2 > 0:
for i in range(aux, m - 1):
for j in range(aux, m - 1):
matriz[i][j] = sm + 1
sm += 1
aux += 1
m -= 1
for i in matriz:
for j in i:
print('{:4}'.format(j), end='')
print('')
I have to print the matrix as the example below. It's an URI Online Judge exercise (num 1435). The dots below are spaces and I can't have any after the last element of the matrix.
Accepted Output Your Output
1 ··1···1···1···1 1 ···1···1···1···1
2 ··1···2···2···1 2 ···1···2···2···1
3 ··1···2···2···1 3 ···1···2···2···1
4 ··1···1···1···1 4 ···1···1···1···1
6 ··1···1···1···1···1 6 ···1···1···1···1···1
7 ··1···2···2···2···1 7 ···1···2···2···2···1
8 ··1···2···3···2···1 8 ···1···2···3···2···1
9 ··1···2···2···2···1 9 ···1···2···2···2···1
10 ··1···1···1···1···1 10 ···1···1···1···1···1
Thanks in advance.
Try using str.rjust(width[, fillchar]), you can then use the fillchar to get the dots
https://docs.python.org/3.6/library/stdtypes.html?highlight=rjust#str.rjust