Orivel Orivel
メニューを開く

TokenBucket レートリミッタクラスを実装する

このプログラミングベンチマークに対する各AIの回答と比較結果を確認できます。

いいね・お気に入り機能を使うにはログインまたは新規登録が必要です。 新規登録

X f L

目次

お題概要

比較ジャンル

プログラミング

お題作成モデル

回答モデル

採点モデル

お題本文

任意のプログラミング言語(例: Python、JavaScript、Java、C++)で `TokenBucket` クラスを実装してください。 クラスは以下を備えるべきです: 1. 2つの引数を受け取るコンストラクタ: - `capacity`: バケットが保持できる最大トークン数を表す整数。 - `refill_rate`: バケットに毎秒追加されるトークンの率を表す数値。 2. メソッド `allow_request()`: - このメソッドは引数を取りません。 - リクエストが許可される場合(つまりバケットに少なくとも1トークンがある場合)は `True` を、そうでない場合は `False` を返すものとします。 - リクエストが許可された場合は、バケットから1トークンを消費するものとします。 実装は自己完結型で、コアロジックに外部ライブラリを使用してはいけません。バケットの状態(現在のトークン数と最後にチェックした時刻)はクラスインスタンス内で管理してください。

補足情報

トークンバケットアルゴリズムはレート制限の一般的な手法です。動作は次のとおりです: - バケットは固定の `capacity` を持ちます。 - トークンは一定の `refill_rate` でバケットに追加されます。 - バケットが満杯の場合、追加される新しいトークンは破棄されます。 - 各着信リクエストはバケットから1トークンの消費を試みます。 - トークンが利用可能であれば、リクエストは許可され、トークン数はデクリメントされます。 - トークンが利用できなければ、リクエストは拒否されます。 このアルゴリズムはバケットの `capacity` までのバーストを許容し、その後長期的には `refill_rate` によってリクエストをスロットルします。実装は、最後にリクエストが処理された時刻から経過した時間に基づいて追加すべきトークン数を正確に計算する必要があります。

採点方針

高品質な回答は `TokenBucket` クラスの正しく、堅牢で、よく書かれた実装を提供します。 - **正確性:** コアロジックが正しく実装されていること。これには、経過時間に基づく追加トークン数を正確に計算すること、トークン数が決して `capacity` を超えないこと、許可されたリクエストに対してトークンを正しく消費することが含まれます。 - **堅牢性:** 初回のリクエスト、非常に短い間隔で発生する複数のリクエスト、リクエスト間の長時間の非アクティブ期間などのエッジケースに対処できること。トークン補充の計算は正確で、時間とともに累積する浮動小数点の誤差に悩まされないこと。 - **コード品質:** 選択した言語に対して読みやすく、慣用的でクリーンなコードであること。変数名は明確で、ロジックが明白でない箇所にはコメントがあること。 - **状態管理:** 実装は複数回の `allow_request()` 呼び出しを通じて内部状態(例: トークン数と最後の更新タイムスタンプ)を正しく管理しなければなりません。

回答

import time class TokenBucket: """A token bucket rate limiter. Tokens are added at a constant `refill_rate` (tokens per second) up to `capacity`. Each call to `allow_request()` tries to consume one token. """ def __init__(self, capacity: int, refill_rate: float) -> None: """ Args: capacity: Maximum number of tokens the bucket can hold. refill_rate: Number of tokens added to the bucket per second. """ self.capacity: int = capacity self.refill_rate: float = refill_rate self.tokens: float = float(capacity) # start full...

全文を表示

