Jelly、309バイトのJellyエンコーディング
“Æ÷“¥s“ɲ“¡µ’;“ịƊ⁴çNṂ‘_\
OḌ;¢*5$%¥/µ“+⁷ż!¤ña¡jIȧƁfvḶg/Ọ=^ƝĠ0Ẇƭ³½N~=.Ɗ°ɗẇ⁵\ɦ*ɠPf⁾?ṾHḣ 2=⁹ƒ!©ƊĠṣƥ®Ƙ0Yƙ>!ȧtƊN0w,$ɠẎ46fẋ⁷(ṣẆm⁾ŻƓṫµsçwṣḂḲd0Ruṛ’ḃ21+\iµØW“&;:' ”;“¡3ȧ%⁾xƑ?{Ñṃ;Ċ70|#%ṭdṃḃ÷ƑĠẏþḢ÷ݳȦṖcẇọqƁe ʠ°oḲVḲ²ụċmvP[ỴẊẋ€kṢ ȯḂ;jɓỴẏeṾ⁴ḳḢ7Ẓ9ġƤṙb€xÇ4ɗ⁻>Ẉm!Ƈ)%Ḃẇ$ġ£7ȧ`ỵẈƘɗ¡Ṃ&|ƙƥ³ẏrṛbḋƙċ⁻ṁƲRṀẹṾ<ñ⁻Ṅ7j^ɓĊ’b58¤ị;0ị@
ḲÇ€t0”@;Ṫ
オンラインでお試しください!
私は自分の挑戦に出かけた頃だと判断しました。Jelly(およびその8ビットコードページ)を使用すると、ASCIIのみの言語に比べて12.5%の利点が得られます。また、Jellyは、短い名前のベース変換演算子が組み込まれているため、この課題に便利です。これは、より良い圧縮アルゴリズムによるものです(このプログラムは、モンスターのタイプごとに平均して1バイト未満です)。
アルゴリズムと説明
単語ベースの分類
良いスコアを得るためには、入力の構造を他のエントリよりも活用する必要があると判断しました。非常に注目すべきことの1つは、多くのモンスターが「形容詞 種」という形式の名前を持っていることです。a red dragon
とa blue dragon
は両方ともドラゴンのタイプであり、したがってとして表示されD
ます。他の一部のモンスターには、「種の 仕事」という形式の名前がありorc shaman
ます。orcのタイプであるため、これはとして表示されo
ます。問題を複雑にしているのはアンデッドです。a kobold zombie
はコボルドとゾンビの両方であり、後者の状態はNetHackモンスターのネーミングで優先されるため、これをとして分類したいと思いZ
ます。
そのため、モンスター名に表示される単語を次のように分類しました。インジケータは、適切なモンスタークラスを強く示唆する単語です(たとえばsphere
、モンスターがクラスに属していることを強く示唆しe
ます)。あいまいな言葉はあまり提案の作る言葉です(lord
多くのを教えてくれません)、および他のすべての単語があるnonwords我々は気にしないこと。基本的な考え方は、モンスター名の単語を最後から最後まで見て、最初に表示されるインジケータを選択することです。そのため、各モンスター名に少なくとも1つのインジケータが含まれていることを確認する必要があり、インジケータの後にはあいまいな単語が続きます。例外として、モンスターの名前に現れる言葉は@
(最大のグループ)はすべて曖昧として分類されます。インジケータの前に何でも表示できます。たとえば、色名(などred
)は、インジケータよりも常に名前の前に表示されるため、非単語と見なされます(モンスターの身元を判断する際に検査されないため)。
最終的に、このプログラムは、他のプログラムと同様にハッシュテーブルになります。ただし、テーブルには、すべてのモンスター名、またはモンスター名に表示されるすべての単語のエントリは含まれていません。むしろ、インジケータのみが含まれています。あいまいな単語のハッシュはテーブルに表示されませんが、空のスロットに割り当てる必要があります(あいまいな単語を検索しようとすると、常に空になります)。非単語の場合、非単語を検索する値を使用しないため、単語がテーブルに表示されるかどうか、またはハッシュが衝突するかどうかは関係ありません。(テーブルはかなりまばらなので、ほとんどの非単語はテーブルに表示されませんが、flesh
ハッシュ衝突の結果としてテーブル内にあるようないくつかの単語が見つかります。)
プログラムのこの部分がどのように機能するかの例を次に示します。
woodchuck
は1ワードの長さ(したがってインジケーター)であり、テーブルルックアップwoodchuck
は意図した答えを提供しますr
。
abbot
も1語の長さですが、のように見え@
ます。そのためabbot
、あいまいな単語と見なされます。テーブルルックアップは空になり@
、デフォルトで回答を返します。
vampire lord
インジケータ(にvampire
対応V
)とあいまいな単語(lord
、テーブルにない)で構成されます。これは、両方の単語を(逆順で)チェックし、の正しい答えを与えることを意味しV
ます。
gelatinous cube
非単語(gelatinous
、H
ハッシュの衝突cube
に対応する)とインジケータ(に対応するb
)で構成されます。テーブルで見つかった最後の単語のみを取得するため、b
期待どおりにを返します。
gnome mummy
はにgnome
対応するG
とにmummy
対応する2つのインジケータで構成されM
ます。最後のインジケーターを取得しM
、取得します。これは必要なものです。
単語ベースの分類を処理するコードは、Jellyプログラムの最後の行です。仕組みは次のとおりです。
ḲÇ€t0”@;Ṫ
Ḳ Split on spaces
Ç€ Call function 2 (table lookup) on each entry
t0 Remove trailing zeroes (function 2 returns 0 to mean "not found")
”@; Prepend an @ character
Ṫ Take the last result
2つの実際のケースがあります。入力が完全にあいまいな単語で構成されている場合、t0
テーブル検索の出力全体を削除し、@
デフォルトで結果を取得します。入力にインジケータがある場合t0
、右端のインジケータの右側にあるものをすべて削除し、Ṫ
そのインジケータに対応する結果を提供します。
テーブル圧縮
もちろん、入力を単語に分割しても、それだけで問題は解決しません。インディケーターと対応するモンスタークラス間の対応(およびあいまいな単語からの対応の欠如)をエンコードする必要があります。これを行うために、181個のエントリが使用されたスパーステーブルを作成しました(181個のインジケータに対応しています。これは378個のモンスターよりも大幅に改善されています!)。テーブルは、2つの文字列を使用してプログラムでエンコードされます。最初の文字列は、テーブルの「ギャップ」のサイズを指定します(エントリを含まない)。2番目の文字列は、各エントリに対応するモンスタークラスを指定します。これらは両方とも、ベース変換を介して簡潔に表現されます。
Jellyプログラムでは、テーブルルックアップのコードは、プログラム自体と一緒に、最初から2行目に表示されµ
ます。プログラムのこの部分の仕組みは次のとおりです。
“…’ḃ21+\iµØW“&;:' ”;“…’b58¤ị;0ị@
“…’ Base 250 representation of the gap sizes
ḃ21 Convert to bijective base 21
+\ Cumulative sum (converts gaps to indexes)
i Find the input in this list
µ Set as the new default for missing arguments
ØW Uppercase + lowercase alphabets (+ junk we ignore)
“&;:' ”; Prepend "&;:' "
“…’ Base 250 representation of the table entries
b58 Convert to base 58
¤ Parse the preceding two lines as a unit
i Use the table to index into the alphabets
;0 Append a zero
i@ Use {the value as of µ} to index into the table
全単射の基数21は、基数21に似ていますが、21は有効な数字であり、0はそうではない点が異なります。これは、2つの隣接するエントリのギャップが1であるとカウントし、累積合計で有効なインデックスを見つけることができるため、より便利なエンコーディングです。値を保持するテーブルの部分になると、58個の一意の値があるため、最初に58個の連続する整数にデコードし、次にこれらを使用されている実際の文字にマップするルックアップテーブルを使用してデコードします。(これらのほとんどは文字であるため、このセカンダリルックアップテーブルを非文字エントリで&;:'
開始し、次に大文字と小文字のアルファベットで始まるJelly定数を追加します。他のジャンクもありますが、気にしませんそのことについて。)
Jellyの「インデックスが見つかりません」センチネル値は、リストにインデックスを付けるために使用すると、リストの最後の要素を返します。そのため、ルックアップテーブルにゼロ(テーブルのほとんどが文字で構成されていても整数ゼロ)を追加して、エントリが不足していることを示す適切なセンチネルを提供しました。
ハッシュ関数
プログラムの残りの部分はハッシュ関数です。これは単純に、OḌ
; これにより、入力文字列がASCIIコードに変換され、最後のコード、最後から2倍のコード、さらに前のコードの100倍などが計算されます(Jellyでは、一般的に文字列→整数変換関数)。ただし、モジュラス演算を介してこのハッシュを直接単純に減らすと、かなり大きなテーブルが必要になります。その代わりに、テーブルを削減する一連の操作から始めます。これらはそれぞれ次のように機能します。現在のハッシュ値の5乗を取得します。次に、定数を法とする値を減らします(どの定数は使用する操作に依存します)。このチェーンは、2つの方法で、(操作のチェーン自体をエンコードする必要があるという点で)コストよりも(結果のテーブルサイズを減らすという点で)より多くの節約を提供します。はるかに小さく(3529エントリではなく966エントリ)、複数のステージを使用すると、有益な衝突を引き起こす機会が増えます(これはあまり起こりませんでしたが、衝突が1つあります:両方Death
とYeenoghu
806へのハッシュ。彼らは両方に行くので、テーブルからのエントリ&
)。ここで使用されるモジュラスは[3529、2163、1999、1739、1523、1378、1246、1223、1145、966]です。ちなみに、5乗する理由は、値を直接取得する場合、ギャップは同じサイズのままになる傾向があるのに対し、累乗はギャップを移動し、テーブルがより均等に分布するようにすることができるためですローカルミニマムでスタックするのではなく、チェーン(より均等に分散されたギャップにより、ギャップサイズのより簡潔なエンコーディングが可能になります)。これは事実防止するために、奇数のパワーである必要があり、X( - ²= X)²導入衝突、及び5は、3よりも良好に働いています。
プログラムの最初の行は、デルタエンコーディングを使用してモジュライのシーケンスをエンコードします。
“…’;“…‘_\
“…’ Compressed integer list encoding, arbitrary sized integers
; Append
“…‘ Compressed integer list encoding, small integers (≤ 249)
_\ Take cumulative differences
プログラムの残りの部分である2行目の開始部分は、ハッシュ関数を実装します。
OḌ;¢*5$%¥/
O Take ASCII codepoints
Ḍ "Convert from decimal", generalized to values outside the range 0-9
;¢ Append the table of moduli from the previous line
/ Then reduce by:
*5$ raising to the power 5 (parsing this as a group)
%¥ and modulusing by the right argument (parsing this as a group, too).
検証
これは、プログラムが正しく機能することを確認するために使用したPerlスクリプトです。
use warnings;
use strict;
use utf8;
use IPC::Run qw/run/;
my %monsters = ("Aleax", "A", "Angel", "A", "Arch Priest", "@", "Archon", "A",
"Ashikaga Takauji", "@", "Asmodeus", "&", "Baalzebub", "&", "Chromatic Dragon",
"D", "Croesus", "@", "Cyclops", "H", "Dark One", "@", "Death", "&", "Demogorgon",
"&", "Dispater", "&", "Elvenking", "@", "Famine", "&", "Geryon", "&",
"Grand Master", "@", "Green-elf", "@", "Grey-elf", "@", "Hippocrates", "@",
"Ixoth", "D", "Juiblex", "&", "Keystone Kop", "K", "King Arthur", "@",
"Kop Kaptain", "K", "Kop Lieutenant", "K", "Kop Sergeant", "K", "Lord Carnarvon",
"@", "Lord Sato", "@", "Lord Surtur", "H", "Master Assassin", "@", "Master Kaen",
"@", "Master of Thieves", "@", "Medusa", "@", "Minion of Huhetotl", "&",
"Mordor orc", "o", "Nalzok", "&", "Nazgul", "W", "Neferet the Green", "@", "Norn",
"@", "Olog-hai", "T", "Oracle", "@", "Orcus", "&", "Orion", "@", "Pelias", "@",
"Pestilence", "&", "Scorpius", "s", "Shaman Karnov", "@", "Thoth Amon", "@",
"Twoflower", "@", "Uruk-hai", "o", "Vlad the Impaler", "V", "Wizard of Yendor",
"@", "Woodland-elf", "@", "Yeenoghu", "&", "abbot", "@", "acid blob", "b",
"acolyte", "@", "air elemental", "E", "aligned priest", "@", "ape", "Y",
"apprentice", "@", "arch-lich", "L", "archeologist", "@", "attendant", "@",
"baby black dragon", "D", "baby blue dragon", "D", "baby crocodile", ":",
"baby gray dragon", "D", "baby green dragon", "D", "baby long worm", "w",
"baby orange dragon", "D", "baby purple worm", "w", "baby red dragon", "D",
"baby silver dragon", "D", "baby white dragon", "D", "baby yellow dragon", "D",
"balrog", "&", "baluchitherium", "q", "barbarian", "@", "barbed devil", "&",
"barrow wight", "W", "bat", "B", "black dragon", "D", "black light", "y",
"black naga hatchling", "N", "black naga", "N", "black pudding", "P",
"black unicorn", "u", "blue dragon", "D", "blue jelly", "j", "bone devil", "&",
"brown mold", "F", "brown pudding", "P", "bugbear", "h", "captain", "@",
"carnivorous ape", "Y", "cave spider", "s", "caveman", "@", "cavewoman", "@",
"centipede", "s", "chameleon", ":", "chickatrice", "c", "chieftain", "@",
"clay golem", "'", "cobra", "S", "cockatrice", "c", "couatl", "A", "coyote", "d",
"crocodile", ":", "demilich", "L", "dingo", "d", "disenchanter", "R", "djinni",
"&", "dog", "d", "doppelganger", "@", "dust vortex", "v", "dwarf king", "h",
"dwarf lord", "h", "dwarf mummy", "M", "dwarf zombie", "Z", "dwarf", "h",
"earth elemental", "E", "electric eel", ";", "elf mummy", "M", "elf zombie", "Z",
"elf", "@", "elf-lord", "@", "energy vortex", "v", "erinys", "&", "ettin mummy",
"M", "ettin zombie", "Z", "ettin", "H", "fire ant", "a", "fire elemental", "E",
"fire giant", "H", "fire vortex", "v", "flaming sphere", "e", "flesh golem", "'",
"floating eye", "e", "fog cloud", "v", "forest centaur", "C", "fox", "d",
"freezing sphere", "e", "frost giant", "H", "gargoyle", "g", "garter snake", "S",
"gas spore", "e", "gecko", ":", "gelatinous cube", "b", "ghost", " ", "ghoul",
"Z", "giant ant", "a", "giant bat", "B", "giant beetle", "a", "giant eel", ";",
"giant mimic", "m", "giant mummy", "M", "giant rat", "r", "giant spider", "s",
"giant zombie", "Z", "giant", "H", "glass golem", "'", "glass piercer", "p",
"gnome king", "G", "gnome lord", "G", "gnome mummy", "M", "gnome zombie", "Z",
"gnome", "G", "gnomish wizard", "G", "goblin", "o", "gold golem", "'",
"golden naga hatchling", "N", "golden naga", "N", "gray dragon", "D", "gray ooze",
"P", "gray unicorn", "u", "green dragon", "D", "green mold", "F", "green slime",
"P", "gremlin", "g", "grid bug", "x", "guard", "@", "guardian naga hatchling",
"N", "guardian naga", "N", "guide", "@", "healer", "@", "hell hound pup", "d",
"hell hound", "d", "hezrou", "&", "high priest", "@", "hill giant", "H",
"hill orc", "o", "hobbit", "h", "hobgoblin", "o", "homunculus", "i",
"horned devil", "&", "horse", "u", "housecat", "f", "human mummy", "M",
"human zombie", "Z", "human", "@", "hunter", "@", "ice devil", "&", "ice troll",
"T", "ice vortex", "v", "iguana", ":", "imp", "i", "incubus", "&", "iron golem",
"'", "iron piercer", "p", "jabberwock", "J", "jackal", "d", "jaguar", "f",
"jellyfish", ";", "ki-rin", "A", "killer bee", "a", "kitten", "f", "knight", "@",
"kobold lord", "k", "kobold mummy", "M", "kobold shaman", "k", "kobold zombie",
"Z", "kobold", "k", "kraken", ";", "large cat", "f", "large dog", "d",
"large kobold", "k", "large mimic", "m", "leather golem", "'", "lemure", "i",
"leocrotta", "q", "leprechaun", "l", "lich", "L", "lichen", "F", "lieutenant",
"@", "little dog", "d", "lizard", ":", "long worm", "w", "lurker above", "t",
"lynx", "f", "mail daemon", "&", "manes", "i", "marilith", "&", "master lich",
"L", "master mind flayer", "h", "mastodon", "q", "mind flayer", "h", "minotaur",
"H", "monk", "@", "monkey", "Y", "mountain centaur", "C", "mountain nymph", "n",
"mumak", "q", "nalfeshnee", "&", "neanderthal", "@", "newt", ":", "ninja", "@",
"nurse", "@", "ochre jelly", "j", "ogre king", "O", "ogre lord", "O", "ogre", "O",
"orange dragon", "D", "orc mummy", "M", "orc shaman", "o", "orc zombie", "Z",
"orc", "o", "orc-captain", "o", "owlbear", "Y", "page", "@", "panther", "f",
"paper golem", "'", "piranha", ";", "pit fiend", "&", "pit viper", "S",
"plains centaur", "C", "pony", "u", "priest", "@", "priestess", "@", "prisoner",
"@", "purple worm", "w", "pyrolisk", "c", "python", "S", "quantum mechanic", "Q",
"quasit", "i", "queen bee", "a", "quivering blob", "b", "rabid rat", "r",
"ranger", "@", "raven", "B", "red dragon", "D", "red mold", "F",
"red naga hatchling", "N", "red naga", "N", "rock mole", "r", "rock piercer", "p",
"rock troll", "T", "rogue", "@", "rope golem", "'", "roshi", "@", "rothe", "q",
"rust monster", "R", "salamander", ":", "samurai", "@", "sandestin", "&",
"sasquatch", "Y", "scorpion", "s", "sergeant", "@", "sewer rat", "r", "shade", " ",
"shark", ";", "shocking sphere", "e", "shopkeeper", "@", "shrieker", "F",
"silver dragon", "D", "skeleton", "Z", "small mimic", "m", "snake", "S",
"soldier ant", "a", "soldier", "@", "spotted jelly", "j", "stalker", "E",
"steam vortex", "v", "stone giant", "H", "stone golem", "'", "storm giant", "H",
"straw golem", "'", "student", "@", "succubus", "&", "tengu", "i", "thug", "@",
"tiger", "f", "titan", "H", "titanothere", "q", "tourist", "@", "trapper", "t",
"troll", "T", "umber hulk", "U", "valkyrie", "@", "vampire bat", "B",
"vampire lord", "V", "vampire", "V", "violet fungus", "F", "vrock", "&", "warg",
"d", "warhorse", "u", "warrior", "@", "watch captain", "@", "watchman", "@",
"water demon", "&", "water elemental", "E", "water moccasin", "S", "water nymph",
"n", "water troll", "T", "werejackal", "d", "wererat", "r", "werewolf", "d",
"white dragon", "D", "white unicorn", "u", "winged gargoyle", "g",
"winter wolf cub", "d", "winter wolf", "d", "wizard", "@", "wolf", "d",
"wood golem", "'", "wood nymph", "n", "woodchuck", "r", "wraith", "W", "wumpus",
"q", "xan", "x", "xorn", "X", "yellow dragon", "D", "yellow light", "y",
"yellow mold", "F", "yeti", "Y", "zruty", "z");
for my $monster (sort keys %monsters) {
run ["./jelly", "fu", "monsters.j", $monster], \ "", \my $out;
print "$monster -> \"$out\" (",
($out ne $monsters{$monster} ? "in" : ""), "correct)\n";
}
mail daemon
> _ <