読者です 読者をやめる 読者になる 読者になる

00,01,02 : 言語処理100本ノックでPythonのお勉強

言語処理100本ノックというPython自然言語処理を学ぶのに最適なウェブページがあるので、やってみる。こちらが2015年版の問題週。今回は00から03までやってみます。

環境

macOS Sierra 10.12.2 python3.5.2 (pyenv)

00. 文字列の逆順

"stressed"という文字列を逆順にする。 Pythonでは、スライスという機能があり、この機能を使うと簡単に逆に出来る。 スライス機能はコロンで区切って、3つの値を入力して処理させることができる。 例えば、"helloworld"[0:-1:2]と書くと、0文字目から末尾の1つ手前まで一文字おきにを切り取ることが出来て、"hllol"を取り出すことが出来る。-1は逆順を表す。

# knock1_00.py
l = "stressed"
re_l = l[::-1]
print(re_l)

01.パタトクカシーー

「パタトクカシーー」という文字列の1,3,5,7文字目を取り出して、連結し文字列にする。 これもスライス機能を使う。

# knock_01.py
l = "パタトクカシーー"
l2 = l[::2]
print(l2)

# 2,4,6,8文字目を取り出す場合はこうする。
l3 = l[1::2]
print(l3)

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

「パトカー」と「タクシー」という文字列を先頭から交互に連結して、「パタトクカシーー」という文字列をつくる。

# knock_03.py
l = []
l2 = 'パトカー'
l3 = 'タクシー'
for i in range(len(l2)):
    l.append(l2[i])
    l.append(l3[i])
l = ''.join(l)

# 他の方法1 - zip関数を使う。こっちの方が随分簡潔。
result = ''
for (a, b) in zip(l2, l3):
    result  += a + b
print(result)  
    

深センを見てきた - 2016年8月 -

2016年8/15日に行われたニコ技深セン観察会に参加してきました。 僕はファブラボ鎌倉というモノづくり施設の運営をしていて、 今回そのファブラボの国際会議であるFAB12にも参加していたため、 1週間ほど深センに滞在していましたが、スケジュールの関係でこちらのツアーは1日だけの参加となりました。 深センの情報は、本ツアーの主催者であるチームラボ高須さんが書いた、ツアーの参加者が書いたブログを見て事前に予習しておくといいです。

f:id:mio_kt:20160823064725j:plain

1. 深センに滞在する

SIMカード

深センに滞在する際に快適に過ごすために必要なことを少し書いておきます。 まずインターネットですが、アマゾンで香港用のSIMカードを買っておきましょう。 僕は買い忘れて深センに着いてから、回展中心駅のシェラトンホテルで現地のSIMを買って、 iPhone6S(SIMフリー)に入れてVPNを通して使い始めたのですが、VPN(HMAとTunnelBear)が不安定なのか更新中のグルグルマーク が消えず、ページを読み込まなくなることが多々ありました。ちなみに深センのSIMでは、普通に接続すると、 Facebook, Twitter, Line, Googleあたりが見れません。日本で買い忘れた方は仕方ないので買いましょう。

f:id:mio_kt:20160823064730j:plain [シェラトンで変えるSIMカード]

アプリケーション

知らない土地でGoogleMapが使えないのは痛いです。Appleの地図は使えますが、位置が不正確で全く使えません。 仕方がないので、連絡はWeChat、地図はBaiduMapを使いました。WeChatは現地の人とも連絡取れるし、 内部の連絡もこちらを使うので入れるのは必須です。BaiduMapは中国語しか選べませんが、地図は正確で使いやすいです。

ホテル

AgodaでColour Inn Shenzhen というホテルを予約して泊まりました。こちら安くて比較的綺麗なのでおすすめです。一泊3,500円くらい。 超大きい家電街、華強北までも電車、徒歩含めて20分くらいでいけます。

電車

電車は行き先を指定してコイン(RFID入)を購入し、Suicaみたいにタッチして入場して、出るときはタッチしてコインを戻します。 またSuicaのようなチャージできるカードも購入できるので、今後も深センに行くなら持っておくと便利です。 毎回コインを買うのに並ぶのが面倒くさいので。カードは100元で購入し、20元がデポジット、80元が使用できます。 一度に乗るのに必要な料金は2.7元くらいです。

f:id:mio_kt:20160823064733j:plain [中国版Suica]

2. Seeed Studio 組立工場

基板を少量ロットで生産してくれるサービス、FusionPCBで有名なSeeed Studioの組立工場を見学に行きました。

f:id:mio_kt:20160823064652j:plain [Seeed Studio 組立工場]