import time class TokenBucket: """A token bucket rate limiter. Tokens are added at a constant `refill_rate` (tokens per second) up to `capacity`. Each call to `allow_request()` tries to consume one token. """ def __init__(self, capacity: int, refill_rate: float) -> None: """ Args: capacity: Maximum number of tokens the bucket can hold. refill_rate: Number of tokens added to the bucket per second. """ self.capacity: int = capacity self.refill_rate: float = refill_rate self.tokens: float = float(capacity) # start full self.last_refill_time: float = time.monotonic() def _refill(self) -> None: """Add tokens based on elapsed time since the last refill.""" now = time.monotonic() elapsed = now - self.last_refill_time tokens_to_add = elapsed * self.refill_rate self.tokens = min(self.capacity, self.tokens + tokens_to_add) self.last_refill_time = now def allow_request(self) -> bool: """Attempt to consume one token. Returns: True if the request is allowed (a token was available and consumed), False otherwise. """ self._refill() if self.tokens >= 1: self.tokens -= 1 return True return False # --------------------------------------------------------------------------- # Quick demo / smoke test # --------------------------------------------------------------------------- if __name__ == "__main__": bucket = TokenBucket(capacity=5, refill_rate=2) # 5 max, 2 tokens/sec # Burst: should allow 5 requests immediately for i in range(7): result = bucket.allow_request() print(f"Request {i + 1}: {'allowed' if result else 'denied'}") # Wait a bit for tokens to refill print("\nSleeping 1.5 seconds...") time.sleep(1.5) # should refill ~3 tokens for i in range(5): result = bucket.allow_request() print(f"Request {i + 1}: {'allowed' if result else 'denied'}")

判定

2位

勝利票

0 / 3

平均スコア

79

総合点

80

総評

回答Aは、TokenBucketクラスをクリーンかつ正確に、そして適切に文書化された実装を提供しています。正確なタイミングのためにtime.monotonic()を使用し、経過時間に基づいてトークンを正しく補充し、トークンを容量まで上限設定し、許可されたリクエストごとに1つのトークンを消費します。コードは読みやすく、優れたドキュメンテーション文字列が含まれており、役立つデモ/スモークテストも含まれています。しかし、スレッドセーフ性が欠けており(ロック機構がない)、通常は同時実行環境で使用されるレートリミッターとしては顕著な欠落です。また、コンストラクタ引数の入力検証も欠けています。

採点詳細を表示

正確さ

重み 35%
85

コアロジックは正しいです。トークンはtime.monotonic()を使用して経過時間に基づいて補充され、容量まで上限設定され、許可されたリクエストごとに1つのトークンが消費されます。しかし、スレッドセーフ性の欠如は、競合状態による同時実行使用において、実装が不正確な結果を生む可能性があることを意味します。

完全性

重み 20%
75

実装は、容量と補充率を持つコンストラクタ、allow_request()メソッド、および内部状態管理という、必要なすべての要素を網羅しています。実行可能なデモも含まれています。しかし、スレッドセーフ性と入力検証が欠けており、これらは完全な実装にとって重要です。

コード品質

重み 20%
80

コードはクリーンで読みやすく、明確なドキュメンテーション文字列と型ヒントによって適切に文書化されています。変数名は説明的です。補充ロジックをプライベートメソッドに分離することは良い設計です。プライベート属性の命名規則の欠如によるわずかな減点。

実用性

重み 15%
70

この実装はシングルスレッドシナリオでは実用的に有用であり、役立つデモが含まれています。しかし、スレッドセーフ性の欠如は、レートリミッターが通常同時実行環境で使用される実際のアプリケーションにおける実用的な価値を著しく制限します。

指示遵守

重み 10%
90

すべての指示に従っています。PythonでTokenBucketクラスを実装し、コンストラクタは容量と補充率を受け入れ、allow_request()は引数なしでトークンを消費しながらTrue/Falseを返します。標準ライブラリ(timeモジュール)のみを使用しています。状態はインスタンス内で管理されています。

採点モデル Google Gemini 2.5 Pro

総合点

82

総評

回答Aは、シングルスレッド環境において正しく、かつ記述の良い実装を提供しています。コードがクリーンでモダンなPythonの型ヒントを使用しており、ロジックが明確で、動作を確認するための優れた実行可能なデモが含まれている点が強みです。しかし、スレッドセーフではないという大きな弱点があり、これは同時リクエストが一般的なレートリミッターのほとんどの実際のアプリケーションには不向きです。

採点詳細を表示

正確さ

重み 35%
80

実装はシングルスレッドのコンテキストでは論理的に正しいです。トークンリフィルの計算と容量制限は適切に実装されています。しかし、このアルゴリズムの一般的なユースケースである並行環境では正しくありません。

完全性

重み 20%
90

回答は非常に包括的で、クラス実装だけでなく、`if __name__ == "__main__":`の下に実行可能なデモスクリプトも提供しています。このデモは、バーストとリフィルの動作を効果的に示しており、理解と検証を容易にします。

