600000007

プログラムと折り紙のブログです。

照れくさいからお祝いメッセージを難読化&アスキーアートにしてみた

同僚が入籍しました。
お祝いメッセージを送りたいのですが真正面から伝えるのはなんだか照れくさいですよね。
ということで、お祝いメッセージを難読化してみました。
これなら照れくさくない!

   eval  (%w(               p
  r    i  n
 t        f
 (        " %s   ",[02*   0x0     2*0b1
 0        *0  b    10  1    0    0     0
 0        0   0    1        *     0b1
 1        0   0    1        0        00
  0    0  0   1    1        1    1     1
   1111  111 11* 0x86d    56fc3   35,0b

                   11
                  0
                  1
                   1
                  10
                 1  1  1
                 ,  0 b
                 1   1
                  *0b 11

 *0b 11*                 0b         1    01
  *   0                   b               1
  0   0                   1               1
   * 0    b1001   11011   1 ,0    b10     *  0b   10*0b
   1 1   0     0 1     1  1*  0     b     1  0   1     0
    0    0     1  100     1   1     1     1 1    1     1
    1    1     0     10   0   1     1     101    ]     .
    m    a     p {     |  s   |     s     .  t   o     _
   s(2    *2*3*   3)}*"  \s" +33  .chr)   )   .   join)

ソースコード:message.rb
これを実行すると、お祝いメッセージが出力されます。

$ ruby message.rb 
congratulations on your wedding!


難読化方法
こちらのブログを参考にしました。
多謝。
手順はこんな感じです。

  1. メッセージを決める
  2. アスキーアートのデザインを決める
  3. ざっくり難読化
  4. 字数調整


1.メッセージを決める
今回は"congratulations on your wedding!"にしました。
あまり短すぎると難読化しずらくなります。
これでベースとなるソースコードが出来上がります。

puts "congratulations on your wedding!"

2.アスキーアートのデザインを決める
難読化前に決めてしまいましょう。
今回はbannerコマンドを使って原型を作成しました。

   XXXX  XX                 X
  X    X  X
 X        X
 X        X XX   XXX XX   XXX     XXXXX
 X        XX  X    XX  X    X    X     X
 X        X   X    X        X     XXX
 X        X   X    X        X        XX
  X    X  X   X    X        X    X     X
   XXXX  XXX XXX XXXXX    XXXXX   XXXXX

                   XX
                  X
                  X
                   X
                  XX
                 X  X  X
                 X  X X
                 X   X
                  XXX XX
  

 XXX XXX                 XX         X    XX
  X   X                   X               X
  X   X                   X               X
   X X    XXXXX   XXXXX   X XX    XXX     X  XX   XXXXX
   X X   X     X X     X  XX  X     X     X  X   X     X
    X    X     X  XXX     X   X     X     X X    X     X
    X    X     X     XX   X   X     X     XXX    X     X
    X    X     X X     X  X   X     X     X  X   X     X
   XXX    XXXXX   XXXXX  XXX XXX  XXXXX  XX   XX  XXXXX

このAAの文字数は237文字です。
なので難読化ソースコードも237文字になるように調整します。


3.ざっくり難読化

文字を36進数に変換します。出力する時は数値を文字に再変換します。

puts 77896456584017463722584.to_s(36) + " " + 887.to_s(36) + " " + 1618515.to_s(36) + " " + 70526026924.to_s(36) + "!"


数値を配列に格納して、空白で結合するようにします。

puts [77896456584017463722584,887,1618515,70526026924].map{|s|s.to_s(36)}* " " + "!"


アスキーアート化できるようにする為にeval(%w( ... ).join)で囲います。
このとき囲いの中にスペースがあると実行できないので、putsをprintfに変更し、" "を"¥s"に変更してスペースを消しています。

eval(%w(printf("%s",[77896456584017463722584,887,1618515,70526026924].map{|s|s.to_s(36)}*"\s"+"!")).join)

だいぶ難読化されて来ましたね〜。
この状態になるとeval(%w( ... ).join)の中は自由に整形できます。

eval(%w(prin
 tf("%s",[7789
  6456584017
   463722584,8
    87,1618515,7
     0526026924].
      map{|s|s.to_s(
       36)}*"\s"+"!")).join)


4.字数調整

