NLEの詳しい仕様

NLEとはNumerical Limit Exceedの略. 日本語にすると, 「数値の制限を超えました」というところでしょうか.
数値の制限とは, ルール説明において

絶対値が255を超える数値を扱うことは出来ません。

として説明されている部分です.
どのようなコードが, どのようなタイミングでNLE判定を食うかについて, 詳しく調べてみました.
なお, Herbert EditorはNLE判定までは本家と同じ実装がされていないようで, 今回の調査ではHOJ本家を用いています.

256以上の数値が呼び出された瞬間

NLEの基本は, 256以上の数値が呼び出されることです.

a(T):sa(T+T)
a(1)

とすると, a(128+128)が呼び出された時点でNLEします.

b(T):sb(256-T-T)
b(1)

とすると,

b(1) = sb(254) = ssb(-252) = ss

となりそうですが, b(256-T-T)というコードをプログラム側で解釈する瞬間に,
まず「256」「T」「T」という数値を読み取るために?NLEになります. なお, 同じようでも

c(T):sc(255+1-T-T)
c(1)
d(T):sd(256)
sss

などのコードはNLEにならずに実行できます. 前者は, 「255」「1」「T」「T」を認識し,
一気に「255+1-T-T」を計算し, その数値に対してNLE判定を行っていると考えられます.
後者は定義したもの実行しておらず, 定義するだけならNLE判定は起こらないことが分かります.

ルールのうそ?

数値の制限として, ルールに

絶対値が255を超える数値を扱うことは出来ません。

という記述があることは既に述べた通りです. しかし,

a(T):sa(1-T-T)
a(255)

というコードはNLEせずに実行できるようです.
どうやら, 関数の引数が負になった場合, 「0以下のときの処理」がNLE処理よりも 優先されるようですね.

優先順位は左から

数値が256以上になるにもかかわらず, NLE判定をくぐり抜けることがあります.

a(A,B):sa(A-1,B+1)
a(1,255)

これを実行すると, a(0,256)と256の数値が現れますが, NLEにはならず実行されます.
「0以下の数値なので何もしない」という処理がNLEよりも優先して働いていますね.

同じようでも

a(A,B):sa(A+1,B-1)
a(255,1)

とすると, 今回はa(256,0)と0以下の数値が現れるにもかかわらずNLE判定を食らいます.

どうやら, 「0以下ならその関数は無視する」「256以上ならNLE」という処理を
左側の引数から順番にしている影響だと思われます.
非常に些細な差ですが, この差が運命を分けたコードもあるようなので,
一応知っておくにこしたことはないでしょう.

謎の一歩

最後に不思議な現象を紹介しておきましょう.

a(T):ssa(T+1)ssss
a(255)

このコード, ss動いた直後にNLE判定で停止..するかと思いきや, なぜか3歩進んで止まります.

a(T):ssa(T+1)rsss
a(255)

なら, ssrまで実行されます. どうやら, NLE判定が出ても1歩は動けるみたいです(笑)
「実行されるけど, 回収してもClearにならないんだろ?」と思いきや, どうやら
NLE宣言された次の1歩でちょうどClearした場合, 正常なスコアと扱われます.

ロケ地:Problem 0545.

a(T):a(256)s
a(1)
b(T):sb(T+1)
llsllb(255)b(255)

こんなのがまともな更新に役立つとはあまり思えませんが. どうもこの現象はテクニックというよりはバグの1種という気もしますw

以上, あまり役に立たないことばかりでしたが, NLEについてmasの知るところをすべて記したつもりです.
ほかに何か面白い現象がありましたら教えてください♪


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2013-01-19 (土) 01:33:35 (4115d)