📚

Julia言語で競技プログラミング(入出力編)

2020/12/14に公開

筆者は競技プログラミング初心者で、DPわからんといいつづけてます。
とくに最初の方は入出力の処理にめちゃくちゃ手間取っていたということもあり、そのような悲劇を自分で終わらせるべく、備忘録も兼ねて筆をとることにしました。(競プロ界でもJulia流行ってくれたのむ)

入力の処理

標準入力

Juliaの標準入力の処理は主にreadlinereadlinesの2通りあります。
readlineは標準入力の1行分を受け取って文字列として返し、他方readlinesの返り値は各行の文字列を格納した配列であることに注意する必要があります。
具体例として、以下のような入力を処理する場合について考えてみましょう。

N
M

readlinereadlinesでそれぞれの場合についてみてみましょう。

  • 標準入力から1列の文字列を受け取る
N = readline()
M = readline()
  • 標準出力から全ての列の文字列を受け取る
NM = readlines()
N = NM[1]
M = NM[2]

文字列→数値への変換について

競技プログラミングでは入力が数値であることが多いが、先ほどのままでは文字列として扱われてしまうため、変換の処理が必要です。Julia言語ではこのような変換はparse(T, str)でサポートされています。第一引数は変換先の型、第二引数は変換したい文字列が入ります。
余談ですが、Juliaには任意精度整数が実装されており、通常の整数型ではREとなる問題であっても任意精度整数へ変換するだけで通ったという場合もかなりあるため、整数が大きくなりすぎるような問題では任意精度整数への変換を常に検討しましょう。

parse(Int64, str) #整数への変換。Int64はIntでも可
parse(BigInt, str) #任意精度整数への変換
parse(Float64, str) #実数への変換。Float64はFloatの省略は不可

空白の処理

競技プログラミングの入力ではしばしば1行に空白文字を挟んで複数の数字が現れることがあります。
このような入力を整数として正しく処理するには、split関数を用います。

N M
A_1 A_2 \cdots A_M

上記のような2行の入力は、筆者の場合には次のように処理することが多いです。

parseInt(str=readline()) = parse.(Int, split(str))
N, M = parseInt()
A = parseInt() #要素数Mの配列

split関数は受け取った文字列をデリミタ(デフォルトは空白)で分割し、配列として返す関数です。parse関数のとなりについている奇妙なピリオドはJulia言語のブロードキャストという機能で、配列が引数に入っている場合に各要素に関数をかけたものの配列を返り値として返してくれるという便利機能です。例えばN=26, M=42という引数をparseIntで受け取るという作業をあえて書き下すとこんな感じです。

parseInt
str = readline() #"26 42"という文字列
strs = split(str) #["26", "42"]という文字列を要素とする配列
N, M = parse.(Int, strs) #[parse(Int, "26"), parse(Int, "42")] = Int[26, 42]

出力

標準出力へ出力するにはprintprintlnの2通りあります。printはそのまま標準出力へ流すのに対して、printlnは内容を標準出力へ流した後改行してくれるものです。恐らく競技プログラミングの文脈においてはprintlnさえ知っておけば問題ないでしょう(少なくとも筆者は競プロでprintを一度も使用したことがないです)。引数は数値でも文字列でも問題なく表示してくれるのでそこは安心して使いましょう。

"Yes"
42

と2行の出力を表示させたい場合には以下のように記述します。

N = 42
println("Yes")
println(N)

Discussion