Początkowo, dla ułatwienia zakładając że przedział jest otwarty...
Ponieważ jest to zadanie matematyczne bardziej aniżeli brute-force programistyczny który podsunęli koledzy wyżej :)
I teraz prosta sprawa, ile liczb w przedziale jest podzielnych? Dokładnie tyle, ile się w nim mieści.
Całość, w uproszczeniu da się zamknąć w bardzo prostej linijce:
Kopiuj
len(range(*map(int, input().split())))
Wygląda to trochę jak codegolf, bo można to śmiało dla czytelności rozbić na więcej linii.
map(int, input().split()) - poda nam tuple z trzema argumentami.
* - rozpakuje ją jako argumenty dla range.
len - poda nam długość range, czyli ilość liczb podzielnych przez tą liczbę w przedziale.
Komplikacja się pojawia poza przykładami które podałeś, gdy modulo z początku i z końca zakresu jest równe bądź większe od liczby dzielącej. Wtedy należy od wyniku odjąć jeden. I to jest właśnie ten element którego nie zawiera powyższe uproszczenie.
Korzystając z przykładu @sig:
Kopiuj
pocz, kon, dziel = map(int, input().split()) #~ 4, 17, 3 (Zawiera 4 liczby podzielne przez 3, powyższe uproszczenie poda 5)
suma = len(range(pocz, kon, dziel))
if (pocz%dziel)+(kon%dziel) >= dziel:
suma -= 1
print(suma)
Zakładając że u ciebie przedział ma być specjalnie zaznaczony gdy domykający wyraz będzie podzielny, możesz dodać trzecie modulo sprawdzające czy przedział jest domknięty.
Kopiuj
if not (kon%dziel): #~ Jeśli modulo będzie równe 0
wynik = str(suma+1)+">"
print(wynik)
Trzy modulo, jedno porównanie i jedno dodawanie + prawie że brak zużycia pamięci przez wykorzystanie generatora. Wydaje mi się że ciężko ten problem byłoby rozwiązać lepiej, ewentualnie niech mnie ktoś poprawi :)
Pozostaje ci złożyć klocki podane wyżej do kupy :D
No i zastanowić się skoro tak brzmi polecenie, co wtedy gdy podadzą nam tylko początek i koniec przedziału, zakładam że wtedy należy po prostu zliczyć liczby w przedziale +1 dla zamkniętego przedziału, ponieważ każda liczba całkowita jest podzielna przez 1.
@Edit:
Koniec końców, jak to przeczytałem ponownie, w sumie chyba trzeba użyć list comprehension aby to jakoś wyglądało, jak podsunął @migmig13, albo skorzystać z funkcji i argumentu domyślnego... Oba rozwiązania w sumie mogą być eleganckie.
Kopiuj
def podzielnosc(p, k, d=1):
suma = len(range(p, k, d))
if (p%d)+(k%d) >= d:
suma -= 1
if not k%d and k%p:
return str(suma+1)+">"
elif not k%d:
return str(suma)+">"
return str(suma)
wynik = podzielnosc(*map(int, input().split()))
#~ LUB:
wynik = podzielnosc( *[int(_) for _ in input().split()])
Odnośnie komentarza z modulo, modulo zawsze jest w przedziale całkowitym od 0 do dzielnika (wyłączając sam dzielnik) skoro suma dwóch modulo będzie równa dzielnikowi bądź większa, to nie ma możliwości aby koniec przedziału był zerem :)
Jest późno, jakbym się gdzieś machnął w rozumowaniu lub kodzie, to mnie poprawcie.
Ale tutaj jeszcze wrzucę jak testowałem pokrótce:
@Edit2:
Jeszcze zrobiłem kilka błędów w logice, zapomniałem o początku zakresu że może napsuć oraz niepotrzebnie liczyć kilka razy modulo, bo to potrafi zająć 'dużo' czasu, ogólnie już bez tłumaczenia, kod + sprawdzenia :)
Kopiuj
def podzielnosc(p, k, d=1):
p_mod_d = p%d
if p_mod_d:
suma = len(range(p+(d-p_mod_d), k, d)) #~ Ustawiamy od pierwszej podzielnej
else:
suma = len(range(p, k, d)) #~ Jak pierwsza jest podzielna
if not k%d: #~ Jeśli koniec jest podzielny dodajmy jeden i zamknijmy zakres.
return str(suma+1)+">"
return str(suma)
def sprawdz(wynik, a, b, c=1):
oczekiwany = podzielnosc(a,b,c)
print("{:>4},{:>4},{:>4} | {:^4} == {:^4} | {}".format(a, b, c, oczekiwany, wynik, oczekiwany==wynik))
sprawdz("4>", 3, 10, 2)
sprawdz("2>", 4, 9, 3)
sprawdz("2", 4, 10, 3)
sprawdz("2", 4, 11, 3)
sprawdz("3>", 4, 12, 3)
sprawdz("3>", 5, 12, 3)
sprawdz("3>", 6, 12, 3)
sprawdz("2>", 10, 20, 10)
sprawdz("11>", 10, 20)
print("~"*40)
sprawdz("802550194>", 120321, 3210321096, 4)
sprawdz("508540289", 13216, 8645198132, 17)
Dla długich łańcuchów jak na przykład ostatnie testowe, powinno być bardzo szybkie w stosunku do rozwiązań w innych postach. A podejrzewam że do takich testów właśnie wyskakuje ci timeout, jak to bywa z codewars itd. :)