Official

A - flip Editorial by MMNMM


AtCoder をはじめたばかりで何をしたらよいか分からない方は、まずは practice contest の問題A「Welcome to AtCoder」を解いてみてください。基本的な入出力の方法が載っています。
また、プログラミングコンテストの問題に慣れていない方は、AtCoder Beginners Selection の問題をいくつか解いてみることをおすすめします。


この問題は、

  • 入力から文字列を読み込む
  • 文字列の文字を対応する文字に変更する
  • 変更された文字列を出力する

ことができれば解くことができます。

実装例のみが気になる人のために、C++ と Python での実装例を置いておきます。 実装例の下に、言語機能の差による実装方針の違いについての話があります。

#include <iostream>
#include <string>
using namespace std;

int main() {
    string s;
    cin >> s;
    
    for (char c : s)
        if (c == '0')
            cout << '1';
        else
            cout << '0';

    cout << endl;

    return 0;
}
s = input()
print(s.replace('0', 'x').replace('1', '0').replace('x', '1'))

使っている言語にどのような機能があるかによって、どのように実装するのが簡単かが変わります。

まず、「文字列の文字を対応する文字に変更する」処理について、

  • 複数の対応する文字どうしを一斉に置き換える方法が用意されている
    • Bash 、Ruby など
  • 文字列中に出現するある \(1\) 文字を、対応する別の \(1\) 文字に一斉に置き換える方法が用意されている
    • Python など
  • 上のような方法が用意されていないか、少し高度な概念を使うため自分で書くほうが簡単になる場合がある
    • C++ 、Haskell など

ような言語に分けることができます。

また、「入力から文字列を読み込む」「変更された文字列を出力する」処理について、

  • 入力の文字列をそのまま変更して出力する方法がある
    • Bash 、Haskell など
  • 入力の文字列を読み込んで変数に入れる方法、変数に入った文字列を出力する方法がある
    • Ruby 、Python 、C++ など
  • \(1\) 文字ずつ読み込む方法しかない
    • ここでは解説しませんが、Brainfuck などがあたります

ような言語に分けることができます。

Bash 、Haskell 、Ruby 、Python 、C++ について、実装例とともに解説をします。

Bash

Bash の tr コマンドを使うと、入力に含まれる文字をそれぞれ対応する文字に変更して出力することができます。
tr ab cd のように書くと、入力の ac に、bd に変更した文字列が出力されます。

実装例は以下のようになります。

tr 01 10

Haskell

Haskell には interact という関数があり、文字列を変換する関数を渡すと入力を変換して出力することができます。 map という関数を用いると、文字を変換する関数を渡すことで文字列のそれぞれの文字を変換する関数を得ることができます。

01 に、10 に変更するパートは自分でロジックを書くほうが(おそらく)シンプルになります。

main = interact $ map (
    \c -> if c == '0' then
              '1'
          else if c == '1' then
              '0'
          else
              c
    )

Ruby

Ruby の文字列には tr というメソッドがあり、s.tr("ab", "cd") などと書くことで ac に、bd に変換することができます。

gets で入力を受け取り、tr で文字を置き換えて puts で出力をするような形になります。

puts gets.tr("01", "10")

Python

Python の文字列には replace というメソッドがあり、s.replace('a', 'b') などと書くと文字列中の ab に変換することができます。 今回のような \(2\) つを入れ替えるような操作は

s.replace('0', '1').replace('1', '0') # うまくいかない例

のように続けて書くとうまくいきません。 一度目の replace('0', '1') で文字列がすべて 1 になってしまうためです。 このような場合、一旦 0 を関係のない文字に置換してしまうことで正しい操作が行えます。

s.replace('0', 'x').replace('1', '0').replace('x', '1') # うまくいく例

input で入力を受け取り、replace で文字を置き換えて print で出力をするとこの問題を解くことができます。

print(input().replace('0', 'x').replace('1', '0').replace('x', '1'))

また、Python の文字列には translate というメソッドがあり、適切な map を渡すことでそれぞれの文字を与えた文字列で変更することができます。

print(input().translate({ord('0'): '1', ord('1'): '0'}))

translate に渡す map は str.maketrans 関数を用いて作成するのがよいでしょう。

print(input().translate(str.maketrans({'0': '1', '1': '0'})))

print(input().translate(str.maketrans('01', '10')))

のような書き方ができます。

C++

C++ では、string 型の変数に入力を受け取ったあと、\(1\) 文字ずつ変換して変換した結果を出力することができます。

#include <iostream>
#include <string>
using namespace std;

int main() {
    string s;
    cin >> s;

    for (char c : s)
        if (c == '0')
            cout << '1';
        else
            cout << '0';

    cout << endl;

    return 0;
}

\(s\) を編集して、最後に \(s\) を出力する形式にすることもできます。

#include <iostream>
#include <string>
using namespace std;

int main() {
    string s;
    cin >> s;

    for (char& c : s)
        if (c == '0')
            c = '1';
        else
            c = '0';

    cout << s << endl;

    return 0;
}

C++ には replace という関数があり、範囲内のある値を別の値に変更することができます。 replace 関数を用いると、次のように実装できます。 Python での例と同様に、一度無関係な文字を挟まないとうまくいかないことに注意してください。

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

int main() {
    string s;
    cin >> s;

    replace(s.begin(), s.end(), '0', 'x');
    replace(s.begin(), s.end(), '1', '0');
    replace(s.begin(), s.end(), 'x', '1');

    cout << s << endl;

    return 0;
}

posted:
last update: