Ruby と Perl と Java と Python で解く AtCoder ABC 107 B 文字列操作

# はじめに
*[AtCoder Problems](https://kenkoooo.com/atcoder/#/)* の Recommendation を利用して、過去の問題を解いています。
AtCoder さん、AtCoder Problems さん、ありがとうございます。
# 今回のお題
*[AtCoder Beginner Contest 107 B - Grid Compression](https://atcoder.jp/contests/abc107/tasks/abc107_b)*
<font color="brown">Difficulty: 434</font>

今回のテーマ、文字列操作
# Ruby
```ruby.rb
h, w = gets.split.map(&:to_i)
a = []
h.times do |i|
  s = gets.chomp
  a.push(s) if s.index('#')
end
(w - 1).downto(0) do |i|
  if a.all?{|x| x[i] == '.'}
    a.each do |x|
      x[i] = ''
    end
  end
end
puts a
```
```count.rb
  a.push(s) if s.count('.') != w
  a.push(s) if s.index('#')
  a.push(s) if s.contain?('#')
```
`count`メソッド、`index`メソッド、`contain`メソッド、その他正規表現でもOKです。

```index.rb
      x[i] = ''
```
*Ruby* の場合、インデックスで指定した文字を直接置換することができます。
**追記**
頂いたコメントより、コードを見直しました。
# Python
```python.py
h, w = map(int, input().split())
a = []
for i in range(h):
    s = input()
    if s.count('.') != w:
        a.append(s)
b = []
for i in range(w):
    f = True
    for x in a:
        if x[i] != '.':
            f = False
    if f:
        b.append(i)
for x in a:
    for i in range(len(x)):
        f = True
        for j in b:
            if i == j:
                f = False
        if f:
            print(x[i], end='')
    print()
```
```find.py
    if s.count('.') != w:
    if s.find('#') == -1:
```
`find`メソッドでもOKです。

*Python* は文字位置での置換もしくは削除ができませんので、削除位置を保管し出力時にスキップしています。
# Perl
```perl.pl
chomp (my ($h, $w) = split / /, <STDIN>);
my @a;
for my $i (1..$h) {
  chomp (my $s = <STDIN>);
  if (scalar(grep {$_ eq '.'} (split '', $s)) != $w) {
    push @a, $s;
  }
}
for my $i (1..$w) {
  my $f = 1;
  for my $x (@a) {
    $f = 0 if substr($x, $w - $i, 1) ne '.';
  }
  if ($f) {
    for my $x (@a) {
      substr($x, $w - $i, 1) = '';
    }
  }
}
for my $x (@a) {
  print "$x\n";
}
```
```grep.pl
  if (scalar(grep {$_ eq '.'} (split '', $s)) != $w) {
  if (index($s, '#') == -1) {
```
`index`でもOKです。
# Java
```java.java
import java.util.*;

class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int h = Integer.parseInt(sc.next());
        int w = Integer.parseInt(sc.next());
        List<String> a = new ArrayList<>();
        for (int i = 0; i < h; i++) {
            String s = sc.next();
            if (s.contains("#")) {
                a.add(s);
            }
        }
        sc.close();
        List<Integer> b = new ArrayList<>();
        for (int i = 0; i < w; i++) {
            boolean f = false;
            for (String x : a) {
                if (x.charAt(i) == '#') {
                    f = true;
                    break;
                }
            }
            if (f) {
                b.add(i);
            }
        }
        for (String x : a) {
            for (int i = 0; i < w; i++) {
                if (b.contains(i))
                    System.out.print(x.charAt(i));
            }
            System.out.println();
        }
    }
}
```
```contains.java
            if (s.contains("#")) {
```
簡単に`.`の個数をカウントする方法が無いようなので、`contains`メソッドを使用しています。
**追記**
コメント欄より、`.`で`split`するアイデアを頂きました。
また、`substring`より`charAt`の方がいいというコメントをいただきましたので、コードを修正しました。

*Java* は、文字位置で置換もしくは削除ができませんので、こういった工夫が必要です。

||Ruby|Python|Perl|Java|
|:--:|:--:|:--:|:--:|:--:|
|コード長|226 Byte|457 Byte|410 Byte|1042 Byte|
|実行時間|9 ms|35 ms|5 ms|219 ms|
|メモリ|1788 KB|4468 KB|512 KB|25032 KB|
# まとめ
+ ABC 107 B を解いた
+ Ruby に詳しくなった
+ Python に詳しくなった
+ Perl に詳しくなった
+ Java に詳しくなった