技術をかじる猫

適当に気になった技術や言語、思ったこと考えた事など。

Scala で解く「プログラマ脳を鍛える数学パズル」

病院行ったついでに待ち時間暇すぎて書店で見かけたやつ。

www.amazon.co.jp

これの問2 1000 - 9999 の中で、「351 , 3 * 51 = 153」(計算結果が元の逆順になる)みたいな数字を見つけ出せ。
使っていいのは四則演算のみで、必ず1回は計算すること。

これ、JavaScript/Ruby/Python だと瞬殺できる。
こいつらには eval があるので、四則演算「+-*/(何もなし)」を適当に埋め込んで eval すればいい。

しかしコンパイル言語でそんなファジーな事は残念ながらできない。
なので、真面目に考えた。

基本的に +-/ を入れた時点で、4桁の結果を出すことが不可能である(厳密には可能だが、組み合わせが存在しない)事を考えると、どこに掛け算の演算子を入れるかの世界になってくる。

演算子を入れれるパターンは、4桁という点で下記 7 パターンしか存在しない。

X XXX (1, 3)
XX XX (2, 2)
XXX X (3, 1)
X X XX (1, 1, 2)
X XX X (1, 2, 1)
XX X X (2, 1, 1)
X X X X (1, 1, 1, 1)

の7通りのみ。

っつー事で、substring で分解して、掛け算走らせればOK

object Main extends App {
  val splitPatterns = Seq(
    Seq(1, 3), Seq(2, 2), Seq(3, 1), 
    Seq(1, 1, 2), Seq(1, 2, 1), Seq(2, 1, 1), 
    Seq(1, 1, 1, 1)
  )

  def split(s: String, p: Seq[Int]): Seq[String] =
    s.substring(0, p.head) +: (if (p.tail.isEmpty) Seq.empty else split(s.substring(p.head), p.tail))

  (1000 to 9999).foreach(v => {
    splitPatterns.foreach(p => {
      val origin = v.toString
      val seq = split(origin, p).map(_.toInt)
      if(seq.product == origin.reverse.toInt) {
        println(s"Found Answer: $v ($seq)")
      }
    })
  })
}

結果

[info] Running Main 
Found Answer: 5931 (List(5, 9, 31))
[success] Total time: 4 s, completed 2016/01/17 19:10:21

最初に掛け算以外考えなくて済むというところに気づくと、上記みたいな解になるが、後から四足演算を計算しようと考えた時に、下記みたいな配列作って、計算で再起すべきかとか考えてしまった…。
何かスッキリ実装できる方法がないのかと思わなくはない。

  val operatorFunc: Seq[Function2[Int, Int, Int]] = Seq(
    (a, b) => a * b, (a, b) => a - b, (a, b) => a / b
  )

split を tail call にするのもまだ慣れていないせいかなかなか上手く行ってない…。
別に深くなるわけでもないので、気にしなかったのだが。

というか、他の言語は「逆ポーランド記法使う」ってそれむしろどうやるのかわからなかった…。

JavaScript(CoffeeScript) で似非 Ctrl + F 作ってみた。

まじかと思ったんだけど、マジだったので驚いてる。

shertan.me

ちょっと待て基本だろ常考
こんなもん、Windows XP 初期の時代からデフォルトだぜ?

Keyboard Shortcuts for Internet Explorer 6

記憶が確かなら、Windows 98 時代からあった気もする。

まぁ、言ってもしょうがない。
仕方ないので、それっぽいものを作ってみた。

github.com

f:id:white-azalea:20151025153314p:plain

いつも通り、Play2.4 なので、Java8 入ってれば動くはず。

続きを読む

Play2.4 でネストしたJsonをバインドする

何で今更かというと、これつかえねーかなと思ったから。

最初は、Forms でのバインドをしようとしたのだけど、早速フォーラムが見つかりました。
キーワードは Play recursive form

https://groups.google.com/forum/#!topic/play-framework/Ya1hPmR2QtY

この中で、「Form はそもそもHttpRequestを前提にしてんだからそんな事すんじゃねぇ」と言われていて、「Play Json 使え」とも誰か言ってた。
そこで、キーワード変更で、「Play recursive json」でググったところ、

ScalaJsonCombinators

を発見。

2.4 になってかなり使いやすくなってきてたので、これでざっくり実装してみた。

import play.api.libs.json._ // JSON library
import play.api.libs.json.Reads._ // Custom validation helpers
import play.api.libs.functional.syntax._ // Combinator syntax


case class Nested(name: String, content:String, friends: Seq[Nested])