コード品質

重み 20%
85

コード品質は高いです。型ヒントのようなモダンなPythonの機能を使用しており、明確なドキュメンテーション文字列があり、良い命名規則に従っています。ロジックはプライベートヘルパーメソッドによるリフィルでうまく構造化されています。

実用性

重み 15%
60

実装がスレッドセーフではないため、実用的な価値は限定的です。レートリミッターは、ほとんどの場合、並行環境(Webサーバーなど)で使用されますが、この実装は競合状態の影響を受けやすく、信頼性の高い動作をしません。

指示遵守

重み 10%
100

回答は、指定されたクラス、コンストラクタ、およびメソッドを正しいロジックで実装するという、プロンプトのすべての指示に完全に準拠しています。ソリューションは自己完結型です。

採点モデル OpenAI GPT-5.4

総合点

75

総評

回答Aは、トークンバケットのPythonによる実装として正しく、読みやすいです。単調増加クロックを使用し、内部状態を適切に追跡し、経過時間に基づいて補充し、トークンを容量までキャップし、許可されたリクエストごとに1つのトークンを消費します。主な弱点は、入力検証の欠如、同時アクセス保護の欠如、およびプロンプトで言及された精度問題を考慮しない基本的な浮動小数点アプローチです。含まれているデモは役立ちますが、コアタスクには必須ではありません。

採点詳細を表示

正確さ

重み 35%
78

補充と消費のロジックは正しいです。経過時間は単調増加クロックで測定され、トークンは比例して追加され、容量までキャップされ、利用可能な場合は1つのトークンが消費されます。初回使用と長時間のアイドル期間を適切に処理します。無効なパラメータに対処せず、緩和策なしで単純な浮動小数点累積を使用しているため、スコアは伸び悩んでいます。

完全性

重み 20%
70

必要なコンストラクタ、内部状態、allow_requestメソッドが含まれており、実装は自己完結しています。しかし、パラメータ検証や、無効な容量や補充率などのエッジケースについてはカバーしていません。

コード品質

重み 20%
76

コードはクリーンで読みやすく、慣用的であり、命名も良く、役立つドキュメンテーション文字列が付いています。構造はシンプルで理解しやすいです。公開状態が直接公開されていることと、追加のデモコードがコア実装の一部ではないため、いくつかのポイントを失っています。

実用性

重み 15%
66

単純なシングルスレッドシナリオで使用可能であり、簡単なスモークテストで動作を示しています。より現実的な設定では、検証とスレッドセーフの欠如が運用上の有用性を低下させます。

指示遵守

重み 10%
88

必要なコンストラクタとallow_request動作を備えた自己完結型のTokenBucketクラスを実装することで、タスクをうまく実行しています。唯一のわずかな問題は、要求されたコア回答を超えた追加のデモコードが含まれていることです。

import time import threading class TokenBucket: """ A simple token bucket rate limiter. Args: capacity (int): maximum number of tokens in the bucket. refill_rate (float): tokens added per second. Methods: allow_request() -> bool: returns True and consumes one token if available, otherwise False. """ def __init__(self, capacity, refill_rate): if capacity <= 0: raise ValueError("capacity must be > 0") if refill_rate < 0: raise ValueError("refill_rate must be >= 0") self.capacity = float(capacity) self.refill...

全文を表示

import time import threading class TokenBucket: """ A simple token bucket rate limiter. Args: capacity (int): maximum number of tokens in the bucket. refill_rate (float): tokens added per second. Methods: allow_request() -> bool: returns True and consumes one token if available, otherwise False. """ def __init__(self, capacity, refill_rate): if capacity <= 0: raise ValueError("capacity must be > 0") if refill_rate < 0: raise ValueError("refill_rate must be >= 0") self.capacity = float(capacity) self.refill_rate = float(refill_rate) # current tokens may be fractional to account for partial refill self._tokens = float(capacity) self._last_time = time.monotonic() self._lock = threading.Lock() def _refill(self): """Refill tokens based on time elapsed since last refill.""" now = time.monotonic() elapsed = now - self._last_time if elapsed <= 0: return added = elapsed * self.refill_rate # cap tokens at capacity self._tokens = min(self.capacity, self._tokens + added) self._last_time = now def allow_request(self): """ Attempt to consume one token. Returns: bool: True if a token was available and consumed, False otherwise. """ with self._lock: self._refill() if self._tokens >= 1.0: self._tokens -= 1.0 return True return False # Example usage: # bucket = TokenBucket(capacity=10, refill_rate=1.5) # 1.5 tokens per second # if bucket.allow_request(): # # process request # else: # # reject or throttle request

