Caesar decoder in Standard ML

Caesar decoder in Standard ML

Standard MLは華麗なシンタックスシュガーが少ないので、書く人によって劇的にコードが変化して、知らん機能とか理屈とかを目にして困惑するということが少なく、プログラミングや関数型言語の入門に向いていると思います。しかしながら検索してもコピペするコードがほとんど出てこず、あるいは出てきても英語で難しそうなことが書いてあるようなページが表示され、まるであなた達みたいなヌルい方々に用はないの、お帰りなさい、とでも言われているかのよう。

と書いてみたけどそれとはあまり関係なく、

遊びでつくった真似しにくいStandard MLのコードを日本語でばら撒いて宿題の邪魔をするコーナー、始めました。

今日は基本編で、簡単なカエサルを簡単に解く簡単なプログラム。難度は「コード普通だし、内容も参考になりかねない」です。

プログラムはSML# version 1.2.0で動かしています。

けっこう適当なので、指摘等ありましたらお願いします。

カエサル暗号

ggrks。

仕様

こんな感じの変数をパラメータとして定義しておく。

val allChars = explode "abcdefghijklmnopqrstuvwxyz"
val allLen = length allChars

val enfreq =
    [8.2, 1.5, 2.8, 4.3, 12.7, 2.2, (* abcdef *)
     2.0, 6.1, 7.0, 0.2, 0.8,  4.0, (* ghijkl *)
     2.4, 6.7, 7.5, 1.9, 0.1,  6.0, (* mnopqr *)
     6.3, 9.1, 2.8, 1.0, 2.4,  0.2, (* stuvwx *)
     2.0, 0.1]                      (* yz *)

シフトされる文字と、各文字の文章内における出現頻度を書きます。
リストallCharsi番目の要素の出現頻度が、enfreqi番目の要素くらい、という意味。

残り

早くも飽きてきました。

この子達はリストをどうにかする関数です。

fun index x xs = let
  fun idx i nil = NONE
    | idx i (h::t) = if x = h then SOME i else idx (i+1) t
in idx 0 xs end

fun minimum f nil = raise Match
  | minimum f (h::t) = foldr (fn (a, b) => if f a > f b then b else a) h t

fun count p xs = length (List.filter p xs)

カエサル暗号化された各文字をcaesar型とします。この名付け方はなんか微妙ですが気にしない。

datatype caesar = Fix of char | Enc of int
fun toCaesar x = case index x allChars of SOME i => Enc i | NONE => Fix x
fun fromCaesar (Fix c) = c
  | fromCaesar (Enc i) = List.nth (allChars, i)
fun shiftCaesar n (Enc i) = Enc ((i + n) mod allLen)
  | shiftCaesar _ x = x

そして、カエサル文に出てくる文字の出現頻度と、はじめに用意した英文のアルファベット出現頻度を比較してマッチ度(?)を計算します。

fun freqs chars =
    map (fn c => real (count (fn x => x = c) chars) / real (allLen)) allChars

val chisqr =
    ListPair.foldr (fn (x, y, sum) => sum + Math.pow (x - y, 2.0) / y) 0.0

fun calcMatching caes = let
  val encs = List.mapPartial (fn (Enc x) => SOME x | Fix _ => NONE)
in chisqr (freqs (encs caes), enfreq) end

最後に暗号化、復号化関数。

fun encode n =
    implode o
    map (fromCaesar o shiftCaesar n o toCaesar o Char.toLower) o
    explode
fun decode s =
    let
      val caes = map (toCaesar o Char.toLower) (explode s)
      val encodeds =
          foldr (fn (_, nil) => [map (shiftCaesar 1) caes]
                  | (_, (h::t)) => map (shiftCaesar 1) h :: h :: t)
                nil allChars
      val matcheds = map calcMatching encodeds
      val (ans, _) = minimum #2 (ListPair.zip (encodeds, matcheds))
    in
      implode (map fromCaesar ans)
    end

使い方

まずは平文。

val original = "Hentai is a word of Japanese origin which entered usage in Meiji era scientific and psychological journals. While it literally means a change of appearance or strange condition, its association with perversion stems from popular sexology. With the sexualization of Japan, a renewed interest in perverse publications led to normalization of the word in everyday life. The term entered English usage in the 1990s, as a catch-all term to describe erotic anime and manga pornography. Due to its ambiguous and broad attribution, the hentai genre is often superseded by the classification and categorization of specific themes and acts into sub-genres."

皆様にも馴染み深いHentai – Wikipedia, the free encyclopediaからとってきました。

そして暗号化。

val q = encode 13 original
val _ = print q

uragnv vf n jbeq bs wncnarfr bevtva juvpu ragrerq hfntr va zrvwv ren fpvragvsvp naq cflpubybtvpny wbheanyf. juvyr vg yvgrenyyl zrnaf n punatr bs nccrnenapr be fgenatr pbaqvgvba, vgf nffbpvngvba jvgu creirefvba fgrzf sebz cbchyne frkbybtl. jvgu gur frkhnyvmngvba bs wncna, n erarjrq vagrerfg va creirefr choyvpngvbaf yrq gb abeznyvmngvba bs gur jbeq va rirelqnl yvsr. gur grez ragrerq ratyvfu hfntr va gur 1990f, nf n pngpu-nyy grez gb qrfpevor rebgvp navzr naq znatn cbeabtencul. qhr gb vgf nzovthbhf naq oebnq nggevohgvba, gur uragnv traer vf bsgra fhcrefrqrq ol gur pynffvsvpngvba naq pngrtbevmngvba bs fcrpvsvp gurzrf naq npgf vagb fho-traerf.

すごい人なら読めそうですね!

復号化。

val a = decode q
val _ = print a

hentai is a word of japanese origin which entered usage in meiji era scientific and psychological journals. while it literally means a change of appearance or strange condition, its association with perversion stems from popular sexology. with the sexualization of japan, a renewed interest in perverse publications led to normalization of the word in everyday life. the term entered english usage in the 1990s, as a catch-all term to describe erotic anime and manga pornography. due to its ambiguous and broad attribution, the hentai genre is often superseded by the classification and categorization of specific themes and acts into sub-genres.

おー、すごい。

このコードのいいところは、使う文字にアルファベットを仮定したりとかしていないことです。allCharsenfreqsを変えると不思議な世界のなんだかよくわからない言語も作れます。その割りに変数名とか中途半端ですが、面倒なので放置です。

マルチバイト対応?なにそれ?鉱物の名前?

Post a Comment

Your email is never shared.

引く

PageTop