アスキーアートに必要なのは237文字ですが、現在は105文字しかありません。
今回は以下のテクニックを使って字数を調整しました。

  • 数値を素因数分解する
  • 数値を2進数、8進数、16進数にする
  • 文字をASCIIコードで表現する
    • "!" -> 33.chr # 2文字増えた!

そして完成したのがこれです。

eval(%w(printf("%s",[002*0x02*0b10*0b1010000001*0b1100100000011111111111111*0x86d56fc335,0b1101110111,0b11*0b11*0b11*0b101*0b10011*0b1001110111,0b10*0b10*0b1100111*0b1010001100111111111010011101].map{|s|s.to_s(2*2*3*3)}*"\s"+33.chr)).join)

変数名を長くしたり、数値を+1+1+1 ... したりすれば簡単に文字数を増やせますが、それだとつまらないので不採用にしました。
最終的には整形の都合で239文字になっています。
あとはこれをアスキーアートと同じ形に整形すれば完成です。


いやあ、これで照れずにお祝いメッセージを送れますね。
よかったよかった。

第18回折紙探偵団コンベンション

第18回折紙探偵団コンベンションの3日目(8/12)に参加してきました。


時既に遅し

実はコンベンションが開催されているのに気づいた時には既に2日目が始まっていました。
参加申し込みもとうの昔に締め切られていたのですが、定員までは引き続き募集しますという告知がサイトにあったので、どうにか参加できないか思慮する事数時間。
・・・が、特に名案は浮かばず現地にアポなしで直行してみる事にしました。


当日参加
はっきり言って迷惑行為ですね。すいませんでした。
門前払いされる事も覚悟しました。それも仕方ないです。

そもそもこんな飛び込み営業みたいな事は超苦手なので心臓ばっくばくでしたが、ここで行かないと後悔する!と覚悟を決めました。


そして3日目の朝。
参加申し込み無し、アポ無しでも快く対応して頂き、無事参加することができました。
本当にありがとうございました。
受付の方から頂いた「楽しんできてください」という一言が忘れられません。
申し込みが無いせいで受付手続きが面倒だったのに、男前な一言でした。

決してこの方法を推奨するわけではないので、ちゃんと締め切り前に応募しましょう!
・・・ほんとすいませんでした次からは必ずそうします。


ツル星人

ここまで頑張ったのは、全てはこのためでした。
長年折りたくて仕方が無かったツル星人の折紙教室にも、なんやかんやと参加させて頂く事が出来ました。
本当に感謝の言葉しかありません。

f:id:sakamoto_desu:20120813005608j:plain
そして念願のツル星人!
出来はまだまだですねー。
今後も精進して、よりいっそう気持ちの悪いツル星人を量産したい所存です。


マスタークラスの競演

その他の教室や展示作品も堪能させて頂きました。
まさに折り紙の祭典ですね。
そして何より、先生方がそこらへんを普通に歩いてるんですよ。
自分が持っている折り紙の本の著者が勢揃いしているんですよ。
凄い事なんですよ。
なんかもう、陳腐な言葉しか出てこないのが歯がゆいですね。


来年も参加します。・・・正規ルートで。

素人がゼロからプライベート名刺をデザインしてみた

プライベート名刺が欲しい。
その決意から完成までを書き留めておきます。


モチベーション
プログラムの勉強会に顔を出すようになって、プライベート用名刺が欲しくなりました。

ある日のイベント後に突然名刺交換が始まったのですが、渡せるのは会社の名刺しかありませんでした。
でも、この名刺に書いてあるアドレスでは連絡は取りたくありません。
まあ仕方ないかと交換を続けると、頂いた名刺の中に、会社名が無い物がありました。

「これ、プライベート用の名刺なんです。」

こーゆー時に必要なのか!と軽く感動を覚え、プライベート用の名刺作成を決意しました。


アイデア
どんな名刺にしようか・・・。
どうせなら癖がある物にしたい。
自分に関連する要素を入れたい。

という訳で、自分は折り紙が趣味なのでミウラ折り名刺を作る事にしました。

渡された方のリアクションに困った姿や、名刺ケースに収まらなくてめんどくさかがる姿が容易に想像できます。
でもいいんです。
名刺を交換した方にはこれから迷惑をかけるんですから、その第一歩です。
最初の迷惑です。