implicit lazy val userReads: Reads[Nested] = (
  (__ \ "name").read[String] and
  (__ \ "content").read[String] and
  (__ \ "friends").lazyRead(Reads.seq[Nested](userReads))
)(Nested)

val json = Json.parse("""{"name":"Example", "content":"content", "friends":[{"name":"ChildName", "content":"childContent", "friends":[]}]}""")
val result = json.validate[Nested].asOpt
println(result)

して結果が

Some(Nested(Example,content,List(Nested(ChildName,childContent,List()))))

わーい。
Json で設定ファイルとかできるでw

フォームヘルパーをタグ調整する(Play 2.4.x) with マルチセレクトチェックボックス

Playframework 2.4 において、フィールドコンストラクタの仕様も変わったので、対応したチェックボックスを作ってみる。

Custom Field Constructors

これがなんなのかというと、input とかの helpers の外枠の事。
いつぞや Bootstrap 対応した フォームヘルパーをタグ調整する(Play 2.3.x) - 謎言語使いの徒然 を焼き直す。

Bootstrap インストール

まずは、いろいろやるのが面倒なので、build.sbt に下記を用意する。

libraryDependencies ++= Seq(
  "com.github.aselab" %% "scala-activerecord" % "0.3.1",
  "com.h2database" % "h2" % "1.4.185" % "test",
  "mysql" % "mysql-connector-java" % "5.1.34",

  // この下 3 行を追加
  "org.webjars" %% "webjars-play" % "2.4.0-1",
  "org.webjars" % "jquery" % "1.11.3",
  "org.webjars" % "bootstrap" % "3.3.5",
  evolutions,
  jdbc,
  cache,
  ws,
  specs2 % Test
)

// あとから書くのも面倒なので追加。
TwirlKeys.templateImports += "views.html.commons._"

そしたら、conf/routes に下記を追記

