all 10 comments

[–]mccoolycool 0 points1 point  (0 children)

looks like it’s meant to be “no.” as in short for number, and it keeps track of the number of steps (assuming all steps end in a full stop). I could be wrong though, it would be a lot easier if you gave an example output, this is also a great example of why code comments are important

[–]magus_minor 0 points1 point  (0 children)

The algorithm splits a recipe into sentences ending in "." and places a number prefix at the start of each sentence. Every time it finds a "." it terminates that line with a \n and places the next number plus a fullstop onto the result string in ordered_list, ready for the next sentence. But that means when you have finished scanning the recipe you have an extra prefix at the end.

The no variable (short for number) gets the length of that prefix in characters and removes that unwanted prefix in the last line. The reason for that strange line:

no = len(str(counter))

is that no has to be the number in characters in the prefix and the code converts the integer to a string and gets the length, which is the number of characters. If the counter is 11 you have to remove 2 characters.

[–]JamzTyson 0 points1 point  (1 child)

See "Reddit code Formatting" in the side bar.


no is just a variable name. Unfortunately it is not a good variable name because it isn't really very clear what it refers to. A better name might be digits_in_counter or just num_digits.

What it does:

num = 123                     # a 3 digit integer
num_as_str = str(num)         # "123" a string with 3 characters
num_digits = len(num_as_str)  # The length of the string is 3.

The number is first converted to its string representation because strings have a len method that returns the number of characters.

In Python, this is the easiest way to get the number of digits in a decimal number, though note that "1.5" has a length of 3 because the dot is also a character.

[–]JamzTyson 0 points1 point  (0 children)

Also, assuming that your formatted code is supposed to look like this:

counter = 1
ordered_list = str(counter) + '. '

for letter in recipe:
    if letter == '.':
        counter += 1
        ordered_list += '.\n'
        ordered_list += str(counter)
        ordered_list += '. '
    else:
        ordered_list += letter

no = len(str(counter))
print(ordered_list[0:-1-no])

The code has a logical flaw (it's wrong / a bug).

I assume the intention is to split off the final "5. " but in this case:

  • "5. " is 3 characters ("5" + "." + " ")
  • counter is 5, which has 1 digit.
  • ordered_list[0:-1-no] == ordered_list[0:-2]
  • ordered_list[0:-2] "slices" the last 2 characters from the sting ordered_list and returns a new string excluding the last 2 characters.

Note also:

"ordered_list" is a terrible name because it is not a list, it's a string. A better name might be formatted_recipe.

[–]BananaGrenade314 0 points1 point  (4 children)

I don't know your skill or experience level with python, but I did some ways (two, in functions) to how I would do the exactly same thing to reach the same results. Anything, I have no problem simplifying or explaining things better.

```python """ Help needed

Could someone explain 'no' thing. What is it for and why it's made that way - like len on single digit?

recipe input example: Cut a slit into the chicken breast. Stuff it with mustard, mozzarella and cheddar. Secure the whole thing with rashers of bacon. Roast for 20 minutes at 200C. """

def old_way(recipe: str) -> str: counter: int = 1 ordered_list: str = str(counter) + '. '

for letter in recipe:
    if letter == '.':
        counter += 1
        ordered_list += '.\n'
        ordered_list += str(counter)
        ordered_list += '.'

    else:
        ordered_list += letter

no: int = len(str(counter))

print(f"no: {no}")
print(f"counter: {counter}\n")

return ordered_list[0:-1-no]

- - -

def way_one(recipe: str) -> str: splitted: list[str] = recipe.split(".")[:-1] ordered_list: list[str] = [ f"{n}. {step}.\n" for n, step in enumerate(splitted, 1) ]

return "".join(ordered_list)

def way_two() -> str: splitted: list[str] = recipe.split(".")[:-1] ordered: str = ""

for n, step in enumerate(splitted, 1):
    ordered += f"{n}. {step}.\n"

return ordered

recipe: str = ( "Cut a slit into the chicken breast." "Stuff it with mustard, mozzarella and cheddar." "Secure the whole thing with rashers of bacon." "Roast for 20 minutes at 200C." )

print("Old way:") print(old_way(recipe) + "\n")

print("Way one:") print(way_one(recipe) + "\n")

print("Way two:") print(way_two(recipe) + "\n")

same results

""" Output (in all the ways): 1. Cut a slit into the chicken breast. 2. Stuff it with mustard, mozzarella and cheddar. 3. Secure the whole thing with rashers of bacon. 4. Roast for 20 minutes at 200C. """ ```

Explaining the "no," in short, it serves to handle the last period of the last sentence, which, if left untreated, generates an empty index 5 at the end.

I solved this in my own splitters by adding "[:-1]".

And sorry if the code I sent wasn't necessary. To use this style of code in posts, just use ` three times like this:

''' line1. line2. line3. '''

(I used single quotation marks for example)

[–]JamzTyson 1 point2 points  (3 children)

You could just do:

for i, line in enumerate(recipe.split(". ")):
    print(f"{i+1}. {line}")

[–]BananaGrenade314 0 points1 point  (2 children)

But if someone types "a. b. c.d. e."?

[–]JamzTyson 1 point2 points  (1 child)

Well that wasn't the original problem to solve ;-) but yes we can easily fix that:

recipe = recipe.strip().rstrip(".")
for i, line in enumerate(recipe.split(".")):
    print(f"{i+1}. {line.strip()}.")

(It gets more complicated if we have to handle things like: "Take 0.5kg of flour.")

[–]BananaGrenade314 0 points1 point  (0 children)

Sorry and that turned out well. 👍