早稲田大学の校歌の歌詞って水樹奈々さんのどの楽曲の歌詞に似ているの?

この記事は「早稲田大学 Advent Calendar 2016」23日目の記事です。

こんにちは、卒論がヤバいいっちーです。

今回は doc2vec を使って、早稲田大学の校歌が水樹奈々さんのどの楽曲の歌詞に似ているのかを類似度判定していきたいと思います。

なぜ水樹奈々さんなのか

好きだからです。

doc2vec とは

gensim という Python のライブラリのモジュールの1つです。

word2vec を応用して、単語だけではなく文章をベクトル表現化することができます。

word2vec の説明はこちらの記事(人工知能の今と一歩先を発信するメディア)が分かりやすかったです。

方法

こちらのブログ(おいしいとこはすこしだけ 文系出身SE見習いの備忘録。)を参考にさせていただきました。

手順1 : データを作る

※仕様上、タイトルと歌詞の行数が対応している必要があります。

手順2 : コードを書く

Gist にあげておきました。

チェック

1. Synchrogazer に似た歌詞を持つ楽曲を探してみます。

f:id:icchii0618:20161223223354p:plain

Synchrogazer-Aufwachen Form- は Synchrogazer の前奏をアレンジしただけの曲で歌詞は同じです。

歌詞が同じ曲で 類似度 0.999716699123。1 にならないのが気になりますが、ほぼ一致って感じですね。

2. ETERNAL BLAZE に似た歌詞を持つ楽曲を探してみます。

f:id:icchii0618:20161223223600p:plain

BRIGHT_STREAM や innocent_starter など 「魔法少女リリカルなのは」の楽曲が上位に来ています。

良い感じですね。

結果

それでは、都の西北の歌詞と類似度の高い水樹奈々さんの楽曲を探してみましょう。

f:id:icchii0618:20161223224714p:plain

うーん。

一番 類似度の高い曲でも 0.374414801598 ですか。。。

お世辞にも高い類似度とは言い難いですね。悲しい。

まとめ

残念ながら、都の西北と類似度の高い水樹奈々さんの楽曲は見つかりませんでした。

他のアーティストでも試して、都の西北と類似度の高い楽曲を探し出してみたいですね。

系属校、付属校の校歌でも試したいなと思ったのですが、卒論があるので解散です!

Template method パターン

Template method パターン

テンンプレートメソッドパターンは、「似たような流れの処理」をスーパークラスで共通化し、「固有の処理」をサブクラスにまかせることで、「処理のテンプレート」を作成するパターンです。

引用: 「サルでもわかる 逆引きデザインパターン」

案件

とあるアイドル2人がいました。

彼女たちはLIVEでは同じように歌って、踊ります。しかし、人気には差があります。

1人はシングル曲の選抜メンバーに選ばれるほどの人気者(kojiharu)で、握手の列が大混雑。

もう1人は研究生で人気はまだまだ(asapon)。握手のレーンはまばらです。

ある日、2人はLIVEを行う事になりました。

LIVEは歌って、踊って、握手をします。

しかし、2人の人気に差があるので、歌って、踊りつつ、握手の対応だけ変えたいということになりました。

実装

// 2人のスーパークラス
class Idol {
    
    func live() {
        sing()
        dance()
        shakeHand()
    }
    
    func sing() {
        print("歌う");
    }
    
    
    func dance() {
        print("踊る");
    }
    
    func shakeHand() {
        fatalError("オーバーライドしてね")
    }
}

// 握手の対応だけ変えます

//人気な選抜メン
class Senbatsu: Idol {
    override func shakeHand() {
        print("サクッと対応する")
    }
}

// 研究生
class Kenkyusei: Idol {
    override func shakeHand() {
        print("ゆっくりファンの人との会話を楽しむ")
    }
}

// kojiharu
let kojiharu = Senbatsu()
kojiharu.live() //歌う 踊る サクッと対応する

//asapon
let asapon = Kenkyusei()
asapon.live() //歌う 踊る ゆっくりファンの人との会話を楽しむ

結果

処理の構造を変えずに、サブクラスで変えたい処理の内容を再定義することができました。

これは継承を使っていますが、委譲を使って同じことを実現するStrategyパターンもあるようなので、後日実装したいです。

継承を使うとスーパークラスの変更があった場合、サブクラスに影響が出るので、委譲を使ったほうがクラスと実装を疎結合にできそうな機運は高まってますね。

Swift Delegateを理解する

Delegate(委譲)とは

今回はデザパタからは一旦離れて、Delegateを理解します。

何故かと言うと、Adapterパターンの手法の中で「委譲」が出てきて、「そういえばDelegateって理解が曖昧だったかも〜」と思ったからですね。

ずばり、Delegateとは処理を任せるです。

なぜ、Delegateするのか

例えば、func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellメソッド

この関数はUITableVIewDelegateのメソッドTableViewにどんなCellを表示するかを指定するメソッドです。

なんでTableViewがこのメソッドDelegateメソッドにしているかというと表示するCellはControllerに指定してもらったほうが良いからです。

Viewを担うTableViewが何を表示するか決めるようとするとModelと密結合になってしまったり、TabaleVIewの再利用性が低くなってしまいます。

案件

今回はこんなシチュエーションを想定します。

  • Idolクラス(カメラマンにポーズを決めてもらいたい)
  • IdolDelegate(「写真を取るときにポーズを指定してね」と教える)
  • CameraManVIewController(アイドルの写真を撮る)

実装

IdolDelegate

Delegateするためには、処理を委譲してもらうクラスに、なにを実装すればいいかを教えるProtocolを使います。

import Foundation
protocol IdolDelegate: NSObjectProtocol {
    
    func takePicture() -> String?
}

Idol

Delegateしてもらうクラス

Delegateメソッドで返してもらったポーズをとります

import Foundation

class Idol :NSObject{
    
    var delegate: IdolDelegate?

    func pose() {
        if let poseName = self.delegate?.takePicture() {
            print("アイドルは\(poseName)のポーズをした")
        }
    }
}

CameraManViewController

アイドルのDelegateMethodを使ってポーズを決めます

import UIKit

class CameraManViewController: UIViewController, IdolDelegate {
        
    var poseName: String?
    let idol = Idol()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        self.idol.delegate = self
        self.designatePose("ピース")
        
        idol.pose()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    // MARK: - Private Method
    func designatePose(poseName: String) {
        self.poseName = poseName
    }
    
    // MARK: - Delegate Method
    func takePicture() -> String? {
            return self.poseName
    }
}

結果

アイドル「ポーズを指定してね!!」

カメラマン「デュフっ、ピースして欲しいコポォ!!!」

アイドル「はい!(ピース)」

カメラマン「(パシャっ)」

って感じになりました。

Delegateすると幸せになるのか、何をDelegateするのかを考えて実装すると結構楽しいかもしれないですね!

swiftでデザインパターンを実装(Adapterパターン:委譲)

Adapterパターン:委譲

前回に引き続きAdapterパターンを実装していきます。 今回は委譲を使った手法です。 この手法はAdapterクラスがTargetクラスを継承し、メンバ変数にAdapteeクラスを持つことによって実現します。

案件

登場人物

  • Adaptee(MizukiNana)
    • 水樹奈々さん。既存のクラス。今までどおり歌って、演技をしていきたい。
  • Target(Kohaku)
    • 紅白歌合戦に出場するために継承しなければならないクラス。kohaku()が定義されている。
  • Adapter(NanaMizuki)

実装(Playground)

// Adaptee
class MizukiNana {
    func perform() {
        print("演技する")
    }
    func sing() {
        print("歌う")
    }
}

// Target
class Kohaku {
    func kohaku() {
        fatalError("サブクラスで使ってね")
    }
}

// Adapter
class KohakuMizuki: Kohaku {
    private let mizukiNana = MizukiNana()
    
    override func kohaku() {
        mizukiNana.sing() //委譲
    }

    func engi(){
        mizukiNana.perform()
    }
    
}

let nana = KohakuMizuki()
nana.kohaku()
nana.engi()

結果

無事、奈々さんは普段通り演技もできて、紅白に出場するためのクラスを継承することができた。

感想

2回に分けてAdapterパターンを実装してきたわけですが、実装手法の「継承」や「委譲」は、

  • AdapterクラスがAdapteeクラスを継承する
  • AdapterクラスがAdapteeクラスに委譲する という文脈で使われていると気付きました。

次回はAdapterパターンのもう少し実践的な実装(紅白出場歌手を水樹奈々さんではなくラブライブに変更したい場合)やOSSでどのように使われているのかを調査したいと思います。

swiftでデザインパターンを実装(Adapterパターン:継承)

今回はAdapterパターンを実装します

  • Adapterパターンとは?

    既存のクラスに対して修正を加えることなく、インタフェースを変更することができる。

    Wikioediaより引用

Adapterパターンは「継承」と「委譲」の2つの手法で実現できます。

今回は「継承」を用いた手法を実装してみます。

案件

登場人物

  • Adaptee(MizukiNana)
    • 水樹奈々さん。既存のクラス。今までどおり歌って、演技をしていきたい。
  • Target(KohakuProtocol)
    • 紅白歌合戦に出場するために実装しなければならないinterface。kohaku()が定義されている。
  • Adapter(NanaMizuki)

実装(Playground)

// Adaptee
class MizukiNana {
    func perform() {
        print("演技する")
    }
    func sing() {
        print("歌う")
    }
}

// Target
protocol KohakuProtocol {
    func kohaku()
}

