毎日投稿する技術ブログ(WEB系)

2018年12月から毎日技術ブログを投稿してます。 何か不備があれば、お気軽にコメント頂けると有り難いです。

Rubyの「|」「&」「||」「&&」の違い

f:id:ryoutaku_jo:20190716022323p:plain

【結論】

・「||」「&&」は、論理演算子と呼ばれ、条件式で論理積(AND)や論理和(OR)を指定する際に用いられる

・「|」「&」は、Integerクラス(数値)ではビット演算子、Arrayクラス(配列)では集合の演算子として機能する

・「|」「&」はオーバーライド可能だが、「||」「&&」はオーバーライド出来ない。

【目次】

【本題】

「|」「&」「||」「&&」について

Ruby演算子「|」「&」「||」「&&」は、それぞれ役割が異なります。

今回は、それぞれの機能についてまとめます。

論理演算子「||」「&&」

「||」「&&」は、論理演算子と呼ばれ、条件式で論理積(AND)や論理和(OR)を指定する際に用いられます

#「&&」は全ての式が真だとtrue
1 == 1 && 2 == 2
=> true

1 == 1 && 2 == 3
=> false

#「||」はいずれかの式が真だとtrue
1 == 1 || 2 == 2
=> true

1 == 1 || 2 == 3
=> true

1 == 2 || 2 == 3
=> false

なお、論理演算子においては左辺で結果が確定している場合、右辺は評価されません。

「||」の場合、左辺が真であれば結果は確定します。

「&&」の場合、左辺が偽であれば結果が確定します

これらの場合、仮に右辺が例外の発生する様な式だとしても、評価されてないのでエラーは出なくなります。

オブジェクトによって動きの変わる「|」「&」

「|」「&」は使用するオブジェクトのクラスによって動きが変わります。

Integerクラス(数値)の場合、ビット演算子となります

#「|」は論理和を返します
10 | 3
=> 11

#「&」は論理積を返します
10 & 3
=> 2

Arrayクラス(配列)の場合は、集合の演算子となります。

a = [1,2,3,4,5,6]
=> [1, 2, 3, 4, 5, 6]

b = [2,4,6]
=> [2, 4, 6, 8, 10]

#「&」はいずれにも含まれる値を返します
a & b
=> [2, 4, 6]

#「||」はいずれかに含まれる値を返します
a | b
=> [1, 2, 3, 4, 5, 6, 8, 10]

「||」「&&」はオーバーライド不可

「|」「&」演算子として機能していますが、オブジェクトによって動きを変える使用上、実際にはメソッドとして定義されています。

その為、「|」「&」はオーバーライド(再定義)する事が可能となっています。

しかし、「||」「&&」は演算子として定義されている為、オーバーライド(再定義)出来ない仕様となっています。

参考情報

Ruby | 再定義できる演算子 で組み込み演算子風のメソッドを定義する #ruby - Qiita

ビット演算入門 - Qiita

《今日の学習進捗(3年以内に10000時間に向けて)》

明日のRubysilver受験に向けて勉強中。

学習開始からの期間 :220日
今日までの合計時間:2114h
一日あたりの平均学習時間:9.7h
今日までに到達すべき目標時間:2009h
目標との解離:105h
「10,000時間」まで、

残り・・・「7886時間!」

破壊的メソッドについて

f:id:ryoutaku_jo:20190715004206p:plain

【結論】

・破壊的メソッドとは、レシーバにあたるオブジェクトの値を変更してしまうメソッド

・破壊的メソッドは、メソッド名にを付ける慣習がある

・しかしRubyでは、他に同名のメソッドが存在しない破壊的メソッドにはが付いていない為、注意が必要

【目次】

【本題】

破壊的メソッドについて

破壊的メソッドとは、レシーバにあたるオブジェクトの値を変更してしまうメソッドの事です。

具体例は以下の通りです。

text = '12345'
=> "12345"

#非破壊的メソッドを実行
text.chop
=> "1234"

#オブジェクトの値は変わらない
text
=> "12345"

#破壊的メソッドを実行
text.chop!
=> "1234"

#オブジェクトの値も変わる
text
=> "1234"

を付ける慣習

なお、破壊的メソッドのメソッド名にはを付ける慣習が存在します。

しかしこの慣習は、同じメソッド名の破壊的メソッドと非破壊的メソッドの両方が存在する場合に、それぞれを見分ける為に用いられます。

その為、同じメソッド名の非破壊的メソッドが存在しない場合は、破壊的メソッドであったとしてもは付いていません。

そういったメソッドを不用意に使用してしまうとオブジェクトの値が書き換わり、予期せぬバグを生み出す恐れがある為、が付かない破壊的メソッドは一通り把握しておく必要があります。

が付いていない破壊的メソッドの例

concat (Array):配列arrayの末尾に引数の配列other_arrayを結合します。
insert(Array):第一引数で指定した位置に第二引数を要素として挿入します。
push(Array):配列の末尾に引数を要素として追加します
unshift(Array):第一引数を配列の先頭に要素として追加します。
delete(Array):配列から引数と同じ要素を探して、すべて削除します。
delete_at(Array):配列から引数の位置の要素を削除します。
delete_if(Array):ブロックの戻り値が真になった要素を削除します。
clear(Array):要素をすべて削除し、配列を空にします。
shift(Array):配列の最初の要素を削除し、その要素を返します
pop(Array):配列の末尾の要素を削除し、その要素を返します。