判定

1位 | 勝者

勝利票

3 / 3

平均スコア

86

総合点

87

総評

回答Bは、TokenBucketクラスの正しい、堅牢で、本番品質の実装を提供します。回答Aのコアロジックをすべて含んでいますが、重要な機能強化が追加されています。具体的には、threading.Lock()によるスレッドセーフティ、無効なコンストラクタ引数に対する意味のあるエラーメッセージ付きの入力検証、およびカプセル化を向上させるためのプライベート命名規則(_tokens、_last_time、_lock)です。elapsed <= 0に対するガードは、マイナーな防御的タッチです。コードはクリーンで、十分に文書化されており、Pythonの慣習に従っています。唯一のマイナーな弱点は、実行可能なデモがないことですが、使用例のコメントが部分的に補っています。

採点詳細を表示

正確さ

重み 35%
90

コアロジックは正しく、さらにthreading.Lock()によって保護されており、並行環境での競合状態を防ぎます。入力検証により、オブジェクトは常に有効な状態になります。elapsed <= 0ガードは、マイナーですが妥当な防御チェックです。

完全性

重み 20%
85

実装は必要なすべての要素をカバーしており、さらにスレッドセーフティ、入力検証、適切なカプセル化を備えています。使用例のコメントはガイダンスを提供します。唯一のマイナーなギャップは、実行可能なデモがないことですが、これはマイナーな懸念事項です。

コード品質

重み 20%
85

コードはクリーンで、読みやすく、構造化されています。カプセル化を向上させるためにプライベート命名規則(_tokens、_last_time、_lock)を使用し、明確なdocstringを含み、Pythonの慣習に従っています。クラスレベルのdocstringは包括的です。カプセル化と防御的プログラミングの点ではAよりもわずかに優れています。

実用性

重み 15%
85

この実装は、実世界のユースケースに非常に実用的です。スレッドセーフティにより並行アプリケーションに適しており、入力検証により誤用を防ぎ、クリーンなAPIにより統合が容易です。使用例のコメントは、実用的な採用をさらに支援します。

指示遵守

重み 10%
90

すべての指示に従っています。PythonでTokenBucketクラスを実装し、コンストラクタはcapacityとrefill_rateを受け入れ、allow_request()は引数なしでTrue/Falseを返し、トークンを消費します。標準ライブラリ(time、threadingモジュール)のみを使用しています。状態はインスタンス内で管理されます。

採点モデル Google Gemini 2.5 Pro

総合点

85

総評

回答Bは、トークンバケットアルゴリズムの堅牢で実用的な実装を提供しています。その主な強みは、ロックを使用したスレッドセーフであることと、入力検証が含まれていることで、同時実行環境や本番環境に近い環境での使用に適しています。コードはよく構造化されていますが、型ヒントと実行可能なデモンストレーションが欠けており、これらがあれば明確さと完全性が向上したでしょう。

採点詳細を表示

正確さ

重み 35%
90

ロックの使用により、シングルスレッドおよびマルチスレッドの両方のコンテキストで論理的に正しい実装となっています。これにより、はるかに広範で現実的なシナリオでソリューションが正しいものとなります。

完全性

重み 20%
65

回答は必要なクラスを提供していますが、使用例のコメントアウトされたスニペットのみが含まれています。機能を確認するための実行可能なデモンストレーションやテストケースが欠けており、回答Aよりも完全性が低いです。

コード品質

重み 20%
80

コード品質は良好で、明確なドキュメンテーション文字列、妥当な変数名、および良好なプラクティスである入力検証が含まれています。しかし、可読性と保守性を向上させるためのモダンPythonの標準である型ヒントが欠けています。

実用性

重み 15%
95

実用的な価値は非常に高いです。スレッドロックを含めることで、実装はスレッドセーフであり、実際のマルチスレッドアプリケーションで使用する準備ができています。入力検証の追加は、その実用性と堅牢性をさらに高めています。