とても綺麗な工場で、工員の作業環境も良く、快適に仕事ができそうです。Seeedのウェブサイトを見ればわかりますが、現在SeeedはPCBの製造だけでなく、部品実装からレーザー加工、3Dプリントのようなサービスも受けてくれるようで、少量生産で作りたいMakerにとって無くてはならないインフラとなってきています。 僕はPCB製造しか頼んだことないですが、他のサービスも試してみようと思いました。

f:id:mio_kt:20160823064701j:plain [レーザー加工機]

f:id:mio_kt:20160823064657j:plain [通電試験用の治具]

f:id:mio_kt:20160823064705j:plain [デスクワーカー達の作業風景]

一通り、工場の中を案内してくれた後、Seeedが行なっているビジネスについてプレゼンをしてくれました。 Seeedは世界のMakerの人たちに向けてサービスを行なっていて、現在は国内に関してはあまり見てないようです。 依頼してくるMakerの数はアメリカ、ヨーロッパが中心ですが、日本も増えてきていて、今は20%は日本からの依頼とのこと。 世界中のMakerに向けてサービスを行なっているので、英語が堪能なスタッフがいることは当然で、カスタマサポートなどにも 力を入れていて、他の中国の工場とは一線を画してると思います。受けた印象としては、SaasやPaasといったソフトウェアのクラウドサービス のハードウェア板という感じがして、細かい指示を出さなくても、よしなにハードウェアを作ってくれる工場のクラウドサービスを目指している気がしました。

3. PCB工場

SeeedにPCBを発注すると、SeeedがPCBをすべてつくるわけではなく、さまざまな工場と連携して製造しています。 こちらはSeeedからの発注を受けているPCB工場で、日本の企業から直接発注を受けることもあるそうです。 僕はPCB工場を見学するの初めてなので、比較はできませんが、こちらの工場では手作業の部分が数多くあり、昔ながらの工場という印象を受けました。

f:id:mio_kt:20160823064709j:plain [基板のチェック]

f:id:mio_kt:20160823064714j:plain [通電チェック風景]

f:id:mio_kt:20160823064718j:plain [基板を切り抜く作業風景]

4. ロボットベンチャー

PCB工場をあとにして僕らはNXROBOというロボットをつくっているスタートアップを見に行きました。 NXROBOは家庭用のロボットを作っていて、デザインは部屋に溶け込むようにソファとかと似た布で覆われています。 現在Kickstarterのキャンペーンを行なっています。かなりお手頃な価格で手に入るので気になりますね。 一家に一台ロボットが来る日は近いなと感じました。ただ結構大きいので、現状では日本の狭いマンションとかには 厳しいかな。もう少し小型化したバージョンもぜひ開発してほしい。

5. おわりに

深セン面白い!現在深センは、日本の高度経済成長期のようなバブル(体験してませんが)の雰囲気もあり、 玉石混交の面白ガジェットが街に溢れかえり、人々はいきいきとしています。 深センで知り合ったArduinoなどのマイコンボードを販売していいる会社の社長は、18才で起業して、まだ26才の若さです。 彼はマイコンボードなどを売っていますが、ファブラボやMakerについては、あまり知らないようで、興味津々にいろいろと聞いてきます。 また、Seeedのような国際的なインフラになりつつある会社があり、Haxのようなハードウェアスタートアップを支援するエコシステムも存在します。 この生態系の中に日本のMakerも入っていくことで、面白い化学反応が起こるように思います。一度見ただけでは、わからない部分もあるので、 10月に行われるMakerFaire Shenzhenにも参加してみようと思います。

SwiftでCorebluetoothを使ってKonashiのLEDをチカチカさせる

iPhone6Sを買ったしSwiftでいろいろと遊んでます。
今回は以前買ったKonashi v2をKonashiSDKを使わないでCorebluetoothでLチカさせてみました。 こちらの本"iOSxBLE Core Bluetoothプログラミング"で学びながら作ってます。

開発環境
開発環境 : XCode7.2
使用機器 : iPhone6S, iOS9.2
Konashi : Konashi v2(koshian)

アプリケーションが実行する処理の流れ

  1. アプリに配置したスキャンボタンを押して、周辺のペリフェラル(Konashiとか)を検索。
  2. ペリフェラルを発見したら接続。
  3. ペリフェラルと接続できたら、ペリフェラルが提供するサービスを検索。
  4. 提供しているサービスを見つけたら、サービスに含まれるキャラクタリスティックを検索。
  5. 目的のキャラクタリスティックを発見したら、そのキャラクタリスティックをプロパティに保持しておく。
  6. アプリに配置したスイッチボタンでキャラクタリスティックの値を書き換える。
  7. キャラクタリスティックの値が変更されるとLEDが点灯/消灯します。
