(変更履歴)
2017/2/2:yu_ishikawaさん、表の整形どうもありがとうございました!
および、f補完子の小数書式を訂正しました。
大上段なタイトルですが、paizaやCodeIQターゲットなので競技というほどでもありませんが……。
標準入出力
ロジックは別として結構面倒なのが標準入出力周りではないでしょうか。。
入力
paizaでよくある入力のパターンとして、以下の形式がある。
1.一行目は設定
2.二行目以降に実データ
たとえば、以下のような入力が与えられる。
5 3
123 456 789
111 222 333
1 2 3
63 72 81
100 200 300
1行目の二つの数字は、それぞれ実データのレコード件数、および1レコード内のフィールド数となる。二行目以降に実データ(上記の例では5行3列のデータ)が与えられる。
一行ずつ読み込む - io.StdIn.readLine
動きがわかりやすいのが利点です。
object Main extends App {
import scala.io.StdIn.readLine
val Array(rows, cols) = readLine split " " map(_.toInt)
val xss = for(i<- (1 to rows)) yield readLine split " " map(_.toInt) toList
println(xss.mkString(" "))
// 結果
// List(123, 456, 789) List(111, 222, 333) List(1, 2, 3) List(63, 72, 81) List(100, 200, 300)
}
Scannerを使う - java.util.Scanner(System.in)
おそらくこれが最も使い勝手が良いです。
object Main extends App {
val sc = new java.util.Scanner(System.in)
val rows, cols = sc.nextInt
val xss = List.fill(rows, cols)(sc.nextInt)
println(xss)
// 結果
// List(List(123, 456, 789), List(111, 222, 333), List(1, 2, 3), List(63, 72, 81), List(100, 200, 300))
}
複数行読み込む - io.Source.stdin.getLines
Paizaでは使える場面が思いつかないが、他では使えるのではないでしょうか。
入力が続く限り読み込むケース
object Main extends App {
val xss = for(l <- scala.io.Source.stdin.getLines) yield (l split " " map(_.toInt) toList)
println(xss.mkString(" "))
// 結果
// List(5, 3) List(123, 456, 789) List(111, 222, 333) List(1, 2, 3) List(63, 72, 81) List(100, 200, 300)
}
特定の数値を受け取るまで読み込むケース
たとえば、-1が与えられるまで読み込む場合。
1 2 3
1 2 3
1 2 3
1 2 3
1 2 3
-1
for式とifガードをつかって"-1"という文字列が来るまでyieldすれば良いです。
object Main extends App {
val xss = for (l <- scala.io.Source.stdin.getLines; if l != "-1") yield (l split " " map(_.toInt) toList)
println(xss.mkString(" "))
// 結果
// List(1, 2, 3) List(1, 2, 3) List(1, 2, 3) List(1, 2, 3) List(1, 2, 3)
}
特定の書式に従って読み取る。
特定の書式(たとえばyyyy/mm/ddなど)に従って入力が与えられるケースです。正規表現とIteratorで乗り切ります。
以下の入力が与えられるとします。
2017/01/31 10:09:32
一例として
object Main extends App {
import scala.io.StdIn.readLine
val r = """\d{2,4}""".r
val dt = r.findAllIn(readLine)
val yyyy, mm, dd, hour, min, sec = dt.next.toInt
println(yyyy, mm, dd, hour, min, sec)
// 結果
// (2017, 1, 31, 10, 9, 32)
}
結論
Paiza、CodeIQでは以下をまずコピペしておくと捗るはずです。
object Main extends App {
val sc = new java.util.Scanner(System.in)
/* Sample Code */
val rows, cols = sc.nextInt
val xss = List.fill(rows, cols)(sc.nextInt)
println(xss)
}
参考:
Scalaで標準入力を受け取る - Perl日記
Scalaで競技プログラミング(入出力編) - Qiita
Scalaの標準入力 - Qiita
競技プログラミングにおけるScalaの標準入力を楽にする - Qiita
【Scala】 正規表現による文字列検索 - takafumi blog
Pythonで競技プログラミングする時に知っておきたいtips(入出力編) - Qiita
出力
入力処理に比べてパターンは少ないです。
普通のprintln
println("Hello, World!")
// Hello, World!
println("Hello,\nWorld!")
// Hello,
// World!
s補完子
変数、式を埋め込める。
val w = "World"
println(s"Hello, ${w}!")
// Hello, World!
println(s"1 + 1 = ${1+1}")
// 1 + 1 = 2
println(s"${for (i<-(1 to 10)) yield i}")
// Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
f補完子
s補完子に書式指定の機能を追加したもの
val a = 12
val b = "aaa"
println(f"${a}%03d")
// 012
println(f"${a}%04.2f")
// 12.00 (本来は0012.00という動きを期待していたのだが……)
println(f"${b}%10s")
// " aaa"
参考:
scalaの文字列いろいろありすぎて笑ったけど便利だった | KentaKomai Blog
printfで文字列の最大文字数を指定する - 揮発性のメモ
フォーマット指定子一覧
fprintf()
プリミティブ型
PaizaではIntもしくはLongで十分と思われますが、念のため。
型名 | 説明 | 範囲(数値型の場合) | 例 |
---|---|---|---|
Boolean | 真偽値 | true,false | |
String | 文字列 | "abcde" | |
Char | 2バイトUnicode文字 | 'A','あ' | |
Byte | 8ビット符号付整数値 | -128~127 | (省略) |
Short | 16ビット符号付整数値 | -32768~32767 | (省略) |
Int | 32ビット符号付整数値 | -2147483648~2147483647 | (省略) |
Long | 64ビット符号付整数値 | -9223372036854775808~9223372036854775807 | (省略) |
Float | 32ビット浮動小数点数 | -3.4028235E38~3.4028235E38 | 0.2f, 1e-2f |
Double | 64ビット浮動小数点数 | -1.7976931348623157E308~1.7976931348623157E308 | 0.2, 0.2d, 1e-2, 1e-2d |
BigInt | 任意桁数の整数 | 多分ない | BigInt(10), BigInt("123179623176239716237619241") |
BigDecimal | 任意桁数の数値(小数点有り) | ある程度整数部が大きいと小数部が丸められる | BigDecimal(10000.12345), BigDecimal("123719.1823761238") |
ScalaのLong型はc言語で言うところの「long long」型に相当します。
BigIntはこんな風に使います。すんごい大きな数字を扱うのに便利です(遅いけど)。
scala> val v = BigInt(1234567890)
v: scala.math.BigInt = 1234567890
scala> v + v
res14: scala.math.BigInt = 2469135780
scala> v * v
res15: scala.math.BigInt = 1524157875019052100
scala> v * v * v
res16: scala.math.BigInt = 1881676371789154860897069000
scala> v * v * v * v
res17: scala.math.BigInt = 2323057227982592441500937982514410000
scala> (v * v * v * v).toDouble
res18: Double = 2.3230572279825926E36
scala> val v2 = v * v * v * v
v2: scala.math.BigInt = 2323057227982592441500937982514410000
scala> v2
res19: scala.math.BigInt = 2323057227982592441500937982514410000
scala> val v3 = BigInt(23179871238719823798138927198)
<console>:1: error: integer number too large
val v3 = BigInt(23179871238719823798138927198)
^
scala> v2 * -1
res20: scala.math.BigInt = -2323057227982592441500937982514410000
scala> v2 * -1 + 10
res21: scala.math.BigInt = -2323057227982592441500937982514409990
参考:
第6章:Scalaのプリミティブ型を語る - Qiita
猿でも分かるScala!:Scalaの型 - Qiita
アスリートの皆様
参考:
Scalaで競技プログラミングしてみる - Lizan's note
scalaで競技プログラミング -ABC001- - scache's diary
競技プログラミングモードのscalaを書いてみたw
競技プログラミング特有の変な実装テク // ichyo.jp → C++だけど有用です
Scala歴0日で競技プログラミングの問題にScalaで解答してみた - はむ吉(のんびり)の練習ノート
競技プログラミング in Scala - 純粋関数型雑記帳
ScalaでCodeforces#97 Div2参加してみた - くじらにっき++
Pythonで競技プログラミングする時に知っておきたいtips - Qiita → Pythonだけど結構Scalaにも応用できます。
一般論
競技プログラミングへの心構え、解き方
動的計画法、幅優先探索、深さ優先探索などなど。
競技プログラミング | ソフトウェア工房
競技プログラミング Wiki*
競技プログラミングの問題の解き方、そのマニュアル · うさぎ小屋
競技プログラミング頻出アルゴリズム攻略
有名競技プログラミングサイト
yukicoder
Topcoder | Deliver Faster through Crowdsourcing
AtCoder
AIZU ONLINE JUDGE: Programming Challenge
Welcome To PKU JudgeOnline