webネタ

Webエンジニアが業務に関係することをメモしていく

Scalaで最短経路問題

アルゴリズムの勉強中...

  • 深さ優先探索幅優先探索
  • ベルマンフォード法 (閉炉を見つけれる)
  • ダイクストラ(よりコストの低い道を進む)
  • A* (よりゴールに近いほうから進む)
  • ワーシャルフロイド法 (全ペアの最短経路を見つける)

深さ優先探索幅優先探索

ベルマンフォード法

ダイクストラ

A* (えーすたー)

ワーシャルフロイド法

ワーシャルフロイド法は、重み付き有向グラフの全ペアの最短経路問題を求めるアルゴリズム

とある問題に気づいたけどそのうち直そう...。

gitで重いリポジトリをcloneするとき

git clone http://example.com/fuga.git

remote: Counting objects: 3203, done.
remote: warning: suboptimal pack - out of memory
remote: fatal: Out of memory, malloc failed
error: git upload-pack: git-pack-objects died with error.
fatal: git upload-pack: aborting due to possible repository corruption on the remote side.
remote: aborting due to possible repository corruption on the remote side.
fatal: protocol error: bad pack header

エラーになるので少しずつ落とす

git clone --depth 1 http://example.com/fuga.git
git fetch --depth 10
git fetch --depth 100 # 値は調整しつつ
git fetch --unshallow # 最後に全部落とす このオプションは最新のgitでないとない

Ajaxでクロスドメイン通信

Ajaxでクロスドメイン通信について調べたのでまとめ。

シンプルな例

client

var xhr = new XMLHttpRequest();
var url = 'http://example.com/xhr-response.php';
xhr.open('GET', url, true);
xhr.send();

server

<?php
header('Access-Control-Allow-Origin: *');
echo "ok";

Access-Control-Allow-Origin: *を付けてレスポンスすると、エラーにならず結果を受け取れる。

クッキー付きの送信

client

var xhr = new XMLHttpRequest();
var url = 'http://example.com/xhr-response.php';
xhr.withCredentials = true; 
xhr.open('GET', url, true);
xhr.send();

xhr.withCredentials = true;をつけることで、クッキー付きで送信される。

sever

<?php
header('Access-Control-Allow-Origin: ' . getenv('HTTP_ORIGIN'));
header('Access-Control-Allow-Credentials: true');

echo "ok";

Access-Control-Allow-Credentials: trueをつけ、

かつAccess-Control-Allow-OriginにはHTTPヘッダーのOriginをつける。

このOriginは、クロスドメインの通信の場合自動的に付与されて送られてくる。

対応ブラウザ

IE以外はok。

IE8,9はXMLHttpRequestではなく、XDomainRequest を使うことで対応可能。

IE6,7はいつも通り動きません。

GET以外

POSTリクエストやPUTリクエストなどは、あらかじめOPTIONSリクエストで許可をもらわないといけない。

client

OPTIONS
Origin: http://example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER

server

Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER
Access-Control-Max-Age: 3600

再度、あらためてPOSTを送る。

参考

Part2 : ErlangVMで動くRuby風の関数型言語Elixir(エリクサー) : 基礎編

Part1はこちら

インターフェース

defprotocolでinterfaceのようなものが定義できる

defprotocol Checker do
  def ok?(data)
end

defimplでinterfaceの実装を定義できる

defimpl Checker, for: List do
  def ok?([]), do: "ng"
  def ok?([h | _]) when h == 1, do: "ok"
  def ok?([2 | _]), do: "ok2"
end
defimpl Checker, for: Number do
  def ok?(1), do: "ok"
  def ok?(_), do: "ng"
end
Checker.ok?([1,2,3]) # ok
Checker.ok?([2,3,4]) # ok2
Checker.ok?([3,4,5]) # ng
Checker.ok?(1) # ok
Checker.ok?(2) # ng

関数をキャプチャ

定義済みの関数を、別の関数に渡したいとき等に。

f = &Integer.odd?/1
Enum.map([1,2,3,4,5], f) # [true, false, true, false, true]

Erlangの関数をコール

:(コロン)をつけるとErlangのモジュールが呼べる。

:timer.sleep 1000 # 1秒sleep

プロセス生成

spawnで生成。receiveで外から値を受け取れる。

defmodule Process do
  def from do
    receive do
      i -> 
        IO.inspect i * i
    after
      100 ->
        IO.inspect "timeout.."
    end
  end
end
p = spawn Process, :from, []
p <- 2 # プロセスに値を送るとreceiveで受け取れる。

Stream

scalaにもある無限のリストを作るコレクション