GET     /webjars/*file                    controllers.WebJarAssets.at(file)

app/view/main.scala.html も Bootstrap 取り込み。

@(title: String)(content: Html)

<!DOCTYPE html>

<html lang="en">
    <head>
        <title>@title</title>
        <link rel="stylesheet" media="screen" href="@routes.Assets.versioned("stylesheets/main.css")">
        <link rel="shortcut icon" type="image/png" href="@routes.Assets.versioned("images/favicon.png")">
        <!-- custom for bootstrap -->
        <link rel='stylesheet' href='@routes.WebJarAssets.at(WebJarAssets.locate("css/bootstrap.min.css"))'>
        <script type='text/javascript' src='@routes.WebJarAssets.at(WebJarAssets.locate("jquery.min.js"))'></script>
        <script type='text/javascript' src='@routes.WebJarAssets.at(WebJarAssets.locate("js/bootstrap.min.js"))'></script>
    </head>
    <body>
        <!-- Wrap bootstrap container -->
        <div class="container-fluid">@content</div>
    </body>
</html>

跡はTodoリストでも勝手に書いて。
ちなみに、Bootstrap の入力フォームは、各 input タグに class="form-control" 入れないとデザイン整わないので注意。

カスタムフィールドコンストラクタの作成

と言っても言うほどの事もないか?
app/views/commons/bootstrapFields.scala.html 作って、下記を置く。

@(elements: helper.FieldElements)
<div class="form-group @if(elements.hasErrors){has-error}">
    <label for="@elements.id" class="col-sm-2 control-label">@elements.label</label>
    <div class="col-sm-10">
        @elements.input
    </div>
    @if(!elements.infos.isEmpty){
    <div class="col-sm-10 col-sm-offset-2">
    <span class="help-inline">
      @for(info <- elements.infos){
      <span class="label label-warning">@info</span>
      }
    </span>
    </div>
    }

    @if(elements.hasErrors) {
    <div class="col-sm-12">
        <div class="alert alert-danger">
            <ul>
                @for(msg <- elements.errors){
                <li>@msg</li>
                }
            </ul>
        </div>
    </div>
    }
</div>

そして、パッケージオブジェクトを作成する。

package views.html

package object commons {
  import views.html.helper.FieldConstructor
  implicit val bootStrapFieldConstructor = FieldConstructor(bootstrapFields.f)
}

import 設定は、build.sbt に入れてあるので、後は普通に helpers.input とか使うだけ。

マルチセレクトチェックボックス

デフォルトのヘルパーにいないので、頑張って作ってみた。
え?頑張ってないじゃないかって?実は問題が一つあるんだけど、後で話そう。

@(field: play.api.data.Field, keyValues: Map[String, String])(implicit messages: play.api.i18n.Messages)

@helper.input(field) { (id, name, value, htmlArgs) =>
    @defining(keyValues.toList.zipWithIndex){ results =>
        @for(kv_i <- results){
        <label class="checkbox-inline">
            <input id="@{id}_@{kv_i._2}" name="@{name}[@{kv_i._2}]" type="checkbox"
                   value="@{kv_i._1._2}" @if(value.exists(v => {keyValues.exists(_._2 == v)})){selected}> @kv_i._1._1
        </label>
        }
    }
}

使い方的には、フォームを下記の定義にして

  val checkBoxes = {
    import play.api.data.Forms._
    Form(single("multiSelect" -> list(longNumber)))
  }

テンプレート上でこう

@multipleCheckBox(checkBoxes("multiSelect"), Map("first" -> "1", "second" -> "2", "third" -> "3"))

そして、問題はなんなのかというと、バインドしたフォームを指定してもチェックが付かないという事。
解決しようと 3 時間くらい粘ったけど、結局未解決。

知ってる方は是非 scala - Playframework2.4 の Form で list(number) をバインドした時のフィールドコンストラクタ挙動で、value 値が取得できない。 - スタック・オーバーフロー

追記。

上記リンク先で、無事解決しました。

kawty さんありがとうございます。

Mac で ansible 基礎設定やってみた。

Ansible のことをちまちまやったので、その件メモ。
ネカフェでやってるんだけど、近くのネカフェは速度が遅すぎてこれ以上はちょっと厳しかった。

Install

と言ってもこれだけ。

$ brew install ansible

ちなみにバージョンは

$ ansible --version
ansible 1.9.2
  configured module search path = None

OSS でよくある話だけど、後方互換ってなくなるから…

セットアップ先環境

テストだから Vagrant で環境作った。
自分の環境は 1.7.1 で、バージョンアップしたらコマンド変わってるかもわからん。
あと、VirtualBox4.3.30 とちょっと古め。新しいやつ推奨かな。
環境もかなり適当に Cent6 を A list of base boxes for Vagrant - Vagrantbox.es から拾ってきた。

vagrant box add cent6.6 [https://github.com/2creatives/vagrant-centos/releases/download/v6.5.3/centos65-x86_64-20140116.box]
vagrant init centos6.6

成功したら、Vagrantfile というファイルが出来上がるので、ssh 用の設定を追加。

  # Create a forwarded port mapping which allows access to a specific port
  # within the machine from a port on the host machine. In the example below,
  # accessing "localhost:8080" will access port 80 on the guest machine.
  # config.vm.network "forwarded_port", guest: 80, host: 8080

  # Create a private network, which allows host-only access to the machine
  # using a specific IP.
  # ここの設定を有効化。サンプルでは下記のIP
  config.vm.network "private_network", ip: "192.168.33.10"

最後に vagrant up で起動する。

Ansible hosts 設定

ansible は基本的に専用の hosts ファイルで接続先を設定する。
mac で、Homebrew 経由の場合、/usr/local/etc/ansible/hosts に書いてある。

なんか指定しないと怒られる雰囲気だったので、下記のように指定。

[servers]
192.168.33.10

ここまできたら、まずは vagrant up を実行し、起動後に vagrant ssh-config --host vagrant >> ~/.ssh/configssh 設定を設定ファイルに流し込んでおく。
その後、~/.ssh/config を開くと、下記のような設定ができている。

Host vagrant
  HostName 127.0.0.1
  User vagrant
  Port 2222
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile /Users/hoge/Documents/projects/play_2.4_activerecord/ansibles/.vagrant/machines/default/virtualbox/private_key
  IdentitiesOnly yes
  LogLevel FATAL

重要なのは「IdentityFile」で、これを元に、下記のような定義を作っておく。

Host 192.168.33.*
  IdentityFile /Users/hoge/Documents/projects/play_2.4_activerecord/ansibles/.vagrant/machines/default/virtualbox/private_key
  User vagrant
  PasswordAuthentication no

これで設定完了。
一応 ssh 192.168.33.10 が通るかだけ確認しておくと良い。

続きを読む

LL Ring 行ったメモ

LLRing memo

第一試合 Ruby vs Perl vs PHP vs JS

Python はイベント衝突で不参加

Javascript

ECHMA Script 2015 が発表、ECHMA 6 が名称変更で、正式公開。
言語仕様の追加が行われてる。

JavaScript の仕様が変わるとみんな地獄をみる。しかし、ALT JS なんか結構出てきたんだ。
ES2015 では class, ラムダ式 なんかが入る。
Babel というプロジェクトで、新しい文法を書きつつ、ES5 以下のコードにコンパイルもできる。

モダンな書き方に移行しつつある。
let,val などもそうだが静的型に寄ってきた。
言語仕様として強制が大きい。

ここがすごい

世界で一番動いてるはず。
Acrobat reader にすら乗ってる(結構攻撃に使われるけどね)
地デジでも使われる。

全部 immutable なのはいいんだけどさ。

いまいち

数字の Number が浮動小数点なんだよね。
64bit 整数とか扱えないんだよね。
ES2015 から、整数演算のやりようができる…。

NaN に隠しデータを持たせることがテクニックとしてある。

この辺がいい

コンパイラのバックエンドをされたり、ソースマップ機能があるので、デバッグも容易。
ビット演算をすると、32bit 整数に変換される。
言語仕様を逆手に取るのが普通

PHP

PHP7 がそろそろ出る。
現在 RC2 で 11月に正式版が出る。

PHP7 で速度が倍!基本のデータ構造が変わる。
内部の構造が大きく変わったという話で、PHP コードはあんま変わんない。
C で書いた extention なんかが死ぬ可能性大。

ここ数年で、無名関数とか少しづつ入った。しかし、言語的に強制はしない。
一応 PHP7 から少しづつライブラリが変わる。

ここがすごい

ちょっと困っちゃう…。
追いついたと思うと、他のは先に行ってる…PHP は共和制だからなぁ。
カリスマ主導者ないよね

いまいち

非同期の扱いがないからなぁ。
言語仕様も貧弱だからなぁ。

この辺がいい

Perl

Perl5 が不定期更新だったが、年1度にバージョンアップに変わった。
Perl6 を今年のクリスマスに出す!(ラリー・ウォール氏)

Perl6 は完全に互換性がない。
ともかくたくさんの意味不明なオペレータがあるwww
内積をとるとか、配列のreduceをとるオペレータとか…
今回からクラスがきちんと入ってる。
文字列連結とか色々変わった。「.」から「~」に、「.」はメソッド呼び出しに変更。

基本的にバージョンアップで何も動かなくなる。 余計な言語仕様を削除していく方向も。

ここがすごい

機能が豊富。
パーサーを書く機能まで入ったし、言語仕様自体も改変可能。
Perl6 で書かれたVMで動いてる。

いまいち

Perl6 は遅いし、Perl5 はもう変化ないんだよね。
Perl5 の 100 倍遅い…。
最近 JIT 頑張ってる

この辺がいい

Perl5 でパーサーを自分のコードで乗っ取りができる。
まじ正規表現はダントツだよね〜。

正規表現で普通にパーサー書けるくらいだぜ。

Ruby

Ryby 2.0 が出たので、仕様変更は抑えめ。
クリスマスに 2.3 が出る。
最近は速度改善がメイン。
バイト列の扱いが大きく変わって一部が泣いた。

文字列リテラルが全部 immutable にするぞーとか言い部が騒いでる。

2.0 で古いのがっさーいった。
バイト列を自分で操作するのは止めましょうとかそういう方向。

ここがすごい

Rails があるところ!むしろ Rails のためのランタイムだ!
Bundler もすごいよ?

いまいち

JRuby とか羨ましい、ブラウザで動く JavaScript とかいいなぁ。
ネイティブエクステンションでひどいことになってるけどきれない

この辺がいい

C 拡張ライブラリが書きやすいし、ライブラリが一通り揃ってるからね。
PHP を dis るのに非常に便利?

質疑

JavaScript

問:typescript の機能は、ES6 にいつ入る?
ES7 が検討中で、どこまで入るか不明。
型は、Babel で対応しているし、今後それが普通になる。

JavaScript

問:node って JavaScript と仕様上何か影響がある?
これまで、ブラウザ依存の処理系だったんだけど、nodejs は純粋な言語仕様の世界。
そのおかげで、言語仕様としての論議が発展した感じがある。
ES6 で import とか入ってくる。モジュール化も仕様として入ってきた。

LL で MultiThread はどうなるかね?

  • JavaScipr: nodeJSどおよ?
  • PHP: 1リクエスト1レスポンスでしか考えない。
  • Perl6 : Thread は当たり前、でも fork はないかな?
  • Ruby : JRuby やれや、マルチプロセスでってのは課題。書けるけど、ライブラリへぼいか?GO で拡張ライブラリ書けるから、それでやるんじゃね?

言い残したこと

  • JavaScript : Babel やってよー楽しいぜ?
  • PHP : あんま愛を語ってないことか…早くなるのは楽しみか?
  • Perl6 : リリース直前!触ってて楽しいぜ?
  • Ruby : クリスマスに 2.3 出ます、そろそろまた会議あるので、提案出してください!
続きを読む