参考情報

【Ruby】「!」が付かない破壊的メソッドまとめ - Qiita

Rubyの破壊的メソッドについて - Qiita

《今日の学習進捗(3年以内に10000時間に向けて)》

実家帰省中だが、隙間の時間でRubysilverの勉強中。

学習開始からの期間 :219日
今日までの合計時間:2108h
一日あたりの平均学習時間:9.7h
今日までに到達すべき目標時間:2000h
目標との解離:108h
「10,000時間」まで、

残り・・・「7892時間!」

Rubyのパーセント記法について

f:id:ryoutaku_jo:20190714065630p:plain

【結論】

・文字列(Stringクラスのインスタンス)を生成する際、通常は""''で文字を囲って、文字列と認識させる必要がある

・パーセント記法とは、""''以外の記号などで文字列を囲って、文字列と認識させる記法

・可読性の向上やコード量の削減といった目的で利用されるケースが多い

【目次】

【本題】

パーセント記法について

Rubyでは、通常文字列(Stringクラスのインスタンス)を生成する際、通常は""''で文字を囲って、文字列と認識させる必要があります。

パーセント記法とは、""''以外の記号などで文字列を囲って、文字列と認識させる記法です。

パーセント記法の種類

パーセント記法には生成したい値によって記法が異なります。

以下が、生成される値と対応した記法です。

%・・・ダブルクォート文字列(%Qと同等) %Q・・・ダブルクォート文字列(%と同等) %q・・・シングルクォート文字列 %s・・・シンボル %W・・・要素がダブルクォート文字列となる配列 %w・・・要素がシングルクォート文字列となる配列 %x・・・コマンド入力 %r・・・正規表現

ダブルクォート文字列・シングルクォート文字列

基本的な""''で文字を囲った時と同じ働きをする記法です。

ダブルクォート文字列を生成する場合は、%Qを用います。

%*hoge*
=> "hoge"

%Q(hoge)
=> "hoge"

シングルクォート文字列を生成する場合は、%qを用います。

%q!hoge!
=> "hoge"

シンボル

シンボルを生成する場合は、%sを用います。

%s!hoge!
=> :hoge

配列

パーセント記法では配列も生成出来ます。

要素としたい文字列を空白文字で区切って用います。

要素の文字列をシングルクォート文字列にしたい場合は%w、ダブルクォート文字列にしたい場合は%Wを利用します。

%W[pen pineapple apple pen]
=> ["pen", "pineapple", "apple", "pen"]

%w[pen pineapple apple pen]
=> ["pen", "pineapple", "apple", "pen"]
=> :hoge

コマンド入力

コマンド入力を実行する場合は、%xを用います。

%x(date)
=> "Sun Jul 14 07:31:05 JST 2019\n"

正規表現

%r正規表現を扱う事もできます

%rを用いれば、特殊文字エスケープする必要する必要は無くなります。

#通常通りの正規表現オブジェクトの記法だとエスケープが必要
/http:\/\/sample\.com/

