Translate

BTemplates.com

Powered by Blogger.

ラベル ruby の投稿を表示しています。 すべての投稿を表示
ラベル ruby の投稿を表示しています。 すべての投稿を表示

2021年3月11日木曜日

2021-03-11 到達点メモ


ブログ記事を書くのがあまりにも久しぶりすぎる・・・。

普通に操作しているとフォルダの中の合計がわかりにくいので、フォルダのそれぞれのサイズ一覧を一括でわかるようにしたかった。

ひとまずRubyで実装はできたのだが、この記事を書く際にふと気になって調べてたら、(見にくいが)PowerShellでも普通にできます・・・。

Get-Childitem -Path ./ -Directory | ForEach-Object -Process{Write-Host $_; Get-Childitem -Path $_ -Recurse | Measure-Object -property length -sum | Format-List sum}

参考サイト:[備忘録]Windoes10:フォルダ毎の容量を調べる方法 | CEOブログ 


まぁ、見やすさ重視だったので一応無駄ではない
最近、全然コードを書いていなかったから、書いておきたかったし・・・。


■ 躓いたところ

・コマンドライン引数でWindowsのフォルダパスを渡したら、何も取得できなかった。

-理由
今回はDir.glob使用しており、Dir.globにパスを渡すさいは、"C:/php/dev"といったふうに、"/"でないといけない。しかし、Windowsのパスは"\"のため、そのまま使うとだめだった。

-対処方法
 File.expand_path()を使うか、.gsub(/\\/,"/") で変換するかで対応できる


・コマンドライン引数でテスト時のフォルダパスだとできたのに他のフォルダパスだとできなかった問題

-理由
フォルダ名に半角スペースが入っており、データの取得がARGV[0]で行ったため、半角スペース以降の文字列が別の配列のデータに格納されてしまったため。

-対処方法
コマンドライン引数で渡す際に、””で囲むようにした。結合とかも一瞬考えたが、オプションを半角スペースで区切って渡すのが、本来の仕様だと思うので、それに従ったほうが良いと思ったため。


・フォルダ名:サイズKBの形式にし、文字数に応じて半角スペースで埋めて揃えようとしたところ、日本語が入るとばらばらになってしまった。

-理由
半角文字と全角文字を考慮していなかった。むしろ、最初は日本語をどう見つけるか、もしくは省くかを考えてしまい、半角文字と全角文字という区分に気がつくまでに時間がかかった。

-対処方法
考え方としては半角文字を1とし、全角文字は2とした。
Rubyの仕様だと、半角全角関わらず単純に文字数を数え上げてしまうようなので、半角英数字記号以外を数えて、それを足すことで解決した。
半角カタカナには対応していないが、使われるケースは稀と考えたので今回は考慮しなかった。