IO.inspect Stream.map(1..1000000000, &(&1 * &1)) |> Enum.take(5) # [1, 4, 9, 16, 25]

File

ファイルをread。

case File.read("/etc/hosts") do
  { :ok, body } -> IO.inspect body
  { :error, reason } -> IO.inspect reason
end

!を付けると例外を飛ばすようになる。rubyっぽい...

body = File.read!("/etc/hosts")
IO.inspect body

例外をcatchしてみる

try do
  File.read! "/etc/hogeeeee"
rescue
  File.Error -> IO.inspect "catche!"
end

様々なファイル操作の関数がある

File.rm_rf! "/tmp/fuga"
File.mkdir! "/tmp/fuga"
File.write! "/tmp/fuga/elixir.txt", "elixir!"
IO.puts File.read! "/tmp/fuga/elixir.txt"
IO.inspect File.ls! "/tmp/fuga"
File.rm! "/tmp/fuga/elixir.txt"

pmap

Elixir関係ないけど、便利なErlangの関数だったので。

1ループを1プロセスで実行するmap。ものすごい並列感...

defmodule Par do
  def exec(i) do
    :timer.sleep 1000
    i * i
  end
end
:rpc.pmap {Par, :exec}, [], [1,2,3,4,5,6,7,8,9] # 1sかかる
Enum.map [1,2,3,4,5,6,7,8,9], &Par.exec/1 # 9sかかる

公式サイトを翻訳したほうが早いんじゃないかと思えてきた...

ErlangVMで動くRuby風の関数型言語Elixir(エリクサー) : 基礎編

Erlangの奇妙な文法を覚えることなく、Erlangの機能が使えるエリクサー。

Ruby風の文法なのでRubyistには馴染みの関数などが使えるが、以下のことを頭にいれておくべし。

楽天Technologyカンファレンスでセッションがあったり、Erlangを簡単に書ける言語としてこれから普及していくのではないでしょうか!

インストール

brew install elixir

iex

iex

irbのようにiexで、試し書きが簡単にできます。(iexはerlのラッパー)

基本文法

四則演算

1 + 1    # 2
1 - 1    # 0
1 * 1    # 1
1 / 1    # 1.0
div 1, 1 # 1
rem 2, 4 # 2
# 2 % 4 not work

"a"             # string
1               # integer
1.2             # float
:id             # atom
[1,2,3]         # list
{1,2,3}         # tuple
[a: "a", b: 2]  # keyword

文字列

s = "str"
"[" <> s <> "]"          # [str]
"[#{s}]"                 # [str]
String.reverse "str"     # rts
String.slice "str", 1, 2 # tr
String.first "str"       # f
String.last "str"        # r
String.at "str", 1       # t
String.graphemes("str") # ["s", "t", "r"]

変数

v = "v"
# v = "vv" 不変なので代入不可

デバッグ

IO.inspect [1,2,3]
IO.puts "foo"  # 文字列のみ(改行コード付き)
IO.write "foo" # 文字列のみ(改行コードなし) 

コレクション

[head | tail] = [1,2,3]
head # 1
tail # [2,3

Enum.map [1,2,3], fn(i) -> i * i end   # [1,4,9]
Enum.map [1,2,3], &(&1 * &1)           # [1,4,9]

Enum.filter [1,2,3], &(Integer.odd?(&1)) # [1,3]
Enum.find [1,2,3], &(&1 == 1)    # 1
Enum.all? [1,3], &(Integer.odd?(&1))     # true  [scala = forall]
Enum.any? [1,3], &(Integer.odd?(&1))     # true  [scala = exists]
Enum.at [1,2,3], 1               # 2
Enum.max [1,2,3]                 # 3
Enum.join [1,2,3], "-"           # 1-2-3

f = fn
  i when rem(i, 2) == 0 -> [i]
  _ -> []
end
Enum.flat_map(1..10, f)              # [2, 4, 6, 8, 10]
Enum.map(1..10, f) |> List.flatten # [2, 4, 6, 8, 10]

パイプ

[1,2,3,4,5] |> Enum.filter(&(rem(&1,2) != 0)) |> Enum.map(&(&1 * &1)) # [1,9,25]

"str" |> String.graphemes |> Enum.map(&("-#{&1}-")) |> Enum.join # "-s--t--r-"

気軽に繋げて書くことができる。

条件

if

if true do
  "ok" # ok
else
  "ng"
end

# 簡易版
if true, do: "ok", else: "ng" # ok
if true, do: 1           # 1
if false, do: 1, else: 2 # 2

unless

unless false, do: "unless"

case

case 1 do
  1 -> p "ok" # ok
  _ -> p "ng"
