LoginSignup
0
0

More than 3 years have passed since last update.

Perl AtCoder ABC 159 D で嵌った話、うまくいった話

Last updated at Posted at 2020-03-23

はじめに

以前、厳選!Perl アルゴリズム実装に使える 25 の 標準ライブラリ【前編】という記事を投稿しましたが、それが役立った話と、嵌った話です。

D - Banned K

AtCoder Beginner Contest 159 D - Banned K
ボールが N 個あり、i 番目のボールには整数 Ai が書かれています。

うまくいった話

各整数ごとの出現頻度を取得するために、以前の投稿の ハッシュの利用 が役立ちました。

hash.pl
$h{$_}++ for @list;

もう少し丁寧にすると

hash2.pl
for $_ (@list) {
  if (exists $h{$_}) { # ハッシュにキーが存在するか?
    $h{$_}++;
  } else {             # 存在しない場合
    $h{$_} = 1;
  }
}

Perl では存在しないキーのハッシュは未定義値を返しますので、未定義値に ++ 演算子を使用すると、0 + 1 => 1 の扱いとなり hash.pl の書き方でも正しく動作します。
流石 TMTOWTDI

どやっ

WA.pl
use v5.18; # strict say state
use warnings;

chomp (my $n = <STDIN>);
my @a = split / /, <STDIN>;
my (%h, %k, %g);
$h{$_}++ for @a;
my $sum = 0;
for (keys %h) {
  $sum += $k{$_} = $h{$_} * ($h{$_} - 1) / 2;
  $g{$_} = ($h{$_} - 1) * ($h{$_} - 2) / 2;
}
for (0..($n-1)) {
  say  $sum - $k{$a[$_]} + $g{$a[$_]};
}
WA

ぐぬぬ

嵌った話

後半の for ループの中の計算式をいろいろ触ってもうまくいかず、元のハッシュの中を見てみますと、

入力例1.txt
5
1 1 2 1 2
Keys Values
1 3
2 1
2 1

あっ、2 が別れてカウントされている。
といいますか、2 の後ろに改行コード(見えない)が含まれていました。

before.pl
my @a = split / /, <STDIN>;
after.pl
chomp (my @a = split / /, <STDIN>);

他の競技者を参考にするなら

another.pl
my @a = map {$_ + 0} split (/ /, <STDIN>);

これも Perl の仕様で、

another.pl
print "2\n" + 0;                          # => 2
print "1 dollar 2 dollars" + "3 dollars"; # => 4

+ 演算子で数値と文字が混在した場合、先頭の数値部分のみを評価することを利用して、改行コードを除去しています。
やっぱり TMTOWTDI

他言語

java.java
int a = Integer.parseInt(scanner.next());
ruby.rb
a = gets.split.map(&:to_i) 

後発のオブジェクト指向言語は型を指定して、スペースや改行コードをうまいことやってくれるんですよね。

まとめ

  • 投稿した記事が役立った
  • 新たな知見を得た
  • TMTOWTDI
  • 隣の芝生は青く見える

参照したサイト
exists関数 - ハッシュのキーの存在確認

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0