4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

F#で言語処理100本ノック 第1章

Posted at

急にF#が書きたくなったのでよく見かける言語処理100本ノックをやりました.
始めて3日ほどなので良い書き方を教えていただきたいです.

問題はこちらです.
http://www.cl.ecei.tohoku.ac.jp/nlp100/

今回は手軽に書いて実行できるF# Interactiveを使いました.

環境

  • .NET Core v3.0.0-preview6
  • F# 4.6

本題

00. 文字列の逆順

let stringReverse (str : string) =
    str
    |> Seq.rev
    |> Seq.map string
    |> String.concat ""

stringReverse "stressed" |> printfn "%s"
// desserts

01. 「パタトクカシーー」

let getOddIndices (str : string) =
    seq {
        for i in 0..str.Length - 1 do
            if i % 2 = 1 then yield str.[i]
    }
    |> Seq.map string
    |> String.concat ""

getOddIndices "パタトクカシーー" |> printfn "%s"
// タクシー

02. 「パトカー」+「タクシー」=「パタトクカシーー」

let stringConcat (str1 : string) (str2 : string) =
    let minLength = Array.min [| str1.Length; str2.Length |]
    seq {
        for i in 0..minLength - 1 -> string str1.[i] + string str2.[i]
    }
    |> Seq.reduce (+)

stringConcat "パトカー" "タクシー" |> printfn "%s"
// パタトクカシーー

03. 円周率

let decomposeAndCount (str : string) = str.Split(' ') |> Seq.map String.length

"Now I need a drink, alcoholic of course, after the heavy lectures involving \
quantum mechanics."
|> decomposeAndCount
|> printfn "%A"
// seq [3; 1; 4; 1; ...]

04. 元素記号

let genElemMap (l : int []) (str : string) =
    let s = str.Split(' ')
    seq {
        for i in 1..s.Length do
            if Seq.contains i l then yield string s.[i - 1].[0]
            else yield s.[i - 1].[0..1]
    }
    |> Seq.zip (seq {
                    for i in 1..s.Length -> i
                })
    |> Map.ofSeq

let singleList = [| 1; 5; 6; 7; 8; 9; 15; 16; 19 |]

"Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also \
Sign Peace Security Clause. Arthur King Can."
|> genElemMap singleList
|> printfn "%A"
// map
//  [(1, "H"); (2, "He"); (3, "Li"); (4, "Be"); (5, "B"); (6, "C"); (7, "N"); (8, "O"); (9, "F"); ...]

05. n-gram

task5.fsx
let makeNGram (n : int) (sequence : seq<_>) =
    let s = Seq.toList sequence
    seq {
        for i in 0..s.Length - n -> s.[i..i + n - 1]
    }

// word n-gram
"I am an NLPer".Split(' ')
|> makeNGram 2
|> printfn "%A"
// string n-gram
"I am an NLPer"
|> makeNGram 2
|> printfn "%A"
// seq [["I"; "am"]; ["am"; "an"]; ["an"; "NLPer"]]
// seq [['I'; ' ']; [' '; 'a']; ['a'; 'm']; ['m'; ' ']; ...]

06. 集合

上で作ったmakeNGramを利用しています.
F# Interactiveでは #load "hoge.fsx"として別ファイルを読み込んで実行できるのですが, 関数のみを読み込んだり, 或いはPythonのif __name__ == '__main__':のように呼び出された時は実行しないオプションみたいなのはあるのでしょうか...

#load "./task5.fsx"

open Microsoft.FSharp.Collections
open Task5

let x =
    "paraparaparadise"
    |> makeNGram 2
    |> set

let y =
    "paragraph"
    |> makeNGram 2
    |> set

let except x y = x - Set.intersect x y

Set.union x y |> printfn "Union: %A"
except x y |> printfn "Except: %A"
Set.intersect x y |> printfn "Intersect: %A"
// Union: set [['a'; 'd']; ['a'; 'g']; ['a'; 'p']; ['a'; 'r']; ['d'; 'i']; ['g'; 'r']; ['i'; 's']; ['p'; 'a']; ['p'; 'h']; ...]
// Except: set [['a'; 'd']; ['d'; 'i']; ['i'; 's']; ['s'; 'e']]
// Intersect: set [['a'; 'p']; ['a'; 'r']; ['p'; 'a']; ['r'; 'a']]

07. テンプレートによる文生成

let generateTemplate x y z = string x + "時の" + string y + "は" + string z

generateTemplate 12 "気温" 22.4 |> printfn "%s"
// 12時の気温は22.4

08. 暗号文

open System

let reverseLowerCase c = 219 - int c |> char

let cipher str =
    str
    |> Seq.map (function
                | c when Char.IsLower c -> reverseLowerCase c
                | c -> c
                >> string)
    |> Seq.reduce (+)

"Hello F#!"
|> cipher
|> printfn "%s"
// Hvool F#!

09. Typoglycemia

open System

let permuteWord str =
    match String.length str with
    | n when n <= 4 -> str
    | n ->
        let rnd = Random()

        let middle =
            str.[1..n - 2]
            |> Seq.sortBy (fun _ -> rnd.Next())
            |> Seq.map string
            |> Seq.reduce (+)
        string str.[0] + middle + string str.[n - 1]

let typoglycemia (str : string) =
    str.Split(' ')
    |> Seq.map permuteWord
    |> String.concat " "

"I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind ."
|> typoglycemia
|> printfn "%s"
// I cun'odlt believe that I cluod altulcay utnaesrdnd what I was ranideg : the paennoehml power of the huamn mind .
4
3
2

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
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?