日記帳

プログラミングのことをつぶやく日記です。

最近競技プログラミングしていてよく使う書き方とかメソッドとか

Rubyで競プロを解くときによく使うんだけど、よく忘れるのでメモする📝

一文字ずつ文字列を処理する

chars メソッドを使用すると配列を返す。これを each するだけで一文字ずつ比較などができる。

'abcde'.chars
=> ["a", "b", "c", "d", "e"]

標準出力を式の戻り値によって切り替える

puts に三項式を渡せば切り替えることができる。

puts rand * 10 > 5 ? 'high' : 'low'
# low

インクリメント

Ruby++ ができないので += を使用する。よく逆に書いてしまう。

num += 1

初期化した配列を作る

new の第一引数に、要素の数、第二引数に初期値を渡す。

Array.new(2,0)
=> [0, 0]

標準入力のn行を配列に入れる

これは他の方法で代用するのでいつも使用しないけどメモしておく。 while の条件を line = gets のように書いておくと標準入力の1行が line に入るので、それを Array#push してあげて追加していく。

lines = []
while line = gets
  lines.push(line.chomp)
end

0からnまでindexをアップしていく

Integer#upto を使う。 Range オブジェクトを使うより便利。でもよく忘れる。逆は downto

0.upto(2) do |i|
  p i
end

特定の文字列が入っているか確認する

正規表現を使用する。 a にdogかcatが含まれていればtrueになる。

a =~ /(dog|cat)/ 

配列を検索して、その要素の位置を取得する

指定した配列の次の要素をいじるのとかで必要になるやつ。 Array#index を使用する。

a = [1,2,3]
a.index(2)
=> 1

もっといいやつとか間違ってたら教えてください。

Hubotでスレッドにコメントするようにした。

今日の日記 とても雑なメモ

https://github.com/slackapi/hubot-slack/blob/master/docs/_pages/basic_usage.md#working-with-threads

nodeのhubot-slackを使ってHubotのコメントをスレッドに返せないかどうか調べていた。そしたら上記の書き方が見つかったので、自分のHubotに適用してあげた。そしたら動くようになった。 thread_ts? はスレッドかどうかの判定関数みたい。普段node.jsとか触らないので書き方も全然わからない。

module.exports = (robot) ->

  robot.hear /badger/i, (res) ->
    if res.message.thread_ts?
      res.send "すでにスレッドで会話しているときは、スレッドに返すよ"
    else
      res.message.thread_ts = res.message.rawMessage.ts
      res.send "スレッドではないときは、スレッドに返事をするよ"

自分のHubotプロジェクトはcoffeeで書かれているのでTSで書き直そうと思っている。

nodeのバージョンをあげた

作業も忘れてしまうので雑にメモ

# リモートのnodeのバージョン一覧を確認する
nodebrew ls-remote
# 12.10.0をインストールする
nodebrew install-binary v12.10.0
# 手元のマシンにインストールされているか確認する
nodebrew ls
# 12.10.0に切り替える
nodebrew use v12.10.0

nodeのパッケージをアップデートする

npm-check-updatesはpackage.jsonを一括で最新バージョンにしてくれるらしい。

# グローバルにnpm-check-updatesを入れる
npm install -g npm-check-updates
# 実行する
npm-check-updates -u
# パッケージをアップデートする
npm update

競技プログラミングを解くときにsplitやchompを削ると実行時間が速くなる

今日、やっとAtCoder Beginners Selectionの問題を全部解き終えた。感想はACになったときにアドレナリンが出るということと、人の解法が勉強になるということだった。

すべての提出 - AtCoder Beginners Selection

だいたいこんな感じ、各問題の初回のACは実力で、2回目以降は他の人の解法を眺めながらやった。そこでコード量はたいして変わらないのに、実行時間が違うんだーということがあった。見つけたのはこの問題を解いているときであった。

ABC086C - Traveling

最初の僕のコードはこちら。

Submission #7131569 - AtCoder Beginners Selection

def init
  $n = $stdin.gets.chomp.split(" ").map(&:to_i)
  $line = %w()
  while line = gets
    $line.push(line.chomp.split(' ').map(&:to_i))
  end
end

init

def plan
  $line.each do |l|
    return if l[0] < l[1] + l[2] 
    return unless ((l[0] - (l[1] + l[2])) % 2).zero?
  end
  true
end

puts plan ? 'Yes' : 'No'

結構速い実行時間のでは?とか思っていたけど 210 ms で、あれ?意外と遅くない?とか思った。ただRubyに限定した話をすれば最速は 154 ms であった。(他人のコードなので、このブログには転載しない、またRuby言語以外だと20ms台の実行時間もあるので、Ruby自体がこの問題では僕が想像していた速いタイムにはならない。)

Submission #6047015 - AtCoder Beginners Selection

なるほどーgetsをしながらループをすれば読み込みと実際の処理を一緒にできて速くなるなーと思い真似してみた。すると 172 ms になり、速くはなったが150ms台にならない。なぜだろうと思った。

