砂肝がおいしいブログ

ソフト開発のお勉強メモを書いていくブログ。

【Python】Project Euler - Problem01

プロジェクトオイラーという、数学の問題をプログラミングで解いていこう、という練習問題集があります。

Pythonの練習用にこれをやり始めてみたので、記録として作ったプログラムを載せていきます。 これがベストな解法とは思ってなくても、自分にとっては(制限時間ありの)今のベストです。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

##############################################################################
def _IsThreeTimes(num):
    if num % 3 == 0:
        return True
    else:
        return False

##############################################################################
def _IsFiveTimes(num):
    if num % 5 == 0:
        return True
    else:
        return False

##############################################################################
def eval(max):
    list = []

    for i in range(1, max):
        if _IsThreeTimes(i) is True:
            list.append(i)
        elif _IsFiveTimes(i) is True:
            list.append(i)
        else:
            pass

    print("NUM(" + str(max) + ") = " + str(len(list)))
    print("SUM(" + str(max) + ") = " + str(sum(list)))

##############################################################################
def main():
    eval(10)
    eval(1000)

###############################################################################
if __name__ == '__main__':
    main()

http://odz.sakura.ne.jp/projecteuler/

【Python】【Excel】 win32comモジュールでExcelを操作する

EXCELスクリプトから操作する方法はいくつかありますが、 今回はPythonでwin32comというモジュールを使った方法を紹介。

インストー

こちらが分かりやすい。 [www.yukun.info/blog/2012/05/python-win32com-module-install.html:embed]

スクリプト

自分がよく使うものだけ列挙。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import win32com.client

"""
Excelの操作
"""

# Excelのインスタンスを用意
xlApp = win32com.client.Dispatch("Excel.Application")

# Excelを閉じる
xlApp.Quit()

"""
ブックの操作
"""

# ブックを開く(読み取り専用)
wb = xlApp.Workbooks.Open("sample.xls", ReadOnly="True")

# ブックを別名保存する
# ファイル名を指定すると、カレント・ディレクトリに保存する。フルパスでの指定も可能。
# 読み取り専用で開くダイアログを表示しない
# Excel95-97形式
wb.SaveAs("sample.xls", ReadOnlyRecommended="False", FileFormat=xlExcel9795)

# ブックを閉じる
# - True: 保存して閉じる
# - False: 保存しないで閉じる
wb.Close(True)

"""
シートの操作
"""
# シートを追加
ws = wb.Worksheets.Add()

# シートを末尾(<シート数>個目のシートの後)に移動。
# 第1パラメータの`None`が無いと動かない。これで数日ハマった。。。
ws.Move(None, wb.Worksheets(wb.Worksheets.Count))

# コピーも同様。
ws.Copy(None, wb.Worksheets(1))

# シート名の変更
ws.Name = "sample2"

# シートの表示倍率を変更 [%]
ws.PageSetup.Zoom = 70

# 列の幅の変更
# A列からG列について、それぞれの列幅をWorksheet'origin'の同じ列の幅に設定する
for i in ws.Range("A:G"):
    i.ColumnWidth = wb.Worksheets("origin").Columns(i.Column).ColumnWidth

# オートフィルタ
# 3~7行目にオートフィルタを設定する(3行目にフィルタのドロップダウン▼マークがつく)
ws.Rows("3:7").AutoFilter()

# 配列で入力する
# オートフィルタの列名入力等に便利。
str_array = ["name 1", "name 2", "name 3", "name 4"]
ws.Range("A1:A4").Value = str_array


"""
セル範囲の操作
"""
# 列の挿入
# 1列目の左に、1列分を挿入
ws.Columns(1).Insert()

# 行の挿入
# 3行目の上に、5行分を挿入
ws.Rows("3:7").Insert()

# 行の削除
ws.Rows("1:6").Delete()

# セル範囲の内容を削除
ws.Range("A:C").ClearContents()

# セル範囲の背景色を変更
ws.Range("A1:D8").Interior.ColorIndex = 24 # Ice Blue : 24

# セル範囲の文字色を変更
ws.Rows("2:6").Font.ColorIndex = 1 # black : 1

# copy contents
ws.UsedRange.Copy(ws.Range("A1"))

# 値の貼り付け
ws.Range("A1:C3").PasteSpecial(Paste=xlPasteValues) # xlPasteValues = 

