Open5

AtCoderでDartが使えるようになってたのでオレオレコードスニペットまとめ

菊池紘菊池紘

AtCoderで使用できるのは2.7.2(2021年10月9日現在)

なのでExtensionやnull safetyは入っていない。
collection ifやcollection forは使用可能。

菊池紘菊池紘

開始時のテンプレート

import 'dart:io';

void main() {
  final x = int.parse(stdin.readLineSync());

}

入力値のタイプによってのパース方法

// 入力値が一行に一つだけ
final x = int.parse(stdin.readLineSync());

// 入力値が空白区切りで固定数
final inputs = stdin.readLineSync().split(" ").map(int.parse).toList();
final x = inputs[0];
final y = inputs[1];
final z = inputs[2];

// 2つだけならtoListはなくてもいい
final inputs = stdin.readLineSync().split(" ").map(int.parse);
final x = inputs.first;
final y = inputs.last;

入力が多いとき、また1行あたりの文字数が多いときは readLineSync() だと遅くて実行時間制限にひっかかるケースがある -> AtCoder に登録したら解くべき精選過去問 10 問をDartで解いてみた
こういうときはstdinをStream扱いして非同期読み込みする。
基本的に1行ずつ操作していくことになる。

import 'dart:io';
import 'dart:convert';

void main() async {
  final lines = stdin.transform(utf8.decoder).transform(LineSplitter());

  await for (final line in lines) {
    
  }
}
菊池紘菊池紘

よく使いそうなメソッド。
どのクラスが何を持っているのかわからなくなる時があるので。

  • 絶対値
    • num.abs()
  • ソート
    • List.sort((a, b) => a - b) で昇順ソート
    • b - a にすると降順ソートになる
  • 文字列切り出し
    • String.substring(start, end)
    • 第一引数が 0 だと、第二引数の文字数だけ切り出してくれる、と覚えれば良さそう
      • abcdefghif は6文字目。 substring(0, 6) => abcdef
  • 偶奇判定
    • int.isEven / int.isOdd で判定可能
    • 2つの数の偶奇が一致するかどうかは a %2 == b % 2 で見たほうがよい
  • 畳み込み系
    • Iterable.reduce((prev, value) => prev + value) 初期値がいらない
    • Iterable.fold(true, (prev, value) => prev && value) 初期値がいる
菊池紘菊池紘

AtCoder Beginners Selection

PracticeA - Welcome to AtCoder

import 'dart:io';

void main() {
  final a = int.parse(stdin.readLineSync());
  final bc = stdin.readLineSync().split(" ").map(int.parse);
  final b = bc.first;
  final c = bc.last;
  final s = stdin.readLineSync();
  print("${a+b+c} ${s}");
}

ABC081A - Placing Marbles

import 'dart:io';

void main() {
  final cond = stdin.readLineSync();
  final parsed = [
    cond[0] == "1" ? 1 : 0,
    cond[1] == "1" ? 1 : 0,
    cond[2] == "1" ? 1 : 0,
  ];
  final sum = parsed.reduce((value, element) => value + element);
  print(sum);
}

ABC081B - Shift only

import 'dart:io';

void main() {
  final n = stdin.readLineSync();
  var as = stdin.readLineSync().split(" ").map(int.parse);
  var allEven = false;
  var count = 0;
  do {
    allEven = as.fold(true, (v, e) => v && e % 2 == 0);
    if (allEven) {
      count++;
      as = as.map((e) => e ~/ 2);
    }
  } while (allEven);
  print(count);
}

ABC087B - Coins

import 'dart:io';

void main() {
  final a = int.parse(stdin.readLineSync());
  final b = int.parse(stdin.readLineSync());
  final c = int.parse(stdin.readLineSync());
  final x = int.parse(stdin.readLineSync());
  
  var count = 0;
  for (int fh = 0; fh <= a; fh++) {
    for (int oh = 0; oh <= b; oh++) {
      for (int ft = 0; ft <= c; ft++) {
        if (canMakeX(fh, oh, ft, x)) {
          count++;
        }
      }
    }
  }
  print(count);
}

bool canMakeX(int fh, int oh, int ft, int x) => x == (500 * fh + 100 * oh + 50 * ft);

ABC083B - Some Sums

import 'dart:io';

void main() {
  final inputs = stdin.readLineSync().split(" ").map(int.parse).toList();
  final n = inputs[0];
  final a = inputs[1];
  final b = inputs[2];
  
  final l = <int>[];
  for (int x = 1; x <= n; x++) {
    final sum = splitDigits(x).reduce((p,n) => p+n);
    if (a <= sum && sum <= b) {
      l.add(x);
    }
  }
  print(l.reduce((p, n) => p + n));
}

List<int> splitDigits(int x) {
  final l = <int>[];
  for (int d = 1; d <= x; d *= 10) {
    final above = x ~/ (d * 10);
    l.add((x - (above * d * 10)) ~/ d);
  }
  return l;
}

ABC088B - Card Game for Two

import 'dart:io';

void main() {
  final n = int.parse(stdin.readLineSync());
  final as = stdin.readLineSync().split(" ").map(int.parse).toList();
  
  as.sort((a, b) => b - a);
  int diff = 0;
  for (int i = 0; i < n; i++) {
    if (i % 2 == 0) {
      // Aliceの番
      diff += as[i];
    } else {
      // Bobの番
      diff -= as[i];
    }
  }
  print(diff);
}

ABC085B - Kagami Mochi

import 'dart:io';