// Adapter
class KohakuNana: MizukiNana, KohakuProtocol {
    
    override func perform() {
        print("普段の水樹奈々の演技")
    }
    
    func kohaku() {
        super.sing()
    }
}

let nana = KohakuNana()

nana.perform()
nana.kohaku()

結果

無事、奈々さんは普段通り演技もできて、紅白に出場するためのinterfaceを実装することができた。

感想

今回はkohaku()の中身がsing()をラッピングするだけの形になり、ただ単にメソッド名が変わっただけになった。 collaboWithNishikawa()みたいな他の機能も追加したくなった場合、どう実装していくのか調査していきたいです。

swiftでデザインパターンを実装(Iteratorパターン)

今回はIteratorパターンを実装します

  • Iteratorパターンとは?

  • 登場人物

    • Iterator
      • 走査、データの取り出しを行うためのインタフェース
    • ConcreateIterator
      • Iteratorインタフェースを実装するクラス
    • Aggregate
      • 集合を管理し、Iteratorオブジェクトを生成するためのインタフェース
    • ConcreateAggregate
      • Aggregateインタフェースを実装するクラス
    • Element
      • ConcreateAggregateで管理される要素クラス

参考: (株)オージス総研「事例で学ぶデザインパターン 第2回 Iteratorパターンの適用例を見て学ぼう」

参考: developers.IO 「[iOS 8] Swiftでデザインパターン No.2 Iterator」

Element

class Song {
    private var name: String
    
    init (name: String) {
        self.name = name
    }
}

Aggreate

class Aggregate {
    func iterator() -> Iterator {
        fatalError("サブクラスで使ってね")
    }
}

Iterator

class Iterator {
    func next() -> AnyObject {
        fatalError("サブクラスで使ってね")
    }
    
    func hasNext() -> Bool{
        fatalError("サブクラスで使ってね")
    }
}

ConcreateIterator

class SongIterator: Iterator {
    private var songAggregate: SongAggregate
    private var index = 0
    
    init(songAgregate: SongAggregate) {
        self.songAggregate = songAgregate
    }
    
    override func next() -> AnyObject {
        return songAggregate.songAtIndex(index++)
    }
    
    override func hasNext() -> Bool {
        return songAggregate.countOfSongs() > index
    }
    
}

ConcreateAggregate

class SongAggregate: Aggregate {
    private var songs = [Song]()
    
    override func iterator() -> Iterator {
        return SongIterator(songAgregate: self)
    }
    
    func addSong(song: Song) {
        songs.append(song)
    }
    
    func countOfSongs() -> Int {
        return songs.count
    }
    
    func songAtIndex(index: Int) -> Song {
        return songs[index]
    }
}

使い方

var songAggregate = SongAggregate()

songAggregate.addSong(Song(name: "POP MASTER"))
songAggregate.addSong(Song(name: "ETERNAL BLAZE"))
songAggregate.addSong(Song(name: "DISCOTIQUE"))

let songIterator = songAggregate.iterator()


while songIterator.hasNext() {
    let song = songIterator.next() as! Song
    print(song.name)
}

swift固有の書き方

  • SequenceTypeとGeneratorTypeを用いた実装方法があるみたいなので今度実装してみたいと思います。

参考: kanetaiの二次記憶装置

感想

Iteratorを挟むことによって、Controller側がElement(Model)のことを気にせずにアクセスできています。 Modelに変更があった場合、Contorollerへの影響が少なくて済むのではないでしょうか Iteratorパターンが使われているOSSも探してみたいと思います。

swiftでデザインパターンを実装

デザインパターンって何

  • デザインパターンとは「設計に関する先人たちの知恵」です。
  • デザインパターンを学習、習得することで、再利用性の高い設計やチーム内での共通言語として使うことができ、開発が捗ります。

今回はシングルトンを実装、シングルトンとは?

  • 今回はシングルトンパターンを実装していきます。
  • シングルトンとはアプリ内でクラスのインスタンスを1つしか生成できないようにし、そのインスタンスに対してアプリのどこからでも参照できるようにする設計手法です。

シングルトンのコード

  • シングルトンが管理するModel
class Song {
 var name: String
 var time: Int

 init(name: String, time: Int) {
  self.name = name
  self.time = time
 }
}
  • シングルトンのMizukiNanaクラスの実装

class SingletonMizukiNana {
    
    static let sharedInstance = SingletonMizukiNana()
    var songs: [Song]
    
    private init() {
        songs = []
    }
}
  • 使い方
let nana = SingletonMizukiNana.sharedInstance

nana.songs.append(Song(name: "POP MASTER", time: 240))
  • モダンな書き方
class Singleton {
 static let sharedInstance: Singleton = {
  let instance = Singleton()
  // ここで初期値セットアップのコードを書きます。
  return instance
 }()

}