#%記法ならエスケープ不要
%r(http://sample.com)

パーセント記法を利用するメリット

通常の記述方法でも、文字列は生成出来ますが、それでも敢えてパーセント記法を用いるメリットは、以下の2点にあります。

可読性の向上

パーセント記法を用いる事で、コードが読みやすくなるというメリットがあります。

例えば、URLを正規表現で特定する際、「http:// で始まる」という条件をそのまま/^http:\/\//と書くと見にくいので、%r|^http://|と書くと見やすくなります。

コード量の削減

パーセント記法を用いる事で、コードを書く量が減らせられるというメリットがあります。

例えば、配列に文字列を格納する際、それぞれにダブルクォート(シングルクォート)を書くとなると、非常に手間が掛かりますが、パーセント記法を用いれば、それを省けます。

参考情報

Rubyで%記法(パーセント記法)を使う - Qiita

Rubyの%(パーセント)を使った記法まとめ - Hack Your Design!

【チートシート】Rubyの%(パーセント)記法の使い方 | shin>>media

Ruby - Ruby パーセント記法の使い道について|teratail

《今日の学習進捗(3年以内に10000時間に向けて)》

実家帰省につき、勉強は少なめ。

Rubysilverの試験が3日後に迫っているので、3連休はそちらの勉強に費やす予定。

改めて基本的な事を何も知らないと実感している。試験に受かったとしても、リファレンス読み返したりして、色んな実装方法を学ぶ必要性を感じた。

それと今回でブログの投稿数が200件に達した。

3年続けるとなると、まだ5分の1にも満たないが、それなりに達成感はある。

とりあえず、これからも淡々と続けていく。

学習開始からの期間 :218
今日までの合計時間:2102h
一日あたりの平均学習時間:9.7h
今日までに到達すべき目標時間:1991h
目標との解離:111h
「10,000時間」まで、

残り・・・「7898時間!」

CKEditorの編集領域でpタグにmarginが設定されてしまうのを回避する方法

f:id:ryoutaku_jo:20190713151019p:plain

【結論】

・デCKEditorでは、デフォルトの書式で入力した文章はpタグで出力されるが、ブラウザCSSによってmarginが設定されてしまい、意図せぬ空白が生まれてしまう

・divタグであれば、ブラウザCSSによる影響を受けないので、書式を「標準(div)」にすれば、空白は生じない

・デフォルトでdivタグを有効にする設定も存在する

【目次】

【本題】

前回の記事でも紹介しましたが、ChromeなどのブラウザはデフォルトのCSSを持っており、それにより意図せずデザインが崩れる事があります。

ryoutaku-jo.hatenablog.com

今回つまずいたのが、CKEditorの編集領域のpタグです。

CKEditorでは、デフォルトの書式で入力した文章はpタグで出力されます。

pタグは、ブラウザCSSによって、以下の様なmarginが設定されています。

f:id:ryoutaku_jo:20190711224205p:plain

f:id:ryoutaku_jo:20190711224154p:plain

本来は文章同士は空白が無い様にしたいので、ブラウザCSSが邪魔です。

しかしCKEditorの編集領域は、JavaScriptで生成される関係上、通常の方法ではリセットCSSが適用されません。

ファイル一式をホストすれば、CKEditor側のCSSファイルでpタグのmarginの設定を追記してやれば何とか出来そうですが、今回はCDNを使っているので、別の方法でこの空白に対処する事にしました。

divタグであれば影響は受けない

CKEditorでは入力文字の書式を選択できますが、そこで標準(div)を選択すると、pタグではなくdivタグで出力されます。

これによりブラウザCSSのmarginによる影響を回避出来ます。

CKEDITOR.replace( 'editor', {
  //ツールバーのカスタマイズ
  toolbarGroups: [
    { name: 'styles',    groups: [ 'styles' ] },
    { name: 'paragraph', groups: [ 'align' ] },
    { name: 'links',     groups: [ 'links' ]},
    { name: 'insert',    groups: [ 'insert' ]},
  ],

  //不要なツールバーのボタンを削除
  removeButtons:
    'Styles,FontSize,Font,Italic,Underline,Strike,Subscript,Superscript,JustifyBlock,' +
    'Flash,Table,HorizontalRule,Smiley,SpecialChar,PageBreak,Iframe,Unlink,Anchor',

  //書式の選択肢
  format_tags: 'div;h1;h2;h3',
});

f:id:ryoutaku_jo:20190713154041p:plain

f:id:ryoutaku_jo:20190713154053p:plain

デフォルトでdivタグを適用させる方法

なお先ほどの方法だと、毎回書式を設定する必要があります。

デフォルトでdivタグを設定する場合は、以下のコードで実装可能です。

  //標準文章がpタグではなくdivタグで囲われる様に変更(pタグはブラウザCSSの影響で余計なmarginが適用される為)
  enterMode: CKEDITOR.ENTER_DIV,

参考情報

https://ckeditor.com/docs/ckeditor4/latest/features/format.html

https://ckeditor.com/docs/ckeditor4/latest/features/enterkey.html

《今日の学習進捗(3年以内に10000時間に向けて)》

CMS機能の改修を通して、フロントエンド側の開発は、開発完了を定義がしづらいと改めて感じた。

ユーザーにとっての使いやすさを考慮しだすと、画面構成やサイト導線など、拘り出せばいくらでも改良の余地がある。

一方で、バックエンドの開発であれば、ユーザーにとっての使いやすさを考慮しても、要件を分解すれば、特定の機能を追加するだけなので、「〇〇が出来る」という明確な完了の定義が設定しやすい。

完了の定義が曖昧だと、手戻りの発生などによる作業の遅延に繋がるので、フロント側も関わる開発に着手する際は、完了の定義をより明確にする必要性を感じました。

学習開始からの期間 :217日
今日までの合計時間:2100h
一日あたりの平均学習時間:9.7h
今日までに到達すべき目標時間:1982h
目標との解離:118h
「10,000時間」まで、

残り・・・「7900時間!」

デベロッパーツールで確認出来るCSSの「user agent stylesheet」について

f:id:ryoutaku_jo:20190711222301p:plain

【結論】

・「user agent stylesheet」とは、ブラウザ毎に定義されているデフォルトのCSS

GoogleChromeデベロッパーツールで確認する事が可能

・リセットCSSを使っても消えない場合があり、その時はスタイルを上書きして対処する

【目次】

【本題】

user agent stylesheet

全てのブラウザはデフォルトでCSSを持っています。

それにより、本来意図したCSSが適用されず、ページのデザインが崩れてしまうことがあります。

「user agent stylesheet」とは、そういったデフォルトのCSSを指します。

「user agent stylesheet」は、GoogleChromeデベロッパーツールで確認する事が可能です。

f:id:ryoutaku_jo:20190711224154p:plain

f:id:ryoutaku_jo:20190711224205p:plain

リセットCSSについて

こういったブラウザ固有のCSSを打ち消す為に、リセットCSSが存在します。

リセットCSSは無料でコードが配布されていたりするので、簡単に導入する事が可能です。

webdesign-trends.net

coliss.com

適用されない場合もある

しかしリセットCSSを使用しても消えない場合もあるので、その場合はスタイルを上書きして修正します。

f:id:ryoutaku_jo:20190711224216p:plain

f:id:ryoutaku_jo:20190711224229p:plain

参考情報

Chromeのデベロッパーツールに出てくる「user agent stylesheet」とは

user agent stylesheetとは何者か - 日々精進

https://coliss.com/articles/build-websites/operation/css/user-agent-stylesheets.html

CSSのuser agent stylesheetとは。 - よくきたわね、いらっしゃい

《今日の学習進捗(3年以内に10000時間に向けて)》

機能性を重視して複雑になってしまった機能の改修を行っているが、シンプルな構成を維持することの難しさを改めて感じた。

自社のサービスがSaaSという事もあり、様々な要望に汲み取って機能を増やしているが、それによって操作が複雑になったり、一画面の情報量が多くなった箇所が増えたことで、さっと試した人に取っ付きにくいという印象を与えてしまうことを懸念している。

例えば、必ずしも全ての人が設定しない項目も、等しく表示されることで、設定不要な人から煩わしく感じられるかもしれないといったことである。

(例え任意の項目ばかりだったとしても、設定項目が大量に並んでいると、心理的なハードルは上がると考えられる。)

また、ある程度サービスに触れた人から出た要望というのは、サービスに初めて触れる人にとっては仕様を理解しづらいかもしれない。

必須で無かったり、使用する人が稀な機能であれば、フォームを目立たない様にしたり、本流のサイト導線とは別のところに設定画面を設けるなどして、心理的な負担を軽減させる措置は必要だと考えている。

学習開始からの期間 :216日
今日までの合計時間:2092h
一日あたりの平均学習時間:9.7h
今日までに到達すべき目標時間:1973h
目標との解離:119h
「10,000時間」まで、

残り・・・「7908時間!」

CKeditor4の機能拡張方法(ドラック&ドロップ・動画埋め込み・カスタムスタイル)

f:id:ryoutaku_jo:20190710204423p:plain

【結論】

uploadfileを導入すれば、ドラック&ドロップでアップロードも可能になる。

embedを導入すれば、YouTubeなどの動画メディアを埋め込める。autoembedを導入すれば、リンクを貼り付けるだけで自動で埋め込める。

・画像を均等に横並びさせるなど、任意をスタイルを当てたい場合は、カスタムスタイルを設定する事も可能。

【目次】

【本題】

CKeditor4の機能拡張方法

リッチエディタであるCKeditorは、デフォルトでも多くの機能を提供していますが、更に機能を追加したい場合は、各種プラグインを導入する必要があります。

今回は、そのプラグインについてまとめます。

※CKEditorについては、以下の記事参照

ryoutaku-jo.hatenablog.com

ryoutaku-jo.hatenablog.com

ドラック&ドロップでファイルアップロード(uploadfile)

ファイルをアップロードする際、アイコンから選択しなくても、ドラック&ドロップでアップロードされる様にする場合は、uploadfileを導入します。

CKEDITOR.replace( 'editor', {

  //拡張プラグインを導入
  extraPlugins: [ 'image2', 'uploadfile', ],

〜中略〜

});

f:id:ryoutaku_jo:20190711001323g:plain

なお、画像の場合は、そのまま表示されます

f:id:ryoutaku_jo:20190711001451g:plain

YouTubeなどの動画メディアの埋め込み

YouTubeなどの動画メディアの埋め込みたい場合はembedを利用します。

また埋め込むメディアを認識させる為に、コールバック用のURLも指定する必要があります。

CKEDITOR.replace( 'editor', {

  //拡張プラグインを導入
  extraPlugins: [ 'image2', 'uploadfile', 'embed' ],

  //embedとの連携用(動画メディアのURLを貼り付けるだけ自動埋め込み)
  embed_provider: '//ckeditor.iframe.ly/api/oembed?url={url}&callback={callback}',

〜中略〜

});

f:id:ryoutaku_jo:20190711001948g:plain

またautoembedを導入することで、動画のURLをフォームに貼り付けるだけで自動埋め込みが出来ます。

CKEDITOR.replace( 'editor', {

  //拡張プラグインを導入
  extraPlugins: [ 'image2', 'uploadfile', 'embed', 'autoembed', ],

〜中略〜

});

f:id:ryoutaku_jo:20190711001759g:plain

画像の横並びに対応(カスタムスタイル)

画像を横一列に均一な幅で配置させたい場合などは、独自のスタイルを設定して、それを適用させる必要があります。

//カスタムスタイルの定義
CKEDITOR.stylesSet.add( 'my_styles', [
  // Block-level styles.
  { name: 'グレーライン',  element: 'h3', styles: {
    'background': '#eeeeee',
    'border': '1px solid #cccccc',
    'padding': '15px' }
  },

  // Inline styles.
  { name: '画像横並び', element: 'span', styles: {
    'justify-content': 'space-around',
    'display': 'flex',
    'text-align': 'center',
    'flex-direction': 'row',
    'flex-wrap': 'wrap',
    'align-items': 'center', }
  },
  { name: 'イエローマーカー', element: 'span', styles: {
    'background-color': 'Yellow' }
  },
]);

CKEDITOR.replace( 'editor', {

〜中略〜

  stylesSet: 'my_styles',
});

f:id:ryoutaku_jo:20190711002200g:plain

この他にも独自のスタイルを設定することで、様々なレイアウトを適用させる事が可能です。

参考情報

※ファイルアップロードについて https://ckeditor.com/docs/ckeditor4/latest/guide/dev_howtos_file_upload.html

※動画の貼り付けについて https://ckeditor.com/docs/ckeditor4/latest/examples/mediaembed.html

※スタイルのカスタマイズについて https://ckeditor.com/docs/ckeditor4/latest/guide/dev_howtos_styles.html

《今日の学習進捗(3年以内に10000時間に向けて)》

CKEditorだが、現状の仕様でもWrodを使える程度のITリテラシーのある方なら問題なく使えると考えていたが、CTOからこれでは分かりづらいとレビューを受けて、認識が甘かったと実感した。

実際に開発に携わるエンジニアとして、最もサービスに触れる機会が多い事で、こういった認識のズレは今後も発生すると考えている。

今後は、実際にサービスを利用される非エンジニア(特に事務局)の方は、自分の想像以上にITリテラシーは低いと想定して開発に取り組むことで、開発効率とサービスの品質向上に努めたい。

学習開始からの期間 :215日
今日までの合計時間:2084h
一日あたりの平均学習時間:9.7h
今日までに到達すべき目標時間:1963h
目標との解離:121h
「10,000時間」まで、

残り・・・「7916時間!」

Railsでデータの初期値を設定する方法(DBとモデルの設定パターン)

f:id:ryoutaku_jo:20190710002327p:plain

【結論】

Railsでデータの初期値を設定するには、DB側で設定する方法と、モデルで設定する2通りが存在する

・DBで設定する場合は、マイグレーションファイルの該当カラムのオプションにdefault値を設定する。

・モデルで設定する場合は、after_initializeで対応できる。動的に初期値を設定できる反面、インスタンスが生成されたときに発火する為、whereメソッドなどでもコールバックが実行されるので、実装には注意が必要。

【目次】

【本題】

Railsでデータの初期値を設定する方法

フォームに入力する項目などのデータの初期値を設定する場合、Railsでは主に2通りの方法が存在します。

今回は、その方法についてまとめます。

DB側で設定する方法

まず一つが、DB側で設定する方法です。

これは、マイグレーションファイルの該当カラムのオプションにdefault値を記述して設定する。

t.integer :role, null: false, default: 0

モデルで設定する場合

もう一つは、モデルで設定する方法です。

after_initializeインスタンスを生成した際に、デフォルト値を登録するメソッドを呼び出す様に実装します。

after_initialize :set_default, if: :new_record?

  def set_default
    self.role ||= 1
  end

DBの設定だと決まった値した設定できませんが、モデルの場合だと動的に値を設定する事が出来ます。

モデルで設定する場合の注意点

after_initializeには、インスタンスが生成される度に発火するという特徴があります。

その為、whereメソッドなどでもコールバックが実行されてしまうという欠点があります。

なので、安易に実装すると思わぬ不具合を招く恐れがある為、取り扱いには注意が必要です。

参考情報

Railsのモデルのデフォルト値設定 - Qiita

Ruby - これは ActiveModelのafter_initialize ということでしょうか?|teratail

Railsのコールバックまとめ | TECHSCORE BLOG

after_initializeの使いドコロがわからない

《今日の学習進捗(3年以内に10000時間に向けて)》

CKEditorの機能拡張(ファイルアップロード・動画埋め込み・テンプレートなど)を行ったが、やはりユーザーのニーズを満たすには程遠い仕様だと感じる。

CKEditorに頼らないCMSの実装が必要だと改めて実感した。

なお、サービスの本格リリースに必要な機能は、現状私のタスクを残すのみなので、全体のスケジュールが遅延しない様に、なんとか今週中には形にしたい。

学習開始からの期間 :214日
今日までの合計時間:2072h
一日あたりの平均学習時間:9.7h
今日までに到達すべき目標時間:1954h
目標との解離:118h
「10,000時間」まで、

残り・・・「7928時間!」

「permutation」「combination」メソッドによる順列/組み合わせの数え上げ

f:id:ryoutaku_jo:20190708223534p:plain

【結論】

permutation メソッドは、配列から引数n個の要素を選んだときの順列を数え上げる。

combinationメソッドは、配列から引数n個の要素を選んだときの組合せを数え上げる。

・要素の重複を許可する場合はrepeated_combination メソッド(repeated_permutationメソッド )を利用する。

【目次】

【本題】

順列と組み合わせの違い

Rubyには、配列から順列・組み合わせと数え上げるメソッドが存在します。

それらの解説の前に、それぞれの違いについて説明します。

「順列」「組み合わせ」は、以下の様に定義されています。

・順列 n個の中から、r個を順番に取り出して並べる総数。

・組み合わせ n個の集合の中からm個を取り出す組合せ

これだけだと分かりづらいですが、簡単に言うと「順序違いによる重複を許可するか?しないか?」の違いです。

例えば「1・2・3・4・5」の5枚のカードがあるとします。

この5枚のカードについて、2種類の問題を出します。

1:「このカードから2枚を選び、2ケタの数字を作る場合、作れる数字は何通りあるか?」 2:「このカードから2枚を選ぶ場合、選び方は何通りあるか?」

それぞれ同じ問題に見えますが、答えが異なります。

1の答えが「20通り」です。 2の答えが「10通り」です。

1の場合、「1・2」と「2・1」という順番が違うが組み合わせが同じ場合でも、数にカウントされます。 2の場合、「1・2」と「2・1」は、同じ組み合わせ(重複)と見なされて、片方が数にカウントされません。

その為、この様な違いが生まれています。

permutationメソッド

permutationメソッドは、配列から引数n個の要素を選んだときの順列を数え上げます。

numbers = [1, 2, 3, 4, 5]
numbers.permutation(2) {|a, b| printf("(%d, %d) ", a, b) }
=> (1, 2) (1, 3) (1, 4) (1, 5) (2, 1) (2, 3) (2, 4) (2, 5) (3, 1) (3, 2) (3, 4) (3, 5) (4, 1) (4, 2) (4, 3) (4, 5) (5, 1) (5, 2) (5, 3) (5, 4)

combinationメソッド

combinationメソッドは、配列から引数n個の要素を選んだときの組合せを数え上げる。

numbers = [1, 2, 3, 4, 5]
numbers.combination(2) {|a, b| printf("(%d, %d) ", a, b) }
=> (1, 2) (1, 3) (1, 4) (1, 5) (2, 3) (2, 4) (2, 5) (3, 4) (3, 5) (4, 5)

要素の重複

なお先ほどのメソッドだと、同じ要素の重複を許可していません。

要素の重複を許可する場合はrepeated_combination メソッド(repeated_permutationメソッド )を利用します。

numbers = [1, 2, 3, 4, 5]
numbers.repeated_permutation(2) {|a, b| printf("(%d, %d) ", a, b) }
=> (1, 1) (1, 2) (1, 3) (1, 4) (1, 5) (2, 1) (2, 2) (2, 3) (2, 4) (2, 5) (3, 1) (3, 2) (3, 3) (3, 4) (3, 5) (4, 1) (4, 2) (4, 3) (4, 4) (4, 5) (5, 1) (5, 2) (5, 3) (5, 4) (5, 5)
numbers = [1, 2, 3, 4, 5]
numbers.repeated_combination(2) {|a, b| printf("(%d, %d) ", a, b) }
=> (1, 1) (1, 2) (1, 3) (1, 4) (1, 5) (2, 2) (2, 3) (2, 4) (2, 5) (3, 3) (3, 4) (3, 5) (4, 4) (4, 5) (5, 5)

参考情報

permutation (Array) - Rubyリファレンス

combination (Array) - Rubyリファレンス

repeated_combination (Array) - Rubyリファレンス

repeated_combination (Array) - Rubyリファレンス

《今日の学習進捗(3年以内に10000時間に向けて)》

本日、CTOとの1on1にて、最近タスクが遅延してしまっている事を相談したが、そこで「システムだけでなく運用と併せて要件を満たせれば良い」というアドバイスを頂き、それが非常に参考になった。

具体例として、実際にタスクが遅延した「ユーザー削除機能」をあげる。

「ユーザー削除」の実装においては、誤って削除したり、退会したユーザーの投稿内容を確認したい場合に備えて、ユーザーの復元が行える様に「論理削除」での実装を試みた。 論理削除は開発の難易度が高く、実装できてもパフォーマンスや拡張性に難が出る事が予想された為、それらの問題に対処する方法の調査に時間を割く結果となった。 しかし、要件を洗い直すと、UIを工夫するなどすれば、物理削除で十分にニーズを満たせる(むしろ論理削除では満たせない)ということが判明し、論理削除に割いた工数が無駄となってしまった。

こうなってしまった原因は、システムだけで要件を満たそうとした事にあった。 本来ソフトウェアの要件を定める際は、システムで対処できない事象は、運用でカバーするという様な、システムと運用の両方で要件を満たすものである。 今回で言えば、誤って削除する恐れがあるのであれば、ボタン操作だけで削除出来ない様に入力操作を要求したり、削除確認ページを設けるといった事で要件を満たすことが出来た。 にも関わらず、システムだけで解決する事に拘った結果、論理削除の実装に執着してしまった。

更に言えば、「誤って削除したり、退会したユーザーの投稿内容を確認したい場合」というのは仮定の話で、現実に発生している問題では無いので、発生する頻度が高いと見込まれない問題に、多くのコストを割くべきでは無かった。

今後機能実装を行う際は、その機能が求められている理由/背景を掘り下げて、本当に満たすべき要件を定義し、システム・運用の両面で実装方法を検討し、最も費用対効果の高い実装方法を定めてから、開発に着手する様にしたい。

また、こういった運用の工夫については、C向け・B向け問わず、様々なサービスを実際に利用してみて、そこからノウハウを得るのが最も効果的だともアドバイス頂いた。 なので、様々なサービスに触れる機会を増やすとともに、それらが運用面でどういった工夫を行っているか?という観点で利用する様にしていきたい。

それと、昨日が七夕だったと、さっき気づいた。 神頼みが出来なくなったので、自力で自社サービスの成功に向けて開発に努める。

学習開始からの期間 :213日
今日までの合計時間:2060h
一日あたりの平均学習時間:9.7h
今日までに到達すべき目標時間:1945h
目標との解離:115h
「10,000時間」まで、

残り・・・「7940時間!」

【AtCoder:10回目】AtCoder Beginner Contest 133の振り返り(Ruby)

f:id:ryoutaku_jo:20190707232505p:plain

【目次】

【本題】

振り返り

今回は 7/7(日)に開催されたAtCoder Beginner Contest 133の振り返りを行います。

AtCoder Beginner Contest 133 - AtCoder

今回は1問しか回答できませんでした・・・

f:id:ryoutaku_jo:20190707234851p:plain

数学要素の強い問題だと全く歯が立たないです・・・

f:id:ryoutaku_jo:20190707234741p:plain

A - T or T

問題文 私たちは N 人で旅行しようとしており、その交通手段として電車とタクシーがあります。

電車を使うと 1 人あたり A 円かかります。

タクシーを使うと N 人で B 円かかります。

全員の交通費の合計は最小でいくらになるでしょうか。

制約 入力は全て整数である。 1 ≤ N ≤ 20 1 ≤ A ≤ 50 1 ≤ B ≤ 50

私の回答はこちら。

n,a,b=gets.split.map(&:to_i)

if n*a < b
  puts n*a
else
  puts b
end

両方を配列に格納してminメソッドを利用した方が、よりシンプルです。

n,a,b=gets.split.map(&:to_i)
puts [n*a,b].min

B - Good Distance

問題文 D 次元空間上に N 個の点があります。

i 番目の点の座標は ( X i 1 , X i 2 , . . . , X i D ) です。

座標 ( y 1 , y 2 , . . . , y D ) の点と座標 ( z 1 , z 2 , . . . , z D ) の点の距離は √ ( y 1 − z 1 ) 2 + ( y 2 − z 2 ) 2 + . . . + ( y D − z D ) 2 です。

i 番目の点と j 番目の点の距離が整数となるような組 ( i , j )

( i < j ) はいくつあるでしょうか。

制約 入力は全て整数である。 2 ≤ N ≤ 10 1 ≤ D ≤ 10 − 20 ≤ X i j ≤ 20 同じ座標の点は与えられない。すなわち、 i ≠ j ならば X i k ≠ X j k なる k が存在する。

模擬回答がこちら。

N, D = gets.split.map(&:to_i)
XS = N.times.map { gets.split.map(&:to_i) }
 
ans = 0
XS.combination(2) do |xs1, xs2|
  sum = 0
  D.times do |i|
    sum += (xs1[i] - xs2[i])**2
  end
 
  sq = Math.sqrt(sum)
  ans += 1 if sq == sq.to_i
end
 
puts ans

combinationメソッドってのを初めて知った。これは便利そう・・・

combination (Array) - Rubyリファレンス

C - Remainder Minimization 2019

問題文 非負整数 L , R が与えられます。 2 つの整数 i , j を L ≤ i < j ≤ R を満たすように選びます。 ( i × j ) mod 2019 の最小値を求めてください。

制約 入力は全て整数 0 ≤ L < R ≤ 2 × 10 9

色々もがいた結果、最後まで通らなかったコードがこちら。

l,r=gets.split.map(&:to_i)

if l/2019 != r/2019 || (l.lcm(r) >=l && l.lcm(r) <= r)
  puts 0
elsif 1+l/2019-l/2019.to_f < r/2019.to_f-r/2019
  puts r*(r-1)%2019
else
  puts l*(l+1)%2019
end

模擬回答がこちら。

L, R = gets.split.map(&:to_i)
 
ans = 2019
 
L.upto(R-1) do |i|
  (i+1).upto(R) do |j|
    mod = (i * j) % 2019
    if mod == 0
      puts 0
      exit
    end
 
    ans = mod if mod < ans
  end
end
 
puts ans

全探索で出来るんですね・・・

《今日の学習進捗(3年以内に10000時間に向けて)》

今日は一日休暇日(AtCoderはするけど)

学習開始からの期間 :212日
今日までの合計時間:2049h
一日あたりの平均学習時間:9.7h
今日までに到達すべき目標時間:1936h
目標との解離:113h
「10,000時間」まで、

残り・・・「7951時間!」

「SINGLE TASK」を読んで、生産性の低いマルチタスクを脱却する

f:id:ryoutaku_jo:20190706231912p:plain

【結論】

マルチタスクは、集中力を低下させ、生産性を低下させる

・高い集中力を維持して生産性を高めるには、シングルタスクを徹底して実践するしか無い

・あらゆる場面でシングルタスクを実践し、ささやかな例外(マルチタスク)も認めてはならない

【目次】

【本題】

必死に働いているのに生産性が上がらない

「あれもこれもと、忙しなく作業していた筈なのに、1日が終わっても思った以上に仕事が片付いていなかった・・・」

そういった徒労感を感じる場面が最近何度かあり、解決策を探っているところ、「SINGLE TASK」という書籍を見つけました。

ここに書かれていた内容が、自分の課題に非常にハマっていたので、今回はこの内容をまとめます。

マルチタスクは害でしか無い

本書で一貫して主張されている内容はマルチタスクは害である」ということです。

これは人間の脳が、一度の複数の事に注意を向ける事が出来ない構造になっている事に起因します。

上手くマルチタスクを実践している様に見える人でも、高速でタスクを切り替えているか、個々の事象に対する注意力を犠牲にしている見せかけだけのものだと、著者は断じています。

なお、この様なマルチタスカーは、集中力が弱く生産性が低いという事も研究で判明しています。

また、マルチタスクは目の前の人の話に集中出来なくなるなど、良好な人間関係の構築にも悪影響を与えます。

しかし、人は既に目の前にあるものより「目新しいタスク」に目を向けたくなる性質があるので、意識していないとマルチタスクに走ってしまいます。

「ふとTwitterのTLが気になって、ちょっと眺めるだけのつもりが、ドップリのめり込んでしまっていた・・・」

「インターネットで調べ物をしていた時、リンク先や広告の内容が気になって、本来の目的とは違う内容を調べていた・・・」

「現在着手しているタスクとは別のタスクの事が気になって、どっちつかずになってしまう・・・」

こういったものも、マルチタスクによる弊害です。

これらに対処するにはなにがあっても「マルチタスク」を試みないと心に決めて、シングルタスクを徹底するしかありません。

シングルタスク実践法1:パーキングロット

シングルタスクを妨害する要因は、主に「頭に浮かんだ別の思考」と「外部からの刺激」に分類されます。

これらに対して効果的な対策がパーキングロットという手法です。

パーキングロットとは、会議を円滑に進める際に用いられる手法で、本来の議題と無関係のテーマが話題に上がったら、ホワイトボードなどに記録して、後ほど議論するといったものです。

これを普段の作業にも応用させ、もし作業中に無関係のタスクに関する考えが浮かんだり、誰かから別の用事を頼まれた際に、メモ帳などにそれを記録して、現在の作業が終わった後に直ぐ取り掛かれる様にしておきます。

これにより、同時進行で複数のタスクをこなす必要は無くなります。

また、メモにまとめることで、頭の中が整理され、気が散るのも防げます。

シングルタスク実践法2:スマートフォンを分離する

スマートフォンなどの多機能デバイスは生活を便利にしてくれた反面、絶えず情報を供給することで、集中力を低下させる要因となっています。

なので、作業中は、電話やメール受信など全ての通知をミュートにしておくなど、注意散漫の原因になる要素を排除する必要があります。

シングルタスク実践法3:1日の予定を立てる

あらかじめ予定を立てる事で、仕事に追われる受け身の対応ではなく、先を見越した行動を起こせる様になります。

予定の立て方としては、以下の様に実践します。

・1日の始めに、今日なにをすべきか予定を立てる

・最重要のタスクと、後回しにできるものとを区別する(バイタル・フューの法則)

・「受信メールのチェック」「打ち合わせの予定を組む」など、「類似タスク」はグループ分けして、1日の同じ時間帯にまとめて片付ける

・1日に2回は空白の時間を設けて、トラブルに対処できる様にする

・生産性の高い時間とリラックスの時間を交互にもつ

・シングルタスクから脱線した回数を記録して、毎日振り返りを行う

シングルタスク実践法4:生活の全ての状況でシングルタスクを徹底する

・相手の話を聞いている間は、別の作業や考え事は行わず、話の内容についてよく思案する

・自身の課題を三人称で表現して客観的に考える習慣をもつ

・食事も会話も、全てに置いて常に「一度に一つ」に集中する事を徹底する

・ささやかな例外も認めない

所感

本書で一番自分に響いたのは以下の文章でした。

奇妙にも人は自分を疲弊させ、すり減らすことで「自分は重要な人間だ」という認識を持というとしている

現状転職仕立てで実力が伴わない状況の為、それを忙しさで補っているつもりでしたが、実際には膨大な要求に答えられずに、期待した成果を上げられないという状況に陥っていました。

本書を読んでいると、自分のここ最近の生産性の低下の要因がズバリ言い当てられている様で、非常に参考になりました。

また時間を置いて読み返したい本です。

参考情報

書籍「SINGLE TASK 一点集中術――「シングルタスクの原則」ですべての成果が最大になる」

《今日の学習進捗(3年以内に10000時間に向けて)》

最近集中力が落ちている様に感じる・・・実際に業務のタスクも遅延気味・・・

今回読んだ内容を実践して、作業効率を高めて行きたい

学習開始からの期間 :211日
今日までの合計時間:2045h
一日あたりの平均学習時間:9.7h
今日までに到達すべき目標時間:1927h
目標との解離:118h
「10,000時間」まで、

残り・・・「7955時間!」