Rubyで言語処理100本ノック 00-04
Rubyの練習のために始めました.
4章からは難しそうなので3章まで頑張りたい.でも飽きたらやめるかも.
コードを書く基礎が足りない気がするのでもっと書かないと.
始めるにあって,とりあえずRuby 2.2.3のStringクラスは一通り目を通してきました.
全体的に末尾再帰でなんとかしようとしてます.
Rubyは末尾再帰の最適化がないって聞いたんですがどうなんですかね?
Rubyっぽい書き方がわからないので,Rubocop先生に出来るだけ怒られないように書いてます.
00
# 00 文字列を受け取り,末尾から順に表示する class String def my_reverse size = length result = '' while size > 0 size -= 1 result << self[size] end result end # Like tail call def iter_reverse iter('', length) end private def iter(str, str_len) if str_len > 0 iter(str + self[str_len - 1], str_len - 1) else str end end end 'reverse'.my_reverse # => "esrever" 'a'.my_reverse # => "a" ''.my_reverse # => "" 'reverse'.iter_reverse # => "esrever" 'a'.iter_reverse # => "a" ''.iter_reverse # => ""
01
# 01 文字列の奇数番目だけ取り出した新しい文字列を返す class String def str_odd iter(0, '') end private def iter(index, str) if index < length if index.even? iter(index + 1, str + self[index]) else iter(index + 1, str) end else str end end end 'hello'.str_odd # => "hlo" 'abcde'.str_odd # => "ace" 'パタトクカシーー'.str_odd # => "パトカー"
02
# 02 2つの文字列を受け取り,先頭から交互に混ぜた文字列をつくる def comb_str(str1, str2) iter(str1, str2, '') end def iter(str1, str2, result) if str1.empty? result + str2 elsif str2.empty? result + str1 else iter(str1[1..-1], str2[1..-1], result + str1[0] + str2[0]) end end comb_str('パトカー', 'タクシー') # => "パタトクカシーー"
03
# 03 文字列から数字のリストをつくる class String def pi split.map(&:length) end end "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics.".pi # => [3, 1, 4, 1, 6, 9, 2, 7, 5, 3, 5, 8, 9, 7, 10]
04
# 04 文字列を受け取り,単語に分解し,1, 5, 6, 7, 8, 9, 15, 16, 19番目の単語は先頭の1文字 # それ以外の単語は先頭に2文字を取り出し,取り出した文字列から単語の位置(先頭から何番目の単語か)への連想配列を返す class String def element recur(split, 1, []) end private def helper(str, i) case i when 1, 5, 6, 7, 8, 9, 15, 16, 19 [str[0], i] else [str[0, 2], i] end end def recur(arr, index, result) if arr.empty? result else recur(arr.drop(1), index + 1, result.push(helper(arr[0], index))) end end end "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can.".element # => [["H", 1], ["He", 2], ["Li", 3], ["Be", 4], ["B", 5], ["C", 6], ["N", 7], ["O", 8], ["F", 9], ["Ne", 10], ["Na", 11], ["Mi", 12], ["Al", 13], ["Si", 14], ["P", 15], ["S", 16], ["Cl", 17], ["Ar", 18], ["K", 19], ["Ca", 20]]
Stringクラスを一読するのに時間がかかったので今日はこれだけ.
OSX クリーンインストール前の準備
yosemiteからEl Capitanへアップデートする前の準備.
dotfilesの準備
.bashrcや.emacs.dなどインストール後に必要になりそうなものをここに入れてしまいます.
他にも次の環境に必要なものはここに入れてしまいます.
そしてシンボリックリンクを貼るスクリプトをつけておきます.
最強の dotfiles 駆動開発と GitHub で管理する運用方法 - Qiita
ここのスクリプトを少し変更して
#!/bin/bash for f in .??* do filepath="${PWD}/${f}" homefile="${HOME}/${f}" [[ "$f" == ".git" ]] && continue [[ "$f" == ".DS_Store" ]] && continue ln -snf $filepath $homefile done
これを実行すればホームディレクトリにシンボリックリンクが張られます.
Homebrewでインストールしたもののリスト,tap先を保存する
Homebrewで何を入れたかなんて覚えていられませんね.
tapで何を追加したのかも覚えていられません.
なのでファイルに書き出しておきます.
ここから抜き出して一気にインストールなんてことが出来るかは知りません.
クリーンインストール後に調べます.
$ brew tap > ~/dotfiles/brewtaplist $ brew list > ~/dotfiles/brewlist
これで全て書きだされます.
さっきのスクリプトはドットファイル以外のシンボリックリンクは作らないのでこれらのリンクは作られません.
iTerm2の設定のエクスポート
iTerm2の設定も覚えていられませんね.
未来を見てきたらこういうのです.(timemachineで戻ってきました)
なので設定ファイルをエクスポートしておきます.
iTerm2の設定をインポート・エクスポートする方法 - Qiita
ここを見てきてください.
Preferences > General > Prefeences のLoad preferences ... のチェックボックスをクリックしてホームディレクトリのdotfilesにします.
ディレクトリを確認して com.googlecode.iterm2.plist
があればOK.
なければもう一度保存先のディレクトリ名があってるか確認してください.
Karabinerの設定のエクスポート
Karabinerの設定も覚えていられませんね.
快適な環境を維持するためにこれもエクスポートして次の環境に持って行きましょう.
$ /Applications/Karabiner.app/Contents/Library/bin/karabiner export > ~/dotfiles/karabiner.sh
これで大丈夫です.
最後に
以上の作業で作ったdotfilesをgithubに上げるなり,dropboxに上げるなり,外付けHDDに入れるなりして次の環境に送りましょう.
準備完了です.
初めてのgem
キャメルケース,スネークケース,パスカルケースを相互に変換するgemを書きました.
書き方わからずに色々やってたら最初にリリースした分は盛大にバグってました.
とりあえずバグが取れたのでまたgemに.
一応 gem install case_converter
で入れられます.
使い方はこんな感じ
"camel_case".snake_to_camel # => "camelCase" "string ca_mel_case string".snake_to_camel # => "string caMelCase string" "pascal_case".snake_to_camel # => "pascalCase" "string pas_cal_case string".snake_to_camel # => "string pasCalCase string" "snakeCase".camel_to_snake # => "snake_case" "foo snakeCase bar".camel_to_snake # => "foo snake_case bar" "pascalCase".camel_to_pascal # => "PascalCase" "foo pasCalCase bar".camel_to_snake # => "foo pas_cal_case bar" "SnakeCase".pascal_to_snake # => "snake_case" "foo SnaKeCase bar".pascal_to_snake # => "foo sna_ke_case bar" "CamelCase".pascal_to_camel # => "camelCase" "foo CaMelCase bar".pascal_to_camel # => "foo caMelCase bar"
初心者でもこれなら簡単に書ける!
Nginxでsites-enabledが読み込まれない
nginx version: nginx/1.8.1
ここを見ながらnginxでVirtual Host を構築しようとしていました.
ただここのやり方では /etc/nginx/conf.d/default.conf
が読み込まれてしまうのその対処方法を書きます.
/etc/nginx/nginx.conf
を開くとこうなっているはずです.
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; keepalive_timeout 65; gzip on; include /etc/nginx/conf.d/*.conf; }
http内のincludeの次の行に新しくincludeを追加します.
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; keepalive_timeout 65; gzip on; include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; }
Debian 8 に MySQL 5.7.11をインストール
MySQL :: Download MySQL APT Repository
ここの数字を確認する. 数字が変わっていれば以下のmysql-apt-config_NUMBER_all.debのNUMBER部分を変更する.
$ mkdir ~/src $ cd ~/src $ wget http://dev.mysql.com/get/mysql-apt-config_0.6.0-1_all.deb
次にこのダウンロードしたdebパッケージをdpkgでインストールする.
$ sudo dpkg -i mysql-apt-config_0.6.0-1_all.deb
mysql-5.7を選択
mysql-5.7を選択
applyを選択
# リポジトリのアップデート $ sudo apt-get update # mysqlのインストール $ sudo apt-get install mysql-server
mysqlサーバのrootのpasswordを聞かれるので入力する.
インストールの確認
$ sudo service mysql status $ sudo service mysql stop $ sudo service mysql start
問題がなければ完了.
/etc/init.d/mysqld がないけど,5.7ではないの?
よくわからず5時間くらい探しまわった.
ここに書いた内容は公式サイトから.
MySQL5.7.11でユーザを追加できない.
環境はdebian8, mysql5.7.11.
mysql> grant all on blog_app.* to 'foo'@localhost identified by 'hogehoge'; ERROR 1054 (42S22): Unknown column 'password_last_changed' in 'mysql.user'
以上のようなエラーが出ました.
対処方法は以下になります.
$ sudo mysql_upgrade -u root -p $ sudo systemctl restart mysql
MySQL unknown column 'password_last_changed' - Stack Overflow
Rubyの正規表現でそれぞれのケースへの変換
今日は正規表現に苦しんだので練習しました。
snake_case、camel_Case、Pascal_Caseのそれぞれへの変換です。
capitalizeなくても書けるけど一応。
m[0].upcase + m[1..-1]
はちょっと汚いですしね。
Rubular使えばテストケースが期待通りのマッチになるまで簡単に
トライ&エラーが出来ていいです。
class String def snake_to_camel self.gsub(/\b[a-z][a-z\d]*[a-z_\d]*\b/) do |match| match.gsub(/_[a-z\d]/) { |m| m[1..-1].capitalize} end end def snake_to_pascal self.gsub(/\b[a-z][a-z\d]*[a-z_\d]*\b/) do |match| match.gsub(/[a-z][a-z\d]*/) { |m| m.capitalize } end end def camel_to_snake self.gsub(/\b[a-z]+[A-Z][a-z\d]+\b/) do |match| match.gsub(/[A-Z][a-z\d]+/) { |m| "_" + m.downcase } end end def camel_to_pascal self.gsub(/\b[a-z]+[A-Z][a-z\d]+\b/) do |match| match.capitalize end end def pascal_to_snake self.gsub(/\b[A-Z][a-z\d]*([A-Z][a-z\d]+)*\b/) do |match| match.gsub(/[A-Z][a-z\d]*/) { |m| "_" + m }.downcase[1..-1] end end def pascal_to_camel self.gsub(/\b[A-Z][a-z\d]+([A-Z][a-z\d]+)*\b/) do |match| match.gsub(/\b[A-Z][a-z\d]*/) { |m| m.downcase } end end end