From 47a267669e0740007ef9f46cac8b90fea27cecab Mon Sep 17 00:00:00 2001 From: Petre Mierlutiu Date: Sat, 20 Dec 2025 21:58:35 +0200 Subject: [PATCH 01/10] robot-name approach: fix typos, minor rephasing/improvements - Fixed a few typos. - Rephrased here and there where I subjectively thought it useful. Please let me know if they're undesirable. - Expanded some contractions - this might help non-native speakers. - When another approach is mentioned, added link to it - hopefully this is useful rather than an distraction - I thought the explanation about the alternative to using the walrus operator was not clear, so rephrased and added a code snippet. I hope this is useful. --- .../robot-name/.approaches/introduction.md | 6 ++--- .../mass-name-generation/content.md | 7 ++--- .../.approaches/name-on-the-fly/content.md | 27 ++++++++++++------- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/exercises/practice/robot-name/.approaches/introduction.md b/exercises/practice/robot-name/.approaches/introduction.md index c4b6738380..be8932a254 100644 --- a/exercises/practice/robot-name/.approaches/introduction.md +++ b/exercises/practice/robot-name/.approaches/introduction.md @@ -1,8 +1,8 @@ # Introduction -Robot Name in Python is an interesting exercise for practising randomness. +Robot Name in Python is an interesting exercise for practicing randomness. ## General Guidance -Two ways immedietely come to mind: generate all the possible names and then return them sequentially, or generate a random name and ensure that it's not been previously used. +Two ways immediately come to mind: generate all the possible names and then return them sequentially, or generate a random name and ensure that it's not been previously used. Randomness can be a little, well, random, so **it's very easy to have an incorrect solution and still pass the tests**. It's strongly recommended to submit your solution for Code Review. @@ -30,7 +30,7 @@ Note that selecting randomly from the list of all names would be incorrect, as t For more detail and explanation of the code, [read here][approach-mass-name-generation]. ## Approach: name on the fly -Another approach is to generate the name on the fly and add it to a cache or a store, and checking if the generated name hasn't been used previously. +Another approach is to generate the name on the fly and add it to a cache or a store, checking if the generated name hasn't been used previously. A possible way to implement this: diff --git a/exercises/practice/robot-name/.approaches/mass-name-generation/content.md b/exercises/practice/robot-name/.approaches/mass-name-generation/content.md index 392a34ca19..948509d712 100644 --- a/exercises/practice/robot-name/.approaches/mass-name-generation/content.md +++ b/exercises/practice/robot-name/.approaches/mass-name-generation/content.md @@ -1,5 +1,5 @@ # Mass Name Generation -We'd first have to generate all the possible names, shuffle them, and then use `next` (the simplest way) or maintain a `current_index` and get the name. +We would first have to generate all the possible names, shuffle them, and then either use `next` (the simplest way) or maintain a `current_index` and get the name. Note that selecting randomly from the list of all names would be incorrect, as there's a possibility of the name being repeated. Here's a possible way to do it: @@ -37,13 +37,14 @@ When the tests reseed `random`, this has no effect as the names were shuffled be We then set `NAMES` to the iterable of names, and in `reset`, set the robot's name to the `next(name)`. If you'd like, read more on [`iter` and `next`][iter-and-next]. -Unlike the on the fly approach, this has a relatively short "generation" time, because we're merely giving the `next` name instead of generating it. +Unlike the [on the fly approach][approach-name-on-the-fly], this has a relatively short "generation" time, because we're merely giving the `next` name instead of generating it. However, this has a huge startup memory and time cost, as 676,000 strings have to be calculated and stored. For an approximate calculation, 676,000 strings * 5 characters / string * 1 byte / character gives 3380000 bytes or 3.38 MB of RAM - and that's just the memory aspect of it. -Sounds small, but it's relatively very expensive at the beginning. +Sounds small, but this might be a relatively significant startup cost. Thus, this approach is inefficient in cases where only a small number of names are needed _and_ the time to set/reset the robot isn't crucial. [random-seed]: https://docs.python.org/3/library/random.html#random.seed [iter-and-next]: https://www.programiz.com/python-programming/methods/built-in/iter [itertools-product]: https://www.hackerrank.com/challenges/itertools-product/problem +[approach-name-on-the-fly]: https://exercism.org/tracks/python/exercises/robot-name/approaches/name-on-the-fly diff --git a/exercises/practice/robot-name/.approaches/name-on-the-fly/content.md b/exercises/practice/robot-name/.approaches/name-on-the-fly/content.md index 0aa9f9a3fa..87cec7e324 100644 --- a/exercises/practice/robot-name/.approaches/name-on-the-fly/content.md +++ b/exercises/practice/robot-name/.approaches/name-on-the-fly/content.md @@ -1,5 +1,5 @@ # Find name on the fly -We generate the name on the fly and add it to a cache or a store, and checking if the generated name hasn't been used previously. +We generate the name on the fly and add it to a cache or a store, checking if the generated name hasn't been used previously. A possible way to implement this: ```python @@ -22,14 +22,22 @@ class Robot: def __init__(self): self.reset() ``` -We use a `set` for the cache as it has a low access time, and we don't need the preservation of order or the ability to be indexed. +We use a `set` for the cache as it has a low access time, and because we do not need the preservation of order or the ability to access by index. -This way is merely one of the many to generate the name. +Using `choices` is merely one of the many ways to generate the name. Another way might be to use `randrange` along with `zfill` for the number part, and a double `random.choice` / `random.choice` on `itertools.product` to generate the letter part. -This is the shortest way, and best utilizes the Python standard library. +The first is shorter, and best utilizes the Python standard library. -As we're using a `while` loop to check for the name generation, it's convenient to store the local `name` using the [walrus operator][walrus-operator]. -It's also possible to find the name before the loop and find it again inside the loop, but that would unnecessary repetition. +As we are using a `while` loop to check for the name generation, it is convenient to store the local `name` using the [walrus operator][walrus-operator]. +It's also possible to find the name once before the loop, and then find it again inside the loop, but that would be an unnecessary repetition: +```python +def reset(self): + name = self.__get_name() + while name in cache: + name = self.__get_name() + cache.add(name) + self.name = name +``` A helper method ([private][private-helper-methods] in this case) makes your code cleaner, but it's equally valid to have the code in the loop itself: ```python def reset(self): @@ -39,14 +47,15 @@ def reset(self): self.name = name ``` -We call `reset` from `__init__` - it's syntactically valid to do it the other way round, but it's not considered good practice to call [dunder methods][dunder-methods] directly. +We call `reset` from `__init__` - it is syntactically valid to do it the other way around, but it is not considered good practice to call [dunder methods][dunder-methods] directly. This has almost no startup time and memory, apart from declaring an empty `set`. -Note that the _generation_ time is the same as the mass generation approach, as a similar method is used. +Note that the _generation_ time is the same as the [mass generation approach][approach-mass-name-generation], as a similar method is used. However, as the name is generated at the time of setting/resetting, the method time itself is higher. In the long run, if many names are generated, this is inefficient, since collisions will start being generated more often than unique names. [walrus-operator]: https://realpython.com/python-walrus-operator/ [private-helper-methods]: https://www.geeksforgeeks.org/private-methods-in-python/ -[dunder-methods]: https://dbader.org/blog/python-dunder-methods \ No newline at end of file +[dunder-methods]: https://dbader.org/blog/python-dunder-methods +[approach-mass-name-generation]: https://exercism.org/tracks/python/exercises/robot-name/approaches/mass-name-generation From 56c302b6485e38ab8d6f311e23b9d1a49524262a Mon Sep 17 00:00:00 2001 From: PetreM Date: Sun, 21 Dec 2025 13:12:33 +0200 Subject: [PATCH 02/10] Update exercises/practice/robot-name/.approaches/mass-name-generation/content.md Co-authored-by: BethanyG --- .../robot-name/.approaches/mass-name-generation/content.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/practice/robot-name/.approaches/mass-name-generation/content.md b/exercises/practice/robot-name/.approaches/mass-name-generation/content.md index 948509d712..01ec88ea51 100644 --- a/exercises/practice/robot-name/.approaches/mass-name-generation/content.md +++ b/exercises/practice/robot-name/.approaches/mass-name-generation/content.md @@ -1,6 +1,6 @@ # Mass Name Generation We would first have to generate all the possible names, shuffle them, and then either use `next` (the simplest way) or maintain a `current_index` and get the name. -Note that selecting randomly from the list of all names would be incorrect, as there's a possibility of the name being repeated. +Note that selecting randomly from the list of all names would be incorrect, as there is a possibility of the name being repeated. Here's a possible way to do it: From d9def28151ab623fec18821f7d8b734012e5d2e7 Mon Sep 17 00:00:00 2001 From: PetreM Date: Sun, 21 Dec 2025 13:12:54 +0200 Subject: [PATCH 03/10] Update exercises/practice/robot-name/.approaches/mass-name-generation/content.md Co-authored-by: BethanyG --- .../robot-name/.approaches/mass-name-generation/content.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/practice/robot-name/.approaches/mass-name-generation/content.md b/exercises/practice/robot-name/.approaches/mass-name-generation/content.md index 01ec88ea51..a099322a63 100644 --- a/exercises/practice/robot-name/.approaches/mass-name-generation/content.md +++ b/exercises/practice/robot-name/.approaches/mass-name-generation/content.md @@ -2,7 +2,7 @@ We would first have to generate all the possible names, shuffle them, and then either use `next` (the simplest way) or maintain a `current_index` and get the name. Note that selecting randomly from the list of all names would be incorrect, as there is a possibility of the name being repeated. -Here's a possible way to do it: +One possible way to do it: ```python from itertools import product From 229c957bc782e560ad6de65ba73d22fde6e81134 Mon Sep 17 00:00:00 2001 From: PetreM Date: Sun, 21 Dec 2025 13:13:18 +0200 Subject: [PATCH 04/10] Update exercises/practice/robot-name/.approaches/mass-name-generation/content.md Co-authored-by: BethanyG --- .../robot-name/.approaches/mass-name-generation/content.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/practice/robot-name/.approaches/mass-name-generation/content.md b/exercises/practice/robot-name/.approaches/mass-name-generation/content.md index a099322a63..baa696c39d 100644 --- a/exercises/practice/robot-name/.approaches/mass-name-generation/content.md +++ b/exercises/practice/robot-name/.approaches/mass-name-generation/content.md @@ -35,7 +35,7 @@ After the name generation, the names are shuffled - using the [default `seed`][r When the tests reseed `random`, this has no effect as the names were shuffled before that. We then set `NAMES` to the iterable of names, and in `reset`, set the robot's name to the `next(name)`. -If you'd like, read more on [`iter` and `next`][iter-and-next]. +If you are interested, you can read more on [`iter` and `next`][iter-and-next]. Unlike the [on the fly approach][approach-name-on-the-fly], this has a relatively short "generation" time, because we're merely giving the `next` name instead of generating it. However, this has a huge startup memory and time cost, as 676,000 strings have to be calculated and stored. From eddb5fe7b1ab05a3d8c1412c89f202da4a0977b6 Mon Sep 17 00:00:00 2001 From: PetreM Date: Sun, 21 Dec 2025 13:13:46 +0200 Subject: [PATCH 05/10] Update exercises/practice/robot-name/.approaches/mass-name-generation/content.md Co-authored-by: BethanyG --- .../robot-name/.approaches/mass-name-generation/content.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/practice/robot-name/.approaches/mass-name-generation/content.md b/exercises/practice/robot-name/.approaches/mass-name-generation/content.md index baa696c39d..5e2dc73087 100644 --- a/exercises/practice/robot-name/.approaches/mass-name-generation/content.md +++ b/exercises/practice/robot-name/.approaches/mass-name-generation/content.md @@ -37,7 +37,7 @@ When the tests reseed `random`, this has no effect as the names were shuffled be We then set `NAMES` to the iterable of names, and in `reset`, set the robot's name to the `next(name)`. If you are interested, you can read more on [`iter` and `next`][iter-and-next]. -Unlike the [on the fly approach][approach-name-on-the-fly], this has a relatively short "generation" time, because we're merely giving the `next` name instead of generating it. +Unlike the [on the fly approach][approach-name-on-the-fly], this has a relatively short "generation" time, because we are merely giving the `next` name instead of generating it. However, this has a huge startup memory and time cost, as 676,000 strings have to be calculated and stored. For an approximate calculation, 676,000 strings * 5 characters / string * 1 byte / character gives 3380000 bytes or 3.38 MB of RAM - and that's just the memory aspect of it. Sounds small, but this might be a relatively significant startup cost. From 18b8d0047ea7e641202659e894ab1ffaccf19c5e Mon Sep 17 00:00:00 2001 From: PetreM Date: Sun, 21 Dec 2025 13:14:16 +0200 Subject: [PATCH 06/10] Update exercises/practice/robot-name/.approaches/name-on-the-fly/content.md Co-authored-by: BethanyG --- .../practice/robot-name/.approaches/name-on-the-fly/content.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/practice/robot-name/.approaches/name-on-the-fly/content.md b/exercises/practice/robot-name/.approaches/name-on-the-fly/content.md index 87cec7e324..9f46276406 100644 --- a/exercises/practice/robot-name/.approaches/name-on-the-fly/content.md +++ b/exercises/practice/robot-name/.approaches/name-on-the-fly/content.md @@ -1,5 +1,5 @@ # Find name on the fly -We generate the name on the fly and add it to a cache or a store, checking if the generated name hasn't been used previously. +We generate the name on the fly and add it to a cache or a store, checking to make sure that the generated name has not been used previously. A possible way to implement this: ```python From 4c4f1e0b72db01d7b592fd2952a6e761833600c1 Mon Sep 17 00:00:00 2001 From: PetreM Date: Sun, 21 Dec 2025 13:15:03 +0200 Subject: [PATCH 07/10] Update exercises/practice/robot-name/.approaches/name-on-the-fly/content.md Co-authored-by: BethanyG --- .../practice/robot-name/.approaches/name-on-the-fly/content.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/practice/robot-name/.approaches/name-on-the-fly/content.md b/exercises/practice/robot-name/.approaches/name-on-the-fly/content.md index 9f46276406..01ef58060d 100644 --- a/exercises/practice/robot-name/.approaches/name-on-the-fly/content.md +++ b/exercises/practice/robot-name/.approaches/name-on-the-fly/content.md @@ -24,7 +24,7 @@ class Robot: ``` We use a `set` for the cache as it has a low access time, and because we do not need the preservation of order or the ability to access by index. -Using `choices` is merely one of the many ways to generate the name. +Using `choices` is one of the many ways to generate the name. Another way might be to use `randrange` along with `zfill` for the number part, and a double `random.choice` / `random.choice` on `itertools.product` to generate the letter part. The first is shorter, and best utilizes the Python standard library. From 36858d7235e8f3906576e33b24391a42fa716a22 Mon Sep 17 00:00:00 2001 From: PetreM Date: Sun, 21 Dec 2025 13:17:50 +0200 Subject: [PATCH 08/10] Update exercises/practice/robot-name/.approaches/mass-name-generation/content.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: AndrĂ¡s B Nagy <20251272+BNAndras@users.noreply.github.com> --- .../robot-name/.approaches/mass-name-generation/content.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/practice/robot-name/.approaches/mass-name-generation/content.md b/exercises/practice/robot-name/.approaches/mass-name-generation/content.md index 5e2dc73087..57230673d9 100644 --- a/exercises/practice/robot-name/.approaches/mass-name-generation/content.md +++ b/exercises/practice/robot-name/.approaches/mass-name-generation/content.md @@ -1,5 +1,5 @@ # Mass Name Generation -We would first have to generate all the possible names, shuffle them, and then either use `next` (the simplest way) or maintain a `current_index` and get the name. +We first generate all the possible names, shuffle them, and then either use `next` (the simplest way) or maintain a `current_index` to get the name. Note that selecting randomly from the list of all names would be incorrect, as there is a possibility of the name being repeated. One possible way to do it: From 4eea484431adeca7cf326d9c0e92346e1fec9e50 Mon Sep 17 00:00:00 2001 From: Petre Mierlutiu Date: Sun, 21 Dec 2025 13:48:15 +0200 Subject: [PATCH 09/10] blank lines after headers and remove trailing whitespace --- exercises/practice/robot-name/.approaches/introduction.md | 4 ++++ .../robot-name/.approaches/mass-name-generation/content.md | 7 ++++--- .../robot-name/.approaches/name-on-the-fly/content.md | 7 ++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/exercises/practice/robot-name/.approaches/introduction.md b/exercises/practice/robot-name/.approaches/introduction.md index be8932a254..6e4bc8e9c5 100644 --- a/exercises/practice/robot-name/.approaches/introduction.md +++ b/exercises/practice/robot-name/.approaches/introduction.md @@ -1,12 +1,15 @@ # Introduction + Robot Name in Python is an interesting exercise for practicing randomness. ## General Guidance + Two ways immediately come to mind: generate all the possible names and then return them sequentially, or generate a random name and ensure that it's not been previously used. Randomness can be a little, well, random, so **it's very easy to have an incorrect solution and still pass the tests**. It's strongly recommended to submit your solution for Code Review. ## Approach: mass name generation + We'd first have to generate all the possible names, shuffle them, and then use `next` (the simplest way) or maintain a `current_index` and get the name. Here's a possible way to do it: @@ -30,6 +33,7 @@ Note that selecting randomly from the list of all names would be incorrect, as t For more detail and explanation of the code, [read here][approach-mass-name-generation]. ## Approach: name on the fly + Another approach is to generate the name on the fly and add it to a cache or a store, checking if the generated name hasn't been used previously. diff --git a/exercises/practice/robot-name/.approaches/mass-name-generation/content.md b/exercises/practice/robot-name/.approaches/mass-name-generation/content.md index 57230673d9..c79714a04b 100644 --- a/exercises/practice/robot-name/.approaches/mass-name-generation/content.md +++ b/exercises/practice/robot-name/.approaches/mass-name-generation/content.md @@ -1,4 +1,5 @@ # Mass Name Generation + We first generate all the possible names, shuffle them, and then either use `next` (the simplest way) or maintain a `current_index` to get the name. Note that selecting randomly from the list of all names would be incorrect, as there is a possibility of the name being repeated. @@ -31,14 +32,14 @@ numbers = (str(i).zfill(3) for i in range(1000)) names = [l + n for l in letter_pairs for n in numbers] ``` -After the name generation, the names are shuffled - using the [default `seed`][random-seed] in the `random` module (the current timestamp). +After the name generation, the names are shuffled - using the [default `seed`][random-seed] in the `random` module (the current timestamp). When the tests reseed `random`, this has no effect as the names were shuffled before that. -We then set `NAMES` to the iterable of names, and in `reset`, set the robot's name to the `next(name)`. +We then set `NAMES` to the iterable of names, and in `reset`, set the robot's name to the `next(name)`. If you are interested, you can read more on [`iter` and `next`][iter-and-next]. Unlike the [on the fly approach][approach-name-on-the-fly], this has a relatively short "generation" time, because we are merely giving the `next` name instead of generating it. -However, this has a huge startup memory and time cost, as 676,000 strings have to be calculated and stored. +However, this has a huge startup memory and time cost, as 676,000 strings have to be calculated and stored. For an approximate calculation, 676,000 strings * 5 characters / string * 1 byte / character gives 3380000 bytes or 3.38 MB of RAM - and that's just the memory aspect of it. Sounds small, but this might be a relatively significant startup cost. diff --git a/exercises/practice/robot-name/.approaches/name-on-the-fly/content.md b/exercises/practice/robot-name/.approaches/name-on-the-fly/content.md index 01ef58060d..7e346c90b0 100644 --- a/exercises/practice/robot-name/.approaches/name-on-the-fly/content.md +++ b/exercises/practice/robot-name/.approaches/name-on-the-fly/content.md @@ -1,4 +1,5 @@ # Find name on the fly + We generate the name on the fly and add it to a cache or a store, checking to make sure that the generated name has not been used previously. A possible way to implement this: @@ -10,7 +11,7 @@ cache = set() class Robot: - def __get_name(self): + def __get_name(self): return ''.join(choices(ascii_uppercase, k=2) + choices(digits, k=3)) def reset(self): @@ -19,7 +20,7 @@ class Robot: cache.add(name) self.name = name - def __init__(self): + def __init__(self): self.reset() ``` We use a `set` for the cache as it has a low access time, and because we do not need the preservation of order or the ability to access by index. @@ -53,7 +54,7 @@ This has almost no startup time and memory, apart from declaring an empty `set`. Note that the _generation_ time is the same as the [mass generation approach][approach-mass-name-generation], as a similar method is used. However, as the name is generated at the time of setting/resetting, the method time itself is higher. -In the long run, if many names are generated, this is inefficient, since collisions will start being generated more often than unique names. +In the long run, if many names are generated, this is inefficient, since collisions will start being generated more often than unique names. [walrus-operator]: https://realpython.com/python-walrus-operator/ [private-helper-methods]: https://www.geeksforgeeks.org/private-methods-in-python/ From 78e5ac22c08a56fd2c85a5238f290c31db0a5295 Mon Sep 17 00:00:00 2001 From: Petre Mierlutiu Date: Sun, 21 Dec 2025 20:50:06 +0200 Subject: [PATCH 10/10] add blank lines around code snippets and expand one more contraction --- exercises/practice/robot-name/.approaches/introduction.md | 4 +++- .../robot-name/.approaches/mass-name-generation/content.md | 1 + .../robot-name/.approaches/name-on-the-fly/content.md | 5 +++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/exercises/practice/robot-name/.approaches/introduction.md b/exercises/practice/robot-name/.approaches/introduction.md index 6e4bc8e9c5..d0140e6534 100644 --- a/exercises/practice/robot-name/.approaches/introduction.md +++ b/exercises/practice/robot-name/.approaches/introduction.md @@ -4,7 +4,7 @@ Robot Name in Python is an interesting exercise for practicing randomness. ## General Guidance -Two ways immediately come to mind: generate all the possible names and then return them sequentially, or generate a random name and ensure that it's not been previously used. +Two ways immediately come to mind: generate all the possible names and then return them sequentially, or generate a random name and ensure that it has not been previously used. Randomness can be a little, well, random, so **it's very easy to have an incorrect solution and still pass the tests**. It's strongly recommended to submit your solution for Code Review. @@ -29,6 +29,7 @@ class Robot(object): def reset(self): self.name = next(NAMES) ``` + Note that selecting randomly from the list of all names would be incorrect, as there's a possibility of the name being repeated. For more detail and explanation of the code, [read here][approach-mass-name-generation]. @@ -38,6 +39,7 @@ Another approach is to generate the name on the fly and add it to a cache or a s A possible way to implement this: + ```python from string import ascii_uppercase, digits from random import choices diff --git a/exercises/practice/robot-name/.approaches/mass-name-generation/content.md b/exercises/practice/robot-name/.approaches/mass-name-generation/content.md index c79714a04b..a245195fa5 100644 --- a/exercises/practice/robot-name/.approaches/mass-name-generation/content.md +++ b/exercises/practice/robot-name/.approaches/mass-name-generation/content.md @@ -26,6 +26,7 @@ class Robot(object): The first few lines of the mass name generation uses [`itertools.product`][itertools-product]. The resultant code is a simplification of: + ```python letter_pairs = (''.join((l1, l2)) for l1 in ascii_uppercase for l2 in ascii_uppercase) numbers = (str(i).zfill(3) for i in range(1000)) diff --git a/exercises/practice/robot-name/.approaches/name-on-the-fly/content.md b/exercises/practice/robot-name/.approaches/name-on-the-fly/content.md index 7e346c90b0..494b32b2d1 100644 --- a/exercises/practice/robot-name/.approaches/name-on-the-fly/content.md +++ b/exercises/practice/robot-name/.approaches/name-on-the-fly/content.md @@ -3,6 +3,7 @@ We generate the name on the fly and add it to a cache or a store, checking to make sure that the generated name has not been used previously. A possible way to implement this: + ```python from string import ascii_uppercase, digits from random import choices @@ -23,6 +24,7 @@ class Robot: def __init__(self): self.reset() ``` + We use a `set` for the cache as it has a low access time, and because we do not need the preservation of order or the ability to access by index. Using `choices` is one of the many ways to generate the name. @@ -31,6 +33,7 @@ The first is shorter, and best utilizes the Python standard library. As we are using a `while` loop to check for the name generation, it is convenient to store the local `name` using the [walrus operator][walrus-operator]. It's also possible to find the name once before the loop, and then find it again inside the loop, but that would be an unnecessary repetition: + ```python def reset(self): name = self.__get_name() @@ -39,7 +42,9 @@ def reset(self): cache.add(name) self.name = name ``` + A helper method ([private][private-helper-methods] in this case) makes your code cleaner, but it's equally valid to have the code in the loop itself: + ```python def reset(self): while (name := ''.join(choices(ascii_uppercase, k=2) + choices(digits, k=3))) in cache: