Orivel Orivel
メニューを開く

プログラミング

コードの正確さ、完成度、実務で使える実装力を比較します。

スナップショット 2026-W42 2026-10-16 時点の結果

6 モデルが同じ 16 題に答えました。すべての回答を同じ判定者(Claude Opus 5.5 / GPT-6.1 Sol / Gemini 3.8 Flash)が10点満点で採点し、表示している点数は 3 人の平均です。

このジャンルのお題は1題なので、下の順番はこのお題の結果です。このジャンルでのモデルの順位ではありません。総合順位は 16 題すべてで決めています。

ひと目でわかる結果

このお題の結果

全か無かの注文を伴うFEFO在庫引当

順位 モデル 平均(10点満点)
1 GPT-6.1 Sol 9.74
2 Claude Sonnet 5.5 9.73
3 GPT-6 Luna 9.66
4 Claude Opus 5.5 9.60
5 Gemini 3.8 Flash 9.12
6 Gemini 3.5 Flash-Lite 8.89
点数の色 ≥ 9 8–9 7–8 6–7 5–6 < 5

最高と最低の平均点の差: 0.85 点

お題

全か無かの注文を伴うFEFO在庫引当

指示

小規模な食品倉庫のために、常に最も早く期限切れになる在庫から出荷するPython 3関数 allocate(lots, orders) を書いてください。

入力:

  • lots: {"id": str, "qty": int, "expires": int} の辞書のリスト。expires は、そのロットを出荷してもよい最後の日番号です。
  • orders: {"id": str, "day": int, "qty": int} の辞書のリストで、任意のキー "all_or_nothing": bool(デフォルトはFalse)を持つことがあります。リストは必ずしも day 順に並んでいません。

要件:

  1. 注文は day の昇順に処理します。同じ day の注文は、入力リストに現れる順に処理します。
  2. day d の注文について、ロットは expires >= d かつ在庫が残っている場合にのみ使用可能です。使用可能なロットから、expires の昇順に在庫を取り、同じ場合はロット id の昇順(単純な文字列比較)で並べて、注文が満たされるか使用可能な在庫が尽きるまで引き当てます。
  3. 通常の注文は一部だけ充足されることがあります。all_or_nothing の注文は、その日の使用可能在庫の合計を数量が超える場合、何も受け取らず、その在庫は後の注文のために引き続き利用可能なままです。
  4. 正確に3つのキーを持つ辞書を返します。"fills" は、すべての注文 id を、在庫が取られた順の (lot_id, qty) タプルのリストに対応付けます(何も引き当てられなかった場合は空リスト)。"short" は、未充足数量が0より大きい注文 id のみを、その未充足数量に対応付けます。"remaining" は、すべてのロット id を、その最終在庫に対応付けます。
  5. いずれかのロットまたは注文の qty が負である場合、またはいずれかのロット id または注文 id が2回以上現れる場合は、何かを引き当てる前に ValueError を送出します。
  6. 標準ライブラリのみを使用します。コードは150行以内に収め、その後に、計算量の時間計算量を明記した200語以内の説明を付けてください。
判定者への採点の指示
要件チェックリスト: (1) 注文を day で安定ソートし、同じ day では入力順を保つこと — 正しさ; (2) 使用可能とは expires >= day かつ在庫 > 0 であり、(expires, id) の順で取ること — 正しさ; (3) 通常注文は部分充足、all_or_nothing はその日の使用可能在庫とだけ比較し、スキップされた all_or_nothing 注文は何も消費しないこと — 正しさ; (4) 戻り値の形が fills/short/remaining と正確に一致すること — 完全性; (5) 何かを引き当てる前に ValueError で検証すること — 完全性; (6) 標準ライブラリのみ、コードは150行以下、説明は200語以下で計算量の記述を含むこと — 指示への従順性; 165行を超えるコードは指示への従順性で -2 以上。 解答キー(事前計算済み。実行せず比較のみ)。 T1 ロット L1(5, exp 10), L2(5, exp 3); 注文 O1 day 1 qty 7 -> fills {O1: [(L2,5),(L1,2)]}, short {}, remaining {L1:3, L2:0}。有効期限でロットをソートすることで決まる。 T2 ロット A(4, exp 5), B(4, exp 8); 注文は X(day 6, qty 4) の後に Y(day 5, qty 5) の順に並ぶ -> fills {Y: [(A,4),(B,1)], X: [(B,3)]}, short {X:1}, remaining {A:0, B:0}。注文を入力順に処理すると失敗する(X [(B,4)], Y [(A,4)], short Y 1 になる)。また、期限を排他的(expires > day)として扱っても失敗する。 T3 ロット P(6, exp 2), Q(4, exp 9); 注文 M(day 3, qty 5, all_or_nothing) の後に N(day 3, qty 3) -> fills {M: [], N: [(Q,3)]}, short {M:5}, remaining {P:6, Q:1}。all_or_nothing の判定に総在庫(10)を使い、使用可能在庫(4)を使わないと失敗する。 T4 ロット b(2, exp 4), a(2, exp 4), c(1, exp 1); 注文 Z(day 1, qty 0), W(day 2, qty 5) -> fills {Z: [], W: [(a,2),(b,2)]}, short {W:1}, remaining {b:0, a:0, c:1}。id による同点の処理と、数量0の注文(fills には存在し、short には存在しない)を検査する。 T5 ロット K(3, exp 5), J(3, exp 6); 注文 R(day 4, qty 2) の後に S(day 4, qty 4, all_or_nothing) -> fills {R: [(K,2)], S: [(K,1),(J,3)]}, short {}, remaining {K:0, J:0}。all_or_nothing 注文の順序が入れ替わると失敗する。 T6 ロット id の重複、または qty -2 の注文 -> ValueError となり、部分的な状態は返さないこと。 コードが読んで T1-T6 を通過し、きれい(ロットを数量単位で不必要に何度も走査しない)で、計算量の記述が正しい(おおよそ O(L log L + O log O + O x L) 以下)場合にのみ 9 点以上。 上限: 注文を入力順に処理する、または排他的な期限を使う -> 正しさ <= 5; all_or_nothing を総在庫と比較する -> 正しさ <= 6; そのまま実行できないコード(構文エラー、未定義の名前)-> 正しさ <= 3; 戻り値の形が誤っている -> 完全性 <= 6。

判定者は評価基準ごとに0〜10点を付けます。点数は評価基準の重み付き平均です。

回答(平均点の高い順)

採点は英語の原文で行っています。翻訳は読むためのものです。

1 GPT-6.1 Sol

平均(10点満点) 9.74
from heapq import heapify, heappop


def allocate(lots, orders):
    # Validate every input before allocating stock.
    remaining = {}
    for lot in lots:
        if lot["qty"] < 0:
            raise ValueError("Negative lot quantity")
        if lot["id"] in remaining:
            raise ValueError("Duplicate lot id")
        remaining[lot["id"]] = lot["qty"]

    seen_orders = set()
    for order in orders:
        if order["qty"] < 0:
            raise ValueError("Negative order quantity")
        if order["id"] in seen_orders:
            raise ValueError("Duplicate order id")
        seen_orders.a...
全文を表示 ▼
from heapq import heapify, heappop


def allocate(lots, orders):
    # Validate every input before allocating stock.
    remaining = {}
    for lot in lots:
        if lot["qty"] < 0:
            raise ValueError("Negative lot quantity")
        if lot["id"] in remaining:
            raise ValueError("Duplicate lot id")
        remaining[lot["id"]] = lot["qty"]

    seen_orders = set()
    for order in orders:
        if order["qty"] < 0:
            raise ValueError("Negative order quantity")
        if order["id"] in seen_orders:
            raise ValueError("Duplicate order id")
        seen_orders.add(order["id"])

    heap = [(lot["expires"], lot["id"])
            for lot in lots if lot["qty"] > 0]
    heapify(heap)
    usable_total = sum(remaining.values())
    fills = {}
    short = {}

    # Python's stable sort preserves input order for equal days.
    for order in sorted(orders, key=lambda order: order["day"]):
        day = order["day"]
        order_id = order["id"]
        need = order["qty"]
        fills[order_id] = []

        # Expired stock stays in remaining but cannot be allocated.
        while heap and heap[0][0] < day:
            _, lot_id = heappop(heap)
            usable_total -= remaining[lot_id]

        if order.get("all_or_nothing", False) and need > usable_total:
            short[order_id] = need
            continue

        while need > 0 and heap:
            _, lot_id = heap[0]
            taken = min(need, remaining[lot_id])
            fills[order_id].append((lot_id, taken))
            remaining[lot_id] -= taken
            usable_total -= taken
            need -= taken
            if remaining[lot_id] == 0:
                heappop(heap)

        if need > 0:
            short[order_id] = need

    return {"fills": fills, "short": short, "remaining": remaining}

検証は在庫の割り当てを行う前にすべて完了します。日付による安定ソートにより、同じ日の注文は元の順序を保ちます。ヒープは、在庫が正の数のロットを有効期限、次にロットIDの順に並べます。注文は日付順に処理されるため、期限切れのロットは最終的な在庫数を変えることなくヒープから永久に取り除けます。

usable_total は、現在出荷可能なすべての在庫を追跡します。これにより、全量引き当て(all-or-nothing)の注文は、何も消費せずに拒否できます。通常の注文は、満たされるか在庫が尽きるまで、ヒープの先頭の在庫を消費します。数量ゼロの注文は、空の fills を受け取り、不足は発生しません。

L をロットの数、M を注文の数、K を返される割り当てタプルの数とします。各ロットはヒープから最大1回だけ取り除かれます。時間計算量は O(L log(L + 1) + M log(M + 1) + K)、出力を含む空間計算量は O(L + M + K) です。

Claude Opus 5.5 9.22

ヒープを用いた、正確で効率的な FEFO(先に期限が切れるものを先に出す)アロケータです。T1 から T6 までを通して確認すると、毎回期待どおりの結果になっています。具体的には、安定した日付ソート、期限日を含む(inclusive)有効期限の扱い、(expires, id) によるヒープの順序付け、利用可能な在庫のみを対象とした all_or_nothing の判定、そして割り当てを行う前に必ず完了する検証です。戻り値の形式も正確で、コードは 58 行、129 語の説明では計算量の上限が正しく示されています。欠点は軽微です。

評価基準ごとの点数

正確さ

95

T1からT6まで読み通すと合格します。安定ソートにより、同じ日の注文は入力順を保ちます。期限判定は expires < day の間だけロットを取り出すため、期限日は含まれます。ヒープは(expires, id)順にロットを並べます。all_or_nothingの判定の前に、usable_totalから期限切れの在庫を差し引いています(T3ではMは[]、Nは[(Q,3)]になります)。数量0の注文は空のfillになり、shortには入りません。all_or_nothingによりスキップされた注文は在庫を消費しません。論理的な誤りは見つかりませんでした。

完全性

92

fills、short、remainingの3つを正確に返しています。すべての注文IDがfillsに含まれ、shortには正の不足分のみが入ります。remainingには期限切れのロットを含むすべてのロットが含まれます。数量が負の場合や、ロットと注文の両方でIDが重複している場合は、割り当ての前にValueErrorを発生させます。キーの欠落などの不正な入力は処理されていませんが、課題ではそこまでは求められていませんでした。

コード品質

90

クリーンで慣用的な実装です。ヒープと実行中のusable_totalを使うことで、ロットの再走査を避け、単位ごとのループも使っていません。コメントも簡潔です。軽微な難点として、在庫の辞書がremainingという名前でありながら返却される写像としても使われており、この二つの役割が結びついている点があります。動作はしますが、役割の分離は弱いです。

実用性

88

効率的で、実際の利用にそのまま使えます。時間計算量は O(L log L + M log M + K) です。解説では設計上の選択や、数量0の注文、期限切れのロットといったエッジケースが明確に説明されています。小規模な倉庫ツールにそのまま組み込める水準です。

指示遵守

93

標準ライブラリ(heapq)のみを使用しています。コードは58行で150行の上限を大きく下回り、解説は129語で200語未満です。計算量の記述 O(L log L + M log M + K) は正しく、参考の上限より優れています。

GPT-6.1 Sol 10.00

この解答はすべての要件を満たしており、目視確認でT1~T6に合格します。安定した時系列順の注文処理、ヒープに基づくFEFO引当、そして全量引当か全量不可かの判断のための正確な使用可能在庫合計を、正しく組み合わせています。検証、出力構造、計算量の分析、および規定された長さの制限も、すべて正しく処理されています。

評価基準ごとの点数

正確さ

100

目視確認によりT1からT6まで合格しています。安定ソートにより同日内の順序が保たれ、ヒープの順序によって有効期限と文字列IDの優先順位が実装され、有効期限は両端を含みます。利用可能在庫の合計は、各割り当ての前に期限切れの在庫を除外します。全件か無かかで却下された注文は在庫を消費しません。部分充足とゼロ数量の注文も正しく動作します。

完全性

100

fills、short、remainingの3つだけを正確に返します。すべての注文はfillsに含まれ、正の不足分のみが記録され、すべてのロットはremainingに保持されます。割り当てが行われる前に、両方の入力にわたって負の数量と重複IDが検証されます。

コード品質

100

実装は読みやすく、自己完結しており、効率的です。わかりやすい変数名と要点を押さえたコメントによって、ヒープと利用可能在庫の不変条件が説明されています。各ロットはヒープから高々1回だけ取り出され、不要な繰り返し走査や単位ごとの処理はありません。

実用性

100

呼び出し側が所有する辞書を変更せずに、指定された入力に対してそのまま使用できます。空の入力、在庫切れ、期限切れの在庫、ゼロ数量、スキップされた全件か無かの注文を扱い、最終的な在庫の正確さも維持します。説明では、出力に依存する正しい時間および空間の上限が示されています。

指示遵守

100

標準ライブラリのみを使用した、要求どおりのPython 3関数が提供されています。測定された58行のコードと129語の説明は、どちらの制限内に収まっており、説明では正しい時間計算量が明示されています。

Gemini 3.8 Flash 10.00

この解答は、非常に丁寧に作られており、正確で効率的です。最小ヒープと利用可能な在庫の累計を併用することで最適な時間計算量を実現しています。また、同じ日の注文に対する同順位の処理と安定ソートも正確に扱っており、すべての制約と書式の指定を厳密に守っています。

評価基準ごとの点数

正確さ

100

すべてのテストケース(T1~T6)が問題なく合格しています。利用可能な在庫は正しく判定されており(有効期限 >= 日付)、ロットIDによる同順位の扱いはヒープの順序によって守られています。また、全数量か無かかの判定は、その日時点で現在利用可能な在庫に対して正確に確認されています。

完全性

100

関数は、割り当てが行われる前にすべての負の数量と重複したIDを検証し、必要な辞書構造を正しく返し、完全に充足された注文を'short'マッピングから適切に除外しています。

コード品質

100

コードは慣用的で、簡潔かつ読みやすく、非常に効率的です。`usable_total`をヒープからの削除と同時に動的に維持しているため、ロットを何度も走査する必要がありません。

実用性

100

数量ゼロの注文、注文の合間に期限切れとなるロット、全数量か無かかの閾値判定など、実際の倉庫で起こる境界ケースを問題なく処理しており、本番環境で使用できる水準です。

指示遵守

100

行数制限(58行 <= 150行)、説明の語数制限(129語 <= 200語)、標準ライブラリの制約をすべて厳守しており、明確な時間計算量の分析も含まれています。

2 Claude Sonnet 5.5

平均(10点満点) 9.73
def allocate(lots, orders):
    # ---- validation (nothing is allocated if this fails) ----
    seen_lots = set()
    for lot in lots:
        if lot["qty"] < 0:
            raise ValueError("negative lot qty: %r" % (lot["id"],))
        if lot["id"] in seen_lots:
            raise ValueError("duplicate lot id: %r" % (lot["id"],))
        seen_lots.add(lot["id"])
    seen_orders = set()
    for o in orders:
        if o["qty"] < 0:
            raise ValueError("negative order qty: %r" % (o["id"],))
        if o["id"] in seen_orders:
            raise ValueError("duplicate order id: %r" % (o["id"],))...
全文を表示 ▼
def allocate(lots, orders):
    # ---- validation (nothing is allocated if this fails) ----
    seen_lots = set()
    for lot in lots:
        if lot["qty"] < 0:
            raise ValueError("negative lot qty: %r" % (lot["id"],))
        if lot["id"] in seen_lots:
            raise ValueError("duplicate lot id: %r" % (lot["id"],))
        seen_lots.add(lot["id"])
    seen_orders = set()
    for o in orders:
        if o["qty"] < 0:
            raise ValueError("negative order qty: %r" % (o["id"],))
        if o["id"] in seen_orders:
            raise ValueError("duplicate order id: %r" % (o["id"],))
        seen_orders.add(o["id"])

    # ---- setup ----
    # Lots in FEFO order: earliest expiry first, ties by id.
    ordered = sorted(lots, key=lambda l: (l["expires"], l["id"]))
    ids = [l["id"] for l in ordered]
    exp = [l["expires"] for l in ordered]
    stock = [l["qty"] for l in ordered]
    n = len(ordered)

    fills = {o["id"]: [] for o in orders}
    short = {}

    # sorted() is stable, so same-day orders keep their input order.
    queue = sorted(orders, key=lambda o: o["day"])

    ptr = 0                 # first lot that is neither expired nor drained
    usable = sum(stock)     # stock in lots not yet expired for current day

    for o in queue:
        d = o["day"]
        need = o["qty"]

        # Days are non-decreasing, so an expired lot stays expired.
        while ptr < n and exp[ptr] < d:
            usable -= stock[ptr]
            ptr += 1

        if o.get("all_or_nothing", False) and need > usable:
            if need > 0:
                short[o["id"]] = need
            continue

        i = ptr
        while need > 0 and i < n:
            take = min(stock[i], need)
            if take > 0:
                fills[o["id"]].append((ids[i], take))
                stock[i] -= take
                usable -= take
                need -= take
            i += 1

        # Drained lots form a prefix of the unexpired lots; skip them.
        while ptr < n and stock[ptr] == 0:
            ptr += 1

        if need > 0:
            short[o["id"]] = need

    remaining = {ids[i]: stock[i] for i in range(n)}
    return {"fills": fills, "short": short, "remaining": remaining}

説明

入力は最初に検証されるため、割り当てを行う前に ValueError が発生する可能性があります。ロットは一度 (expires, id) でソートされます。注文は day でソートされます。Python のソートは安定しているため、同じ日の注文は入力時の順序を保ちます。

ポインタ ptr は、期限切れでも在庫切れでもない最初のロットを指します。日付は減少しないため、期限切れになったロットは期限切れのままです。また、在庫は常に最も早く使用可能なロットから引き当てられるため、在庫がなくなったロットは使用可能なロットの接頭辞を形成します。したがって ptr は前進のみします。

実行中のカウンター usable は、期限切れになっていないロットの在庫を保持します。これにより、全量か無かの注文を O(1) で確認できます。注文量が多すぎる場合は、何も変更されず、在庫はそのまま利用可能な状態に保たれます。

時間計算量: O(n log n + m log m + n + m + F)。ここで n はロット数、m は注文数、F は返される引き当て項目数です。各注文はロットを消費し、部分的に使われたロットは最大1つ残るため、F は最大で m + n です。したがって全体は O(n log n + m log m) です。追加の空間計算量は O(n + m) です。

Claude Opus 5.5 9.18

正しく効率的な解法です。T1〜T6に沿ってトレースしたところ、期待どおりの充当結果、不足分、残りの値が得られました。これには、同日内で安定した順序、期限日を含む有効期限の扱い、(expires, id) によるタイブレーク、そして使用可能な在庫のみを対象に確認される全量一括(オール・オア・ナッシング)の注文処理が含まれます。償却計算されるポインタと、使用可能数を保持するカウンタは妥当であり、記載された計算量は正しく、参照解の上限よりも優れています。コードは67行、説明は185語です。細かな指摘が少し残るのみです。

評価基準ごとの点数

正確さ

94

T1~T6を読み取りで検証した結果、合格しています。注文は日付による安定ソートで並べられ、期限切れの判定は包含的です(exp < d で期限切れ)。ロットは (expires, id) で並べられています。利用可能数カウンタは期限切れでないロットの在庫を正しく追跡するため、全量か無かかの注文は利用可能な在庫と比較され、スキップされた場合は何も消費しません。数量ゼロの注文は short から除外されています。途中に数量ゼロのロットがあっても ptr の不変条件は成立します。

完全性

92

fills、short、remaining の3つを過不足なく返しています。fills は (lot_id, qty) のタプルを保持し、すべての注文IDを含みます。short は正の不足分のみを列挙し、remaining はすべてのロットを対象にしています。負の数量と重複IDは、状態を構築する前に検証されています。

コード品質

90

整理されており、コメントも十分です。償却された前方ポインタとO(1)の利用可能数カウンタを使い、単位ごとの再走査はありません。並列リストによってホットループは単純に保たれています。小さな指摘として、並列配列は、変更可能なレコードのリストに比べるとやや読みにくいです。

実用性

88

想定されるシナリオで効率的であり、明確なエラーメッセージを備えているため、本番利用に耐えます。入力の型や欠落したキーは検証していませんが、それは要求されていませんでした。

指示遵守

93

標準ライブラリのみを使用しています。コードは67行で150行の上限を大きく下回り、説明は185語で200語未満です。計算量の記述 O(n log n + m log m) は正しく、根拠も示されています。

GPT-6.1 Sol 10.00

この実装はすべての要件を満たしており、目視確認でT1〜T6に合格します。日付が進んでも使用可能な在庫を正しく維持し、期限切れの在庫もremainingに保持し、全量でなければ受け付けない注文で、在庫を満たせないものは在庫を消費せずにスキップします。検証、出力構造、および記載された計算量もすべて正しいです。

評価基準ごとの点数

正確さ

100

安定した日の順序、期限日を含む判定、同順位の場合に文字列idで決める FEFO、部分充足、現在有効な在庫に対する全量注文のチェックを正しく実装しています。実行中の有効在庫カウンタと前方のみに進むポインタは、割り当て全体を通して一貫しています。

完全性

100

fills、short、remainingの3つを正確に返しており、必要な場合には空のfillsや変更されていない期限切れ在庫も含まれます。割り当てを始める前に、負の数量と重複するidをすべて検証しています。

コード品質

100

明確な検証フェーズと割り当てフェーズを備えた、簡潔で自己完結したコードです。不変条件に関する分かりやすいコメントがあり、入力を変更しません。ポインタと実行中の在庫合計により、在庫全体を繰り返し走査することを避けています。

実用性

100

指定された入力に対してそのまま使えます。分かりやすい検証エラー、決定的な割り当て、数量の大きさに左右されない効率的な処理を備えています。説明はアルゴリズムとそのリソースコストの両方を正確に述べています。

指示遵守

100

Pythonの標準機能のみを使用し、要求された関数を67行のコードで提供しています。その後に185語の説明が続き、計算量に関する記述も正しいです。

Gemini 3.8 Flash 10.00

この解答は完全に正しく、エレガントで、最適です。すべての要件とエッジケースを厳密に満たしています。具体的には、注文を日付で安定ソートしていること、FEFO(先に期限が切れるものから先に出荷する方式)でロットをソートし、同順位の場合はidで決めていること、処理の前にValueErrorを送出する厳密な検証を行っていること、使用可能な在庫の合計を保持して行うO(1)の全か無かのチェック、そして時間計算量O(n log n + m log m)を達成する正確な二つのポインタによる走査です。行数と単語数の制約も完全に満たしています。

評価基準ごとの点数

正確さ

100

テストケース T1 から T6 までをすべて通過します。ロット ID によるタイブレークを伴う FEFO ソート、日単位で安定した注文キューイング、利用可能在庫のフィルタリング(expires >= day)、そして割り当てを行わない全か無かの在庫保全を正しく処理します。

完全性

100

すべての要件と境界条件が扱われています。負の数量や重複 ID の場合は、割り当ての前に ValueError を送出します。要求された辞書スキーマを正確に返します(すべての注文について fills、未充足の注文についてのみ short、すべてのロットについて remaining)。

コード品質

100

非常に明快で読みやすく、慣用的な Python コードです。ポインタの前進と実行中の利用可能在庫残高を用いた償却線形走査は、洗練されていて効率的です。

実用性

100

冗長なロット走査を避ける、非常に実用的な倉庫割り当ての実装です。そのため高性能で、実運用環境にも適しています。

指示遵守

100

指示にすべて正確に従っています。標準ライブラリのみを使用し、コードは 150 行を大きく下回る(67 行)状態を保ち、説明は 200 語の制限内(185 語)で、正確な時間計算量の分析を含んでいます。

3 GPT-6 Luna

平均(10点満点) 9.66
def allocate(lots, orders):
    # Validate everything before creating or changing allocation state.
    lot_ids = set()
    for lot in lots:
        if lot["qty"] < 0:
            raise ValueError("lot quantity cannot be negative")
        if lot["id"] in lot_ids:
            raise ValueError("duplicate lot id")
        lot_ids.add(lot["id"])

    order_ids = set()
    for order in orders:
        if order["qty"] < 0:
            raise ValueError("order quantity cannot be negative")
        if order["id"] in order_ids:
            raise ValueError("duplicate order id")
        order_ids.add(order["id"])...
全文を表示 ▼
def allocate(lots, orders):
    # Validate everything before creating or changing allocation state.
    lot_ids = set()
    for lot in lots:
        if lot["qty"] < 0:
            raise ValueError("lot quantity cannot be negative")
        if lot["id"] in lot_ids:
            raise ValueError("duplicate lot id")
        lot_ids.add(lot["id"])

    order_ids = set()
    for order in orders:
        if order["qty"] < 0:
            raise ValueError("order quantity cannot be negative")
        if order["id"] in order_ids:
            raise ValueError("duplicate order id")
        order_ids.add(order["id"])

    remaining = {lot["id"]: lot["qty"] for lot in lots}
    sorted_lots = sorted(lots, key=lambda lot: (lot["expires"], lot["id"]))
    fills = {order["id"]: [] for order in orders}
    short = {}

    for order in sorted(orders, key=lambda order: order["day"]):
        order_id = order["id"]
        qty = order["qty"]
        usable = [
            lot for lot in sorted_lots
            if lot["expires"] >= order["day"] and remaining[lot["id"]] > 0
        ]
        available = sum(remaining[lot["id"]] for lot in usable)

        if order.get("all_or_nothing", False) and qty > available:
            short[order_id] = qty
            continue

        needed = qty
        for lot in usable:
            taken = min(needed, remaining[lot["id"]])
            if taken:
                fills[order_id].append((lot["id"], taken))
                remaining[lot["id"]] -= taken
                needed -= taken
            if needed == 0:
                break

        if needed > 0:
            short[order_id] = needed

    return {"fills": fills, "short": short, "remaining": remaining}

注文は日付の昇順で安定的に処理され、ロットは有効期限、次にIDの順で検討されます。全量引当(all-or-nothing)の注文を完全に供給できない場合、在庫は変更されません。入力は引当状態が作成される前に検証され、入力のリストと辞書は変更されません。

L 個のロットと O 件の注文に対して、時間計算量は O(L log L + O log O + OL) です。これは、ロットと注文のソートに加え、各注文について使用可能なロットを走査するためです。空間計算量は、返される引当結果を除いて O(L + O) です。

Claude Opus 5.5 8.99

正しく、すっきりとした解答です。模範解答と照らし合わせて確認したところ、T1からT6までをすべて通過します。日付の安定ソート、有効期限を含める扱い、(expires, id) によるロットの順序付け、使用可能な在庫のみを対象とした全量一括(オール・オア・ナッシング)の判定、そして数量ゼロの注文を short に含めない処理が実装されています。検証は状態を構築する前に実行されており、返り値の形式も正確で、計算量に関する記述も正確です。コードは50行、説明は82語で、どちらも制限内に十分収まっています。弱点は軽微なものだけで、型チェックやキー欠落のチェックがないことと、使用可能なロットが注文ごとに再構築されることです。

評価基準ごとの点数

正確さ

93

6つの回答キーのケースをすべて、コードを読んで確認した限りでは通過しています。Python の sorted は安定ソートなので、同じ日付の注文は入力順を保ちます。有効期限の判定は包含的(>=)で、ロットは (expires, id) の順に並び、全か無かの判定はその日の利用可能在庫と比較されます。注文をスキップする場合は何も消費しません。数量が0の注文は空の fill を生成し、short にはエントリを作りません。

完全性

90

fills、short、remaining のキーを過不足なく返しています。すべての注文IDが fills に含まれ、short には正の不足分のみが含まれ、remaining はすべてのロットを対象としています。負の数量、ならびに重複したロットIDや注文IDに対しては、割り当ての状態が作られる前に ValueError が発生します。型や欠損キーの検証は行われていませんが、タスクではその要求はありませんでした。

コード品質

87

読みやすく簡潔で、名前が明確であり、ロットは事前にソートされ、1単位ごとのループもありません。入力は変更されません。利用可能なロットのリストとその合計は、注文ごとに全体を走査して再構築されていますが、記載された O x L の計算量では許容範囲です。「if taken」のガードはやや冗長です。

実用性

85

倉庫のシナリオにそのまま使えます。小規模なデータセットには十分な効率があり、all_or_nothing のデフォルト値は dict.get で処理されています。ValueError のメッセージは分かりやすいものの、問題のあるIDを明示していません。また、指定された範囲を超える防御的な処理はほとんどありません。

指示遵守

92

標準ライブラリのみを使用しています。コードは50行(上限150行)、説明は82語(上限200語)です。説明には正しい時間計算量 O(L log L + O log O + OL) が記載されており、空間計算量も示されています。記載されたすべての制約を満たしています。

GPT-6.1 Sol 10.00

この実装はすべての要件を満たしており、確認したところT1〜T6に合格しています。安定した順序での注文処理、有効期限を含む境界(期限当日を有効とする扱い)、FEFOの同順位処理、部分充足、および在庫を消費しないオール・オア・ナッシングの失敗を正しく処理しています。検証は割り当ての前に行われ、入力は保持され、簡潔な説明では正しい計算量が示されています。

評価基準ごとの点数

正確さ

100

検査によりT1からT6を通過しています。安定した日単位の並べ替え、期限日を含む有効期限判定、期限とIDによるロットの順序付け、数量ゼロの注文、そして利用可能な在庫のみを対象とする全量か無かかの判定は、いずれも正しく行われています。

完全性

100

fills、short、remainingの3つを、必要な要素とタプル形式の割り当てを含めて正確に返しています。割り当てが行われる前に、両方の入力コレクションについて負の数量と重複IDが完全に確認されています。

コード品質

100

明確で自己完結したコードであり、わかりやすい名前、単純な検証、そして複雑になりすぎない割り当てロジックになっています。入力の変更を避けており、数量の単位ごとに処理を行うこともありません。

実用性

100

指定された入力に対してそのまま使えるものになっており、期限切れの在庫、不足、空の割り当て、スキップされた全量か無かかの注文を正しく扱います。説明は動作と資源コストを正確に表しています。

指示遵守

100

Pythonの組み込み機能のみを使用し、150行のコード制限と200語の説明制限の範囲内に収まっています。コードの後には、正しい時間計算量と補助領域の計算量が示されています。

Gemini 3.8 Flash 10.00

この解答は、すべての仕様と制約を完全に満たしています。注文の日付による安定ソート、有効期限とIDによるロットの優先順位付け、数量が0の注文、利用可能な使用可能在庫に対するオール・オア・ナッシングのチェック、引当前の入力検証、そして出力辞書の正確な形式を、正しく処理しています。付属の説明は簡潔で、時間計算量と空間計算量を正確に述べています。

評価基準ごとの点数

正確さ

100

この実装はテストケース T1 から T6 をすべて通過します。注文日の並べ替えには Python の安定ソートを使用し、`expires >= day` による包含的な有効期限判定で、ロットの利用可能性を正しく評価しています。さらに、現在利用可能な在庫に対して全量か無かかの注文を正確に判定し、ロットの同順位も適切に処理しています。

完全性

100

すべてのエッジケースと検証要件が十分に網羅されています。ロットと注文の両方について、負の数量と重複 ID は、割り当ての状態が変更される前に `ValueError` を発生させます。また、戻り値の構造は要求された辞書の仕様と正確に一致しています。

コード品質

100

コードは慣用的で、簡潔かつ読みやすく、構造も整っています。不要な依存関係や過度に複雑なロジックはありません。

実用性

100

この関数は入力コレクションを変更せず、残りの在庫を適切に追跡します。実際の倉庫での在庫割り当てのシナリオにそのまま使用できます。

指示遵守

100

すべての指示に厳密に従っています。標準ライブラリのみを使用し、150 行の上限を大きく下回る 50 行のコードで、200 語の説明の上限も大きく下回る 82 語です。さらに、時間計算量を明示的に説明しています。

4 Claude Opus 5.5

平均(10点満点) 9.60
def allocate(lots, orders):
    """Allocate stock FEFO (first-expiring, first-out) to orders.

    Returns {"fills": ..., "short": ..., "remaining": ...}.
    Raises ValueError for negative quantities or duplicate ids.
    """
    # ---- Validation (before any allocation) ----
    seen_lots = set()
    for lot in lots:
        if lot["qty"] < 0:
            raise ValueError(f"lot {lot['id']!r} has negative qty")
        if lot["id"] in seen_lots:
            raise ValueError(f"duplicate lot id {lot['id']!r}")
        seen_lots.add(lot["id"])

    seen_orders = set()
    for order in orders:
        if o...
全文を表示 ▼
def allocate(lots, orders):
    """Allocate stock FEFO (first-expiring, first-out) to orders.

    Returns {"fills": ..., "short": ..., "remaining": ...}.
    Raises ValueError for negative quantities or duplicate ids.
    """
    # ---- Validation (before any allocation) ----
    seen_lots = set()
    for lot in lots:
        if lot["qty"] < 0:
            raise ValueError(f"lot {lot['id']!r} has negative qty")
        if lot["id"] in seen_lots:
            raise ValueError(f"duplicate lot id {lot['id']!r}")
        seen_lots.add(lot["id"])

    seen_orders = set()
    for order in orders:
        if order["qty"] < 0:
            raise ValueError(f"order {order['id']!r} has negative qty")
        if order["id"] in seen_orders:
            raise ValueError(f"duplicate order id {order['id']!r}")
        seen_orders.add(order["id"])

    # ---- Setup (input dicts are never mutated) ----
    stock = {lot["id"]: lot["qty"] for lot in lots}
    # FEFO order: earliest expiry first, ties by lot id (string comparison).
    fefo = sorted(lots, key=lambda l: (l["expires"], l["id"]))
    fills = {order["id"]: [] for order in orders}
    short = {}

    # sorted() is stable, so orders on the same day keep their input order.
    for order in sorted(orders, key=lambda o: o["day"]):
        oid, day, need = order["id"], order["day"], order["qty"]

        usable = [l["id"] for l in fefo
                  if l["expires"] >= day and stock[l["id"]] > 0]

        if order.get("all_or_nothing", False):
            available = sum(stock[lid] for lid in usable)
            if need > available:
                # Allocate nothing; stock stays for later orders.
                if need > 0:
                    short[oid] = need
                continue

        for lid in usable:
            if need == 0:
                break
            take = min(need, stock[lid])
            stock[lid] -= take
            need -= take
            fills[oid].append((lid, take))

        if need > 0:
            short[oid] = need

    return {"fills": fills, "short": short, "remaining": stock}

動作の説明

この関数は、まずすべてのロットと注文を検証します。qty が負の値であるもの、または ID が重複しているものがあれば ValueError を送出するため、入力が無効な場合は何も引き当てられません。ロットは一度 (expires, id) で並べ替えられます。注文は day で並べ替えられます。Python のソートは安定なので、同じ日の注文は入力時の順序を保ちます。各注文について、まだ使用可能なロットを列挙します。条件は expires >= day かつ在庫が 0 より大きいことです。全量引当て(all-or-nothing)の注文が、使用可能な在庫の合計を超える数量を必要とする場合、その注文には何も割り当てられず、全数量が short に入ります。それ以外の場合は、FEFO の順序で使用可能なロットから在庫を取り、使用したロットごとに (lot_id, qty) のタプルを記録します。まだ満たされていない数量は short に入ります。数量が 0 の注文には空の引当てリストが与えられ、short には現れません。関数は在庫数量のコピーに対して動作し、入力の辞書は決して変更しません。

計算量: O(L log L + O log O + O·L)。ここで L はロットの数、O は注文の数です。対数を含む 2 つの項はロットと注文のソートから生じます。O·L の項は、各注文ごとにロットを一度ずつ走査することから生じます。使用メモリは O(L + O + F) です。F は引当てタプルの総数です。

Note: The short dict and remaining value semantics are unchanged.

Claude Opus 5.5 9.11

この解答は正しく、読解したところ、six answer-key のテストをすべて通過します。注文には安定ソートを使い、有効期限は当日を含み、ロットは (expires, id) の順に並べ、all_or_nothing の注文は使用可能な在庫のみを対象に確認しています。検証は割り当ての前に行われ、戻り値の形も正確です。コードは短く簡潔で、計算量の説明も正確です。主な欠点は、説明文が220語あり、200語の上限を超えていることです。

評価基準ごとの点数

正確さ

95

6つのテストすべてに合格しています。T1はFEFOのソートから導かれます。T2には安定した日付ソートと、expires >= dayによる当日を含む期限判定が必要で、どちらも含まれています。T3はall_or_nothingの注文を、総在庫(4)ではなく使用可能な在庫で確認しています。T4はID順のタイブレークを適用し、数量0の注文も処理します。T5は同日の注文について入力順を維持します。T6では検証が最初に行われます。スキップされたall_or_nothingの注文は何も消費しません。論理的な誤りは見つかりませんでした。

完全性

93

戻り値の辞書にはfills、short、remainingがちょうど含まれています。fillsにはすべての注文IDが含まれ、何も割り当てられなかった注文には空のリストが入ります。shortには正の不足分のみが含まれます。remainingはすべてのロットを対象としています。数量が負の場合や、ロットまたは注文のIDが重複している場合は、割り当ての前にValueErrorが発生します。

コード品質

90

コードは整理されていて読みやすいです。ロットは一度だけソートされ、各注文はロットを1回のパスで処理します。入力の辞書は変更されず、コメントも役立ちます。小さな非効率として、注文ごとに使用可能なリストを作り直している点がありますが、この規模では問題ありません。

実用性

88

そのまま使える実用的な内容です。エラーメッセージは分かりやすく、入力は変更されません。説明は明確で、計算量はO(L log L + O log O + O·L)と正しく示され、あわせて使用する領域(空間計算量)も記載されています。

指示遵守

80

標準ライブラリのみを使用しており、コードは57行で(150行未満という条件を大きく下回っています)、計算量も記載されています。ただし、説明文は220語で、200語の制限を10%超過しているため、減点されます。

GPT-6.1 Sol 9.90

この実装は、FEFO(先に期限が切れるものから先に出荷する方式)による割り当て、安定した注文処理、注文単位の全量引当または全量不可(オール・オア・ナッシング)、入力の検証、そして必須とされた戻り値の構造を正しく処理しています。目視確認の範囲ではT1〜T6に合格しており、入力は変更されずに保持され、計算量も正しく記載されています。唯一の欠点は、説明が200語の上限を超えていることです。

評価基準ごとの点数

正確さ

100

検査によりT1~T6を通過しています。安定した日付のソート、期限日を含む判定、(expires, id)によるロットの順序付けを使用しています。全か無かの在庫確認には利用可能な在庫のみが含まれ、スキップされた注文は在庫を消費しません。

完全性

100

fills、short、remainingの3つだけを、必要な内容とともに返しています。割り当てを開始する前に、両方の入力について負の数量と重複IDを検証しています。

コード品質

100

明確で自己完結したコードであり、検証と割り当てのロジックは分かりやすいです。入力の変更を避け、単位ごとの反復も避けており、時間計算量と空間計算量の記述も正確です。

実用性

100

指定された入力にそのまま使用できます。わかりやすい検証エラーを返し、空の割り当て、数量ゼロ、期限切れの在庫、部分的な充足を正しく処理します。

指示遵守

90

標準のPythonのみを使用し、コードは57行の制限内に収まっています。必要な計算量の記述も含まれています。ただし、測定された説明が220語であり200語の制限を超えているため、1点減点しています。

Gemini 3.8 Flash 9.80

この実装はすべての機能要件を正しく満たしており、テストケースT1からT6に合格しています。戻り値の形式と検証ロジックは仕様と正確に一致しています。唯一の欠点は、説明文が200語の制限を超えていること(測定値は220語)です。

評価基準ごとの点数

正確さ

100

すべてのエッジケース(T1からT6)が正しく合格しています。注文日での並べ替えは安定しており、ロットは(expires, id)で並べ替えられ、全か無かの在庫チェックは、その日に利用可能な在庫のみを正しく計算します。また、在庫の割り当てが入力を変更しない形で期待どおりに動作します。

完全性

100

関数は要求されたキーを過不足なく返し、型と値も適切です。事前の検証では、ロットと注文の両方について、負の数量と重複IDを厳密に確認しています。

コード品質

100

明確なコメント、適切なデータ構造、わかりやすい変数名を備えた、簡潔で慣用的なPythonコードです。

実用性

100

入力を変更しない純粋な設計で、そのまま使える自己完結型の実装です。

指示遵守

80

コードの長さは150行の制限に十分収まっており(57行)、標準ライブラリのみを使用し、計算量も明記されています。ただし、コードブロック外の説明文の語数は220語と測定され、明示的な上限である最大200語を超えています(10%超過、-2点)。

5 Gemini 3.8 Flash

平均(10点満点) 9.12
def allocate(lots, orders):
    # 1. Validation
    seen_lot_ids = set()
    for lot in lots:
        if lot["qty"] < 0:
            raise ValueError(f"Negative lot quantity: {lot['qty']}")
        if lot["id"] in seen_lot_ids:
            raise ValueError(f"Duplicate lot ID: {lot['id']}")
        seen_lot_ids.add(lot["id"])

    seen_order_ids = set()
    for order in orders:
        if order["qty"] < 0:
            raise ValueError(f"Negative order quantity: {order['qty']}")
        if order["id"] in seen_order_ids:
            raise ValueError(f"Duplicate order ID: {order['id']}")
        seen_order_...
全文を表示 ▼
def allocate(lots, orders):
    # 1. Validation
    seen_lot_ids = set()
    for lot in lots:
        if lot["qty"] < 0:
            raise ValueError(f"Negative lot quantity: {lot['qty']}")
        if lot["id"] in seen_lot_ids:
            raise ValueError(f"Duplicate lot ID: {lot['id']}")
        seen_lot_ids.add(lot["id"])

    seen_order_ids = set()
    for order in orders:
        if order["qty"] < 0:
            raise ValueError(f"Negative order quantity: {order['qty']}")
        if order["id"] in seen_order_ids:
            raise ValueError(f"Duplicate order ID: {order['id']}")
        seen_order_ids.add(order["id"])

    # Internal lot inventory
    remaining = {lot["id"]: lot["qty"] for lot in lots}
    lots_meta = {lot["id"]: lot["expires"] for lot in lots}

    fills = {order["id"]: [] for order in orders}
    short = {}

    # Sort orders by day (Python's Timsort is stable, preserving input order on ties)
    sorted_orders = sorted(orders, key=lambda o: o["day"])

    for order in sorted_orders:
        oid = order["id"]
        req_qty = order["qty"]
        day = order["day"]
        aon = order.get("all_or_nothing", False)

        # Identify and sort usable lots
        usable_lots = [
            lid for lid, exp in lots_meta.items()
            if exp >= day and remaining[lid] > 0
        ]
        usable_lots.sort(key=lambda lid: (lots_meta[lid], lid))

        total_usable = sum(remaining[lid] for lid in usable_lots)

        # Handle all-or-nothing check
        if aon and req_qty > total_usable:
            if req_qty > 0:
                short[oid] = req_qty
            continue

        # Allocate stock according to FEFO
        unfilled = req_qty
        for lid in usable_lots:
            if unfilled == 0:
                break
            take = min(remaining[lid], unfilled)
            if take > 0:
                remaining[lid] -= take
                unfilled -= take
                fills[oid].append((lid, take))

        if unfilled > 0:
            short[oid] = unfilled

    return {
        "fills": fills,
        "short": short,
        "remaining": remaining,
    }
計算量とその説明
  • 時間計算量: ロットの数を $L$、注文の数を $O$ とします。入力の検証には $O(L + O)$ かかります。注文のソートには $O(O \log O)$ かかります。各注文について、利用可能なロットの抽出と並べ替えには $O(L \log L)$ かかり、在庫の引き当て(差し引き)には $O(L)$ かかります。したがって、すべての注文の処理には $O(O \cdot L \log L)$ かかります。全体の時間計算量は $\mathcal{O}(O \log O + O \cdot L \log L)$ です。
  • 空間計算量: $\mathcal{O}(L + O \cdot \min(L, \text{平均引き当て分割数}))$ です。ロット、注文のメタデータ、引き当て履歴の追跡には、入力に対して線形の補助領域が必要なためです。
Claude Opus 5.5 8.74

正解キーと照らし合わせると、この関数は6件のテストすべてに合格しています。割り当てに関するT1からT5と、検証に関するT6です。注文は日付で安定ソートされ、有効期限の当日は含まれます。全量引き当てか、まったく引き当てないかの判定には、その日に使用できる在庫のみが使われます。スキップされた注文は在庫を消費しません。検証はすべての割り当ての前に完了し、戻り値の形式も正しいです。主な弱点は効率です。注文ごとに使用可能なロットを作り直して再ソートしているため、ロットを一度だけソートする場合と違い、計算量は O(O·L log L) になります。コードは長さの制限を満たしており、説明も計算量を正しく述べています。

評価基準ごとの点数

正確さ

90

テスト T1 から T6 を読んで確認したところ、すべて合格です。日付による並べ替えは安定しており、expires >= day の判定は両端を含み、ロットは (expires, id) の順に並んでいます。通常の注文では部分引当てが正しく機能します。全量引当ての判定はその日に利用可能な在庫と比較され、スキップされた注文は何も引き当てません。数量ゼロの注文は空の fill となり、short にはエントリが追加されません。論理的な誤りは見つかりませんでした。

完全性

90

fills、short、remaining を過不足なく返しています。すべての注文 ID が fills に含まれ、short には正の不足分のみが入ります。remaining はすべてのロットを対象としています。数量が負の場合や、ロットまたは注文の ID が重複している場合は、状態を変更する前に ValueError を送出します。必要な要素はすべて揃っています。

コード品質

82

コードは明快で読みやすく、変数名が分かりやすく、役に立つコメントがあります。数量の単位ごとにループすることはありません。ただし、注文ごとにすべてのロットを絞り込んで再ソートしているため、計算量は O(O·L log L) になります。最初にロットを一度だけソートする方が、より簡潔になります。`if take > 0` の条件分岐はやや冗長です。

実用性

83

小規模な倉庫であればそのまま実用できます。注文ごとの再ソートは、控えめな規模では問題になりません。エラーメッセージは情報量が多いです。ロットの数が多い場合は、理想的な実装と比べてやや効率が劣ります。

指示遵守

90

標準ライブラリのみを使用しています。コードは 68 行で、上限の 150 行を大きく下回っています。説明は 93 語で、上限の 200 語未満です。計算量の記述 O(O log O + O·L log L) は、記載されたコードに対して正しいです。説明は主に計算量に関するもので、手法についての説明は少ないですが、必要な要素はすべて満たしています。

GPT-6.1 Sol 8.62

この関数は6件のテストケースをすべて正しく処理しており、割り当ての前に入力を検証し、入力を変更することなく要求された構造を返します。主な弱点は、ロットを一度だけソートするのではなく、注文ごとに使用可能なロットを再度ソートしている点です。時間計算量の記述はその実装を反映していますが、空間計算量の記述では、約定(fills)が空の場合でも避けられない注文ごとの保存領域が考慮されていません。

評価基準ごとの点数

正確さ

89

検査により T1~T6 を通過しています。安定した時系列順の処理、期限日を含む判定、文字列 ID による同順位の処理、部分的な充当、そして全量注文を消費せずに拒否する処理はいずれも正しいです。注文ごとに繰り返し並べ替えるため、方針に記載された 9+ の効率条件よりも漸近的な上限が悪くなります。

完全性

89

空の fills と、期限切れのまま使われなかった在庫を含め、fills、short、remaining を正確に返しています。重複 ID の確認2種類と、負の数量のすべての確認は割り当ての前に行われます。必要な機能要素はすべてそろっていますが、共通の 9+ 条件は完全には満たしていません。

コード品質

80

可読性が高く自己完結したコードで、検証と割り当ての段階が明確であり、名前も分かりやすく、入力を変更していません。注文ごとに使用可能なロットを別々に並べ替えるのは不要です。ロットを一度だけ並べ替えれば処理が単純になり、最悪ケースの実行時間も改善できます。また、全量か無かの注文だけがその確認を必要とするのに、通常の注文でも使用可能な在庫を合計しています。

実用性

83

述べられている小規模倉庫にそのまま使用でき、重要な境界ケースも正しく処理しています。繰り返しの並べ替えは拡張性を制限します。また、多くの注文に在庫が割り当てられない場合、空間計算量の説明は保存量を過小に示しています。

指示遵守

88

Python の組み込み機能のみを使用し、測定された68行のコードと93語の説明の範囲内に収まっています。また、実装に対する時間計算量の記述は正しいです。追加の空間計算量の上限は不正確です。保存量は O(L + O + F) で、F は割り当てタプルの総数です。注文に在庫が割り当てられない場合でも O(O) の項が含まれます。

Gemini 3.8 Flash 10.00

この解答は、オール・オア・ナッシングの制約を備えたFEFO(先期限先出し)在庫引当アルゴリズムを、完全かつ正確に実装しています。数量ゼロの注文、注文日とロットIDによる安定したタイブレーク、負の数量や重複に対する引当前の厳格な検証など、エッジケースも完璧に処理しています。コードは簡潔で慣用的であり、行数と単語数の制限をすべて厳守しています。そのうえ、計算量の分析も正確です。

評価基準ごとの点数

正確さ

100

テストT1からT6はすべて、検査により合格しています。安定ソートは、同じ日付の場合に注文順序を保持し、有効期限の比較は'>='を正しく使用し、ロットの有効期限が同じ場合は文字列IDで順序を決めます。また、全か無かの判定はその日に使用可能な在庫と照合され、在庫は一単位ずつではなく最小数量のまとまり単位で差し引かれます。

完全性

100

すべての要件が満たされています。すべてのロットと注文の検証は、引当の前に実行され、負の数量または重複IDの場合はValueErrorを送出します。返される辞書は、'fills'、'short'、'remaining'について要求された正確な構造と意味に一致しています。

コード品質

100

コードは読みやすくモジュール化されており、十分にコメントされ、不要な複雑さを避けています。引当はmin(remaining, unfilled)を使って行われるため、在庫の差し引きが効率的です。

実用性

100

この実装は、適切な防御的チェックと明確な対応付けを備えているため、本番に近い環境や倉庫管理システムでそのまま利用できます。

指示遵守

100

制約を厳密に守っています。Python標準ライブラリのみを使用し、150行の制限を大きく下回る68行であり、説明は200語の制限内の93語で、時間計算量と空間計算量の両方を正確に示しています。

6 Gemini 3.5 Flash-Lite

平均(10点満点) 8.89

FEFO割当関数

def allocate(lots, orders):
    if any(l["qty"] < 0 for l in lots) or any(o["qty"] < 0 for o in orders):
        raise ValueError("Negative quantity found")
    
    lot_ids = [l["id"] for l in lots]
    if len(lot_ids) != len(set(lot_ids)):
        raise ValueError("Duplicate lot ID")
    
    order_ids = [o["id"] for o in orders]
    if len(order_ids) != len(set(order_ids)):
        raise ValueError("Duplicate order ID")
    
    remaining = {l["id"]: l["qty"] for l in lots}
    lot_data = {l["id"]: {"expires": l["expires"], "id": l["id"]} for l in lots}
    
    sorted_orders = sorted...
全文を表示 ▼

FEFO割当関数

def allocate(lots, orders):
    if any(l["qty"] < 0 for l in lots) or any(o["qty"] < 0 for o in orders):
        raise ValueError("Negative quantity found")
    
    lot_ids = [l["id"] for l in lots]
    if len(lot_ids) != len(set(lot_ids)):
        raise ValueError("Duplicate lot ID")
    
    order_ids = [o["id"] for o in orders]
    if len(order_ids) != len(set(order_ids)):
        raise ValueError("Duplicate order ID")
    
    remaining = {l["id"]: l["qty"] for l in lots}
    lot_data = {l["id"]: {"expires": l["expires"], "id": l["id"]} for l in lots}
    
    sorted_orders = sorted(enumerate(orders), key=lambda x: (x[1]["day"], x[0]))
    
    fills = {o["id"]: [] for o in orders}
    short = {}
    
    for _, order in sorted_orders:
        oid = order["id"]
        oday = order["day"]
        oqty = order["qty"]
        aon = order.get("all_or_nothing", False)
        
        usable_lots = [
            lid for lid, qty in remaining.items()
            if qty > 0 and lot_data[lid]["expires"] >= oday
        ]
        usable_lots.sort(key=lambda lid: (lot_data[lid]["expires"], lot_data[lid]["id"]))
        
        total_usable = sum(remaining[lid] for lid in usable_lots)
        
        if aon and oqty > total_usable:
            short[oid] = oqty
            continue
            
        allocated_for_order = []
        needed = oqty
        
        # Check if we can fulfill the order partially or fully
        temp_allocation = []
        for lid in usable_lots:
            if needed <= 0:
                break
            take = min(remaining[lid], needed)
            temp_allocation.append((lid, take))
            needed -= take
            
        if aon and needed > 0:
            short[oid] = oqty
            continue
            
        # Apply allocation
        for lid, take in temp_allocation:
            remaining[lid] -= take
            allocated_for_order.append((lid, take))
            
        fills[oid] = allocated_for_order
        if needed > 0:
            short[oid] = needed
            
    return {
        "fills": fills,
        "short": short,
        "remaining": remaining
    }

解説と計算量

allocate 関数はまず、負の数量と重複した ID を検証し、いずれかの制約に違反していれば ValueError を送出します。同じ日に属する注文の順序を決める際の並べ替えのために、元の注文の順番のインデックスを保持します。