どうやって作る?
最初は適当にJPEGの絵でも書いて、印刷してもらえばいいかと軽く考えていました。
でも調べてみると、名刺の印刷サービスはイラストレーターのデータしか受け付けてくれませんでした。

さすがにイラストレーターを名刺だけの為に買って修行したくはない・・・
そこで利用したのが、kinko'sの名刺作成サービスです。
このサービスではラフ画から名刺を作成してもらえます。
早速、準備をして最寄りのkinko'sへ向かいました。


作成開始
準備したのはこの3つです。

で、それらをテーブルに並べてぐだぐだな説明をしました。
「このミウラ折りの折り線を入れたいんです」
「山折りは点線で、谷折りは破線で」
「名前は、良い感じの所に置いてもらえれば」
「色はこんな感じがいいんですが、全体を黒にして・・・あとはどうしましょう・・・」

ぐだぐだです。
でも担当の方は根気よく付き合ってくれました。


校正その1
とりあえずサンプルを1枚作ってもらい、校正してから印刷してもらう流れになります。
サンプルは翌日には貰えました。

そこで発覚した問題は以下です。

  • 紙が厚くて折り目が汚くなる
  • 折り目はトナーが剥げてしまう

結局、紙質は薄くて丈夫な物に変更し、黒のべた塗りを辞めました。
この時点で当初の配色プランは破綻したので途方に暮れたのですが、とりあえず2パターンのサンプルを作ってもらう事にしました。


校正その2
またもや翌日にでてくるサンプル。早いですね。
配色を見比べながら相談し決定。
ここで折り線が一部間違っていたことに気づいたので修正を依頼し、印刷を頼みました。


校正その3
印刷を頼んだ後、嫌な予感がしました。
デザインばかりに気を取られて、アドレスを確認していない。
案の定、印刷した完成品をみるとアドレスが間違っていました・・・。
平謝りして再印刷を依頼。特に追加料金もなく対応してくれました。


完成!

f:id:sakamoto_desu:20120808231713j:plain
こんな感じです。

f:id:sakamoto_desu:20120808231853j:plain
折り線が入ってます。


f:id:sakamoto_desu:20120808232511j:plain
ミウラ折り

f:id:sakamoto_desu:20120808232732j:plain
でこぼこで名刺入れには入りずらそうです。予定通り。

当初のイメージとは大分違いますが、アイデアは実現できたので良しとしましょう。
最初の1枚ですしね。


次の課題

やっぱ元々の配色では作ってみたいですね。
でもその為には、もっと高度な印刷が必要だと分かりました。
その理由は、「白いトナーは無い」からです。

当初のイメージは、全体が黒で文字が白 or 青でした。
でも普通のレーザープリンタは、赤青黄黒のトナーを混ぜて紙に置いて印刷する仕組みです。
そのため、白い文字というのは白い紙に文字以外の塗りつぶすしか作成方法がありません。
白いトナーは存在しないのです。
でもその方法では、折り目が汚くなったり、トナーが剥げてしまったりといまいちでした。

なので次回作はもっと高度な印刷ができる業者を探して、デザインを作って・・・となるのでしょうか。
チャンスがあればやってみたいですね。高そうですが・・・

Jenkins ユーザ・カンファレンス 2012 東京

帰宅してブログに書くまでがJenkinseユーザーカンファレンス!という事で書きます。

Jenkins ユーザ・カンファレンス 2012 東京に参加してきました。
参加申し込み1000人超え。勢いありますねー。

参加したセッションは全てさったホールです。
そして案の定知らない単語だらけだったのでメモして後で調べます。
この手の勉強会とかイベントに出る度にこのパターンで勉強不足を痛感しておりますが、カンファレンスに顔を出してなければ知らないままだったので良しとしましょう。

メモした単語は・・・

  • gerrit
  • nexus
  • chef
  • puppet
  • saucelabs

こんな感じです。


ただ一番の収穫は、川口耕介さんに会えた事でした。
実際に会話した訳ではありませんが、人柄とその能力を知る事ができました。

発表は無駄が無くハイテンポ、かつ異常に速いタイピング。
そしてディスプレイ表示の調子が悪ければ主催者にも関わらず他の人の発表時にケーブルを押さえる。
温和で偉そうにしない人なんでしょうね。