・Googleで正規表現 半角英数字記号で調べたら、/^[a-zA-Z0-9!-/:-@¥[-`{-~]*$/とでてきたので、/の中身をそのまま使った。後で気がついたら、なんでこれで全角文字が判別できているんだ?

-理由
Rubyでは^は否定表現である。
参考サイト:正規表現 (Ruby 3.0.0 リファレンスマニュアル) 

-対処方法
今回はふと疑問に思ってテストコードを書いたら発見できた。というか、そもそもちゃんと公式ドキュメントを読もう。


■実装する際に参考にしたサイト

Rubyでコマンドライン引数を取得する方法:ARGV | UX MILK
Rubyでディレクトリを一覧表示する方法を現役エンジニアが解説【初心者向け】 | TechAcademyマガジン
Rubyでディレクトリの中のファイル一覧を取得 – かひわし4v1.memo

 

GitHubに上げるまでやりたかったが、力尽きたので今日はここまで。

2019-11-11、12-03 到達点メモ


EslintとPreitterを使っているのだが、mdファイルが整形されるのは地味に困るので
mdファイルは整形されないようにしたかった。

◆手順
1. プロジェクト直下に.prettierignoreと.eslintignoreを作成する。
2. それぞれに、*.mdと記述する
おわり。

◆参考サイト
.eslintignore の配置場所は気をつけた方がいい - Qiita
Prettierの対象から一部ファイルを除外する- Qiita
eslintで任意のディレクトリ、ファイルをチェック対象から除外する方法- Qiita


最近AtCoderの問題を解いているのだが
たまにRubyのメソッドを使えば、簡単に解けるしまうケースが有る。
なお、今回取り組んだのは、C - Slimes という問題である。

具体的には、以下のようなメソッドである
「squeezeメソッドは、文字列中で同じ文字が連続している部分を1つの文字にまとめ、新しい文字列を返します。」
squeeze, squeeze! (String) - Rubyリファレンスより一部抜粋

これがあれば、わざわざ文字列一個一個を見る必要はなく、しかも早く結果が出る。
実装の問題もあるのだろうが、
自分の実装だと実行時間が771msに対し、ライブラリだと7msである。
一応、自分の実装は配列(1545ms)から文字列に内容を変えた上での結果である
恐らく、一つ一つ見るやり方だと非効率なのだと思われる。


途中まで記事を書いていたが、もう内容は覚えていない・・・。
お蔵入りにするのもあれなので、そのまま上げる

2019年5月3日金曜日

2019-02-27、03-01、05-03 到達点メモ


前に作ったプロジェクトを起動してSyncしたところ以下のエラーが出た。

Error:No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android

幾つか参考にしたサイトだと、NDKをダウンロードして
足りないファイルを入れよう。という話が出ていたのだが
その肝心のmips64el-linux-androidが無かった。

参考サイト:Android Studio 3.2 でビルドエラー「No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android」が出た時の対処方法
参考サイト:Error:No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android


下記のサイトによると、どうもバージョンが上がるとmips64自体が対応されなくなったようである。恐らくなくなってしまった可能性が高い。

参考サイト:"No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android" のコメントより

で、対策に関しては、gradleのバージョンを
 classpath 'com.android.tools.build:gradle:3.3.1'
に上げた後にGradle自体?のバージョンを4.10.1?に上げたところ
エラーが出なくなった。

で、なおしてたらなんか見覚えのあるエラーを見つけた。
Failed to resolve: org.jetbrains.kotlin:kotlin-stdlib-jre7:1.3.11

案の定、以前の日記に同じ現象があった

という訳で前回と同じように以下のように修正した
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"


久しぶりにAdMobを動かしたら、落ちたんだが???
一部のみを抜粋するが、こんなエラー文だった。

02-27 22:12:43.031 28083-28083/? E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.nononagainfo.www.admobtest, PID: 28083
    java.lang.RuntimeException: Unable to get provider com.google.android.gms.ads.MobileAdsInitProvider: java.lang.IllegalStateException: 
    
    ******************************************************************************
    * The Google Mobile Ads SDK was initialized incorrectly. AdMob publishers    *
    * should follow the instructions here: https://goo.gl/fQ2neu to add a valid  *
    * App ID inside the AndroidManifest. Google Ad Manager publishers should     *
    * follow instructions here: https://goo.gl/h17b6x.                           *
    ******************************************************************************
    
    
        at android.app.ActivityThread.installProvider(ActivityThread.java:5921)
        at android.app.ActivityThread.installContentProviders(ActivityThread.java:5510)
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5449)
        at android.app.ActivityThread.-wrap3(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1587)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6184)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
     Caused by: java.lang.IllegalStateException: 
    
    ******************************************************************************
    * The Google Mobile Ads SDK was initialized incorrectly. AdMob publishers    *
    * should follow the instructions here: https://goo.gl/fQ2neu to add a valid  *
    * App ID inside the AndroidManifest. Google Ad Manager publishers should     *
    * follow instructions here: https://goo.gl/h17b6x.                           *
    ******************************************************************************
    
    
        at com.google.android.gms.internal.ads.zzze.attachInfo(Unknown Source)
        at com.google.android.gms.ads.MobileAdsInitProvider.attachInfo(Unknown Source)
        at android.app.ActivityThread.installProvider(ActivityThread.java:5918)
        ... 10 more

で、対策を簡単に述べると
AndroidManifest.xmlに以下のようにAdMobのIDを追加する必要があるようである。
<manifest>
    <application>
        <!-- Sample AdMob App ID: ca-app-pub-3940256099942544~3347511713 -->
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="[ADMOB_APP_ID]"/>
    </application>
</manifest>

更に言うと、 Google Mobile Ads SDK バージョン 17.0.0 でこの対策をしないと
クラッシュするようである

参考サイト:スタートガイド - AndroidManifest.xml を更新する


ruby

evalは文字列をコードとして実行することができる
例:
puts eval "1+2"


javascript

puppeteerで特定のサイトを開いたらチェックボックスにチェックを入れるといった事をしたかった。
なので、以下のように書いた

const puppeteer = require ('puppeteer');
(async () => {
  const browser = await puppeteer.launch ({
    headless: false,
    defaultViewport: {
      width: 1366,
      height: 728,
    },
  });
  const page = await browser.newPage ();
  var linkAdders = 'https://www.nononagainfo.com/';
  await page.goto (linkAdders, {waitUntil: 'domcontentloaded'});
  await page.click ('#test_test_testID');
  await page.waitFor (100);

  const page2 = await browser.newPage ();
  var linkAdders2 = 'https://play.google.com/store/apps/details?id=com.aaa.nononaga.voicetimerr';
  await page2.goto (linkAdders2, {waitUntil: 'domcontentloaded'});
  await page2.waitFor (100);

  const page3 = await browser.newPage ();
  var linkAdders3 ='https://www.nononagainfo.com/p/blog-page_1.html';
  await page3.goto (linkAdders3, {waitUntil: 'domcontentloaded'});
  await page3.waitFor (100);
}) ();

・ヘッドレスモードとは、CUIのみで処理を行う事。
つまり、普通にGUIとして使いたい(ブラウザを表示したい)場合は、launchメソッドで
headless: falseを入れてあげればよい。
・デフォルトだと表示画面が小さいのでlaunchメソッドでdefaultViewport: {}の値を指定する必要がある
・executablePathで、起動するデフォルトchromeをしているすることができるが
その際の注意として、/(バックスラッシュ)は、一つではなく二つ指定する必要がある。
例:'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe'
・チェックボックスに関しては、clickメソッドに対象のIDを指定すればチェックボックスにチェックが入る。
・複数のタブを作りたい場合は、browser.newPage ();を新しく作ればよい

参考サイト:Puppeteer で Headless Chromeを操ってE2Eテストする(予定) - 入力・操作編
参考サイト:Puppeteerでスクレイピング

ただ、一つ問題があってキャッシュを保持したかったのだが
(元々の目的から考えるに当たり前なのだが)保持することは出来なかった。

なんか、操作できる良いやつってなんかあったっけ・・・?


気が付いたら、二ヶ月もたってたわ・・・。

RubyのStringのdeleteの仕様について

以下のコードを書くとどういう結果になると思いますか?

puts "chochoc".delete("ch")

理想
ooc

現実
oo

deleteはどうも一文字ずつを削除する仕様の様で
二文字だけを消したい場合はこの書き方ではできない
どう実装するかというとgsubを使う

puts "chochoc".gsub(/ch/,"")

以上。


2019年2月27日水曜日

2019-02-11、12、15、25、27 到達点メモ


コマンドプロンプト

入力を受け付ける
set /p testdata=

値を代入する
echo %testdata%

参考サイト:バッチファイルでよく使う書き方まとめ


Node.js

コマンドプロンプトから入力した値を使いたい。
例えば以下のように入力した場合、testdataという文字列を使いたいとします
node index.js testdata

この場合、index.js上では以下のように指定する必要があります
var data = process.argv[2];

参考サイト:Node.jsでコマンドライン引数を取得する


ruby

downto
大きい順から特定の値まで一づつカウントダウンする
大きい値から調べたい時は便利。

String[0,x]
左がインデックス番号で、右が文字数。

計算の順番

a=1
b=5
puts a+b > 9 ? "Fin" : a+b

で10以上の時はFinと表示するもしくは、10未満の時は
aとbの合計結果を出したいとする

その際に、毎回a+bって書くのが嫌ので
これを一行に纏めようとした。

a=1
b=5
puts result = a+b > 9 ? "Fin" : result

例えば、上記のように書くと、結果は空になる。
計算の順番的に代入は後になっているものと思われる。
そこで以下のように書けば、ちゃんと合計結果が出る

a=1
b=5
puts (result = a+b) > 9 ? "Fin" : result

正直な所、競技プログラミング以外でこのように一行で書く意味はあまりないと思うが
やり方として覚えておくとよいと思う。

重複の削除の仕方

処理速度の問題は置いておくとして
結果だけ見れば配列の重複したものを削除したい場合
s="testcase".to_a
s.uniq と s | [] と s|s
は全部同じ結果になる

[n..m]と[n...m]の違い

[n..m]
ピリオド二つの奴は、n番目からm番目という意味

[n...m]
ピリオド三つの奴は、n番目からm-1番目という意味。つまり、m番目を含まない

[n..(m-1)]ってやるよりは見た目的には奇麗だが
見逃しが起きそうではある。

参考サイト
[] (Array)

検証してみた話。

rubyで配列のユニークな奴を取りたい場合は
array.uniq か array|[]のどちらかを使えばよいのだが
結局どちらが早いのだろうか?
と思ったので、以下の条件でテストしてみた。
・文字列は1000文字で、AからCのランダムな文字が入る
・同じ文字列を一万回重複削除し、そのタイムを取得する
・100個のタイムを取得し、最大値、最小値、平均値を求める

以下が実際に検証したコードである

valueRandom = Random.new(1024)
alphabet=("A".."Z").to_a
moji = 1000.times.map{alphabet[valueRandom.rand(3)]}

uniqTimes = []
100.times do
    stratTime = Time.now.to_r
    10000.times.map{moji|[]}
    endTime = Time.now.to_r
    uniqTimes << endTime - stratTime
end
puts "array|[]"
puts "FastTime:#{uniqTimes.min.to_f}"
puts "SlowTime:#{uniqTimes.max.to_f}"
puts "AverageTime:#{(uniqTimes.inject(:+)/100).to_f}"

uniqTimes = []
100.times do
    stratTime = Time.now.to_r
    10000.times.map{moji.uniq}
    endTime = Time.now.to_r
    uniqTimes << endTime - stratTime
end
puts "array.uniq"
puts "FastTime:#{uniqTimes.min.to_f}"
puts "SlowTime:#{uniqTimes.max.to_f}"
puts "AverageTime:#{(uniqTimes.inject(:+)/100).to_f}"


結果は以下のようになった。

array|[]
FastTime:0.525499
SlowTime:0.669585
AverageTime:0.55385082

array.uniq
FastTime:0.524965
SlowTime:0.602402
AverageTime:0.55188603

ある意味分かり切った事ではあったが
正直誤差の範囲内だと思う。

今回は、uniqの方が早いが処理順番が逆だった時は
array|[]の方が早かったのでもっと回数をこなすとまた違う結果が出るのかもしれない。

ただ、単純に重複削除をするのであれば
分かりやすいuniqが一番無難なのでは?と思った。

2019年2月8日金曜日

2019-01-30、02-01、02-07、02-08 到達点メモ


AtCoderのRubyでのB - Minesweeperのネタバレあり。


何故か2019/1/30にイスラエルから700くらいアクセスがあった。
普段10くらいしかないのに、一体何があったし・・・。
ざっと調べてみたが、何か事件があった訳ではないようだ。
VoiceTimerでググってみたが、何か特別なことがあった訳でないようだし・・・。
本当に謎だ。

Android

エミュレーターで720dpの画面のテストをしたい場合
xlargeが720dp

Node.js

ワンクリックで特定のサイト群を一括起動する機能が作りたかったので作った。
運用していくと色々やりたいことが出てきそうだが、
ひとまずはnpmのライブラリにあるopenerで十分実現できる
var opener = require ('opener');

opener ('chrome');
opener ('http://yahoo.co.jp);
opener ('http://google.com');
opener ('https://www.nononagainfo.com/');

上記の通りにやるとタブが増える感じで
起動することができる。
他のブラウザを立ち上げていると特に立ち上げたいものが多い場合だと
そっちにが立ち上がる時があるので注意。
やり方がなかなか見つからなかったから
案外難しいのかと思ったが凄く簡単だった。

参考サイト:openerを使ってnpmスクリプトからブラウザを開いてみる
参考サイト:opener
参考サイト:npm script を試す (サンプル付き忘備録)

AtCoder Ruby

B - Minesweeper
動作が上手く行かない時の検証の仕方が凄く下手だ。
今回の問題は文字列の中に含まれる"."が、0の時になることがありえるので
本来は、"#"で検索をかける前に、"."を全て0に変換する必要があるのだが
それを最初にやらなかった為、出力結果が本来加算されるべきところで加算されていなかった。

最初に変換をやっとけと言われてしまえばそれまでなのだが
そもそも変換がきちんと行われていないということに気づくのが遅すぎた。
デバッグの仕方が悪いのはわかるのだが、具体的にどう理屈をつけてやればいいんだろう?

いや、そもそもPrintデバックから卒業する時なんだと思う。
と、下のサイトを見て思いました。
printデバッグにさようなら!Ruby初心者のためのByebugチュートリアル

あと、メモとして書いておくが
事前に0の数値の配列を作っておくという手法は盲点だった。
確かにそれをやったほうが速そうではある。

rubyだと nil || "AAA" だと "AAA"が採用されるようである

具体例

puts nil || "BBB"
結果はBBB

puts "AAA" || "BBB"
結果はAAA


2019年1月28日月曜日

2019-01-19、20、24、26、28 到達点メモ


AtCoderで、B-1 21の問題(コンテストが終了した問題)に関するRubyで解いた
ネタバレがあるので嫌な人は見ないようにしてください。


git logをコマンドプロンプトで使っていたら、日本語が文字化けしていた。
正直なところ、恒久的な対処方法が分からなかったので
git bashを使うことにした。
これなら文字化けしない。

参考サイト:Windowsでgit log見た時日本語が<E6><97>~みたいに化けた時の対処方法
参考サイト:git log、git diff、git showでの日本語の文字化けをまとめて対策

というか、コミットはVisualStudioCodeを使えば割とどうでもなることが良く分かった。
ついで話をもう一つするとshift-jsで開くと文字化けするので、utf8で保存しよう。

正規表現について

以下のような文字列があったとする

Word Adobe PhotoShop (フォトショップ)

これを以下のようにしたい
Word,Adobe PhotoShop (フォトショップ)

その場合は以下のようにすればよい(EmEditorの場合)

検索(分かりにくいが、一番最初の方に半角スペースが入っている)
『 ([^(|^P])』

置換
『,\1』

()でくくったところは置換時に変更しないという意味で
^は否定の意味
[]は[]の中の任意の文字。複数の文字とかを使いたい時に使う?

参考サイト:正規表現
参考サイト:正規表現:文字列を「含まない」否定の表現まとめ
参考サイト:文字列の一部だけを変更したい
参考サイト:特定の文字列を含まないという正規表現


ruby(AtCoderで、B-1 21の問題(コンテストが終了した問題)に関するネタバレ注意)

AtCoderで、B-1 21の問題(コンテストが終了した問題)を解いた際にコードのバイト数が少ない回答を見たのだがその回答に感動しました。
平方数はそうやってもとめるのかと

puts number==(number**0.5).to_i**2 ? :Yes : :No

他の言語はわかりませんが、rubyだと小数の階乗ができるので
そこをInt型に変えて小数を落として、更に二乗すれば
元々平方数が出せる値なら一致するので
大体どの値でも出せて便利だなと思いました。

200.to_s.split("")の処理よりは、200.to_s.charsの処理の方が軽い

あと、よくあるa>bのときは、aが大きい、a=bの時は等しい、a<bの時はbが大きい
とやりたい場合は、以下のような方法もある

judgment = ["等しい","aが大きい","bが大きい"]
puts judgment[a<=>b]

見やすいかどうかはともかくとして、圧縮したい場合は便利。

x |= yを見つけたのでなんじゃこりゃ?
と思って調べてみたらどうやらビット単位のOR代入の省略形らしい。
x=x|y
で、何に使うかというと配列で一意の合成をやりたい場合に便利なんだそうだ。

例えば、以下のようなコードを書いたとする
x = [1,2,3,4,9]
y = [3,4,5]
x |= y
puts x.to_s
x2 = ["aa","bb","abb"]
y2 = ["a","bb","ccc"]
x2 |= y2
puts x2.to_s

結果は以下のようになる
[1, 2, 3, 4, 9, 5]
["aa", "bb", "abb", "a", "ccc"]

uniqの処理って重そうだったし
一々合成するならこれの方が処理が速そう?
きちんと計っていないので何とも言えないが。

参考サイト:Ruby |= assignment operator