//
//  ViewController.swift
//  Corebluetooth LED Blinking Example
//
//  Created by miokato on 1/20/16.
//  Copyright © 2016 miok. All rights reserved.
//

import UIKit
import CoreBluetooth

class ViewController: UIViewController, CBCentralManagerDelegate, CBPeripheralDelegate {

    var isScanning: Bool = false
    var isBlink: Bool = false
    var centralManager: CBCentralManager!
    var peripheral: CBPeripheral!
    var settingCharacteristic: CBCharacteristic!
    var outputCharacteristic: CBCharacteristic!
        
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.centralManager = CBCentralManager(delegate: self, queue: nil)
    }
    
    // ===============================================================================
    // MARK: Actions
    
    // スキャン
    @IBAction func scanBtnTapped(sender: UIButton) {
        if !isScanning {
            isScanning = true
            self.centralManager.scanForPeripheralsWithServices(nil, options: nil)
            sender.setTitle("Stop Scan", forState: UIControlState.Normal)
        }
        else {
            isScanning = false
            self.centralManager.stopScan()
            sender.setTitle("Start Scan", forState: UIControlState.Normal)
        }
    }

    
    // LEDスイッチ
    @IBAction func writeValue(sender: UIButton) {
        if self.settingCharacteristic == nil || self.outputCharacteristic == nil {
            print("konashi is not ready!")
            return
        }
        var value: CUnsignedChar
        
        if !isBlink {
            isBlink = true
            sender.setTitle("Turn Off", forState: UIControlState.Normal)
            // LED2を光らせる
            value = 0x01 << 1
            
        }
        else {
            isBlink = false
            sender.setTitle("Turn On", forState: UIControlState.Normal)
            // LED2を消す
            value = 0x00 << 1
        }
        let data: NSData = NSData(bytes: &value, length: 1)
        
        
        self.peripheral.writeValue(data,
            forCharacteristic: self.settingCharacteristic,
            type: CBCharacteristicWriteType.WithoutResponse)
        
        self.peripheral.writeValue(data,
            forCharacteristic: self.outputCharacteristic,
            type: CBCharacteristicWriteType.WithoutResponse)
    }
    
    // ===============================================================================
    // MARK: CBCentral Manager Delegate
    
    // セントラルマネージャの状態変化があると呼ばれる
    func centralManagerDidUpdateState(central: CBCentralManager) {
        print("state: \(central.state)")
    }
    
    // ペリフェラルが見つかると呼ばれる
    func centralManager(central: CBCentralManager,
        didDiscoverPeripheral peripheral: CBPeripheral,
        advertisementData: [String : AnyObject],
        RSSI: NSNumber)
    {
        print("発見したBLEデバイス: \(peripheral)\n")
        
        if peripheral.name?.hasPrefix("konashi") == true {
            self.peripheral = peripheral
            // 接続開始
            self.centralManager.connectPeripheral(self.peripheral, options: nil)
        }

    }
    
    // ペリフェラルに接続したら呼ばれる
    func centralManager(central: CBCentralManager,
        didConnectPeripheral peripheral: CBPeripheral)
    {
        print("接続成功")
        
        // サービス検索結果を受け取るデリゲートをセット
        peripheral.delegate = self
        // サービス検索開始
        peripheral.discoverServices(nil)
    }
    
    // ペリフェラルへの接続が失敗すると呼ばれる
    func centralManager(central: CBCentralManager,
        didFailToConnectPeripheral peripheral: CBPeripheral,
        error: NSError?)
    {
        print("接続失敗...")
    }
    
    // ===============================================================================
    // MARK: CBPeripheralDelegate
    
    // サービス発見したら呼ばれる
    func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?) {

        if error != nil {
            print("エラー: \(error)")
            return
        }
        
        if peripheral.services?.count <= 0 {
            print("no services")
            return
        }
        
        let services = peripheral.services!
        print("\(services.count)個のサービスを発見しました。\n\(services)\n")
        
        for service in services {
            peripheral.discoverCharacteristics(nil , forService: service)
        }

    }
    
    // キャラクタリスティックを取得したら呼ばれる
    func peripheral(peripheral: CBPeripheral,
        didDiscoverCharacteristicsForService service: CBService,
        error: NSError?)
    {
        if error != nil {
            print("エラー: \(error)")
            return
        }
        
        if service.characteristics?.count <= 0 {
            print("no characteristics")
            return
        }
        
        let characteristics = service.characteristics!
        print("\(characteristics.count)個のキャラクタリスティックを発見しました。\n\(characteristics)\n")
        
        for characteristic in characteristics {

            if characteristic.UUID.isEqual(CBUUID(string: "229B3000-03FB-40DA-98A7-B0DEF65C2D4B")) {
                self.settingCharacteristic = characteristic
                print("KONASHI_PIO_SETTING_UUID を発見")
            } else if characteristic.UUID.isEqual(CBUUID(string: "229B3002-03FB-40DA-98A7-B0DEF65C2D4B")) {
                self.outputCharacteristic = characteristic
                print("KONASHI_PIO_OUTPUT_UUID を発見")
            }
        }
    }
    
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

