LoginSignup
2
2

More than 5 years have passed since last update.

D言語で書く "イケメンなコード" ~ Base64エンコーダをワンライナーで書く ~

Last updated at Posted at 2016-02-02

今回はワンライナーでBase64エンコーダを実装しようと思います。
発端は、「以前自分が書いたなんかよくわからないけどバグっていることだけはわかるD言語で書いたBase64エンコーダ」を見つけてしまい、しかもそのコードが汚かったので"イケメン"な感じで書いてみようと思って書いてみました。
WikipediaBase64の項に書かれている仕様をそのままコードに落としただけなので解説はしません。

では、以下にD言語での一般的なBase64エンコーダのコードを貼っておきます。

import std.algorithm,
       std.string,
       std.ascii,
       std.range,
       std.conv;

R delegate(Args) Z(R, Args...)(R delegate(R delegate(Args), Args) f){
  return (Args args) => f(Z(f), args);
}

string encode(T)(T data) {
  return
    (convb =>
      (table =>
        (converted =>
          (binaries =>
            (bLen =>
              (prepared => 
                (pLen => 
                  (quotients => 
                    pLen % 4 == 0
                      ? quotients
                      : quotients ~ (remainds =>
                                      remainds.map!(remain =>
                                        table[remain]
                                      ).array.join ~ repeat("=", 4 - (pLen % 4)).join
                                    )(prepared[($ - (pLen % 4))..$])
                  )(
                    (pLen / 4).iota.map!(i =>
                      (j =>
                        4.iota.map!(k =>
                          table[prepared[j + k]]
                        ).array.join
                      )(i * 4)
                    ).array.join
                  )
                )(prepared.length)
              )(
                (quotients =>
                  bLen % 6 == 0
                    ? quotients
                    : quotients ~ (remainds =>
                                    remainds ~ repeat("0", 6 - remainds.length).join
                                  )(binaries[($ - (bLen % 6))..$])
                )((bLen / 6).iota.map!(i => binaries[(i * 6)..((i + 1) * 6)]).array)
              )
            )(binaries.length)
          )(converted.join)
        )(data.map!(i =>
          (e =>
            e.length == 8
              ? e
              : repeat("0", 8 - e.length).join ~ e
          )(convb(i, 2))).array
        )
      )((charset => 
        assocArray(
          zip(
            charset.length.iota.map!(i =>
              (e =>
                e.length == 6
                  ? e
                  : repeat("0", 6 - e.length).join ~ e
              )(convb(i, 2))),
            charset))
        )((uppercase ~ lowercase ~ digits ~ "+/").split(string.init))
      )
    )((ulong N, int base) =>
      (convbM =>
        convbM(N, N, [], base)
      )(Z((string delegate(ulong, ulong, ulong[], int base) convbM, ulong N, ulong tmp, ulong[] stack, int base) =>
          tmp ? convbM(N, tmp / base, stack ~ (tmp % base), base) : stack.reverse.map!(e => e.to!string).join)));
}
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2