From d7c88f38f9a06a724c401dbdf5e6db09bf297197 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Sep 2026 21:48:48 +0300 Subject: [PATCH 01/11] Solve task 1 --- src/part1/constants.py | 48 ++++------------ src/part1/snowflake.py | 122 +++++++---------------------------------- 2 files changed, 29 insertions(+), 141 deletions(-) diff --git a/src/part1/constants.py b/src/part1/constants.py index 9abfbba2..86e0499a 100644 --- a/src/part1/constants.py +++ b/src/part1/constants.py @@ -1,38 +1,10 @@ -"""Bit layout and default epoch for the Twitter Snowflake ID generator. - -A Snowflake identifier is a 63-bit positive integer packed as follows, from -the most significant bit downwards: - - 1 bit unused sign bit, always zero - 41 bits milliseconds elapsed since a custom epoch - 10 bits node identifier - 12 bits per-millisecond sequence counter - -The shift and mask constants should be derived from the bit widths so that -changing a width keeps everything else consistent. -""" - -from typing import Final - - -# TODO: замените заглушки (0) на корректные значения, см. TASK.md. -# Все константы, зависящие от ёмкостей *_BITS, должны вычисляться из них. - -# Twitter's original Snowflake epoch: 2010-11-04 01:42:54.657 UTC. -EPOCH_MS_DEFAULT: Final[int] = 0 - -# Node identifier used when the caller does not supply one. -NODE_ID_DEFAULT: Final[int] = 0 - -# Width of each field, in bits. -TIMESTAMP_BITS: Final[int] = 0 -NODE_ID_BITS: Final[int] = 0 -SEQUENCE_ID_BITS: Final[int] = 0 - -# Largest value each field can hold. -TIMESTAMP_MS_MAX: Final[int] = 0 -NODE_ID_MAX: Final[int] = 0 -SEQUENCE_ID_MAX: Final[int] = 0 - -# Здесь можно добавить собственные вспомогательные константы -# (например, сдвиги полей при сборке идентификатора). +EPOCH_MS_DEFAULT = 1288834974657 +NODE_ID_DEFAULT = 1 +TIMESTAMP_BITS = 41 +NODE_ID_BITS = 10 +SEQUENCE_ID_BITS = 12 +TIMESTAMP_MS_MAX = 2 ** TIMESTAMP_BITS - 1 +NODE_ID_MAX = 2 ** NODE_ID_BITS - 1 +SEQUENCE_ID_MAX = 2 ** SEQUENCE_ID_BITS - 1 +NODE_ID_SHIFT = SEQUENCE_ID_BITS +TIMESTAMP_SHIFT = SEQUENCE_ID_BITS + NODE_ID_BITS \ No newline at end of file diff --git a/src/part1/snowflake.py b/src/part1/snowflake.py index d3abf050..14dca85b 100644 --- a/src/part1/snowflake.py +++ b/src/part1/snowflake.py @@ -1,114 +1,30 @@ -"""Twitter Snowflake identifier generator. - -Snowflake produces roughly time-ordered 64-bit integer identifiers without -coordination between nodes. Each identifier packs the milliseconds elapsed -since a custom epoch, a node identifier and a per-millisecond sequence counter -into a single 63-bit positive integer (see ``constants`` for the layout). - -The public entry point is :func:`generate_snowflake_id`. It is stateless: the -caller passes the sequence counter on every call and is responsible for -advancing it within a millisecond and resetting it when the clock ticks over. - -Each packed field can be read back on its own with :func:`decode_timestamp_ms`, -:func:`decode_node_id` and :func:`decode_sequence_id`. -""" - -import time # noqa: F401 - -from .constants import ( # noqa: F401 - EPOCH_MS_DEFAULT, - NODE_ID_DEFAULT, - NODE_ID_MAX, - SEQUENCE_ID_MAX, - TIMESTAMP_MS_MAX, -) +import time +from constants import EPOCH_MS_DEFAULT ,NODE_ID_DEFAULT, TIMESTAMP_BITS ,NODE_ID_BITS , \ +SEQUENCE_ID_BITS ,TIMESTAMP_MS_MAX ,NODE_ID_MAX ,SEQUENCE_ID_MAX ,NODE_ID_SHIFT ,TIMESTAMP_SHIFT def read_current_millis(epoch_ms: int) -> int: - """Read the number of milliseconds elapsed since the custom epoch. - - Args: - epoch_ms: The custom epoch expressed as Unix milliseconds. - - Returns: - The count of whole milliseconds between ``epoch_ms`` and now. May be - negative if ``epoch_ms`` lies in the future. - """ - # TODO: реализуйте функцию - return 0 + return int(time.time() * 1000) - epoch_ms def decode_timestamp_ms(snowflake_id: int, epoch_ms: int = EPOCH_MS_DEFAULT) -> int: - """Read the timestamp field out of a Snowflake identifier. - - Args: - snowflake_id: An identifier produced against the same epoch. - epoch_ms: The epoch the identifier was generated against. Defaults to - the original Twitter epoch (2010-11-04 01:42:54.657 UTC). - - Returns: - The absolute Unix time in milliseconds at which the identifier was - generated. - """ - # TODO: реализуйте функцию - return 0 + return snowflake_id // (2 ** TIMESTAMP_SHIFT) + epoch_ms -def decode_node_id(snowflake_id: int) -> int: - """Read the node identifier field out of a Snowflake identifier. - - Args: - snowflake_id: An identifier produced by :func:`generate_snowflake_id`. - - Returns: - The node identifier packed into ``snowflake_id``, in the range - ``[0, NODE_ID_MAX]``. - """ - # TODO: реализуйте функцию - return 0 +def decode_node_id(snowflake_id: int, epoch_ms: int = EPOCH_MS_DEFAULT) -> int: + return (snowflake_id - ((decode_timestamp_ms(snowflake_id, epoch_ms) - epoch_ms) * 2 ** TIMESTAMP_SHIFT)) // (2 ** NODE_ID_SHIFT) def decode_sequence_id(snowflake_id: int) -> int: - """Read the sequence counter field out of a Snowflake identifier. - - Args: - snowflake_id: An identifier produced by :func:`generate_snowflake_id`. - - Returns: - The per-millisecond sequence counter packed into ``snowflake_id``, in - the range ``[0, SEQUENCE_ID_MAX]``. - """ - # TODO: реализуйте функцию - return 0 - - -def generate_snowflake_id( - sequence_id: int, - node_id: int = NODE_ID_DEFAULT, - epoch_ms: int = EPOCH_MS_DEFAULT, -) -> int | None: - """Build and return a Snowflake identifier for the current millisecond. - - The function is stateless: the caller passes the per-millisecond sequence - counter explicitly. It is the caller's responsibility to increment - ``sequence_id`` for identifiers minted within the same millisecond and to - reset it once the clock advances. - - Args: - sequence_id: The per-millisecond sequence counter, in the range - ``[0, SEQUENCE_ID_MAX]``. - node_id: The identifier of this node, in the range ``[0, NODE_ID_MAX]``. - Optional; defaults to ``NODE_ID_DEFAULT``. - epoch_ms: The start of the epoch as Unix milliseconds. Optional; - defaults to the original Twitter epoch (2010-11-04 01:42:54.657 - UTC). - - Returns: - The Snowflake identifier as a positive 63-bit integer, or ``None`` if - ``node_id`` is outside ``[0, NODE_ID_MAX]``, ``sequence_id`` is outside - ``[0, SEQUENCE_ID_MAX]``, or the elapsed time no longer fits in the - timestamp field (roughly 69 years after ``epoch_ms``). In each of those - cases an explanatory message is printed to stdout first. - """ - # TODO: реализуйте функцию - return 0 + return snowflake_id - ((snowflake_id // 2 ** NODE_ID_SHIFT) * (2 ** NODE_ID_SHIFT)) + + +def generate_snowflake_id(sequence_id: int, node_id: int = NODE_ID_DEFAULT, epoch_ms: int = EPOCH_MS_DEFAULT) -> int | None: + current_millis = read_current_millis(epoch_ms) + if current_millis < 0 or current_millis > TIMESTAMP_MS_MAX: + raise ValueError('Превышен максимальный лимит времени') + if node_id < 0 or node_id > NODE_ID_MAX: + raise ValueError('Node Id выходит за допустимые пределы') + if sequence_id < 0 or sequence_id > SEQUENCE_ID_MAX: + raise ValueError('Sequence Id выходит за допустимые пределы') + return (current_millis * (2 ** TIMESTAMP_SHIFT)) + (node_id * (2 ** NODE_ID_SHIFT) + sequence_id) \ No newline at end of file From 86c89c4bc3d387310bc242c0af8de47940514e49 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Sep 2026 22:09:56 +0300 Subject: [PATCH 02/11] Solve task 1 --- src/part1/snowflake.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/part1/snowflake.py b/src/part1/snowflake.py index 14dca85b..0d14a824 100644 --- a/src/part1/snowflake.py +++ b/src/part1/snowflake.py @@ -1,6 +1,14 @@ import time -from constants import EPOCH_MS_DEFAULT ,NODE_ID_DEFAULT, TIMESTAMP_BITS ,NODE_ID_BITS , \ -SEQUENCE_ID_BITS ,TIMESTAMP_MS_MAX ,NODE_ID_MAX ,SEQUENCE_ID_MAX ,NODE_ID_SHIFT ,TIMESTAMP_SHIFT + +from constants import ( + EPOCH_MS_DEFAULT, + NODE_ID_DEFAULT, + NODE_ID_MAX, + NODE_ID_SHIFT, + SEQUENCE_ID_MAX, + TIMESTAMP_MS_MAX, + TIMESTAMP_SHIFT, +) def read_current_millis(epoch_ms: int) -> int: @@ -22,9 +30,9 @@ def decode_sequence_id(snowflake_id: int) -> int: def generate_snowflake_id(sequence_id: int, node_id: int = NODE_ID_DEFAULT, epoch_ms: int = EPOCH_MS_DEFAULT) -> int | None: current_millis = read_current_millis(epoch_ms) if current_millis < 0 or current_millis > TIMESTAMP_MS_MAX: - raise ValueError('Превышен максимальный лимит времени') + raise ValueError("Превышен максимальный лимит времени") if node_id < 0 or node_id > NODE_ID_MAX: - raise ValueError('Node Id выходит за допустимые пределы') + raise ValueError("Node Id выходит за допустимые пределы") if sequence_id < 0 or sequence_id > SEQUENCE_ID_MAX: - raise ValueError('Sequence Id выходит за допустимые пределы') + raise ValueError("Sequence Id выходит за допустимые пределы") return (current_millis * (2 ** TIMESTAMP_SHIFT)) + (node_id * (2 ** NODE_ID_SHIFT) + sequence_id) \ No newline at end of file From 7bab98912b921a3534229157789ad5614e12798e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Sep 2026 22:17:25 +0300 Subject: [PATCH 03/11] Solve task 1 --- src/part1/constants.py | 8 ++++---- src/part1/snowflake.py | 20 +++++++++++++++----- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/part1/constants.py b/src/part1/constants.py index 86e0499a..faee44a5 100644 --- a/src/part1/constants.py +++ b/src/part1/constants.py @@ -3,8 +3,8 @@ TIMESTAMP_BITS = 41 NODE_ID_BITS = 10 SEQUENCE_ID_BITS = 12 -TIMESTAMP_MS_MAX = 2 ** TIMESTAMP_BITS - 1 -NODE_ID_MAX = 2 ** NODE_ID_BITS - 1 -SEQUENCE_ID_MAX = 2 ** SEQUENCE_ID_BITS - 1 +TIMESTAMP_MS_MAX = 2**TIMESTAMP_BITS - 1 +NODE_ID_MAX = 2**NODE_ID_BITS - 1 +SEQUENCE_ID_MAX = 2**SEQUENCE_ID_BITS - 1 NODE_ID_SHIFT = SEQUENCE_ID_BITS -TIMESTAMP_SHIFT = SEQUENCE_ID_BITS + NODE_ID_BITS \ No newline at end of file +TIMESTAMP_SHIFT = SEQUENCE_ID_BITS + NODE_ID_BITS diff --git a/src/part1/snowflake.py b/src/part1/snowflake.py index 0d14a824..19a4f087 100644 --- a/src/part1/snowflake.py +++ b/src/part1/snowflake.py @@ -16,18 +16,26 @@ def read_current_millis(epoch_ms: int) -> int: def decode_timestamp_ms(snowflake_id: int, epoch_ms: int = EPOCH_MS_DEFAULT) -> int: - return snowflake_id // (2 ** TIMESTAMP_SHIFT) + epoch_ms + return snowflake_id // (2**TIMESTAMP_SHIFT) + epoch_ms def decode_node_id(snowflake_id: int, epoch_ms: int = EPOCH_MS_DEFAULT) -> int: - return (snowflake_id - ((decode_timestamp_ms(snowflake_id, epoch_ms) - epoch_ms) * 2 ** TIMESTAMP_SHIFT)) // (2 ** NODE_ID_SHIFT) + return ( + snowflake_id + - ( + (decode_timestamp_ms(snowflake_id, epoch_ms) - epoch_ms) + * 2**TIMESTAMP_SHIFT + ) + ) // (2**NODE_ID_SHIFT) def decode_sequence_id(snowflake_id: int) -> int: - return snowflake_id - ((snowflake_id // 2 ** NODE_ID_SHIFT) * (2 ** NODE_ID_SHIFT)) + return snowflake_id - ((snowflake_id // 2**NODE_ID_SHIFT) * (2**NODE_ID_SHIFT)) -def generate_snowflake_id(sequence_id: int, node_id: int = NODE_ID_DEFAULT, epoch_ms: int = EPOCH_MS_DEFAULT) -> int | None: +def generate_snowflake_id( + sequence_id: int, node_id: int = NODE_ID_DEFAULT, epoch_ms: int = EPOCH_MS_DEFAULT +) -> int | None: current_millis = read_current_millis(epoch_ms) if current_millis < 0 or current_millis > TIMESTAMP_MS_MAX: raise ValueError("Превышен максимальный лимит времени") @@ -35,4 +43,6 @@ def generate_snowflake_id(sequence_id: int, node_id: int = NODE_ID_DEFAULT, epoc raise ValueError("Node Id выходит за допустимые пределы") if sequence_id < 0 or sequence_id > SEQUENCE_ID_MAX: raise ValueError("Sequence Id выходит за допустимые пределы") - return (current_millis * (2 ** TIMESTAMP_SHIFT)) + (node_id * (2 ** NODE_ID_SHIFT) + sequence_id) \ No newline at end of file + return (current_millis * (2**TIMESTAMP_SHIFT)) + ( + node_id * (2**NODE_ID_SHIFT) + sequence_id + ) From c552b886236370d819d7c344e0a85dc71c19724d Mon Sep 17 00:00:00 2001 From: phantom686 Date: Fri, 25 Sep 2026 22:27:53 +0300 Subject: [PATCH 04/11] Update snowflake.py --- src/part1/snowflake.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/part1/snowflake.py b/src/part1/snowflake.py index 19a4f087..ae1e7ee5 100644 --- a/src/part1/snowflake.py +++ b/src/part1/snowflake.py @@ -1,6 +1,6 @@ import time -from constants import ( +from .constants import ( EPOCH_MS_DEFAULT, NODE_ID_DEFAULT, NODE_ID_MAX, From 1e23410bc949fbef2638a3e25b21ffcf061e79a8 Mon Sep 17 00:00:00 2001 From: phantom686 Date: Fri, 25 Sep 2026 22:35:25 +0300 Subject: [PATCH 05/11] Update constants.py --- src/part1/constants.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/part1/constants.py b/src/part1/constants.py index faee44a5..960e4b82 100644 --- a/src/part1/constants.py +++ b/src/part1/constants.py @@ -1,10 +1,10 @@ -EPOCH_MS_DEFAULT = 1288834974657 -NODE_ID_DEFAULT = 1 -TIMESTAMP_BITS = 41 -NODE_ID_BITS = 10 -SEQUENCE_ID_BITS = 12 -TIMESTAMP_MS_MAX = 2**TIMESTAMP_BITS - 1 -NODE_ID_MAX = 2**NODE_ID_BITS - 1 -SEQUENCE_ID_MAX = 2**SEQUENCE_ID_BITS - 1 -NODE_ID_SHIFT = SEQUENCE_ID_BITS -TIMESTAMP_SHIFT = SEQUENCE_ID_BITS + NODE_ID_BITS +EPOCH_MS_DEFAULT: int = 1288834974657 +NODE_ID_DEFAULT: int = 1 +TIMESTAMP_BITS: int = 41 +NODE_ID_BITS: int = 10 +SEQUENCE_ID_BITS: int = 12 +TIMESTAMP_MS_MAX: int = 2**TIMESTAMP_BITS - 1 +NODE_ID_MAX: int = 2**NODE_ID_BITS - 1 +SEQUENCE_ID_MAX: int = 2**SEQUENCE_ID_BITS - 1 +NODE_ID_SHIFT: int = SEQUENCE_ID_BITS +TIMESTAMP_SHIFT: int = SEQUENCE_ID_BITS + NODE_ID_BITS From 3a6dc3dfa928505efc4315c091d3699c0de1bf4a Mon Sep 17 00:00:00 2001 From: phantom686 Date: Fri, 25 Sep 2026 22:40:01 +0300 Subject: [PATCH 06/11] Update snowflake.py --- src/part1/snowflake.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/part1/snowflake.py b/src/part1/snowflake.py index ae1e7ee5..80808ec6 100644 --- a/src/part1/snowflake.py +++ b/src/part1/snowflake.py @@ -12,25 +12,25 @@ def read_current_millis(epoch_ms: int) -> int: - return int(time.time() * 1000) - epoch_ms + return int(int(time.time() * 1000) - epoch_ms) def decode_timestamp_ms(snowflake_id: int, epoch_ms: int = EPOCH_MS_DEFAULT) -> int: - return snowflake_id // (2**TIMESTAMP_SHIFT) + epoch_ms + return int(snowflake_id // (2**TIMESTAMP_SHIFT) + epoch_ms) def decode_node_id(snowflake_id: int, epoch_ms: int = EPOCH_MS_DEFAULT) -> int: - return ( + return int(( snowflake_id - ( (decode_timestamp_ms(snowflake_id, epoch_ms) - epoch_ms) * 2**TIMESTAMP_SHIFT ) - ) // (2**NODE_ID_SHIFT) + ) // (2**NODE_ID_SHIFT)) def decode_sequence_id(snowflake_id: int) -> int: - return snowflake_id - ((snowflake_id // 2**NODE_ID_SHIFT) * (2**NODE_ID_SHIFT)) + return int(snowflake_id - ((snowflake_id // 2**NODE_ID_SHIFT) * (2**NODE_ID_SHIFT))) def generate_snowflake_id( @@ -43,6 +43,6 @@ def generate_snowflake_id( raise ValueError("Node Id выходит за допустимые пределы") if sequence_id < 0 or sequence_id > SEQUENCE_ID_MAX: raise ValueError("Sequence Id выходит за допустимые пределы") - return (current_millis * (2**TIMESTAMP_SHIFT)) + ( + return int((current_millis * (2**TIMESTAMP_SHIFT)) + ( node_id * (2**NODE_ID_SHIFT) + sequence_id - ) + )) From edd79d85900a747996b88077776f8c82fac6f9c3 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Sep 2026 22:49:29 +0300 Subject: [PATCH 07/11] Solve task 1 --- pl-001-python-basics-task | 1 + src/part1/snowflake.py | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) create mode 160000 pl-001-python-basics-task diff --git a/pl-001-python-basics-task b/pl-001-python-basics-task new file mode 160000 index 00000000..3a6dc3df --- /dev/null +++ b/pl-001-python-basics-task @@ -0,0 +1 @@ +Subproject commit 3a6dc3dfa928505efc4315c091d3699c0de1bf4a diff --git a/src/part1/snowflake.py b/src/part1/snowflake.py index 19a4f087..8fef484d 100644 --- a/src/part1/snowflake.py +++ b/src/part1/snowflake.py @@ -1,12 +1,14 @@ import time - -from constants import ( +from .constants import ( EPOCH_MS_DEFAULT, NODE_ID_DEFAULT, + TIMESTAMP_BITS, + NODE_ID_BITS, + SEQUENCE_ID_BITS, + TIMESTAMP_MS_MAX, NODE_ID_MAX, - NODE_ID_SHIFT, SEQUENCE_ID_MAX, - TIMESTAMP_MS_MAX, + NODE_ID_SHIFT, TIMESTAMP_SHIFT, ) From d173d13d14552d4914e10aa5deb2d83e1979a729 Mon Sep 17 00:00:00 2001 From: phantom686 Date: Fri, 25 Sep 2026 23:16:30 +0300 Subject: [PATCH 08/11] Update snowflake.py --- src/part1/snowflake.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/part1/snowflake.py b/src/part1/snowflake.py index e2f93e26..b3559d66 100644 --- a/src/part1/snowflake.py +++ b/src/part1/snowflake.py @@ -1,8 +1,4 @@ import time -<<<<<<< HEAD -======= - ->>>>>>> 3a6dc3dfa928505efc4315c091d3699c0de1bf4a from .constants import ( EPOCH_MS_DEFAULT, NODE_ID_DEFAULT, From d6563495528fe1bc8ceb96ec961604b3a7e32abe Mon Sep 17 00:00:00 2001 From: phantom686 Date: Fri, 25 Sep 2026 23:19:57 +0300 Subject: [PATCH 09/11] Update snowflake.py --- src/part1/snowflake.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/part1/snowflake.py b/src/part1/snowflake.py index b3559d66..f9bdf778 100644 --- a/src/part1/snowflake.py +++ b/src/part1/snowflake.py @@ -2,9 +2,6 @@ from .constants import ( EPOCH_MS_DEFAULT, NODE_ID_DEFAULT, - TIMESTAMP_BITS, - NODE_ID_BITS, - SEQUENCE_ID_BITS, TIMESTAMP_MS_MAX, NODE_ID_MAX, SEQUENCE_ID_MAX, From ff338aabc03a2e7b958e079293064586d3c0437c Mon Sep 17 00:00:00 2001 From: phantom686 Date: Fri, 25 Sep 2026 23:25:57 +0300 Subject: [PATCH 10/11] Update snowflake.py --- src/part1/snowflake.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/part1/snowflake.py b/src/part1/snowflake.py index f9bdf778..6518cb38 100644 --- a/src/part1/snowflake.py +++ b/src/part1/snowflake.py @@ -2,10 +2,10 @@ from .constants import ( EPOCH_MS_DEFAULT, NODE_ID_DEFAULT, - TIMESTAMP_MS_MAX, NODE_ID_MAX, - SEQUENCE_ID_MAX, NODE_ID_SHIFT, + SEQUENCE_ID_MAX, + TIMESTAMP_MS_MAX, TIMESTAMP_SHIFT, ) From bf59011930c5c7b174a582391fc83a1ede03085b Mon Sep 17 00:00:00 2001 From: phantom686 Date: Fri, 25 Sep 2026 23:29:12 +0300 Subject: [PATCH 11/11] Update snowflake.py --- src/part1/snowflake.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/part1/snowflake.py b/src/part1/snowflake.py index 6518cb38..80808ec6 100644 --- a/src/part1/snowflake.py +++ b/src/part1/snowflake.py @@ -1,4 +1,5 @@ import time + from .constants import ( EPOCH_MS_DEFAULT, NODE_ID_DEFAULT,