あと偶然、川口さんがユーザーさんからの質問に答えるシーンを目撃したのですが・・・
なんですかあのよどみないデバッグ
ユーザーさんがもってきたエラーログを見たとたん、発表と同じテンポで問題を指摘、対応策を説明。
ユーザーさんが別の質問をしても同様。
あんな効率的でスピーディーな口頭デバッグ初めてみました。

単にプログラマとして優秀なだけだときっとコミュニティを盛り上げる事はできないでしょう。
あの人柄と能力があって、今のJenkinsがあるんだなと感じました。


同じくセッションに参加していた同僚の帰り際の一言。
「川口さん雇いたいね」

無理無理。

Scala by Example‎ > 演習9.1.1解答案

Scala by Example > 演習9.1.1の解答案です。

  def isort(xs: List[Int]): List[Int] = xs match {
    case List() => List()
    case x :: xs1 => insert(x, isort(xs1))
  }
  def insert(x: Int, xs: List[Int]): List[Int] = xs match {
    case List() => List(x)
    case y :: ys => if (x <= y) x :: xs else y :: insert(x, ys)
  }

すいませんほぼカンニング状態です。
すぐ下に答えが書いてありますね。

Scala by Example‎ > 演習7.2.2解答案

Scala by Example > 演習7.2.2の解答案です。

  abstract class IntTree
  case object EmptyTree extends IntTree
  case class Node(elem: Int, left: IntTree, right: IntTree) extends IntTree
  def insert(t: IntTree, v: Int): IntTree = t match {
    case Node(e, l, r) => if (e > v) Node(e, insert(l, v), r)
    else if (e < v) Node(e, l, insert(r, v))
    else t
    case EmptyTree => Node(v, EmptyTree, EmptyTree)
  }

  def contains(t: IntTree, v: Int): Boolean = t match {
    case Node(e, l, r) => if (e == v) true
    else if (e > v) contains(l, v)
    else if (e < v) contains(r, v)
    else false
    case EmptyTree => false
  }

IntSetと比べるとcaseクラスを使う事により大分すっきりしていますね。

Scala by Example‎ > 演習6.0.3解答案その2

Scala by Example > 演習6.0.3の解答案その2です。

ヒントその2をベースにした解答です。

あるいは3つの子クラスとして Zero を 0 に、Succ を正の数のため、Pred を負の数のために使い、既知の Nat 実装を Integer へ一般化できます

ちょっと意味が分からない…原文を読んだ結果、NatをIntegerに改造して、その子クラスを3つ作れば良いと解釈しました。

  abstract class Integer {
    def isZero: Boolean
    def predecessor: Integer
    def successor: Integer
    def +(that: Integer): Integer
    def -(that: Integer): Integer
    def isPositive: Boolean
    def negate: Integer
  }

  object Zero extends Integer {
    def isZero: Boolean = true
    def isPositive: Boolean = false
    def predecessor: Integer = new Pred(Zero)
    def successor: Integer = new Succ(Zero)
    def +(that: Integer): Integer = that
    def -(that: Integer): Integer = that.negate
    def negate: Integer = this
  }

  class Succ(x: Integer) extends Integer {
    def isZero: Boolean = false
    def isPositive: Boolean = true
    def predecessor: Integer = x
    def successor: Integer = new Succ(this)
    def +(that: Integer): Integer = x + that.successor
    def -(that: Integer): Integer = x - that.predecessor
    def negate: Integer = {
      def iter(x: Integer, result: Integer): Integer = {
        if (x.isZero) result
        else
          iter(x.predecessor, result.predecessor)
      }
      iter(this, Zero)
    }
  }

  class Pred(x: Integer) extends Integer {
    def isZero: Boolean = false
    def isPositive: Boolean = false
    def predecessor: Integer = new Pred(this)
    def successor: Integer = x
    def +(that: Integer): Integer = x + that.predecessor
    def -(that: Integer): Integer = x - that.successor
    def negate: Integer = {
      def iter(x: Integer, result: Integer): Integer = {
        if (x.isZero) result
        else
          iter(x.successor, result.successor)
      }
      iter(this, Zero)
    }
  }

negateをもっとうまく書けないですかねー。