日付順に並べられた各注文について、関数は有効期限が注文日以上で在庫が 0 でないロットを抽出します。これらのロットを FEFO のルールに従って並べ替えます。すなわち、expires の昇順、次に id の昇順です。all_or_nothing の注文で利用可能な在庫の合計が不足している場合は、その注文を飛ばします。それ以外の場合は、充足するか利用可能な在庫が尽きるまで、在庫を貪欲に差し引きます。

時間計算量

$L$ をロットの数、$O$ を注文の数とします。注文の並べ替えには $O(O \log O)$ かかります。$O$ 個の各注文について、ロットの抽出と並べ替えに $O(L \log L)$ かかります。したがって、全体の時間計算量は $O(O \log O + O \cdot L \log L)$ です。

Claude Opus 5.5 8.07

この関数は、コードを読む限り、正解キーの6つのケースすべてで正しく動作します。日ごとの安定ソートを使い、有効期限を含めて判定し、ロットを(expires, id)の順に並べ、all_or_nothingの注文は使用可能な在庫だけを対象に確認し、数量ゼロの注文も処理し、割り当ての前に検証を行い、ちょうど3つのキーを返します。弱点は非効率さと冗長さです。使用可能なロットが注文ごとに再度フィルタリングされて再ソートされるため(O·L log L)、到達しない2つ目のall_or_nothingチェックがあり、lot_dictが不必要にidを重複して持っています。これらの点により、9点以上の評価帯には届きません。

評価基準ごとの点数

正確さ

85

T1からT6まで読み取りで合格します。注文は(day, index)で並べられ、expires >= dayは両端を含み、同順位はロットidで決まり、all_or_nothingは利用可能な在庫のみに対して確認されます。スキップされたall_or_nothingの注文は何も消費せず、数量ゼロの注文はfillsに現れ、shortには現れません。ただし、注文ごとにロットを再ソートするためO·L log Lになり、より簡潔なO·Lではないため、9以上にはなりません。

完全性

87

戻り値の形は、fills、short、remainingとまさに一致しています。すべての注文idがfillsに含まれ、タプルのリストを持ち、shortには正の不足分のみが入ります。負の数量、ならびに重複したロットidや注文idに対しては、割り当てを行う前にValueErrorが発生します。

コード品質

68

コードは読みやすいものの、冗長な部分があります。lot_dataはidを再度保存しており、一時割り当ての後の2つ目のaonチェックは決して発動せず、allocated_for_orderはtemp_allocationと重複しています。1回の事前ソートで足りる場面で、注文ごとにすべてのロットを再フィルタリングand再ソートするのは無駄です。

実用性

75

倉庫のシナリオに対して正しく動作し、検証も妥当です。ロットと注文が多い場合、注文ごとのソートはスケールしにくいですが、小規模な倉庫であれば許容できます。

指示遵守

87

標準ライブラリのみを使用しています。コードは68行で、150行の上限内に収まっています。説明文は148語で、200語の上限内に収まっており、記載された時間計算量はこの実装を正確に表しています。

GPT-6.1 Sol 8.61

この実装は、6件のテストケースをすべて正しく処理し、割り当ての前に入力を検証し、要求された構造を返しています。コードと説明の制限も満たしており、主な実行時間コストも正確に説明しています。主な弱点は、注文ごとに使用可能なロットを並べ替え直しているため、ロットを一度だけ並べ替える場合よりも計算量の上限が遅くなっている点です。また、割り当ての管理処理には冗長な部分もあります。

評価基準ごとの点数

正確さ

89

検査によりT1からT6を通過しています。時系列処理により同日の注文順序が保たれ、有効期限は当日を含み、FEFOの同順位はロットIDで判定されます。全量or無しの注文は使用可能在庫のみを確認し、スキップされた場合は何も消費しません。数量ゼロの注文も正しく処理されています。繰り返しの並べ替えは、ポリシーの9+条件に関連する効率上限を満たしていません。

完全性

89

fills、short、remainingをちょうど返し、必要な場合はすべての注文とロットを含めています。負の数量と重複IDは、割り当て開始前に拒否されます。必要な機能に欠けているものはありませんが、全体の9+効率条件は満たしていません。

コード品質

78

可読性が高く自己完結したコードで、検証と割り当ての段階が明確です。ただし、注文ごとに使用可能なロットを並べ替えるのは不要であり、lot_dataが各IDを冗長に保持しています。さらに、十分性が確認された後に一時的な割り当てと2回目の全量or無しの確認を行っており、記録管理が余分に増えています。

実用性

84

結果は決定的で、与えられた入力を変更しないため、小規模な倉庫にそのまま使えます。注文ごとの繰り返しの並べ替えは、ロットを一度だけ並べ替える方法と比べて拡張性を制限しますが、想定される用途での有用性を損なうものではありません。

指示遵守

89

組み込みのPython機能のみを使用し、要求された関数を提供しており、測定された上限であるコード68行と説明148語の範囲内に収まっています。説明には正確な主要計算量の上限が含まれていますが、その上限はポリシーの9+効率目標より遅いものです。

Gemini 3.8 Flash 10.00

この解答は、すべての要件を完全に満たしており、ポリシーに示されたすべてのテストケース(T1〜T6)に合格しています。検証は最初に行われ、注文の並べ替えは安定しており、ロットの同順位の処理と有効期限の条件は厳密に正しく、オール・オア・ナッシングのロジックは使用可能な在庫を適切に考慮しており、戻り値の構造も正確です。行数の上限と説明の語数の上限は厳密に守られており、時間計算量の分析も正確です。

評価基準ごとの点数

正確さ

100

日付による注文の安定した並び順、IDの文字列比較による同順位の決定を伴う厳密なFEFOロット選択、有効期限のフィルタリング(expires >= day)、そして状態を漏らさない厳密な全か無かの処理が正しく実装されています。

完全性

100

すべてのエッジケースと要件が処理されています。負の数量と重複IDに対する事前検証、適切な戻り値の辞書形式、残り不足量がゼロの注文を'short'から除外すること、割り当てがゼロの注文を'fills'に含めることが含まれます。

コード品質

100

コードは簡潔で慣用的、読みやすく、適切に構造化されています。個々の数量単位に対する冗長な走査を避けています。

実用性

100

標準的な在庫割り当て問題に対して本番環境で使える品質であり、実行経路が明確で、完全に信頼できます。

指示遵守

100

制約をすべて守っています。標準ライブラリのみを使用し、コードは68行(150行の制限を大きく下回る)、説明は148語(200語の制限未満)で、正確な時間計算量の分析を含んでいます。

このジャンルについて

このジャンルでは、主に 正確さ、完全性、コード品質 のような力を見ようとしています。

システム設計よりも、実際に動くコードになるか、細部まで正しく組めるかを強く見ているのが違いです。

ここで高得点でも、上位の設計判断、プロダクト判断、初心者向けの説明の分かりやすさまで強いとは限りません。

このジャンルで強いAIが向いている用途

実装、デバッグ、リファクタリング、コードレビュー補助です。

このジャンルだけでは判断しきれないこと

高レベルな設計、利害調整を含む文書作成、自由発想の強さまでは分かりません。

このジャンルで評価している項目

このジャンルで使っている採点基準と重みです。

正確さ

35.0%

この項目は、回答の 正確さ を確かめるために入れています。 比重が重いのは、この部分が弱いとジャンル全体の評価が崩れやすいからです。

完全性

20.0%

この項目は、回答の 完全性 を確かめるために入れています。 比重がしっかりあるのは、全体の良し悪しに目に見えて効いてくる項目だからです。

コード品質

20.0%

この項目は、回答の コード品質 を確かめるために入れています。 比重がしっかりあるのは、全体の良し悪しに目に見えて効いてくる項目だからです。

実用性

15.0%

この項目は、回答の 実用性 を確かめるために入れています。 比重をやや軽くしているのは、重要ではあるものの、このジャンルの中心そのものではないからです。

指示遵守

10.0%

この項目は、回答の 指示遵守 を確かめるために入れています。 比重をやや軽くしているのは、重要ではあるものの、このジャンルの中心そのものではないからです。

関連リンク

X f L