PROBLEM SET 7: NUMB3RS | SOLUTION (CS50 PYTHON)

preview_player
Показать описание


––– DISCLAIMER –––

The following videos are for educational purposes only. Cheating or any other activities are highly discouraged!! Using another person’s code breaks the academic honesty guidelines. This solution is for those who have finished the problem sets and want to watch for educational purposes, learning experience, and exploring alternative ways to approach problems and is NOT meant for those actively doing the problem sets. All problem sets presented in this video are owned by Harvard University.

–––
Рекомендации по теме
Комментарии
Автор

Here I am again ;) Maybe make the number regex more strict to accept only numbers with a length of 1-3. Something like `\d{1, 3}`

pieterjdw
Автор

Word of warning!!! the check50 code is a bit buggy. I constantly got ":( test_numb3rs.py catches numb3rs.py only checking first byte of IPv4 address" error. Nothing wrong with my code at all. I finally got it to pass by trying a number other than 255 in some of my test cases. Nuts huh!!! wasted over an hour, but it's a new course and it's free so i won't complain too much hahaha Looks like Giovanna had the same issue too.

Also the RE library has a few quirks. For instance if you want to use quantifiers with groups for example ([0-9]{1, 3}) it will only capture the last group, not all three, which is annoying :( So you'll need to split out the expressions/groups. In the end I wrote an uber REGEX where i didn't even need to inspect the groups and test. But i come from a telco background, so i'm pretty familiar with REGEX. Good luck guys

CaratacusAD
Автор

Also possible to execute this using groups() instead of split() like this:
...
#check if it's IP patter (digit.digit...)
matches = re.search(r"^(\d+)\.(\d+)\.(\d+)\.(\d+)$", ip)
#check if group is within 0-255 range
if matches:
for group in matches.groups():
if int(group) <= 255:
pass
else:
return False
#sys.exit("not ip range")
return True
else:
return False

kyrylldmytrenko
Автор

I don't think we should worry about numbers below zero because it would have to have a minus which would not be how the re is coded

MehdiHuseynzad
Автор

You got me past on of the last checks where I had to check the range for each octet. Thanks!

deemon
Автор

Is there no way of verifying that the numbers are between 0 and 255 inside the re.search command?

hamayun
Автор

my solution for numb3rs using the match expression (although i have to admit that your solution with the list is more clever :) )

import re
import sys

def main():
ad = input("IPv4 Address: ")
x = validate(ad)
print(x)

def validate(ip):
if match := re.search(r"^([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)$", ip):
one = int(match.group(1))
two = int(match.group(2))
three = int(match.group(3))
four = int(match.group(4))
if one <= 255 and two <= 255 and three <= 255 and four <= 255 :
return True
else :
return False
else :
return False

if __name__ == "__main__":
main()

giannisfilippou
Автор

I have managed to solve this problem my using regex only, but man was that hard, damn.
This way is WAY easier and better, I thought about doing it this way but forced myself to practice the regex usage.

SkySesshomaru
Автор

I pass the check test by only using 255 and 512 numbers for test_range part. FYI

beibeiliu
Автор

it's much quicker if you use \d instead of [0-9]

import re
import sys


def main():
print(validate(input("IPv4 Address: ")))


def validate(ip):
if re.search(r"^\d+\.\d+\.\d+\.\d+$", ip):
ip=ip.split(".")
for number in ip:
if 255 < int(number) >0 :
return False
return True
return False



if __name__ == "__main__":
main()

abdqasrawi
Автор

Line 10 of the code:

if int(number) < 0 or int(number) > 255:
return False

int(number) < 0 will always be false so is an unnecessary addition to this if statement. Wonder why? The answer lays in the regular expression. the only thing accepted in the regex is digit or a dot so there won't be any '-' character so it's impossible to get a negative number from it

Another thing, else statement at the end is unnecessary too. I say so because the only way to reach the end of the function is by not passing the if statement which automatically means that the ip is wrong

It may not be a big of a deal but it results in a shorter code that does less operations which should be ideal goal

penteronto
Автор

I used Try Except to catch any wrong input:

def validate(ip):
try:
if match:= re.search(r"^(.+)\.(.+)\.(.+)\.(.+)$", ip):
for i in range(4):
ip_number = int(match.group(i+1))
if ip_number not in range(256):
raise ValueError
return True
else:
return False
except ValueError:
return False

yuz
Автор

very nice approach. here is mine without using a for loop (technically because i'm still telling regex to test it for next parts XD):

import re
import sys

def main():
print(validate(input("IPv4 Address: ")))


def validate(ip):
# expects an IPv4 address as Input as a str
# and then return True or False
parts = ip.split(".")
if len(parts) > 4:
return False

try:
if re.search(r"(\b25[0-5]|\b2[0-4][0-9]|\b[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}", ip):
return True
else:
return False

except:
return False



if __name__ == "__main__":
main()

zaxpeedy
Автор

re.split() was also a solution. RegEx is not as complicated in this case but the code is slightly larger :)

def main():
print(validate(input("IPv4 Address: ")))


def validate(ip):
# Splits by dot
numbers = re.split(r"[.]", ip)

# Number of elements should be 4
if len(numbers) != 4:
return False

# Checks whether number is in range. Also handles the situations where non digits chars were passed to the program
try:
for num in numbers:
if not int(num) in range(0, 256):
return False
except ValueError:
return False

# Returns True if passed
return True


if __name__ == "__main__":
main()

markobondaruk
Автор

my solution works perfectly fine and is much shorter:

import re

def main():
print(validate(input("IPv4 Address: ")))

def validate(addy):
matches = re.search(r"^(\d{1, 3})\.(\d{1, 3})\.(\d{1, 3})\.(\d{1, 3})$", addy)
if matches and (int(matches.group(1)) <= 255 and int(matches.group(2)) <= 255 and int(matches.group(3)) <= 255 and int(matches.group(4)) <= 255):
return True
else:
return False

main()

Rational_consumer
Автор

I passed this one without using regex at all. I think my solution in way simpler

cinthyayotani
Автор

This code will fail if any 'number' in 'list_of_numbers' starts with 0 and has another digit after it. Although int(num) removes redundant zeros, I want the user to write an IP address correctly.

Lukytazcuervo
Автор

Could anyone help look at the code? the terminal shows the 'invalid syntax' error

import re

try:
if re.search(r'^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$', ip):
split_number = ip.split('.')
for a in split_number:
if a < 0 or a > 255:
return False
except:
return True

else:
return False

Sheng-JuiChang
Автор

My approach is diifferent

import re
import sys

def main():
print(validate(input("IPV4 Address: ")))

def validate(ip):
if match_ip := re.search(r"^(\d+)\.(\d+)\.(\d+)\.(\d+)$", ip):
if int(match_ip.group(1)) <=255 and int(match_ip.group(2)) <=255 and int(match_ip.group(3)) <=255 and int(match_ip.group(4)) <=255:
return True
else:
return False

else:
return False

if __name__ == "__main__":
main()

hamadafridi
Автор

import re

def main():
print(validate(input("IPv4 Address: ")))


def validate(ip):
if re.search(r"^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$", ip):
list = ip.split(".")
for i in list:
num = int(i)
if num < 0 or num > 255:
return False
return True
else:
return False



if __name__ == "__main__":
main()

Engr_Abdul_Basit