精選過去問→AtCoder に登録したら次にやること ~ これだけ解けば十分闘える!過去問精選 10 問 ~ - Qiita,
Tasks - AtCoder Beginners Selection
いろんな言語のまとめ→百花繚乱!なないろ言語で競技プログラミングをする資料まとめ - Qiita
既にあるやつ
AtCoderに登録したら解くべき精選過去問10問をD言語で解いてみた (takeoさん)
AtCoderに登録したら解くべき精選過去問10問をD言語で解いてみた - D言語の構文と標準ライブラリを使い倒す編 - 矮小 (yousackさん)
(この記事の新規性は)ないです(たまにはブログ記事を書きたかった)
PracticeA - はじめてのあっとこーだー(Welcome to AtCoder)
import std.stdio : readf, readln, writeln;
import std.string : strip;
void main() {
int a, b, c;
string s;
readf("%d\n", &a);
readf("%d %d\n", &b, &c);
s = readln.strip;
writeln(a+b+c, " ", s);
}
readf
でscanf
と同じように入力できます。ただし
- int以外も全部符号付き整数は
%d
, 符号なし整数は%u
で入力(%lld
とかはつかわない)
\n
が無いと壊れる
などの違いがあります。
readln(1行読み込み)は最後に改行文字がくっついてくるのでstrip, chomp
などで取り除きましょう
なお,core.stdc.stdio
をimportするとC言語のscanf, printf
が使えるようになります。文字列の扱いが難しいのでおすすめしません
import core.stdc.stdio;
import std.string : strip;
void main() {
int a, b, c;
char[] s = new char[100];
scanf("%d %d %d %s", &a, &b, &c, s.ptr);
printf("%d %s\n", a+b+c, s.ptr);
}
ABC086A - Product
import std.stdio;
void main() {
int a, b;
readf("%d %d\n", &a, &b);
writeln(["Even", "Odd"][a*b%2]);
}
配列リテラルは{1, 2, 3}
じゃなくて[1, 2, 3]
です
ABC081A - Placing Marbles
import std.stdio, std.string;
import std.algorithm : count;
void main() {
string s = readln.strip;
writeln(s.count('1'));
}
s.count(x)
でx
の個数を数えられます
ABC081B - Shift only
import std.stdio;
import std.algorithm : map, reduce, min;
import std.string : split;
import std.conv : to;
void main() {
readln;
int[] l = readln.split.to!(int[]);
auto f(int x) {
int cnt = 0;
while (x % 2 == 0) {
cnt++;
x /= 2;
}
return cnt;
}
writeln(l.map!f.reduce!min);
}
高階関数ってやつをやってみます
l
: 入力した配列です
l.map!f
: l
の各要素にf
を適用した配列(のようなもの)です。たとえばl=[8, 12, 40]
ならl.map!f = [3, 2, 3]
l.map!f.reduce!min
: l.map!f
の各要素をmin
を使って畳み込みます,つまりl.map!f = [a, b, c, ...]
としてl.map!f.reduce!min = min(a,b,c,... )
ABC087B - Coins
import std.stdio;
void main() {
int a, b, c, x;
readf("%d\n%d\n%d\n%d\n", &a, &b, &c, &x);
int ans = 0;
foreach (i; 0..a+1) foreach (j; 0..b+1) foreach (k; 0..c+1) {
int y = i*500 + j*100 + k*50;
if (y == x) ans++;
}
writeln(ans);
}
foreach (i; a..b)
はfor (int i = a; i < b; i++)
とだいたい同じです
ABC083B - Some Sums
import std.stdio, std.string, std.conv, std.algorithm;
import std.algorithm : sum;
import std.range : iota;
void main() {
int n, a, b;
readf("%d %d %d\n", &n, &a, &b);
bool ok(int x) {
string s = x.to!string;
int t = s.map!"a-'0'".sum;
return a <= t && t <= b;
}
writeln(iota(1, n+1).filter!ok.sum);
}
iota(1, n+1)
: [1, 2, ..., n]
とだいたい同じです。python2でいうと前者がxrange
で後者がrange
です。
filter!ok
: これも高階関数で,ok(x) = true
となるような要素だけ残します。
sum
: sumを求めます(そうだね)。
つまり,[1, 2, ..., n]
からok
に入力するとtrue
になるようなものを列挙して,それの総和を求めるというコードです。
ABC088B - Card Game for Two
import std.stdio, std.string, std.conv;
import std.algorithm : sort, each;
import std.range : array;
void main() {
readln;
int[] a = readln.split.to!(int[]).sort!"a>b".array;
int[2] res;
a.each!((i, x) => res[i%2] += x);
writeln(res[0] - res[1]);
}
each
でループと同じようなことが出来ます。
ABC085B - Kagami Mochi
import std.stdio, std.range, std.algorithm;
import std.algorithm : uniq;
void main() {
int n;
readf("%d\n", &n);
int[] a = new int[n];
foreach (i; 0..n) {
readf("%d\n", &(a[i]));
}
writeln(a.sort.uniq.array.length);
}
a.sort.uniq
でsortしてuniqueします。
ABC085C - Otoshidama
import std.stdio, std.range;
import std.algorithm : cartesianProduct;
void main() {
int n, y;
readf("%d %d\n", &n, &y);
int ans = 0;
foreach (p; cartesianProduct(iota(n+1), iota(n+1))) {
int a = p[0], b = p[1], c = n-a-b;
if (c < 0) continue;
int x = a*10000 + b*5000 + c*1000;
if (x == y) {
writeln(a, " ", b, " ", c);
return;
}
}
writeln("-1 -1 -1");
}
公式ドキュメント読んでたらcartesianProduct
とかいうの見つけたので使います。
cartesianProduct([1, 2], [3, 4]) = [[1, 3], [1, 4], [2, 3], [2, 4]]
みたいな感じっぽいです。つまり二重ループが出来ます
ABC049C - 白昼夢 / Daydream
import std.stdio, std.string, std.regex;
void main() {
string s = readln.strip;
auto r = regex(r"^(dream|dreamer|erase|eraser)*$");
if (s.matchFirst(r)) {
writeln("YES");
} else {
writeln("NO");
}
}
正規表現も使えます。そう,D言語ならね。
import std.stdio;
import std.math : abs;
import std.typecons : tuple;
import std.meta : AliasSeq;
bool solve() {
int T;
readf("%d\n", &T);
int bt = 0, bx = 0, by = 0;
foreach (i; 0..T) {
int t, x, y;
readf("%d %d %d\n", &t, &x, &y);
int dt = t-bt;
int di = abs(x-bx) + abs(y-by);
if (di % 2 != dt % 2 || dt < di) {
return false;
}
AliasSeq!(bt, bx, by) = tuple(t, x, y);
}
return true;
}
void main() {
writeln(solve() ? "Yes" : "No");
}
AliasSeq!(a, b, c) = tuple(d, e, f)
でC++のtieと同じようなこと(複数同時代入)が出来るっぽいです。