n = gets.chomp.to_i
n.times do
  t, x, y = gets.chomp.split(' ').map(&:to_i)
  distance = x + y
  if t < distance || (distance - t).odd?
    puts 'No'
    exit
  end
end

puts 'Yes'

見比べてみると、Ruby最速コードにはsplitは引数を与えないと空白文字で分割してくれる。早速試してみるとわずかだが速くなり170 ms になった。

split (String) - Rubyリファレンス

Submission #7132131 - AtCoder Beginners Selection

さらに見ていくとchompメソッドもない。あれ?改行マーク取り除かなくても大丈夫?と思ったがto_iでNumericに変換しているので改行マークは外れるようだ。chmodメソッドを削除してみると152 ms になり満足する結果になった。

Submission #7132148 - AtCoder Beginners Selection

n = gets.to_i
n.times do
  t, x, y = gets.split.map(&:to_i)
  distance = x + y
  if t < distance || (distance - t).odd?
    puts 'No'
    exit
  end
end

puts 'Yes'

なるほどーchmopsplitも何回も繰り返すと実行時間が延びるので、入力を読む時点で実行時間を気にして書けばいいのかーと勉強になった。結構前のコードのコピペになりやすいのでこういう発見ができてよかった。

MacからUbuntuに移行したときの作業メモ

leokun0210.hatenablog.com

MacからUbuntuに移行しようといろいろ試行錯誤している。最初の設定でやったことをまとめておく

USキーボードを使用できるようにして、altで英字/かなのトグルができるようにする

Ubuntu18.04 USキーボードで日本語切り替えをaltキーで行う - Qiita

Fcitxをインストールする。FcitxとはLinuxに環境非依存の言語サポートを提供するインプットメソッドフレームワークらしい。

Fcitx - ArchWiki

Fcitxをパッケージからインストールする。 im-config というのは、マニュアルを見る限り、X Window Systemのインプットメソッドの設定を行うツールと書いてある。 -n オプションはインプットメソッドネームを指定するオプション。完了したら一旦再起動、 sudo reboot でも再起動できる。

sudo apt install -y fcitx fcitx-mozc
sudo im-config -n fcitx

fcitx設定を開く。入力メソッドには最初から英字キーボードが認識されていた。アプリケーションから言語サポートを開いて、キーボード入力に使うIMシステムがfcitxになっていることを確認する。fcitx設定に戻って、全体の設定タブに切り替える。入力メソッドのオンオフで左右のaltのキーを割り当てる。

CapsLockをCtrlに割り当てる

Ubuntu 16.04 CapsLockをControlに置換する方法 - Qiita

マニュアルを見る限りキーボードの設定ファイルらしい。

マウスの速度調整

マウスとタッチパッドを開く。

プリンター

Windowsで設定したプリンターが引き継がれていた。

windows10とUbuntuのデュアルブート環境を作った

大学のテストが終わって時間ができたので、以前からやろうとしていたメインマシンをLinuxにしようと作業していた。その作業メモである。ディストリビューションは、楽に入るUbuntuにした。

参考にしたサイト

Windows 10でUbuntuのインストール用USBメモリを作成 | 普段使いのArch Linux

UbuntuとWindowsのDualboot環境を構築する | UnFlexFlex

Ubuntu Desktop 日本語 Remixのダウンロード | Ubuntu Japanese Team

起動ディスクの作成 - Ubuntu 18.04 LTS デスクトップガイド改

推奨するBIOSの入り方 - ThinkPad, ThinkCentre, ThinkStation - CO

作業環境

作業手順

Ubuntuの起動ディスクの作成

19.04を入れることにした。 Ubuntu Desktop 日本語 Remixのダウンロード | Ubuntu Japanese Team よりダウンロードする。そのあとRufusUSBメモリに記録する。選択でisoファイルを選択して、記録媒体を選択するといい感じに項目をセットしてくれる。FPT UEFIコンピュータ用のパーティション構成を選択して、ファイルシステムFAT32 にしておく。

UEFIを設定する

  • ThinkpadのF2キーを押して、 ThinkPad Setup を開く(F1でもいいらしいけど試していない)
  • Boot Priority Orderの順位をWindows Boot ManagerよりUSB HDDを上にする。

    Windows10側の作業

  • UbuntuとWindowsのDualboot環境を構築する | UnFlexFlex これ通りに作業した。

  • 高速スタートアップを無効にする
  • Windowsのドライブを縮小した。とりあえず20GBぐらい確保した。(今考えたら80GBぐらいでもよさそうだった。)

Ubuntuのインストール作業

再起動して、bootするOSを決める。

  • UbuntuのBoot menuがたちあがるので、UbuntuWindows、立ち上げたいOSを選択する。

感想

  • ちょっと最初の容量の割り当てをミスった感じがするので、もう一度インストール頑張ってみるかも
  • 所要時間は調べもの込みで5時間くらい。結構疲れた。
  • 本格的にUbuntuを使うには、まだまだいろいろソフトウェアを入れなければならないが、もうMacは高いので卒業する予定なので頑張る。