end

case [1,2,3] do
  [1 | _] -> p "ok" # ok
  _ -> p "ng"
end

case {1,2,3} do
  {1,2,3} -> p "ok" # ok
  _ -> p "ng"
end

case [1,2,3] do
  [_ | [2,3]] -> p "ok"
  _ -> p "ng"
end

case [1] do
  [h | []] -> p h # 1
  _ -> p "ng"
end

a = 1
case true do
  ^a -> p "not match"
  _ -> p "match"
end

関数

基本

defmodule Math do
  def sum(a, b) do
    a + b
  end
end
Math.sum(1,2) # 3 defmoduleの中でないとdefは定義できない
Math.sum 1,2 # rubyのように()省略可

# ネスト
defmodule Math do
  defmodule Foo do
    def sum(a, b) do
      a + b
    end
  end
end
Math.Foo.sum 1,2 # 3

# 短く
defmodule Math do
  def sum(a, b), do: a + b
end
Math.sum 1, 2 # 3

匿名関数

f = fn(x, y) -> x + y end
f.(1,2) # 3

# 短く
f = &(&1 + &2)
f.(1,2) # 3

高階関数

ff = fn(f) -> f.(2,3) + f.(4,5) end
ff.(f) # 14

ガード

f2 = fn
  x when x < 1 -> "ng"
  _ -> "ok"
end
f2.(1) # ok

サンプル

# フィボナッチ
defmodule Fib do
  def f(l), do: f(l,1,1)
  def f(l, a, b) do
    if l > b, do: [b] ++ f(l, b, a + b), else: []
  end
end
Fib.f(30) # [1, 2, 3, 5, 8, 13, 21]
# リバース
defmodule Reverse do
  def r([head | tail]), do: r(tail) ++ [head]
  def r([]), do: []
end
Reverse.r [1,2,3]    # [3,2,1]
Enum.reverse [1,2,3] # [3,2,1]

クラスのようなもの

defrecord Person, name: "", age: 0 do
  def say(mine) do
    "I am " <> mine.name <> "."
  end
end
tanaka = Person.new(name: "tanaka", age: 20)
tanaka.say # I am tanaka.

AS3で動画を扱ったり、JSと連携したり

ActionScript3で動画に関するメモ

動画再生

動画を再生するには以下のいずれか。

  1. FLVPlaybackを使う。
  2. flexのspark.components.VideoPlayerを使う。
  3. Videoクラスなどを使い自前で作る。

1がスタンダード。

FLVPlayback

使い方

ウインドウ -> コンポーネント -> Videoを開く -> FLVPlaybackをステージに。

import fl.video.FLVPlayback;

var player = new FLVPlayback();
addChild(player);
player.source = "hoge.mp4";
player.autoPlay = true;

対応してる種類

デフォルトで用意されてるコンポーネント。flvと名前が付いてるが、mp4など色々いける。

http://help.adobe.com/ja_JP/ActionScript/3.0_UsingComponentsAS3/WS5b3ccc516d4fbf351e63e3d118a9c65b32-7fe9.html

Flash Player 9 Update 3 では、業界標準H.264 エンコーディングを利用する高解像度の MPEG-4 ビデオ形式がサポートされ、FLVPlayback コンポーネントの機能が向上しています。サポートされる形式は、MP4、M4A、MOV、MP4V、3GP および 3G2 です。

スキン

Macだと以下にスキンがある。同じ位置にflaもあるので自由にカスタマイズできる。

"/Applications/Adobe Flash CC/Adobe Flash CC.app/Contents/Common/Configuration/FLVPlayback Skins/MinimaSilverPlayBackSeekCounterVolMute.swf"

動画に字幕を付ける

字幕を付けるにはFLVPlaybackCaptioningが使える。

var captions = new FLVPlaybackCaptioning();
captions.autoLayout = false;
captions.flvPlayback = player_mc.player;
captions.source = "sample.xml";

残念なことxmlファイルを読み込んでしか使えない...。

xmlオブジェクトを読めるようにしてくれれば...。

JSとFlashの連携

連携に必要な設定

1. allowScriptAccessをalwaysに設定する必要がある

<object ... >
<param name="allowScriptAccess" value="always">
</object>

2. file://だとダメ

http://localhost/ とかでないと、動きません。

3. flashとjsが別ドメインの場合

flash.system.Security.allowDomain('example.com')

js -> flash

html

<object id="hoge" ...>

js

var swf = document.hoge || window.hoge;
swf.to_flash();

flash

if (ExternalInterface.available) {
  ExternalInterface.addCallback('to_flash', function() { test.text = 'receive it!'; });
}