XCodeのAuto Layoutの機能が動画をみたらよくわかった

XCodeのAuto Layoutがわからないなぁと思って調べてました。3Dモデリングソフトの操作方法などは、動画で見ると分かりやすいので、XCodeもStoryBoardの部分は、動画の方が分かりやすいかなと思って、Youtubeこちらの動画を見ました。

めっちゃ分かりやすいです!動画の力すごい。GUIを操作する系のものは、動画で学ぶのがいい気がします。本で読んでもよくわからないなぁと思っていたことが、すぅーっと頭に入ってきます。この動画は、StoryBoardを使ってiPhoneアプリを作る方法を教えている動画の6回目なのですが、他の動画も分かりやすいです。

開発環境 : XCode7.2

Swiftで加速度センサの値を表示する

iPhone6sの加速度センサで取得した値をラベルに表示するサンプルです。ほぼこちらのコードそのままです。こちらのサイトは機能ごとにシンプルなコードを紹介していて、Swiftを用いたiOSアプリ制作を勉強するのに最適です。今回はSwiftの仕様の変更があったようで、こちらを参考に若干修正しています。

動作環境 : iPhone6s iOS9.2
開発環境 : XCode7.2

//
//  ViewController.swift
//  AccelerometerSample
//


import UIKit
import CoreMotion

class ViewController: UIViewController {
    
    var myMotionManager: CMMotionManager!

    // ストーリーボードを使ってプロパティを作成
    @IBOutlet weak var xValue: UILabel!
    @IBOutlet weak var yValue: UILabel!
    @IBOutlet weak var zValue: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        myMotionManager = CMMotionManager()
        
        // 加速度計の更新周期を設定
        myMotionManager.accelerometerUpdateInterval = 0.1
        
        // 加速度取得
        // Handlerに渡す引数はオプショナルとする。
        myMotionManager.startAccelerometerUpdatesToQueue(NSOperationQueue.mainQueue(), withHandler: {(accelerometerData:CMAccelerometerData?, error:NSError?) -> Void in
            // オプショナルとして渡されたデータは!でアンラップする
            self.xValue.text = "x=\(accelerometerData!.acceleration.x)"
            self.yValue.text = "y=\(accelerometerData!.acceleration.y)"
            self.zValue.text = "z=\(accelerometerData!.acceleration.z)"
        })
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

Swiftでスライダーサンプル

Swiftでスライダーを動かすと値が変わるだけのアプリを作ってみる。

実行環境 : iOS9.2
開発環境 : XCode7.2

//
//  ViewController.swift
//  Slider
//


import UIKit

class ViewController: UIViewController {
    
    
    var myLabel: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // 背景を白に
        self.view.backgroundColor = UIColor.whiteColor()
        
        // スライダーを作成する
        let mySlider = UISlider(frame: CGRectMake(0,0,250,30))
        mySlider.layer.position = CGPointMake(self.view.bounds.midX, 600)
        mySlider.backgroundColor = UIColor.whiteColor()
        mySlider.layer.cornerRadius = 10.0
        mySlider.layer.masksToBounds = false
        
        // スライダーの最小値と最大値を設定
        mySlider.minimumValue = 0
        mySlider.maximumValue = 1
        
        // スライダーの位置
        mySlider.value = 0.5
        
        // スライダーの現在位置より左右の色を変える
        mySlider.maximumTrackTintColor = UIColor.grayColor()
        mySlider.minimumTrackTintColor = UIColor.blackColor()
        
        // スライダーの値が変更される毎に"onChangeValueMySlider"メソッドが呼ばれる
        mySlider.addTarget(self, action: "onChangeValueMySlider:", forControlEvents: UIControlEvents.ValueChanged)
        
        // ビューの設定
        self.view.addSubview(mySlider)