void main() {
  final x = int.parse(stdin.readLineSync());
  final ds = [
    for (int i = 0; i < x; i++)
      int.parse(stdin.readLineSync()),
  ];
  
  ds.sort((a, b) => b - a);
  int count = 0;
  int last = ds.first + 1;
  for (int i = 0; i < x; i++) {
    if (ds[i] < last) {
      count++;
      last = ds[i];
    }
  }
  print(count);
}

ABC085C - Otoshidama

import 'dart:io';

void main() {
  final inputs = stdin.readLineSync().split(" ").map(int.parse);
  final N = inputs.first;
  final Y = inputs.last;
  
  for (int ot = 0; ot <= N; ot++) {
    for (int ft = 0; ft <= N - ot; ft++) {
      final tt = N - ft - ot;
      final currentPrice = price(tt, ft, ot);
      if (currentPrice == Y) {
        print("$tt $ft $ot");
        return;
      }
    }
  }
  print("-1 -1 -1");
}

int price(int tt, int ft, int ot) => tt * 10000 + ft * 5000 + ot * 1000;

ABC049C - 白昼夢

import 'dart:io';

void main() {
  const words = ["dream", "dreamer", "erase", "eraser"];
  final S = stdin.readLineSync();

  String rest = S;
  while (rest.length > 0) {
    bool found = false;
    for (final w in words) {
      final s = rest.length - w.length;
      if (s < 0) {
        continue;
      }
      final t = rest.substring(s, rest.length);
      if (t == w) {
        rest = rest.substring(0, s);
        found = true;
        break;
      }
    }
    if (!found) {
      print("NO");
      return;
    }
  }
  print("YES");
}

ABC086C - Traveling

import 'dart:io';
import 'dart:convert';

void main() async {
  final N = int.parse(stdin.readLineSync());
  final lines = stdin.transform(utf8.decoder).transform(LineSplitter()).take(N);

  List<int> prev = const [0, 0, 0];
  await for (final line in lines) {
    final point = line.split(" ").map(int.parse).toList();
  
    final dt = point[0] - prev[0];
    final ddist = (point[1] - prev[1]).abs() + (point[2] - prev[2]).abs();
    if (dt < ddist) {
      print("No");
      return;
    }
    if (dt % 2 != ddist % 2) {
      print("No");
      return;
    }
    prev = point;
  }
  print("Yes");
}
菊池紘菊池紘

AtCoder に登録したら次にやること ~ これだけ解けば十分闘える!過去問精選 10 問 ~ には、Beginners Selectionの次におすすめの問題が書いてあるので、ぽつぽつ挑戦する。

グリッド系の問題

はいはい番兵番兵、って感じで素直に書いたら通った。

AtCoder Beginner Contest 075 : B - Minesweeper

import 'dart:io';

void main() {
  final hw = stdin.readLineSync().split(" ").map(int.parse);
  final H = hw.first;
  final W = hw.last;
  final grid = [
    "." * (W+2),
    for (int i = 0; i < H; i++)
      ".${stdin.readLineSync()}.",
    "." * (W+2),
  ];
  
  String countOrBomb(int i, int j) {
    if (grid[i][j] == "#") return "#";
    int count = 0;
    for (int y = i-1; y <= i+1; y++)
      for (int x = j-1; x <= j+1; x++) {
        count += (grid[y][x] == "#") ? 1 : 0;
      }
    return "$count";
  }

  for (int i = 1; i <= H; i++) {
    final line = <String>[
      for (int j = 1; j <= W; j++)
        countOrBomb(i, j),
    ];
    print(line.join(""));
  }
}

AtCoder Beginner Contest 096 : C - Grid Repainting 2

import 'dart:io';

void main() {
  final hw = stdin.readLineSync().split(" ").map(int.parse);
  final H = hw.first;
  final W = hw.last;
  final grid = [
    "." * (W+2),
    for (int i = 0; i < H; i++)
      ".${stdin.readLineSync()}.",
    "." * (W+2),
  ];
  
  bool canDrawOrThru(int i, int j) {
    if (grid[i][j] != "#") return true;
    return [
      grid[i-1][j],
      grid[i][j-1],
      grid[i][j+1],
      grid[i+1][j],
    ].map((e) => e == "#").fold(false, (p, e) => p || e);
  }

  for (int i = 1; i <= H; i++) {
    for (int j = 1; j <= W; j++) {
      if (!canDrawOrThru(i, j)) {
        print("No");
        return;
      }
    }
  }
  print("Yes");
}

区間の重なり問題

AtCoder Beginner Contest 070 : B - Two Switches

import 'dart:io';
import 'dart:math';

void main() {
  final ABCD = stdin.readLineSync().split(" ").map(int.parse).toList();
  final A = ABCD[0];
  final B = ABCD[1];
  final C = ABCD[2];
  final D = ABCD[3];
  
  // 範囲の後先を考えないといけない。
  // AとCの比較が必要。Aの方が小さければAliceが先にボタンを押した。Cの方が小さければBobが先にボタンを押した。
  // 次に先行区間と後行区間の重なりがあるか調べる。先行区間の終端より後行区間の始端が大きければ重なりなし
  // 重なりがあれば、後行区間の始端から、先行区間の終端か後行区間の終端のどちらか小さい方までが重なり区間になる。
  final fs = (A < C) ? A : C;
  final fe = (A < C) ? B : D;
  final ss = (A < C) ? C : A;
  final se = (A < C) ? D : B;
  
  if (fe <= ss) {
    print("0");
    return;
  }
  print("${min(fe, se)-ss}");
}