F#の無限シーケンスで素数列
Haskellでよくある
primes = [2, 3] ++ filter (\n -> all (\p -> mod n p /= 0) $ takeWhile (\p -> p*p <= n) primes) [5, 7 ..]
的なやつを。
let infty n m = Seq.initInfinite (fun i -> n + i * m) let rec primes = seq { yield! [2; 3] for i in infty 5 2 do if Seq.forall (fun x -> i % x <> 0) (Seq.takeWhile (fun x -> x*x <= i) primes) then yield i }
なんか若干「そういう言語じゃねーから」みたいな感じがしますね。
F#は正格評価の言語なので、C#でいうとIEnumerable<T>とか書く時のごてっとした感じ?
make10
「8 8 9 9」のmake10を四則演算でやれと言う話なので。分かんないので。
アルゴリズムとしては「切符の番号で10を作る」のと同じです。カッコよく言うと分割統治法。コードはあんま美しくないけど。
import Data.List data Expr = C Int | Add Expr Expr | Sub Expr Expr | Mul Expr Expr | Div Expr Expr instance Show Expr where show (C x) = show x show (Add x y) = "(" ++ (show x) ++ "+" ++ (show y) ++ ")" show (Sub x y) = "(" ++ (show x) ++ "-" ++ (show y) ++ ")" show (Mul x y) = "(" ++ (show x) ++ "*" ++ (show y) ++ ")" show (Div x y) = "(" ++ (show x) ++ "/" ++ (show y) ++ ")" instance Eq Expr where (C x) == (C y) = x == y (Add x y) == (Add u v) = (x == u && y == v) || (x == v && y == u) (Sub x y) == (Sub u v) = (x == u && y == v) (Mul x y) == (Mul u v) = (x == u && y == v) || (x == v && y == u) (Div x y) == (Div u v) = (x == u && y == v) _ == _ = False search n a = nub $ concat $ map (\(e,b) -> _search n b (C e)) (picks a) _search :: Int -> [Int] -> Expr -> [Expr] _search n a p = if null a then (if eval p == Just (fromIntegral n) then [p] else []) else concat $ map (\(e,b) -> concat $ map (\q -> _search n b q) (opr (C e) p)) (picks a) where opr x y = [Add x y, Sub x y, Sub y x, Mul x y, Div x y, Div y x] picks a = [pickAt i a | i <- [0..(length a)-1]] pickAt n l = (\(a,b) -> (head b, a ++ tail b)) (splitAt n l) eval :: Expr -> Maybe Rational eval (C x) = Just (fromIntegral x) eval (Add x y) = eval x >>= (\m -> eval y >>= Just.(+ m)) eval (Sub x y) = eval x >>= (\m -> eval y >>= Just.(\n -> subtract n m)) eval (Mul x y) = eval x >>= (\m -> eval y >>= Just.(* m)) eval (Div x y) = eval x >>= (\m -> eval y >>= (\n -> if n == 0 then Nothing else Just (m / n)))
出力結果は
*Main> search 10 [2,3,7,7] [(7+((7+2)/3)),((3+(7*2))-7),(3-(7-(7*2))),(3+((7*2)-7)),(3+((7+7)/2))] *Main> search 10 [8,8,9,9] []
みたいな。要するに最初のは解無しっぽいという話でした。
連分数
みたいなのを連分数と呼ぶ。これだとスペースを取るので
とか(低い位置の+は直前の分数の分母にそれ以降を足す感じ)、分子が皆1の時は+の左の数字を並べてとも書く。
値を求めるには、これをと置くと
よりとなるから
は普通に考えて正なので、の正を取るとこの値は黄金比である。従って
が成り立つ。
実数の連分数展開
ある実数を整数部と小数部に分けられれば、それを連分数に展開できる。
例えば円周率は
という感じでになる(WolframAlphaで計算)。
ここでと近似すると、
という有名な近似分数が現れる。
円周率は二進法なら11.0010010...だし十六進法なら3.243f6a88...だが、連分数展開により現れる数列は円周率の値のみで定まる。
それ故、連分数展開はより数の自然な表現を与えるとも言えよう。
一次分数変換
ところで、定数について
なる函数を一次分数変換とかメビウス(Möbius)変換とか呼ぶ。ではに「潰れる」ので除いておく。
一次分数変換及びを合成してみると
となる訳だが、これは
という行列積の要素と見事に符合している! ので、
という表記を用いると一次分数変換の合成等を行列の計算で扱える。
連分数と行列
さて
を眺めると、これが一次分数変換
により
と表せる事に気付く。
すると、例えばの場合、と置いて
('13/03/06 係数の誤りを訂正)
と対角化する事で
より
を得る。より
なので、再び
を得る。
形態素解析器
C#から直截形態素解析器のライブラリを使いたいよぉ…ふぇぇ…って人に。
茶筌はツン過ぎて辛かっただって何ですかstring[]渡すだけなのに。
using System.Runtime.InteropServices; class MeCab : IDisposable { IntPtr ptr; [DllImport("libmecab.dll", CallingConvention = CallingConvention.Cdecl)] private extern static IntPtr mecab_new2(string arg); [DllImport("libmecab.dll", CallingConvention = CallingConvention.Cdecl)] private extern static IntPtr mecab_sparse_tostr(IntPtr m, string str); [DllImport("libmecab.dll", CallingConvention = CallingConvention.Cdecl)] private extern static void mecab_destroy(IntPtr m); public MeCab() { ptr = mecab_new2(@"-F%m\s%f[6]\s%f[0]\n"); } public string sparse_tostr(string str_in) { return Marshal.PtrToStringAnsi(mecab_sparse_tostr(ptr, str_in)); } public void Dispose() { mecab_destroy(ptr); } } class Chasen { [DllImport("libchasen.dll", CallingConvention = CallingConvention.Cdecl)] extern static int chasen_getopt_argv([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr, SizeParamIndex = 1)]string[] argv, IntPtr file); [DllImport("libchasen.dll", CallingConvention = CallingConvention.Cdecl)] extern static IntPtr chasen_sparse_tostr(string str_in); public Chasen() { string[] argv = { "", "-s", "-F", @"%m %M %H\n", null }; if (chasen_getopt_argv(argv, IntPtr.Zero) == 1) throw new ArgumentException(); } public string sparse_tostr(string str_in) { return Marshal.PtrToStringAnsi(chasen_sparse_tostr(str_in)); } }