        // UILabelを作成
        myLabel = UILabel(frame: CGRectMake(0,0,100,60))
        myLabel.backgroundColor = UIColor.orangeColor()
        myLabel.text = "Value:".stringByAppendingFormat("%.1f", mySlider.value)
        myLabel.textAlignment = NSTextAlignment.Center
        myLabel.layer.masksToBounds = true
        myLabel.layer.cornerRadius = 20.0
        myLabel.layer.position = CGPoint(x: self.view.bounds.width/2, y: self.view.bounds.height/2-20)
        self.view.addSubview(myLabel)
    }
    
    // スライダーの値が変わった時に呼ばれるメソッド
    internal func onChangeValueMySlider(sender: UISlider) {
        myLabel.text = "Value:".stringByAppendingFormat("%.1f", sender.value)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

Swiftでタイマーをつくる1

iPhone6Sを購入したので、swiftでプログラムを書いてみた。 コードはSwift Docsを参考にさせていただきました。 というか、そのままです。新しくプロジェクトを作成したら、UIViewController.swiftのみ編集します。

//
//  ViewController.swift
//  Timer
//

// UIKitライブラリをインポート
import UIKit

// UIViewControllerのクラス
class ViewController: UIViewController {
    
    // タイマーでカウントした値を格納するインスタンスをFloat型で作成する
    var cnt: Float = 0
    // UILabel型のインスタンスを作成する
    var myLabel: UILabel!
    // タイマー
    var timer: NSTimer!
    

    override func viewDidLoad() {

        super.viewDidLoad()
        
        // ラベルを作成
        // ラベルの位置と大きさを指定する
        myLabel = UILabel(frame: CGRectMake(0, 0, 200, 50))
        // UILabの背景色プロパティを白にする
        myLabel.backgroundColor = UIColor.whiteColor()
        myLabel.layer.masksToBounds = true
        // ラベルの角丸プロパティを10.0に設定する
        myLabel.layer.cornerRadius = 10.0
        // ラベルのテキストプロパティに"Time"という文字とタイマーでカウントした数値を表示する
        myLabel.text = "Time:\(cnt)"
        // ラベルの文字の色を黒にする
        myLabel.textColor = UIColor.blackColor()
        // ラベルの影をグレーでつける
        myLabel.shadowColor = UIColor.grayColor()
        // ラベルのテキストの位置を中心にする
        myLabel.textAlignment = NSTextAlignment.Center
        // ラベルの位置を画面の中央の位置に設定する
        myLabel.layer.position = CGPoint(x: self.view.center.x, y: self.view.center.y - 150)
        // ビューの背景色を設定する
        self.view.backgroundColor = UIColor.init(red: 100, green: 1, blue: 10, alpha: 0.5)
        // ビューにラベルを追加する
        self.view.addSubview(myLabel)
        
        
        // タイマー停止用ボタン
        let myButton = UIButton(frame: CGRectMake(0, 0, 200, 50))
        myButton.layer.masksToBounds = true
        myButton.layer.cornerRadius = 20.0
        myButton.backgroundColor = UIColor.blueColor()
        myButton.layer.position = CGPointMake(self.view.center.x, self.view.center.y + 150)
        myButton.setTitle("Stop Timer", forState: UIControlState.Normal)
        myButton.addTarget(self, action: "onMyButtonClick:", forControlEvents: UIControlEvents.TouchUpInside)
        self.view.addSubview(myButton)
        
        
        // タイマーをつくる
        // 0.1秒単位で時間を計測するタイマーを作成する
        timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "onUpdate:", userInfo: nil, repeats: true)
    }
    
    // ボタンが押されたら呼び出されるメソッド
    func onMyButtonClick(sender: UIButton) {
        // タイマーが動いているなら
        if timer.valid == true {
            // タイマーを破棄する
            timer.invalidate()
            // ボタンのタイトルを変更
            sender.setTitle("Start Timer", forState: UIControlState.Normal)
        } else {
            // タイマー起動
            timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "onUpdate:", userInfo: nil, repeats: true)
            // タイマーのタイトルを変更
            sender.setTitle("Stop Timer", forState: UIControlState.Normal)
        }
    }
    
    // NSTimer.scheduledTimerWithTimeIntervalで指定した秒数毎に呼び出すメソッドをつくる
    func onUpdate(timer: NSTimer) {
        // onUpdateメソッドが呼ばれる毎にcntに0.1追加する
        cnt += 0.1
        // 変数を用意し、文字列"Time"と小数点第一位まで含めたcntの数値を合体させて格納する
        let str = "Time:".stringByAppendingFormat("%.1f", cnt)
        // onUpdateメソッドが呼ばれる毎にラベルのテキストプロパティに変数strを代入する
        myLabel.text = str
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}