指示遵守

重み 10%
100

回答は、指定されたクラス、コンストラクタ、およびメソッドを正しいロジックで実装するというプロンプトのすべての指示に完全に従っています。`threading`は標準ライブラリの一部であるため、ソリューションは自己完結型です。

採点モデル OpenAI GPT-5.4

総合点

84

総評

回答Bは、モノトニッククロックを使用し、コンストラクタの入力を検証し、状態をクリーンに管理し、リフィルを正しく上限設定し、安全にトークンを消費するなど、正確でより堅牢なPython実装を提供します。また、ロックによるスレッドセーフティを追加しており、実際のアプリケーションでの実用性が向上しています。唯一の小さな欠点は、長期的な精度蓄積に対する特別な緩和策なしに、依然として浮動小数点演算に依存していることですが、全体としてはより強力で、より本番志向の実装です。

採点詳細を表示

正確さ

重み 35%
84

コアとなるトークンバケットロジックは正しく、状態の更新は一貫して行われます。経過したモノトニック時間に基づいて正しくリフィルし、容量を上限設定し、成功したリクエストごとに1つのトークンを消費します。入力検証は正確性を強化し、ロックはマルチスレッドでの使用における競合関連の不整合を防ぎます。単純な浮動小数点演算にまだ依存しているため、わずかな削減のみです。

完全性

重み 20%
82

要求されたクラスとメソッドを完全に実装し、内部状態を正しく管理し、自己完結型を維持しています。また、コンストラクタの検証と安全なアクセスパターンを通じて重要なエッジケースの処理をカバーしており、ベースライン要件よりも完全です。

コード品質

重み 20%
83

コードは、明確な命名、簡潔なコメント、およびアンダースコア付き属性による優れたカプセル化により、よく構造化され、読みやすく、実用的です。ロックの使用はきれいに統合されており、実装はクラス自体に焦点を当てています。

実用性

重み 15%
85

入力を検証し、同時アクセス下で安全であるため、本番環境での使用に近いです。実装は依然としてコンパクトで、アプリケーションに直接採用しやすいため、実用的な価値が高いです。

指示遵守

重み 10%
92

指示には非常によく従っています。必要なコンストラクタ、状態管理、およびallow_request動作を備えた自己完結型のTokenBucketクラスを提供します。回答は焦点を維持し、期待されるコードのみの実装に密接に一致しています。

比較結果サマリー

最終順位は、採点者ごとの順位集約(平均順位 + ボルダ方式の同点処理)で決定します。平均点は参考表示です。

採点者数: 3

勝利票

3 / 3

平均点

86
この回答を見る

採点結果

採点モデル OpenAI GPT-5.4

勝者理由

回答Bが勝るのは、必要とされるトークンバケットの動作に一致しているうえ、より堅牢で実用的だからです。回答Aと比べると、入力検証とスレッドセーフ性が追加されており、これによって明確さを損なうことなく信頼性が実質的に向上しています。どちらの回答も中核となるロジックは正しいですが、Bのほうがベンチマークの堅牢性および実用的価値に関する期待をよりよく満たしています。

採点モデル Google Gemini 2.5 Pro

勝者理由

回答Bが勝者である理由は、レートリミッターのほぼすべての実用的なアプリケーションにおいて重要な要件であるスレッドセーフな実装を提供しているためです。プロンプトで要求されている「堅牢」なソリューションで、「非常に短い間隔で発生する複数のリクエスト」を処理するということは、並行処理制御の必要性を強く示唆しています。回答Aは、実行可能なデモや型ヒントを備えており、提示方法としては優れていますが、スレッドセーフでないことは、この特定の問題における堅牢性の根本的な欠陥です。回答Bのソリューションはより堅牢であり、実用的な価値が大幅に高いため、より優れたエンジニアリングソリューションとなっています。

勝者理由

回答Bは、実際の並行シナリオで使用されるレートリミッターにとって重要な、threading.Lock()によるスレッドセーフティを含んでいるため、勝利します。また、入力検証とプライベート属性によるより良いカプセル化も追加されています。どちらの回答も機能的には正しいですが、回答Bはより堅牢で本番環境に対応できるため、全体としてより強力な実装となっています。

X f L