# セルに文字列として入力されている数字を、数字として使いたい場合、int()を使う。
# print出力のためには、さらにstr()を使う
print("B1:" + str(int(ws.Cells(1, 2).Value))

# セル範囲に一括入力する例
for i in ws.Range("B1:B10"):
    if ws.Cells(i.Row, 1).Value == None: # A列が空だったら
        i.Value = i.Row                  # B列に行番号を入力

# 並べ替え
# セル(1,1)から(10,10)が対象
# 1列目をキーとする
# 昇順
# 1行目をヘッダとする
sortTable = ws.Range(ws.Cells(1, 1), ws.Cells(10, 10))
sortTable.Sort(Key1 = sortTable.Columns(1), \
    Order1 = xlAscending, \
    Header = xlYes, \
    Orientation = xlSortRows)

"""
セルの操作
"""
# 数式を入力
ws.Range("D1").Formula = "=VLOOKUP($C1,data!$A$3:$I$10,2,0)"

# セルの値がエラーかどうかチェック
if ws.Range("A1").Errors.Item(1).Value == True: # xlEvaluateToError = 1
    ws.Range("B1").Value = "ERROR!"

参考

https://sites.google.com/site/pythoncasestudy/home/pywin32kara-comwo-tsuka-tsu-te-excelwo-sousa-suru-houhou

Python ライブラリ厳選レシピ

Python ライブラリ厳選レシピ

【Excel】 COM定数の一覧

ExcelVBAPythonで操作するときに指定する、ExcelのCOM定数。 この一覧が欲しかったので、出力しました。

順不同というか、勝手に出力された順。 そのうちカテゴリ別にまとめたい。

続きを読む

【CMake】【C++】WindowsでCMakeを使う

[TOC]

ナニソレ?

私がCMakeを導入した目的は、ソースコード(インプット)とビルド結果(アウトプット)を分離するため。

私はソースコードはOneDriveに入れて管理しているのですが、ここに.vsprojファイルや、ビルドしたバイナリや中間ファイルまでアップロードされると困るのです。 なぜなら別PCにクラウド経由で同期したときに、パスが合わずに使えない、という問題が起きるから。

ちなみにCMakeの本来の使い方(最大のメリット)は、同一ソースコードマルチプラットフォームのビルドを簡単に行うこと。

もう一つのメリットとしては、プロジェクト名やフォルダ名を変えたくなったときに、CMakeならば比較的簡単にできること。 そうそうやるべきでないのは理解してますが、案外必要になるのでイザという時に、覚えておいてもよいかと。

つかいかた

以下のURLのノウハウを使わせて頂きました。 以下のように若干修正。

  1. MinGWをインストー
  2. CMakeをインストー
  3. パスを通す
  4. テストプログラムを実行してみる

1. MinGWをインストー

以下からダウンロード。 sourceforge.net

どのパッケージを選ぶかは、他の方がいろいろ書いているので、ググってください。

2. CMakeをインストー

以下からダウンロード。 cmake.orghttps://cmake.org/download/

詳細は他の方がいろい(ry

ここまでが、最初に1回だけやればよい手順になります。 次からは、プロジェクトごとに毎回実行する手順。

3. CMakeを実行する

以下の3つのバッチを作成し、実行します。

  • confdir.bat : 初回だけ実行すればよいです。
  • cmake.bat : 初回または、CMakeファイルに変更を加えたときに実行します。
  • make.bat : 初回または、ソースコードを変更した場合に実行します。

バッチは、ソースコードとは別フォルダ(以下の例では、vbscriptフォルダ)に置きましょう。 そのフォルダにパスを通しておきます。

::confdir.bat
@echo off
set MINGW=c:\mingw\bin

set srcdir=%CD%
echo source dir:    %srcdir%
set CDN=%srcdir%\..\vbscript\CurrentDirectoryName.vbs
for /F "usebackq tokens=* delims=" %%S in (`CALL cscript //NoLogo %CDN% /%srcdir%`) do set ret=%%S
set builddir=C:\build\%ret%
if not exist %builddir% mkdir %builddir%
PATH %builddir%;%PATH%
echo build dir: %builddir%

if %ERRORLEVEL%==0 (
echo [SUCCESS] confdir has been done. Please run "cmake" command.
) else (
echo [ERROR] ERRORLEVEL:%ERRORLEVEL%
)
exit /b

このスクリプトでは、C:\build以下にビルドフォルダを自動生成します。

余談ですが、ビルドフォルダに、ソースフォルダと同じ名前のフォルダを自動生成するため、 カレント・ディレクトリの名前(パスではなく)を取得する方法は、以下を参照。 qiita.com

ビルド結果はここに格納されます。

::cmake.bat
@echo off

set CC=%MINGW%\gcc
set CMAKE_C_COMPILER=%CC%
set CMAKE_C_COMPILER_ID="Intel"

set CXX=%MINGW%\g++
set CMAKE_CXX_COMPILER=%CXX%
set CMAKE_CXX_COMPILER_ID="Intel"

set CMAKE_BUILD_TYPE="Release"
set CMAKE_CXX_FLAGS_RELEASE="-O3 -std=c++11 --enable-auto-import"

if exist "cmake.exe" (
"C:\Program Files\CMake\bin\cmake.exe" -G"MinGW Makefiles" -H. -B%builddir%
) else (
"C:\Program Files (x86)\CMake\bin\cmake.exe" -G"MinGW Makefiles" -H. -B%builddir%
)

if %ERRORLEVEL%==0 (
echo [SUCCESS] cmake is done. Please command "make"!
) else (
echo [ERROR] ERRORLEVEL:%ERRORLEVEL%
)
exit /b

CMakeまで完了。Makeします。

::make.bat
@echo off
mingw32-make -C %builddir%
if %ERRORLEVEL%==0 (
echo [SUCCESS] make is done.
cd /d %builddir%
) else (
echo [ERROR] ERRORLEVEL:%ERRORLEVEL%
)
::pause
exit /b

これでビルドまでできました。

4. テストプログラムを実行

説明の都合でこの順序で書きましたが、わざわざ手順に番号を振っておきながら、 以下のファイル(テストプログラム)がないと「3.」は実行できません。

#CMakeLists.txt

cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
project(HelloWorld)

add_executable(HelloWorld
    src/main.cpp
)

message(STATUS "CMake Start!")

main.cppは、まぁ好きに書けばいいと思います。

実行してみましょう

D:\GitHub> cd CPP_Sample_01_HelloWorld

D:\GitHub\CPP_Sample_01_HelloWorld> confdir.bat
source dir:     D:\GitHub\CPP_Sample_01_HelloWorld
build dir:      C:\build\CPP_Sample_01_HelloWorld
[SUCCESS] confdir has been done. Please run "cmake" command.

D:\GitHub\CPP_Sample_01_HelloWorld> cmake.bat
-- The C compiler identification is GNU 4.8.1
-- The CXX compiler identification is GNU 4.8.1
-- Check for working C compiler: C:/MinGW/bin/gcc.exe
-- Check for working C compiler: C:/MinGW/bin/gcc.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: C:/MinGW/bin/g++.exe
-- Check for working CXX compiler: C:/MinGW/bin/g++.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: C:/build/CPP_Sample_01_HelloWorld
[SUCCESS] cmake is done. Please command "make"!

D:\GitHub\CPP_Sample_01_HelloWorld> \make.bat
mingw32-make: Entering directory 'C:/build/CPP_Sample_01_HelloWorld'
mingw32-make[1]: Entering directory 'C:/build/CPP_Sample_01_HelloWorld'
mingw32-make[2]: Entering directory 'C:/build/CPP_Sample_01_HelloWorld'
Scanning dependencies of target HelloWorld
mingw32-make[2]: Leaving directory 'C:/build/CPP_Sample_01_HelloWorld'
mingw32-make[2]: Entering directory 'C:/build/CPP_Sample_01_HelloWorld'
[ 50%] Building CXX object CMakeFiles/HelloWorld.dir/src/main.cpp.obj
[100%] Linking CXX executable HelloWorld.exe
mingw32-make[2]: Leaving directory 'C:/build/CPP_Sample_01_HelloWorld'
[100%] Built target HelloWorld
mingw32-make[1]: Leaving directory 'C:/build/CPP_Sample_01_HelloWorld'
mingw32-make: Leaving directory 'C:/build/CPP_Sample_01_HelloWorld'
[SUCCESS] make is done.

C:\build\CPP_Sample_01_HelloWorld>HelloWorld.exe
Hello, CMake!

まとめ

WindowsでCMakeをお手軽に使う方法。

【Python】フォルダやファイルのパスを扱う

Pythonでフォルダやファイルのパスを扱う方法。

サンプル

ソースコード

TARGET_DIR = os.path.join('C:', "\\", 'Projects')
TARGET_FILE =os.path.join(TARGET_DIR, 'sample.txt') 
print(TARGET_FILE)

if (os.path.exists(TARGET_FILE)):
    print("exist!")

実行結果

> C:\Projects\sample.txt
> exist!

解説

区切り文字について

Pythonでは、文字列の連結は+で繋ぐだけでできる。 'C:' + '\' + 'Projects'といった感じでパスの指定に使える。

しかし、上記のようにos.path.joinを使うことを推奨する。 その理由は、移植性のため。 こうすることで、環境によって変わってしまう\または/を、ソースコードを変更することなく、自動的に切り替えることができる。

ドライブ名の指定方法

絶対パスでドライブ名まで指定する場合は、上記のように、C:"\\"が必要になる。

ファイル存在チェック

os.path.existで、指定したパスにファイルが存在するかどうかチェックしてから、ファイルオープンすること。

Raspberry Pi + Volumio + Synology Disk Station で音楽再生

前回に引き続き、ネットワークオーディオのシリーズ2回目です。 前回はこちらeuphoniumize-45th.hatenablog.comhttp://euphoniumize-45th.hatenablog.com/entry/2017/05/24/090502

概要

f:id:euphoniumize-45th:20170524090145p:plain (引用元:volumio、改編:砂肝うま太郎)

今回はNAS(右上)の音楽ファイルを、Raspberry Pi + Volumioで再生します。

volumioの設定

初めはNASIPアドレスをvolumioに入力するだけかと思ったのですが、 どうやらそう単純ではないみたいです。

そこで、volumioのオンラインヘルプを読んでみました。

すると、まさにドンピシャな記載がありました。 ざっと意訳すると、こんな感じですかね。

Synology と Volumio for Raspberry Pi は共にUnixベースなので、設定はNSF型のファイル共有を使います。

詳細はこちらを参照。: https://ja.wikipedia.org/wiki/Network_File_System

Synology の設定 SynologyのNFSを有効化するためには、Synologyの詳細ガイドに従ってください。(URL略)

このガイドは、素晴らしく詳細に必要なステップを説明してくれます。

最後のNFSルール・コンフィグレーションは、スクリーンショットを見てください。もっとも重要なところは、Squashの設定です。必要なアクセス権限は読込み/書込み。また、Synologyへのゲスト・アカウントのアクセスを無効化するのが賢明であるため、Squashの設定は全ユーザーを admin にマップに設定しなければなりません。

ふむ。 まぁSynology詳細ガイドというのが用意されているので、それに従って設定を進めればよさそう。 NFSがなんなのかWikipediaを読んでもよくわからないので放っておきます。

NASの設定

そのSynology詳細ガイドはこちら。 上記のVolumio DocumentationにあるリンクのSynologyサイトは英語版です。 How to access files on Synology NAS within the local network (NFS) 日本語版はこちら。 ローカル ネットワーク内の Synology NAS にアクセスする (NFS)

で、実際に私が設定した内容がこちら。 f:id:euphoniumize-45th:20170515010943p:plain マウントしたサブフォルダへのアクセスを許可するにチェックを入れることに注意。

これで設定は完了。 volumioの[Library]画面を見ると、緑色のチェック印とNASの音楽フォルダのパスが表示されています。マウント成功! 思った以上に簡単ですね。 f:id:euphoniumize-45th:20170515010550p:plain

再生

ここまでできたところで、volumioの[Browse]画面を見ると、これまで無かったNASが追加されています。 よし、これでNASの音楽ファイルをプレイリストに登録するだけで、聴けるはず!

と思ったのですが、ここで新たな問題発生。 「NAS」以下にサブフォルダ(アーティスト名、アルバム名)が何も表示されない!! ぐぬぬ

これについては、NAS側のアクセス権設定が不足していたことが原因でした。 以下のように設定したら、volumioの[Browse]画面にNASのサブフォルダもすべて見ることができるようになりました。 (正直、この調査が一番時間がかかった…)

f:id:euphoniumize-45th:20170518052350p:plain f:id:euphoniumize-45th:20170518052353p:plain

一応解説すると、上記のNASの設定で全ユーザーをadminにマップしたのですが、そもそも「全てのユーザー」(というかadmin以外のユーザー)が誰もいなかった(登録してなかった)、というオチでした。

これでプレイリストに登録したところ、ちゃんと再生もできました。ひとまずめでたし。

補足

以下を参照させて頂きましたが、今回の私の環境では、この設定を行うとNASのマウントができませんでした。 yjo-blog.blogspot.jp

まとめ

NASのデジタル音楽ファイルをvolumioで再生しました。 次は高音質化の予定。

Raspberry Pi + Volumio で音楽再生

やりたいこと

一言で言えば、自宅で再生する全ての音楽ソースを同じスピーカーから流したいわけです。 もちろん、追加購入をなるべく抑えて、手持ちの機材でなんとかしてみようと思います。

構成イメージ

とりあえずこんな構成を目指します。 f:id:euphoniumize-45th:20170524090145p:plain (引用元:volumio、改編:Simple Gift)

各デバイス説明

  • 下段右 : アンプ付ミニコンポ&スピーカー
  • Pioneer製
  • CD再生、FM受信。
  • LINE入力端子とAUDIO入力端子を持ってます。
  • 下段左 : PC/スマホ
  • 現在はUSB オーディオI/F経由でミニコンポに接続してます。音楽再生ソフトはfoobar 2000を使用。
  • 今回使うvolumioは、ブラウザまたはスマホから操作することができます。 既にPCに入れているfoobar2000スマホ対応なので、両方共スマホで操作できるようにしてみます。
  • 中段左 : 「RaspberryPi + volumio」
  • 今回のキモ。こいつで、デジタル音楽ファイルを再生します。 理想的には、音楽流しっぱでスピーカーさえ電源ONすればいつでも聴けるジュークボックス。
  • 中段右 : DAC
  • 音楽を高音質化してくれるデバイス。まだ持ってないので無視して、RPとミニコンポを直接つなぎます。
  • 上段左 : Storage Device
  • いわゆるUSBフラッシュメモリー(またはSDカード)。音楽ファイルを入れて、RPに直挿しします。
  • 上段右 : Network Storage
  • いわゆるNAS 。これにデジタル音楽ファイルを保存します。今回はまだ使いません。

Raspberry Pi とは

通称ラズパイ(以下、RP)。 超安価のPCとして結構話題になっています。 (と思っていたんですが、自分の周囲はほとんど誰も知りませんでした。最近やっと知られてきた感じですかね)。

お手軽にLinuxのPCとしてを使えるだけでなく、いま話題のIoTで他の機器と接続することも(専門知識のある人なら)簡単にできます。

ちなみに、私はラズパイを2台購入しました。PC用(RP3)と音楽用(RP2)。それでも合計1万円以下という驚きのコスパ。ケーブルやらなんやらで多少超えますが、電器屋で売ってるPCやオーディオ機器と比べると桁違いです。

さて、ミニコンポとの接続ですが、上記図のRP向けDACを持っていないので、まずはアナログ接続です。 RPのステレオミニジャックからミニコンポのAudio入力へ繋ぎます。 これで、ひとまず音は出ました。気になる音質については後述。

今回やりたいこと

そんなラズパイですが、音楽再生専用機器としても使うことができます。 これまでPCとiTunesが必須だったデジタル音楽ファイルの再生が、PCを立ち上げることなく可能になるわけです。

今回は、RPに挿してあるSDカード(上の図でいう左上のStorage Device)の音楽ファイルを再生します。

Volumio

Raspberry Pi そのままでも音楽再生はできるのですが、音楽再生に特化したOS (Distribution)に入れ替えることで、いろいろ捗ります。

今回使ったのは、Volumio (version 1.55)。

volumio.org

音楽用に特化しているので余計なノイズも減らすことができます。

まずは、音楽ファイルを、RPローカルのlocal.volumio\\USB Musicフォルダへコピー。 WindowsエクスプローラでOK。 これでRPのSDカードの空き領域に保存されます。

ブラウザでlocal.volumioにアクセスして、保存した音楽ファイルをプレイリストに登録します。

f:id:euphoniumize-45th:20170518133212j:plain

これでめでたく再生できました。

f:id:euphoniumize-45th:20170518133103j:plain

スマホからも操作できました。

今後の予定

今回はここまで。 これまで使っていた自作PCは、CPUの負荷が高いときに音にノイズが乗ることが多く、いろいろ調べても解消しなかったので、 今回のRaspberry Pi + Volumioでかなり快適な音楽ライフが実現できそうです。 音質もそう悪くはないです。クラシックとかジャズをガッツリ聴くなら少し苦しいかも。

最終的には、↑に示した図をすべて再現することを目指しますが、 次にやりたいのはこんな感じ。

  • 自宅LAN内にNASを設置し、音楽ファイルは全てNASに入れる。RPからNASのデジタル音楽ファイルを読み込んで再生。
  • RPにDACを接続して高音質化 (できればハイレゾ対応)
  • MPD はSqueeze boxも試してみたい。

ゆるゆるやっていきます。