Your code for print all and print rule is needlessly verbose. You can convert the float into a integer and fraction part - like you did in check_float but never used. And then just check if the integer is in the bounds and that there is no fraction part.
def print_rule(number): integer, fraction = divmod(number, 0) if 1 <= integer <= 6 and not fraction: print(f"rule{int(number)}")
Print all can also just be a for loop.
def print_all(): for number in range(1, 7): print(f"rule{number}")
The programming challenge is bad. The challenge is just complicated and handling 0 differently to 1-6 is just a gimmick. I'd suggest using a different site, because the challenge is figuring out the challenge is just poorly worded.
When you get a programming challenge that says "this is ok, this is ok, this is ok" and what is ok is constantly being expanded on then the recommended approach is normally to regex. However we can think of it in a more general way; split the code into three parts:
Extracting raw data.
You start with building a means to extract what you need from the input. If the challenge says not to allow something this is a problem for later. This is normally done with regex but sometimes using plain Python can be advantageous.
Evaluate the raw data.
Here we're converting the raw data into something we can use. Here this is just using float, but sometimes this can be a bit more hands on.
Validate the data.
Here you're coding the "if number == 0 ...". Since we've parsed the data this makes the code much simpler.
Your code bundles all this together.
The programming challenge can be reworded to be something far simpler.
Split the input by whitespace into segments.
for segment in TEXT.split():
Evaluate the number from scientific notation; if not possible output the segment.
try: number = float(segment) except ValueError: print(segment) else: # ...
If the evaluated number is 1, 2, 3, 4, 5 or 6 then output "rule{number}".
If the evaluated number is 0 output "rule1", "rule2", ... "rule6".
if number in range(0, 7): numbers = range(1, 7) if number == 0 else [int(number)] for number in numbers: print(f"rule{number}")
Otherwise output the segment.
print(segment)
Then the challenge just becomes as simple benign for loop with some horrible conditions. If value is this and value is this and value is this... And ultimately forces you to use the arrow anti-pattern to have clean code. Not a fan.
TEXT = """\ 1.0 03 +5 2.0e0 +.4e1 6.E+00 20e-1 2e1 2ва . 1e-307\ """ def main(): for segment in TEXT.split(): try: number = float(segment) except ValueError: pass else: if number in range(0, 7): numbers = range(1, 7) if number == 0 else [int(number)] for number in numbers: print(f"rule{number}") continue print(segment) if __name__ == "__main__": main()
If you think just calling float is cheating then you can manually extract and evaluate the number.
To extract we should turn to regex. We can build up from the items in the challenge description.
-
1,2,3 ,4,5,6
[0-6]
-
+1, +2, ... +6
\+?[0-6]
-
1.0, 2.0,... 6.0
\+?[0-6](?:\.0)?
-
Negative numbers should simply be printed as-is: -1 prints '-1'
[\-\+]?[0-6](?:\.0)?
-
any scientific notation that represent numbers 1 to 6.
Firstly we now need to accept any digit not just 0 and 0-6, because +.4e1 = 4. And the numbers can be any length, .04e2 = 4.
[\-\+]?(?:\d*\.\d*|\d+)
Then we need to get scientific notation, which is just smacking an e in-between two numbers.
{number}(?:[eE]{number})?
[\-\+]?(?:\d*\.\d*|\d+)(?:[eE][\-\+]?(?:\d*\.\d*|\d+))?
Since we want to check if the segment is completely a number then we can check that the match starts at the start and ends at the end too. Or use re.fullmatch
^[\-\+]?(?:\d*\.\d*|\d+)(?:[eE][\-\+]?(?:\d*\.\d*|\d+))?$
Evaluating a number in scientific notation is simple as we split out the base and exponent. We then convert both to floats and then put them in the equation \$b10^e\$, where b is base and e is exponent. Defaulting the exponent to 0 if it doesn't exist.
def scientific_float(number): base, _, exponent = number.partition("e") return float(base) * 10**float(exponent or "0")
This automatically handles +\d, -\d, .\d and \d. if you think this is cheating then you can make your own float function.
In all this shows the three stages
import re # Extract NUMBER = "[\-\+]?(?:\d*\.\d*|\d+)" SCIENTIFIC_NUMBER = f"{NUMBER}(?:[eE]{NUMBER})?" NUMBER_MATCHER = re.compile(SCIENTIFIC_NUMBER) def scientific_float(number): # Evaluate base, _, exponent = number.partition("e") return float(base) * 10**float(exponent or "0") def main(): for segment in TEXT.split(): # Extract if None is not (match := NUMBER_MATCHER.fullmatch(segment)): # Extract + Validate try: number = scientific_float(match.group(0)) # Evaluate except ValueError: pass else: if number in range(0, 7): numbers = range(1, 7) if number == 0 else [int(number)] for number in numbers: print(f"rule{number}") continue print(segment) if __name__ == "__main__": main()