- 投稿日:2020-08-12T23:57:53+09:00
RubyからCocoaを使ってみる
RubyからCocoa(macOSのAPI)を使ってみる。
以前、RubyCocoaというものがあった。今は動かなくなっているようだ。
近いものとして、cocoaというgem packageがある。
https://github.com/patrickhno/cocoa/インストールする。
% gem install cocoa
Successfully installed cocoa-0.1.6
Parsing documentation for cocoa-0.1.6
Done installing documentation for cocoa after 3 seconds
1 gem installedサンプルプログラムを実行してみる。
test1.rbrequire 'cocoa' Cocoa::NSAutoreleasePool.new app = Cocoa::NSApplication.sharedApplication app.setActivationPolicy Cocoa::NSApplicationActivationPolicyRegular app.activateIgnoringOtherApps true alert = Cocoa::NSAlert.alloc.init.autorelease alert.setMessageText "Hello world!" alert.runModal% ruby test1.rb
/usr/local/lib/ruby/gems/2.7.0/gems/cocoa-0.1.6/lib/cocoa/objc/method_def.rb:154: warning: constant ::Fixnum is deprecated
/usr/local/lib/ruby/gems/2.7.0/gems/cocoa-0.1.6/lib/cocoa/objc/method_def.rb:154: warning: constant ::Fixnum is deprecated
/usr/local/lib/ruby/gems/2.7.0/gems/cocoa-0.1.6/lib/cocoa/objc/method_def.rb:154: warning: constant ::Bignum is deprecated無事実行されるのだが、warningが気になるな。今度、修正してみよう。
- 投稿日:2020-08-12T23:26:21+09:00
google search console の sitemap の api client は searchconsole ではなく webmasters にある
概要
google search console のサイトマップに対する API のクライアントを探していたときに sdk の searchconsole ディレクトリを見て、サイトマップの操作に対するメソッドがないなあと少しはまったので共有です。
結論
ruby sdk の例ですが、
searchconsole_v1
ではなく、
https://github.com/googleapis/google-api-ruby-client/blob/master/generated/google/apis/searchconsole_v1/service.rb
webmasters
にサイトマップの API はあります。
https://github.com/googleapis/google-api-ruby-client/blob/master/generated/google/apis/webmasters_v3/service.rb
- 投稿日:2020-08-12T23:18:18+09:00
Rubyにおける正規表現について
Ruby の正規表現について
先日カリキュラムで学習した正規表現について、『暗号がいっぱい書いてある・・・』という状態でしたので、『学んだ事の整理』と『学習のアウトプット』も兼ねて記事にしてみました。
正規表現って?
文字列の集合を一つの文字列で表現する方法の一つである。正則表現(せいそくひょうげん)とも呼ばれ、形式言語理論の分野では比較的こちらの訳語の方が使われる。まれに正規式と呼ばれることもある。(wikipediaより抜粋https://ja.wikipedia.org/wiki/%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE)これだけだと分かりづらいので、アプリケーションに触れていると『パスワードが6文字未満だと登録できません』とか『電話番号にハイフンが入っていると・・・』というような事が多々あります。では、これは一体どのようにして判断をしているのでしょうか?
例えば電話番号を登録するような場合、
id name tel 1 Aさん 090-0000-0000 2 Bさん 09000000000 Aさん→ハイフンありで登録
Bさん→ハイフンなしで登録といった状況が生まれたりします。これだと別フォーマットで管理する事になってしまうので、統一した方が管理がしやすいです。その際に『余分なハイフンは消す!』といった処理をすると管理もしやすくなります。
このように、『文字列に特定の文字が入っているかどうか?』や『特定の文字を取り除く』といった処理を行う技術が正規表現となります。
正規表現は様々な言語で同じようなコードで表す事ができるので、形を覚えてしまえば別の言語にも応用できるようになっています。
正規表現のメソッド
Rubyでは主に下記3つのメソッドが重要且つよく使われています。
subメソッド
文字列の指定した部分を別の文字列に置き換えるメソッドです。例えば下記のコードのような使い方をします。greeting = "Hello,world" =>"Hello,world" greeting.sub(/Hello/,"Good morning") =>"Good morning,world"/で囲まれた"Hello"という文字列を"Good morning"に置き換える事ができました。
matchメソッド
引数に指定した文字列が、呼び出した文字列の中に含まれているかどうかを判断するためのメソッドです。greeting = "Hello,world" =>"Hello,world" greeting.match(/Hello/) => #<MatchData "Hello"> greeting.match(/Good morning/) => nil上記のように、greetingに代入された文字列は"Hello,world"なのでmatchメソッドで引数を/Hello/で指定した場合にはMatchDateとして"Hello"が呼び出されています。しかし引数を/Good morning/に指定すると、代入された文字列の中には含まれていない文字列となるので、『nil』と表示されます。
gsubメソッド
subメソッドと同じく文字列を置換するためのメソッドですが、g(グローバルメソッド)がつく事で、文字列内に指定した文字列が複数含まれる場合、その全てを置換する役割を持っています。電話番号を例にしてみるとtelA = '090-0000-0000' => "090-00000-0000" telA.gsub(/-/,'') => "090000000000"このように/で囲ったハイフンを取り除く事ができました。
以上のように、メソッドで取り除く文字列や含まれる文字列を指定する事で文字列に制約をかける事ができます。指定するための記述方法は以下にまとめましたので、使うときがありましたら参考にしてください。
パターン 意味 [a-z] アルファベットaからzまでのいずれかにマッチ \d 数字にマッチ [a-z\d] 英数字のいずれか1つにマッチ {n,m} 直前の文字が少なくともn回、多くてm回出現するものにマッチ i 大文字と小文字を区別せずに検索(最後につける) . どの1文字にもマッチ + 直前の文字が1回以上の繰り返しにマッチ \A 直後の文字が先頭にある文字列にマッチ \z 直前の文字が末尾にある文字列にマッチ [ぁ-んァ-ン一-龥] 角括弧に囲まれたかな、カナ、漢字いずれかにマッチ ?= 直後に設定した文字が続く文字列にマッチ *? 直前に設定した文字が0回以上続く文字列をチェックし、?の直後の文字が出た段階でその1文字を返す /\A(?=.?[a-z])(?=.?[\d])[a-z\d]+\z/i 先頭が任意の文字0回以上と英数字で始まり、末尾が英数字の1回以上の連続する文字列にマッチし、大文字小文字の区別がない(英数字混合のパスワードをチェックする時など使えます)
- 投稿日:2020-08-12T22:47:36+09:00
ターミナル が立ち上がらない
こんなことありませんか?
ターミナルで rails s を打ち込んだところAddress already in use - bind(2) for "127.0.0.1" port 3000 (Errno::EADDRINUSE)とエラーが出ることがありますが
・Address already in use
(アドレスは既に使用されております)と翻訳されます。原因
エラー 「"127.0.0.1" port 3000」が既に使われているため
参考
https://qiita.com/nagao_norihiro/items/aba40bd4e0eac9f9a92d
https://qiita.com/Shimba/items/1a234ebb646bb01d16cd
- 投稿日:2020-08-12T21:38:24+09:00
【Rails】定数は、config gemで管理しましょう
環境
$ rails -v Rails 6.0.3.1$ ruby -v ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-darwin19]まずは、Gemのインストール
Gemfilegem 'config'$ bundle install --path vendor/bundleconfigの初期設定を行う
configの初期設定のために関連ファイルをインストールする
$ bundle exec rails g config:install定数定義と、使い方
config/settings.ymlservice: name: 'vdeep' url: 'http://vdeep.net' authentication_password: "foobarbaz"$ rails c > Settings.service.name => "vdeep" > Settings.service[:name] => "vdeep" > Settings[:service][:name] => "vdeep" > Settings.authentication_password => "foobarbaz"
- 投稿日:2020-08-12T21:08:17+09:00
Ruby の paypal-sdk-rest gem で発生する OpenSSL::SSL::SSLError: SSL_connect の解決方法
詳しいことは後日、もう少し追記する予定。
経緯
2020年8月11日の夕方ごろ(日本時間)から
paypal-sdk-rest
gem を使った支払いで下記のエラーが発生するようになった。OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate)対応方法
https://curl.haxx.se/docs/caextract.html から最新の
cacert.pem
をダウンロードして、config/certs/cacert.pem
に配置して、config/paypal.yml
にssl_options
のca_file
の設定を追加する。config/paypal.ymldevelopment: &default mode: sandbox client_id: xxx client_secret: xxx ssl_options: ca_file: config/certs/cacert.pem production: mode: live client_id: xxx client_secret: xxxこの設定で、ローカル開発環境、 production 環境ともに想定通り動作することを確認した。
別の解決方法
参考
- paypal/PayPal-Ruby-SDK: Ruby SDK for PayPal RESTful APIs
- ruby on rails - OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate) - Stack Overflow
- Remove Support of Verisign G5 Root Certificate
- curl - Extract CA Certs from Mozilla
- 投稿日:2020-08-12T20:49:14+09:00
独学半年の実務未経験がRails+Nuxt.jsでSPA作ったので見て欲しい
はじめに
アプリを作ったのはいいものの、フィードバックをくれる人がいなかったのでQiitaで紹介記事を書くことにしました。
独学で周りにアドバイスをもらえる人がいないので、改善点などどんどん指摘してくださると幸いです。自己紹介
作者は今年の2月末ごろから独学でプログラミングを学習しています。
高校時代にほんの少しHTMLを触ったことがある程度で、前提知識はほぼありませんでした。
現在はアプリを作成しながら、10月の基本情報に向けて勉強しています。
アプリ制作は今回で2作目になります。
前作URL
前作リポジトリアプリ概要
これが作成したアプリです。
PolPa(ポルパ)は、学習時間に応じてレベルが上がる学習記録アプリです。
全体像がわかると思うので先にERを貼っておきます。機能紹介
主な機能を一部紹介します。
ゲストログイン
新規登録フォームの下からゲストアカウントでログインできます。
気軽に試すことができるので、見学しに来てください。学習時間を記録する
このアプリのメイン機能です。記録された時間に応じて経験値を獲得できます。
タグをつけてジャンル分けできます。
記録した日には草が生えます。
記録にはコメントやいいねができます。ユーザーをフォローする
ユーザーをフォローすると、タイムラインにそのユーザーの記録が表示されるようになります。
他のユーザーと交流して、モチベーションを高め合いましょう!ユーザーを検索する
ユーザー名で検索できます。
リアルタイムに検索結果が変化します。レスポンシブデザイン
スマホやタブレット用のデザインにも対応しているので、モバイル端末から手軽に利用できます。
他にも紹介してない機能がたくさんあるので、ゲストログインで体験してください。
作った理由
サービスとして
他の学習管理アプリを使っていて、今まで積み上げてきたものをはかる指標があればもっとモチベーションを維持しやすくなるのではないかと考え、「学習時間を記録するとレベルが上がる」という要素をプラスした学習管理アプリがあれば面白いのではないか、と開発を始めました。
個人として
個人的には、Vue.jsとRailsを使って何かを作りたかったから開発を始めたという理由もあります。
作る前はこんな程度のアイデアで開発を始めてもいいのだろうかと思っていましたが、開発を進めていくうちに少し愛着が湧いてきました。技術周りの話
使用している主な技術やリソース
- Ruby、Rails ... バックエンド
- Vue.js、Nuxt.js ... フロントエンド
- Vuetify ... UIフレームワーク
- PostgreSQL ... データベース
- Docker、Docker-compose ... コンテナ仮想化
- Git、GitHub ... バージョン管理システム
- Firebase ... ログイン認証・ホスティング
- heroku ... API用サーバー
Rails
バックエンドにはRailsを使用しています。Railsは学習期間が最も長く、前作でも使用しています。
新しく作るアプリは新しい要素を追加したいと思ったので、バックとフロントで別のフレームワークを使用する手法を取ることにしました。Vue.js、Nuxt.js
Vue.jsは以前から興味があり、Railsとの共存も容易だったため、学習を開始しました。
Vue.jsは書籍一冊学習したのみだったので、雰囲気しか理解していない状態からコードを書き始めました。
Nuxt.js自体は開発を始めてから初めて触りました。Vuetify
フロントのデザインはほとんどVuetifyに頼っています。アプリに必要なデザインコンポーネントが一通り揃っているので、一から作るにはめんどくさいデザインも簡単に実装できました。
種類が豊富なので、Vuetifyの公式リファレンスを見るだけで楽しいです。Firebase
ログイン認証にはFirebaseを用いています。初めての開発手法だったため、自力で安全な認証・認可を実装できないと判断し、Firebaseを使用することにしました。
一人で開発して感じたこと
個人で開発をしていく上で良かったことと、つらかったこと・反省点をいくつかまとめてみます。
良かったこと
前作を制作した時も感じていましたが、アプリ制作は本当に勉強になります。
特に独学だとすべてのエラーを自力で解決しなければならないので、デバック力や問題解決能力が磨かれます。
一人で開発するとWeb開発の技術が全般的に必要になるので、次に勉強したい分野が明確になるのもいい点だと思います。つらかったこと・反省点
- エラーの解決方法がわからないとストレスがたまる
- 開発するときのルールを決めておかないと徐々に雑になる
- あれもこれもと機能を追加しているとキリがない
コードが予想に反する動きをして半日潰れたなんてことは日常茶飯事だったので慣れはしましたが、目に見える成果が全く得られないというのはストレスがたまります。ネットで検索してみてもそれらしい情報が全く出てこなかった時は本当に絶望します。
ただ、良かった点にも書いているようにメリットとは表裏一体です。
なんとか解決してきたので、自分の力にもなっているのかなと思います。最初に張り切って、「今回はこの方法にしたがってコーティングして、この手法を使って開発を進めるぞ!」 なんて思っても大体続きませんでした。だんだん雑になってきて、めんどくさいからいいか、一人だからいいかとなりがちでした。次回があれば、ルールの徹底を意識したいと思います。
これからについて
もっと追加したい機能があるので時間があればアップデートしたいと思っています。
10月中旬の基本情報に向けてJavaを勉強するつもりなので、しばらくは時間がないと思いますが、アプリの完成度を高ていきたいのでフィードバックなどよろしくお願いします。
- 投稿日:2020-08-12T20:45:55+09:00
[備忘録] ``expect``の後ろは``()``か``{}``か。 (Module: RSpec::Matchers)
本編
RSpecのマッチャの書式についての個人的な小メモです。
RSpecのバージョン
RSpec 3.9 - rspec-core 3.9.2 - rspec-expectations 3.9.2 - rspec-mocks 3.9.1 - rspec-rails 4.0.0.beta3 - rspec-support 3.9.3
expect
の後ろは()
か{}
か?結論
下記のgem(
rspec-expectations (3.9.2)
)のドキュメントでMathersのページに各マッチャの記法が列挙されています。用例も多く掲載されています。(#changeなど)Module: RSpec::Matchers — Documentation for rspec-expectations (3.9.2)
expect(..).to be_xxx
に{..}
を誤用した例実際にシステムスペックのファイル内で
(..)
を{..}
と書いてテストを実行した場合のエラーメッセージです。
be successful
のマッチャを使用するには、ブロックではなく引数を渡さなければならないということは教えてくれています。エラーメッセージ例You must pass an argument rather than a block to `expect` to use the provided matcher (be successful), or the matcher must implement `supports_block_expectations?`. # ./spec/system/doing_edit_spec.rb:11:in `block (2 levels) in <top (required)>'
- 投稿日:2020-08-12T19:05:27+09:00
AWS I�oT ボタンとSlackを連携してみた
はじめに
AWS IoTボタンを使ってSlack通知ボタンをつくってみました。
※実は作ったのは半年以上前ですが、なかなか記事が公開できませんでした!会社のウォーターサーバーなのですが、最後の1本を使用した人はSlackで総務へお知らせするフローがありまして、でもどうしても席に戻るとぽかんとお知らせすることを忘れちゃうんですよね。
そこで、うっかり忘れをしないようにIoTボタンを使ってSlackへのお知らせをその場でしよう、というアイデアではじめました。課題解決ドリブンですね。
あとはそこにAWS IoTボタンがあったからです。
それではやっていきましょう!
用意するもの
AWS IoT ボタン ✕ 1 (¥2,500)
https://aws.amazon.com/jp/iotbutton/
見るからにアマゾンダッシュボタンな、今回はこちらを使っていきます。
アマゾンダッシュボタンだとサーバーになるPCが必要そうです、簡単にセットアップできてこの値段も高くもない?ので、これをつかいます。AWSアカウント ✕ 1 (USD$0.25/month)
月額27円くらいかかるみたいです。
https://aws.amazon.com/jp/iot-1-click/pricing/IoTボタンの有効化
まずはAwS IoT ボタンを登録していきます。
コンソールから登録する方法とスマホで登録する方法があるみたいですが、スマホでやるのが簡単そうです。Storeからアプリをダウンロード
iOSであればAppStoreから、AndroidであればGooglePlayからアプリをインストールします。私はiOSで登録しました。
iOS : https://apps.apple.com/us/app/aws-iot-button/id1178216626
Android : https://play.google.com/store/apps/details?id=com.amazonaws.iotbuttonAWSにログインして、デバイスの登録とWifiへの接続を定します。ポチポチ。ピッピ。
カメラで、AWS IoTボタンの側面のバーコードを読み取るだけで登録できます。
PCからAWSコンソールへログインして、有効化をします。
設定してからスクリーンショットを撮ってしまったのですが、こちら最初は無効になってて、かつプロジェクトと配置は未設定となっていると思います。
Slack連携の準備
SlackのAppディレクトリへIncoming Webhookを追加し、Webhook URLを発行します。
Incoming Webhookの名前とアイコンも設定し、メッセージをプレビューします。
▼こんな感じにしてみました
Lambda関数を作成
AWSのLambdaを使って実行するスクリプトを準備します。
今回のスクリプトはこんな感じでした。require "net/https" require "uri" def lambda_handler(event:, context:) uri = URI.parse('https://hooks.slack.com/services/XXXXXXXXXXX/XXXXXXXXXXX/XXXXXXXXXXXXXXXXXX') res = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == "https") { |http| http.request(Net::HTTP::Post.new(uri).tap { |req| req.body = { channel: '通知させたいSlackチャンネル名', username: 'Webhookのときに設定したSlack投稿ユーザー名', text: '<@メンション飛ばす相手のユーザー名> アクアクララ、最後の1本を設置しました。', }.to_json }) } { statusCode: 200, body: res.to_s } endテストを作成してみます。なんでもいいようなので、今回はHelloWorldという既存テンプレートそのままの設定を使って作成し、実行してSlackへの投稿を確認します。
Slackに投稿できればひとまずコードはOKですね。次はいよいよボタンとAWSの連携です。AWS IoT1-Clickページでデバイスに連携
プロジェクトの作成
最後に、IoTボタンとLambda関数を連携させるプロジェクトをAWS IoT1-Clickのページから作成します。
コンソールにログインして、AWS IoT1-Clickのページを開きます。
プロジェクト名をいれてすすめると、デバイステンプレート名とアクションを選べます。
作ったLambda関数を指定します。
プレイスメントの作成
デバイスを指定してプレイスメントというものを作成していきます。
デバイスを指定し、属性の名前と値を入れます
ボタンを押してSlack連携を確認
連携されていればOKです!
参考サイト
この記事は下記Qiita記事を参考にさせていただきました。
おかげさまで半年以上元気に稼働しています、便利ですよ!
https://qiita.com/cumet04/items/11bc8883ae9cc603b84d
- 投稿日:2020-08-12T14:56:10+09:00
【コードゴルフ】コードをDeflate圧縮して短くする【圧縮ゴルフ】
コードゴルフを知っていますか?僕は知っています。できるだけ少ない文字数でコードを書く競技です。
この度、新しく圧縮部門ができてしまったので紹介しようと思います。
コードを圧縮する
まず、次のコードを見てください。
#!ruby -Knrzlib eval Zlib.inflate'x�=�Q � D��OS�c ]r� �����ݳ�By� ����O{4�.��i�aQ(`}cB���I2e�ߣ��IeT�јL>������)u,�p�S�W��H~.�,�: z:Ӊ��g�O7ʲ��vQ�1h�^<����=&�\u7'ほとんど読めないですね。
ですが、最初の方は普通にRubyのコードです。#!ruby -Knrzlib
これはShebangですが、コマンドラインオプションで
-Kn
と-rzlib
を指定しています。
-Kn
は文字コードがないバイナリとして扱うことを示します。#coding:binary
と同じ意味です。
-rzlib
はzlibライブラリをrequireしています。require "zlib"
と同じ意味です。次の行です。
eval Zlib.inflate'…
Zlib.inflate
は圧縮したコードを解凍するメソッドです。'
以降に圧縮された文字列が続いていることからも、このコードは圧縮されたコードを解凍してeval
していることがわかります。やってみる
コードを圧縮してこのようなテンプレートに埋め込めばよいことがわかりました。
これを実際にするには、①コードを書く、②圧縮する、③提出する、の3つのステップが必要です。
特に、圧縮率を下げるためには①と②の間を反復することが必要になります。1. コードを書く
まずはコードを書いてみましょう。(ここではコードの内容は問題ではないです)
agc047_e.rbputs [6484,a=?+,0,1,3,?<,2,3,3]+[0,1].map{|x|[a,x,3,x]+(0..29).map{v=x+4;u=x*60+9+_1;[a,v,v,v,a,v,3,6,*[a,6,6,6]*(29-_1),?<,6,x,u,a,v,u,v]}}+(0..59).map{|t|[a,2,2,2]+(0...t).map{[a,8+t-_1,69+_1,5,?<,3,5,6,a,2,6,2]}}このコードの長さは216 Bytesです。
書けたので、圧縮してみましょう2. 圧縮する
ここでは、 https://pastebin.com/TtNNhyND のスクリプトを使って圧縮していきます。
$ ruby deflate.rb agc047_e.rb > agc047_e.rb 194 B194 Bytesに縮みました!
3. 提出する
圧縮したら、さあ提出といきたいところですが、ひとつ問題があります。
残念ながら、このコードをコピペしてそのまま提出というわけにはいきません。圧縮して生成されたコードはバイナリです。しかし、AtCoderの提出画面はUTF-8です。多くの場合、圧縮してできたコードはUTF-8として正しくないバイト列を含んでいるので、そのままコピペすると化けてしまいます。そこで、DevToolsを使って、URIエンコードしたコード直接提出することにします。
提出画面を開いて、DevToolsを出します。ネットワークタブを開いておいてください。
この状態で提出ボタンを押してください。DevToolsにリクエストが表示されます。
ここで、submitという名前のリクエストを選んで右クリックし、Copy▶Copy as fetchを押してください。fetchするコードがコピーされます。そのままConsoleタブを開いて、今コピーされたコードを貼り付けます。
(画像には表示されていませんが)
sourceCode=
の後ろにURIエンコードされたソースを貼り付けていくことになります。URIエンコードするために https://pastebin.com/TA35nsHZ を使います。(deflate-uriencode.rbとして保存しておいてください)
$ ruby deflate-uriencode.rb agc047_e.rb 194 B %23%21ruby+-Knrzlib%0Aeval+Zlib.inflate%27x%DA-%8DQ%0A%830%10D%AF%D2Ou%B7A%13%5D%14%2B%1E%24%04%C9%01%0AB%13%094%B9%7Bwc%99%8F%81%99%E1%CD%19%C3%E7ai%9CG%F4%DB%0E%D8%E3%80%06%F7%17j6%E3%C0r%E0%D4%DB%9F%DF%9C%B2%F5%988N%0E%9A%5E%29%BD%B4%B5%B8%B6%04%E3%1A%B7%D4Q%0F%0B%1C%C3%CA%BB%ABJ%DC+a%C7%09%89%5C%D7%E8%E5y%0C%AD%5C%10%D3b%DDD%BC%5C%29%95%3A%FD%A99%C8%9D%16%DDw*%DC%05%A73%04f+%C9%19N%822l%84%B2%DE%97%F2%03%93%919%B0%DE%97%F2%03%93%919%B0%27deflate-uriencode.rbでagc047_e.rbを変換します。
出力の2行目の%23
から始まる文字列をコピーして、先程のsourceCode=
の後ろに貼り付けてください。この状態で実行すると提出することができます。
1. コードを書く(さらに短くなるように)
コードを縮めましょう。圧縮後のコードが短くなるためには、2つの方法があります。
- 元のコードを短くする
- 圧縮率を上げる
ここでは主に2の方法をやっていきます。1は普通のゴルフの方法ですね。
圧縮率を上げる
どうすれば圧縮率が上がるでしょうか。今、Deflate圧縮を使っていますが、Deflate圧縮はランレングス圧縮とハフマン符号の組み合わせです。このハフマン符号の方に注目します。
ハフマン符号は、圧縮前のエントロピーが小さい程圧縮率が高くなる特徴があります。エントロピーは、符号の出現確率が偏っている程小さくなります。なので、符号の出現確率を偏らせれば偏らせる程圧縮率が上がるということになりそうです。
出現確率を偏らせるには、文字種を減らしたりするのが有効です。最も簡単な方法としては、変数名を変更するなどです。
最初のコードで、変数
x
やv
の変数名を変更してt
やp
にしてみましょう。すると、関数名のputs
やmap
と被るので、文字種を減らすことができます。agc047_e.rbputs [6484,a=?+,0,1,3,?<,2,3,3]+[0,1].map{|t|[a,t,3,t]+(0..29).map{p=t+4;u=t*60+9+_1;[a,p,p,p,a,p,3,6,*[a,6,6,6]*(29-_1),?<,6,t,u,a,p,u,p]}}+(0..59).map{|t|[a,2,2,2]+(0...t).map{[a,8+t-_1,69+_1,5,?<,3,5,6,a,2,6,2]}}$ ruby deflate.rb agc047_e.rb > agc047_e.min.rb 275 Bあれ?増えてしまいました。
ではp
はやめてs
にしてみます。agc047_e.rbputs [6484,a=?+,0,1,3,?<,2,3,3]+[0,1].map{|t|[a,t,3,t]+(0..29).map{s=t+4;u=t*60+9+_1;[a,s,s,s,a,s,3,6,*[a,6,6,6]*(29-_1),?<,6,t,u,a,s,u,s]}}+(0..59).map{|t|[a,2,2,2]+(0...t).map{[a,8+t-_1,69+_1,5,?<,3,5,6,a,2,6,2]}}$ ruby deflate.rb agc047_e.rb > agc047_e.min.rb 184 B今度はちゃんと減っています。(なぜ増えたのかわからないので、詳しい方お願いします)
このように、書いて圧縮する試行錯誤を繰り返すことで、コードを縮めることができます。
- 投稿日:2020-08-12T14:56:10+09:00
【コードゴルフ】コードをDeflate圧縮してAtCoderに提出する【圧縮ゴルフ】
コードゴルフを知っていますか?僕は知っています。できるだけ少ない文字数でコードを書く競技です。
この度、AGC047 Eに提出された171 Bytesのコードが物議を醸しているので、コードの圧縮について解説しようと思います。
コードを圧縮する
まず、次のコードを見てください。
#!ruby -Knrzlib eval Zlib.inflate'x�=�Q � D��OS�c ]r� �����ݳ�By� ����O{4�.��i�aQ(`}cB���I2e�ߣ��IeT�јL>������)u,�p�S�W��H~.�,�: z:Ӊ��g�O7ʲ��vQ�1h�^<����=&�\u7'ほとんど読めないですね。
ですが、最初の方は普通にRubyのコードです。#!ruby -Knrzlib
これはShebangですが、コマンドラインオプションで
-Kn
と-rzlib
を指定しています。
-Kn
は文字コードがないバイナリとして扱うことを示します。#coding:binary
と同じ意味です。
-rzlib
はzlibライブラリをrequireしています。require "zlib"
と同じ意味です。次の行です。
eval Zlib.inflate'…
Zlib.inflate
は圧縮したコードを解凍するメソッドです。'
以降に圧縮された文字列が続いていることからも、このコードは圧縮されたコードを解凍してeval
していることがわかります。やってみる
コードを圧縮してこのようなテンプレートに埋め込めばよいことがわかりました。
これを実際にするには、①コードを書く、②圧縮する、③提出する、の3つのステップが必要です。
特に、圧縮率を下げるためには①と②の間を反復することが必要になります。1. コードを書く
まずはコードを書いてみましょう。(ここではコードの内容は問題ではないです)
agc047_e.rbputs [6484,a=?+,0,1,3,?<,2,3,3]+[0,1].map{|x|[a,x,3,x]+(0..29).map{v=x+4;u=x*60+9+_1;[a,v,v,v,a,v,3,6,*[a,6,6,6]*(29-_1),?<,6,x,u,a,v,u,v]}}+(0..59).map{|t|[a,2,2,2]+(0...t).map{[a,8+t-_1,69+_1,5,?<,3,5,6,a,2,6,2]}}このコードの長さは216 Bytesです。
書けたので、圧縮してみましょう2. 圧縮する
ここでは、 https://pastebin.com/TtNNhyND のスクリプトを使って圧縮していきます。
$ ruby deflate.rb agc047_e.rb > agc047_e.min.rb 194 B194 Bytesに縮みました!
3. 提出する
圧縮したら、さあ提出といきたいところですが、ひとつ問題があります。
残念ながら、このコードをコピペしてそのまま提出というわけにはいきません。圧縮して生成されたコードはバイナリです。しかし、AtCoderの提出画面はUTF-8です。多くの場合、圧縮してできたコードはUTF-8として正しくないバイト列を含んでいるので、そのままコピペすると化けてしまいます。そこで、DevToolsを使って、URIエンコードしたコード直接提出することにします。
提出画面を開いて、DevToolsを出します。ネットワークタブを開いておいてください。
この状態で提出ボタンを押してください。DevToolsにリクエストが表示されます。
ここで、submitという名前のリクエストを選んで右クリックし、Copy▶Copy as fetchを押してください。fetchするコードがコピーされます。そのままConsoleタブを開いて、今コピーされたコードを貼り付けます。
(画像には表示されていませんが)
sourceCode=
の後ろにURIエンコードされたソースを貼り付けていくことになります。URIエンコードするために https://pastebin.com/TA35nsHZ を使います。(deflate-uriencode.rbとして保存しておいてください)
$ ruby deflate-uriencode.rb agc047_e.rb 194 B %23%21ruby+-Knrzlib%0Aeval+Zlib.inflate%27x%DA-%8DQ%0A%830%10D%AF%D2Ou%B7A%13%5D%14%2B%1E%24%04%C9%01%0AB%13%094%B9%7Bwc%99%8F%81%99%E1%CD%19%C3%E7ai%9CG%F4%DB%0E%D8%E3%80%06%F7%17j6%E3%C0r%E0%D4%DB%9F%DF%9C%B2%F5%988N%0E%9A%5E%29%BD%B4%B5%B8%B6%04%E3%1A%B7%D4Q%0F%0B%1C%C3%CA%BB%ABJ%DC+a%C7%09%89%5C%D7%E8%E5y%0C%AD%5C%10%D3b%DDD%BC%5C%29%95%3A%FD%A99%C8%9D%16%DDw*%DC%05%A73%04f+%C9%19N%822l%84%B2%DE%97%F2%03%93%919%B0%DE%97%F2%03%93%919%B0%27deflate-uriencode.rbでagc047_e.rbを変換します。
出力の2行目の%23
から始まる文字列をコピーして、先程のsourceCode=
の後ろに貼り付けてください。この状態で実行すると提出することができます。
4. コードを修正する(さらに短くなるように)
コードを縮めましょう。圧縮後のコードが短くなるためには、2つの方法があります。
- 元のコードを短くする
- 圧縮率を上げる
ここでは主に2の方法をやっていきます。1は普通のゴルフの方法ですね。
圧縮率を上げる
どうすれば圧縮率が上がるでしょうか。今、Deflate圧縮を使っていますが、Deflate圧縮はランレングス圧縮とハフマン符号の組み合わせです。このハフマン符号の方に注目します。
ハフマン符号は、圧縮前のエントロピーが小さい程圧縮率が高くなる特徴があります。エントロピーは、符号の出現確率が偏っている程小さくなります。なので、符号の出現確率を偏らせれば偏らせる程圧縮率が上がるということになりそうです。
出現確率を偏らせるには、文字種を減らしたりするのが有効です。最も簡単な方法としては、変数名を変更するなどです。
最初のコードで、変数
x
やv
の変数名を変更してt
やp
にしてみましょう。すると、関数名のputs
やmap
と被るので、文字種を減らすことができます。agc047_e.rbputs [6484,a=?+,0,1,3,?<,2,3,3]+[0,1].map{|t|[a,t,3,t]+(0..29).map{p=t+4;u=t*60+9+_1;[a,p,p,p,a,p,3,6,*[a,6,6,6]*(29-_1),?<,6,t,u,a,p,u,p]}}+(0..59).map{|t|[a,2,2,2]+(0...t).map{[a,8+t-_1,69+_1,5,?<,3,5,6,a,2,6,2]}}$ ruby deflate.rb agc047_e.rb > agc047_e.min.rb 275 Bあれ?増えてしまいました。
ではp
はやめてs
にしてみます。agc047_e.rbputs [6484,a=?+,0,1,3,?<,2,3,3]+[0,1].map{|t|[a,t,3,t]+(0..29).map{s=t+4;u=t*60+9+_1;[a,s,s,s,a,s,3,6,*[a,6,6,6]*(29-_1),?<,6,t,u,a,s,u,s]}}+(0..59).map{|t|[a,2,2,2]+(0...t).map{[a,8+t-_1,69+_1,5,?<,3,5,6,a,2,6,2]}}$ ruby deflate.rb agc047_e.rb > agc047_e.min.rb 184 B今度はちゃんと減っています。(なぜ増えたのかわからないので、詳しい方お願いします)
このように、書いて圧縮する試行錯誤を繰り返すことで、コードを縮めることができます。
細かい注意事項など
- 投稿日:2020-08-12T08:41:30+09:00
ruby におけるopensslバージョン情報 OPENSSL_VERSION
$ irb
irb(main):001:0> require 'openssl'
=> true
irb(main):002:0> puts OpenSSL::OPENSSL_VERSION
OpenSSL 1.1.1g 21 Apr 2020
=> nil
irb(main):003:0>又は
$ ruby -ropenssl -e "p OpenSSL::OPENSSL_VERSION"
"OpenSSL 1.1.1g 21 Apr 2020"Mac ruby 2.0.0におけるDEFAULT_CERT_FILEのディレクトリ情報 - Qiita
https://qiita.com/shiro_yone/items/311be28fa29da54d7f11irb(main):002:0> require 'openssl'
=> true
irb(main):003:0> p OpenSSL::X509::DEFAULT_CERT_FILE
"/usr/local/stow/openssl-111g/ssl/cert.pem"
=> "/usr/local/stow/openssl-111g/ssl/cert.pem"
irb(main):004:0>又は
$ ruby -ropenssl -e "p OpenSSL::X509::DEFAULT_CERT_FILE"
"/usr/local/stow/openssl-111g/ssl/cert.pem"参考
RubyのOpenSSL::OPENSSL_VERSIONはなぜ定数? / マスタカの ChangeLog メモ
https://masutaka.net/chalow/2014-04-08-1.html
- 投稿日:2020-08-12T04:26:44+09:00
【Rails】もう迷いたくない。モデル、テーブル、コントローラ、ビューの新規作成。
はじめに
この記事はRailsアプリを立ち上げた後の作業をまとめたものです。
何らかの機能を作る際には、モデルを作ってコントローラ作ってルーティング書いて...といった作業が頻発します。
毎回構文を忘れてしまうので、一連の流れをまとめました。コントローラの作成
まずはコントローラの作成です。
今回は画像を保存する機能を作るのでimagesとします。rails g controller imagesモデルの作成
下記のコマンドでimageモデルを作りましょう!
rails g model imageこれでimageモデルが作成されたと思います。
必要であれば、モデルにバリデーションやアソシエーションを記述しましょう。テーブル作成
モデルを作成した際にマイグレーションファイルも作成されたと思います。
このファイルを編集して主キーやnull制約などの設定を行います。
私の場合は、以下のようにして”filename”を主キーにし、null制約をかけています。
主キーにしたのでそんな制約要らないかもしれませんが...class CreateImages < ActiveRecord::Migration[5.2] def change create_table :images, id: false, primary_key: :filename do |t| t.string :filename, null: false t.timestamps end end endそれではマイグレートを実行し、正常終了すればテーブルが作成されます!
rails db:migrateビューの作成
画像の一覧を表示するページということで、index.html.hamlを作りましょう。
これまでの作業でimagesディレクトリが作成されているので、そこに作成します。
ビューの内容については、今回の記事で詰めるところではないので適当に"HelloWorld"を出しておきます。%h1 HelloWorldルーティング
ここまで来ればほぼ出来たようなものです。
routes.rbにimagesのルーティングを記載します。
今回はresourcesメソッドを使用してindexアクションのみを設定しました。Rails.application.routes.draw do resources :images, only: [:index] end結果
出来ました!これで仕事が捗る...!
- 投稿日:2020-08-12T00:21:42+09:00
Rails Tutorialを咀嚼する【第1章ゼロからデプロイまで】後半
1.4 Gitによるバージョン管理
■Git
バージョン管理ツール。Gitで都度都度作業を保存することで、やり直しができたりする。
addしてからcommitしてpushする。■Bitbucket
git専門のホスティングサービス。GitHubの仲間。1.5 デプロイする
■Heroku
Paas。FFFTPとか使わず、開発したものをサーバーにアップロードすることができる。SQLiteが使えないため、若干厄介。【演習】
1も2も大したことないので省略。■('a'..'z').to_a.shuffle[0..7].join
ランダムなアルファベット8文字を表示してくれる。
aからzのアルファベットを配列に格納。
配列の順番をシャッフルする。
0から7番目(8個)まで取り出す。
結合して文字列にする。【演習】
1も2も省略。分ける必要はなかった。後で結合する。
- 投稿日:2020-08-12T00:14:11+09:00
Ruby文字列操作いろいろ
はじめに
Rubyの文字列操作メソッドを勉強するために解いた問題とその回答を記録として残す。
問題1
"This" " is" " a" " pen"を"This is a pen"に変換しなさい。
回答1
"This" + " is" + " a" + " pen"補足
「+」は文字列を連結することができる。
問題2
"BENZ, BMW, Audi"を["BENZ", " BMW", " Audi"]に変換しなさい。
回答2
"BENZ, BMW, Audi".split(",")補足
[ ]は配列を表す。
splitメソッドは文字列を分割することができる。
回答のように使用するとカンマで区切ることができる。問題3
"apple"を"Apple"に変換しなさい。
回答3
"apple".capitalize補足
capitalizeメソッドは最初の文字を大文字にすることができる。
問題4
"qiita"を"atiiq"に変換しなさい。
回答4
"qiita".reverse補足
reverseメソッドは文字列を反転することができる。
問題5
"Good morning"を"GOOD MORNING"に変換しなさい。
回答5
"Good morning".upcase補足
upcaseメソッドは小文字を大文字に変換することができる。
引用