108 lines
3.6 KiB
Python
108 lines
3.6 KiB
Python
"""
|
|
This module has no real meaning.
|
|
Simply implemented for evaluating students.
|
|
"""
|
|
|
|
from pathlib import Path
|
|
from itertools import chain
|
|
import re
|
|
import string
|
|
|
|
def list_filenames_of_log_files(*foldernames) -> list:
|
|
"""
|
|
List all the `*.log` files stored in the folders specified by foldernames.
|
|
This method returns a list containing the corresponding strings. Ordered in alphabetical order.
|
|
This method does not print anything.
|
|
|
|
:param foldernames:
|
|
:return: list of filenames
|
|
|
|
:raises FileNotFoundError: If one of the speficied folders does not exist
|
|
"""
|
|
def walk(folder):
|
|
if not folder.exists():
|
|
raise FileNotFoundError(f"{folder} does not exist")
|
|
for subfold, childfolds, files in folder.walk():
|
|
for f in files:
|
|
if ".log" in f:
|
|
yield subfold / f
|
|
|
|
# final cast as list would generally be omited but due to the test expecting
|
|
# an indexable object, this cast is need. It would be more idiomatic to return
|
|
# a generator and iterate over it tho.
|
|
return list(chain(*[walk(Path(foldername)) for foldername in foldernames]))
|
|
|
|
|
|
def list_ipv4_listed_in_logfiles(*foldernames) -> list:
|
|
"""
|
|
Parse all the `*.log` files stored in the folders specified by foldernames.
|
|
This method returns a list of ip adresses stored in those files.
|
|
This method does not print anything.
|
|
Only IPv4 format are listed
|
|
No duplicates are returned.
|
|
|
|
:param foldernames:
|
|
:return: list of ips
|
|
|
|
:raises FileNotFoundError: If one of the speficied folders does not exist
|
|
"""
|
|
def get_ip_from_file(file):
|
|
matcher = re.compile(r"(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})")
|
|
with open(file) as f:
|
|
for line in f:
|
|
if match := matcher.search(line):
|
|
yield match.group()
|
|
# cast to a set to delete duplicates
|
|
# cast to a list 'caus the test is hardcoded to get a list
|
|
return list(set(chain(*[get_ip_from_file(file) for file in list_filenames_of_log_files(*foldernames)])))
|
|
|
|
|
|
def cryptarithme(message: str = "SEND + MORE = MONEY") -> list:
|
|
"""
|
|
The `message` is a formatted mathematical operation.
|
|
Each letter represents a number between 0 and 9.
|
|
Each letter represents a different value.
|
|
|
|
Find the value for each letter so that the full sentence is true.
|
|
|
|
Knowing that if the word is longer than 1 letter,
|
|
the first letter of the word cannot be a 0.
|
|
|
|
It can occur that several results are possible.
|
|
If so, all solutions must be returned in differents dictionnairies.
|
|
The order is not relevant.
|
|
Example : A + A = C returns
|
|
[
|
|
{"A" : 1, "C" : 2},
|
|
{"A" : 2, "C" : 4},
|
|
{"A" : 3, "C" : 6},
|
|
{"A" : 4, "C" : 8}
|
|
]
|
|
|
|
:param message: The string to analyse
|
|
:return: List of dictionnaries with the following format : {
|
|
'letter1': value1,
|
|
'letter2': value2
|
|
}
|
|
|
|
:raises ValueError: If the string cannot be parsed properly.
|
|
:raises CryptarithmeError : If the string is not a possible Cryptarithme
|
|
"""
|
|
|
|
# check for syntax
|
|
for i, character in enumerate(message):
|
|
if character not in [*string.ascii_uppercase, "+", "=", " "]:
|
|
raise ValueError(f"illegal character {character} at {i}")
|
|
if len([i for i in message if i == "="]) >= 2 or len([i for i in message if i == "+"]) >= 2:
|
|
raise ValueError("too much =")
|
|
return message
|
|
|
|
class CryptarithmeError(Exception):
|
|
pass
|
|
|
|
if __name__ == "__main__":
|
|
# list_filenames_of_log_files('data')
|
|
# list_ipv4_listed_in_logfiles('data')
|
|
# cryptarithme('A + A +A= B')
|
|
pass
|