全探索 (AtCoder B問題)
What
全探索は、全ての組み合わせを逐一、条件と一致するか確認するアルゴリズムです。
ここの問題を解いていく過程で学んだことや解法を記録しておきます。 qiita.com
Results
全て列挙しなくても解ける問題が多いと感じました。
以下、それぞれの問題に関して、方針や解法を記録しておきます。
ABC144 B_81
for文は1回で済みます。
与えられた数値に対して、1から9で割ります。その商が1から9の範囲内にあれば、true...このようにすれば解けます。
ABC150 B_CountABC
以下のように、正規表現で解けます (標準入力のプログラムは省略)。
エラー回避のため、マッチする文字列がないときは、空配列を与えるようにしています。
const input = lines.split('\n')[1] console.log((input.match(/ABC/g) || []).length)
ABC122 B_ATCoder
入力された文字列の最初から、A, T, C, Gのいずれかの文字があるかどうか確認します。
該当しない文字に当たったら、'\n'で書き換えます。
一旦、配列を結合し、'\n'毎に配列を作りなおし、各要素の大きさだけの配列に変換します。
スプレッド構文を使い、一番大きな要素を出力すれば、完成です。
let lengthArray = input.join('').split('\n').map(function(val){return val.length}) console.log( Math.max(...lengthArray) )
なお、スプレッド構文は以下を満たします。配列の各要素を1つずつ取り出して評価したいときに、使えそうです。
console.log( Math.max(...arr) === Math.max.apply(null, arr)) //=> true
ABC136 B_Uneven Numbers
そんなに難しくないです。桁数 == 文字数が奇数のものを数え上げればできます。
const input = lines.split('\n').map(Number)[0] let count = 0 for(let i=1; i<=input; i++){ if(i.toString().split('').length % 2 === 1){ count++ } } console.log(count)
ABC106 B_105
与えられた数値までの全数値 (奇数) を求める。求めた数値の約数を数え上げる。上記2つのために、for文を2回使います (または、与えられる数値の範囲が狭いため、if文で条件分けしても良さそうです)。
const input = lines.split('\n').map(Number)[0] let count = 0 // 入力した数値までの全数字を求める (奇数なのでi+=2) for(let i=1; i<=input; i+=2){ let tmpCount = 0; // 求めた数値の全約数を求める for(let k=1; k<=i; k++){ if(i%k === 0){ tmpCount++ } } if(tmpCount === 8){ count++ } } console.log(count)
ABC120 B_K-th Common Divisor
それぞれの約数を求め、共通項をくくればできます。
Node.jsのバージョンが高ければ、includesメソッドで共通項を出力できます。
let divisorAB = divisorA.filter(function(element){return divisorB.includes(element);})
しかし、ABC120では、includesメソッドは使えませんでした。
計算量は少し多くなりますが、以下のように書き換えることもできます。
var divisorAB = [] for(var i=0; i<Math.max(divisorA.length,divisorB.length); i++){ for(var k=0; k<Math.max(divisorA.length,divisorB.length); k++){ if( divisorA[i] === divisorB[k]){ divisorAB.push(divisorA[i]) break; } } }
B問題は一旦これで終了なので、続きはまた後日投稿します。
for of vs for in
What
for文におけるofとinの違い
for (let i = 0; i < xxx.length; i++)で書き直すことで、理解を深める。
Results
まず、用語の導入として、プロパティ名とプロパティを簡単に示します。
ハッシュでは、{プロパティ名: プロパティ}となります。
配列の場合は [プロパティ名]ですが、{配列の要素の番号: プロパティ名}とも見なせます。
const array = ['yamada', '25', 12] const hash = {0: 'yamada', 1: '25', 2: 12} console.log(array[1] == hash[1]) // => true console.log(array == hash) // => false
inはプロパティ名を取得
for文でinを使うと、プロパティ名を取得できます。これは、ハッシュや配列、文字列にも適用できます。
const hashObject = {name: 'yamada', age: 25} const str = 'avcde' for (let key in hashObject){ console.log(key) // => name age } for (let key in str){ console.log(key) // => 0 1 2 }
次のようにも書き直せます。Object.keysメソッドは引数においたオブジェクトのキー (プロパティ名) を取得します。
const hashObject = {name: 'yamada', age: 25} const str = 'avcde' for (let i=0; i<Object.keys(hashObject).length; i++){ console.log(Object.keys(hashObject)[i]) } splitHash = str.split('') for (let i=0; i<splitHash.length;i++){ console.log(i) }
ofはプロパティを取得
配列や文字列にしか使えません。
const hashObject = {name: 'yamada', age: 25} const arrayObject = ['yamada', '25', 12] const str = 'abc' for (let value of hashObject){ console.log(value) // type error } for (let value of arrayObject){ console.log(value) // => yamada 25 12 } for (let value of str){ console.log(value) // => a b c }
for (let i=0; ...)での書き換えは、inでの書き換えと似ているため、省略します。ofの代わりに、forEachで書き直すこともできます。inとofはプロパティ名 (キー) を取り出したいのか、プロパティ (バリュー) を取り出したいのかで使い分けます。
/[^\w]/g != new RegExp('[^\\w]', 'g')
What
正規表現の作り方について、理解に手間取ったので、まとめておきます。
文字列 Hi Bob!!をHiBobとして表示したい (空白や特殊文字を排除したい) 場合、以下の2通りの方法があります。
const word = 'Hi Bob!!'; reg1 = /[^\w]/g; regResult1 = word.replace(reg1, ''); console.log(regResult1) // => HiBob
const word = 'Hi Bob!!'; reg2 = new RegExp('[^\\w]', 'g'); regResult2 = word.replace(reg2, ''); console.log(regResult2) // => HiBob
与える結果が同じなので、reg1とreg2は同じものだと考えましたが、以下の結果から分かるように両者は異なるものみたいです。
console.log(reg1 == reg2)
// => false
Solution
答えは、公式ドキュメントにありました。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Regular_Expressions
前者の//で囲む方は正規表現リテラルといい、スクリプトをロードした時に、コンパイルされる正規表現。そのため、正規表現が変化しない場合にパフォーマンスが良い。後者はRegExpのコンストラクタ関数を用いた方法で、該当するコードが実行されるたびにコンパイルされる正規表現。そのため、正規表現が変化する場合にパフォーマンスが良い (正規表現リテラルと異なり、全てのコードをリロードしなくて良いため)。
結論として、
両者とも、与える結果は同じだけど、正規表現のコンパイルのやり方が異なるので、等しくない。
以下正規表現を作成するときに役立つ部分だったので、控えておきます。
正規表現の引数について gとか
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/RegExp
正規表現のマッチャについて
https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Regular_Expressions
Supplement
正規表現^a
と[^a]
の違い
前者は先頭の文字がaだったらマッチするのに対し、後者はaがなかったらマッチする (補集合)。どちらもgを使っていないため、1個マッチした時点でそれ以降は判定しません。
const againLower = 'again' const againUpper = 'Again' regAgainLower = againLower.replace(/^a/, 'x') regAgainUpper = againUpper.replace(/^a/, 'x') console.log(regAgainLower) // => xgain console.log(regAgainUpper) // => Agxin
const againLower = 'again' const againUpper = 'Again' regAgainLower = againLower.replace(/[^a]/, 'x') regAgainUpper = againUpper.replace(/[^a]/, 'x') console.log(regAgainLower) // => axain console.log(regAgainUpper) // => xgain
Nuxt + Firebase | キャッシュを保存しない設定
What
Nuxtでアプリ開発をした際、キャッシュが残り、結果が反映されないことがありました。そのため、キャッシュを保存しない設定を加え、対処しました。
Solution
nuxt.config.jsに以下を追記します。
... , serverMiddleware: [ '~/api/headers.js' ], ...
api/headers.jsに以下を追記します。
module.exports = function(req, res, next){ res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate') next()
確認はできていませんが、以下をHeaderに追加するやり方でも良さそうです。
<meta http-equiv="Pragma" content="no-cache"> <meta http-equiv="Cache-Control" content="no-cache">
参考
https://github.com/nuxt/nuxt.js/issues/2554
https://www.tagindex.com/html_tag/page/meta_pragma.html
Can't verify CSRF token authenticity.
What
Solution
ただ無効化する方法
Qiita等でよくあるやり方は、CSRFを無効化する方法です。
Railsのヘルパーを使っている場合は、トークンが発行されますが、コンポーネント化するために、生HTMLを使用すると、トークンが発行されず、上記の警告が出ます。
そのため、APIを使用しているコントローラーにて、CSRFを無効化すれば、解決するという発想です。
- protect_from_forgery
+ skip_before_action :verify_authenticity_token
[参考]
https://qiita.com/nishina555/items/4ffaf5cc57a384b66230
トークンを発行する方法
CSRFを無効化すると、何のためにトークンを付けてるのかなとなります。
axiosを使っているならば、任意のメソッドに以下を追記すれば、トークンを発行するため、上記エラーも解決します。
createPost: function(){ axios.defaults.headers.common = { 'X-Requested-With': 'XMLHttpRequest', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content') }; ... axios.post(...){ ... }
Nuxt + Firebase
What
ローカルである程度開発し、デプロイして確認しているのですが、ちょいちょいコマンドを忘れるため、そのメモを残しておきます。
Lists
Nuxtアプリを起動する
アプリのあるディレクトリにて、以下を実行します。権限関連でエラーが起きる場合は、適宜権限を与えておくか、sudoで実行しておくと良いです。
$ npm run dev
ビルドし、結果を生成する。
Nuxt.jsはRailsなどと異なり、自動ビルドされないため (もしかすると、やり方があるかもしれない)、コマンドを打つ必要があります。
$ npm run build $ npm run generate
デプロイ!
デプロイに成功しても、アプリの見た目が変わらない場合は、ビルドで失敗している可能性があります。
$ firebase deploy
S3の設定
What
画像ファイル等をAWSの別コンテナに保存し、ec2コンテナを変更しても大丈夫なようにする。
具体的には、carrierwave利用時の画像保存先をS3にします。
Do
Localの設定
config/carrierwave.rbというファイルを作成し、以下記述します。uploaders/image_uploader.rbに書いても良いですが、同じ記述がないようにします。
require 'carrierwave/storage/abstract' require 'carrierwave/storage/file' require 'carrierwave/storage/fog' CarrierWave.configure do |config| if Rails.env.production? config.storage :fog config.fog_provider = 'fog/aws' config.fog_directory = ENV['AWS_S3_PACKET'] config.fog_credentials = { provider: 'AWS', aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'], aws_secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'], region: ENV['AWS_REGION'], path_style: true } else config.storage :file config.enable_processing = false if Rails.env.test? end end
環境変数については、credentials.ymlかec2コンテナに環境変数用のファイルを作成しておきます。
AWSコンソールでの設定
S3でパケットを作ります。この時のパケット名が、ENV['AWS_S3_PACKET']で、リージョンがENV['AWS_REGION']です。リージョンはURLのregion=<リージョン名>からも確認できます。
サービス利用者に擬似的に権限を与え、S3に保存するように設定します。IAMで、画像保存を許可する実体のないユーザーを作成します。アクセスの種類はプログラムによるアクセスです。次に進み、権限をアタッチします。
ユーザーの作成が終わると、アクセスキー (ENV['AWS_ACCESS_KEY_ID']) とシークレットキー (ENV['AWS_SECRET_ACCESS_KEY']) が表示されます。ユーザー名を選択し、ARNを保存しておきます (画像のユーザーは使用していないため、問題ありません。ご心配なく)。
次に、アクセスポリシー > パケットポリシーにて、以下を記述します。
{ "Version": "2012-10-17", "Id": "Policy1544152951996", "Statement": [ { "Sid": "Stmt1544152948221", "Effect": "Allow", "Principal": { "AWS": "<ユーザーのARN>" }, "Action": "s3:*", "Resource": "arn:aws:s3:::<パケット名>" } ] }
画像が保存されると、S3 パケット内でディレクトリが作成されるようになります (ちなみにローカルでは、public配下です)。