C++入門 AtCoder Programming Guide for beginners (APG4b) 第1章(実践3)

APG4b第1章(実践3) プログラミング

前回の記事でC++入門 AtCoder Programming Guide for beginners(APG4b)第1章の「1.04.変数と型」~「1.05.ABC問題(A – Placing Marbles)」まで進みましたので、今回はその続きを進めて行きたいと思います。
まずは以下のサイトへアクセスしてログインしましょう。

AtCoderProgrammingGuideforbeginners(APG4b)トップ画面

引用元:https://atcoder.jp/contests/APG4b

1.06.if文・比較演算子・論理演算子

1.06.if文・比較演算子・論理演算子

ここのページに書かれている内容の「比較演算子」と「論理演算子」について補足します。
比較演算子は2つの値を比べることしか出来ないので、3つの値を一度に比べることは出来ません。
例えば以下のような変数a、変数b、変数cがあったとしてif文で一度に比較すると正しく判定されません。

APG4b_1.06_正しくないプログラムの例

もし3つの値を比較したい場合は以下の2つのパターン(if文を2重にするか&&でつなぐ)で書きます。

【パターン1(if文を2重にする)】

APG4b_1.06_正しいプログラムの例1

【パターン2(&&でつなぐ)】

APG4b_1.06_正しいプログラムの例2

また、論理演算子は複数個を並べて使うことが出来ます。(&&と||を一緒に使うことも出来ます)
例えば以下のような変数a、変数b、変数cがあったとしてif文で一度に複数の比較条件を並べることが出来ます。

APG4b_1.06_正しいプログラムの例3

EX6 – 電卓をつくろう

EX6 – 電卓をつくろう

この問題は算術演算子を表すopの種類ごとにif文で処理を場合分けします。
特にポイントになるのは割り算を表す「A / B」の場合で、割る数(B)がゼロかゼロじゃないかでさらに処理を分けなければならないので「A / B」の場合はif文を2重にするか&&でつなぐ必要があります。
今回の問題についてはopの種類ごとにそれぞれ独立したif文としても、else ifを用いて1つの関連するif文の繋がりとしてもどちらで書いても構いません。また、opの四則演算以外の記号である「?」「=」「!」の扱い方について、それぞれをパターンに分けて”error”を出力しても良いですし、else文でまとめて「その他」として”error”を出力してもどちらでも構いません。
上記の内容を踏まえて解答を以下に2パターン用意しますので、どちらでも正解になります。
また、AtCoderでは以下のようにif文の { から } まで挟んだ範囲を見分けるために、プログラムの行数を表す数字の右に▼マークが表示されるので、クリックするとif文の { から } までの範囲を閉じたり開いたり出来ます。

AtCoderProgrammingGuideforbeginners(APG4b)_C++_1.06.EX6解説
EX6 – 電卓を作ろう:解答1
#include <bits/stdc++.h>
using namespace std;

int main() {
  int A, B;
  string op;
  cin >> A >> op >> B;

  if (op == "+") {
    cout << A + B << endl;
    // ここにプログラムを追記
  }else if(op == "-"){
    cout << A - B << endl;
  }else if(op == "*"){
    cout << A * B << endl;
  }else if(op == "/"){
    if(B == 0){
      cout << "error" << endl;
    }else{
      cout << A / B << endl;
    }
  }else{
    cout << "error" << endl;
  }
}
EX6 – 電卓を作ろう:解答2
#include <bits/stdc++.h>
using namespace std;

int main() {
  int A, B;
  string op;
  cin >> A >> op >> B;

  if (op == "+") {
    cout << A + B << endl;
    // ここにプログラムを追記
  }
  if(op == "-"){
    cout << A - B << endl;
  }
  if(op == "*"){
    cout << A * B << endl;
  }
  if(op == "/"){
    if(B == 0){
      cout << "error" << endl;
    }else{
      cout << A / B << endl;
    }
  }
  if(op == "?"){
    cout << "error" << endl; 
  }
  if(op == "="){
    cout << "error" << endl;
  }
  if(op == "!"){
    cout << "error" << endl;
  }
}

1.06.ABC問題(A – Infinite Coins)

1.06.ABC問題(A – Infinite Coins)

この問題はN円を支払うために、まず無限に持っている500円硬貨で支払えるだけ支払って、500円未満の残りの金額を1円硬貨A枚以内で支払えるか判断する問題です。
つまり言い換えると、もし「N円を500円で割った余り」が「1円硬貨A枚」以下なら支払える、そうでなければ支払えない、ということです。

1.06.ABC問題(A – Infinite Coins):解答
#include <bits/stdc++.h>
using namespace std;

int main() {
  int N , A;
  cin >> N >> A;
  if(N % 500 <= A){
    cout << "Yes" << endl;
  }else{
    cout << "No" << endl;
  }
}

1.06.ABC問題(A – Product)

1.06.ABC問題(A – Product)

この問題はaとbの積が偶数か奇数か判断する問題です。
「偶数か奇数か」を言い換えると「2で割り切れるか割り切れないか」となり、さらに言い換えると「2で割った余りがゼロなのかゼロじゃないのか」となります。

1.06.ABC問題(A – Product):解答
#include <bits/stdc++.h>
using namespace std;

int main() {
  int a , b;
  cin >> a >> b;
  if(a * b % 2 == 0){
    cout << "Even" << endl;
  }else{
    cout << "Odd" << endl;
  }
}

1.06.ABC問題(A – Libra)

1.06.ABC問題(A – Libra)

この問題はA、B、C、Dの重さについて左の皿に乗っている重さ(A + B)と右の皿に乗っている重さ(C + D)を比較した結果を求めなさいっという問題です。
結果をif文を使って3パターン(左に傾く場合と、釣り合う場合と、右に傾く場合)に分けて解きましょう。

1.06.ABC問題(A – Libra):解答
#include <bits/stdc++.h>
using namespace std;

int main() {
  int a , b , c ,d;
  cin >> a >> b >> c >> d;
  if(a + b > c + d){
    cout << "Left" << endl;
  }else if(a + b == c + d){
    cout << "Balanced" << endl;
  }else{
    cout << "Right" << endl;
  }
}

1.06.ABC問題(A – Parking)

1.06.ABC問題(A – Parking)

プラン1(A × T)とプラン2(B)を比較して、どちらのプランが少ないか判断する問題です。

1.06.ABC問題(A – Parking)
#include <bits/stdc++.h>
using namespace std;

int main() {
  int N , A , B;
  cin >> N >> A >> B;
  if(N * A < B){
    cout << N * A << endl;
  }else{
    cout << B << endl;
  }
}

1.06.ABC問題(A – Good Integer)

1.06.ABC問題(A – Good Integer)

この問題は4桁の整数の左3桁または右3桁が同じ数字かどうか判断する問題です。
一般的な解き方と少し変わった解き方の2パターンについて解説します。

【パターン1】
一般的な解き方は1.05.ABC問題(A – Placing Marbles)の解答のように4桁を1桁ずつ千の位、百の位、十の位、一の位にバラバラにして、左3桁が同じ(千の位 = 百の位 = 十の位)または 右3桁が同じ(百の位 = 十の位 = 一の位)場合は”Yes”、それ以外は”No”を表示します。
入力される4桁の数字を変数N、千の位の値を変数S、百の位の値を変数H、十の位の値を変数J、一の位の値を変数Iとすると、S、H、J、Iは以下の式で求められます。(S、H、J、Iは各位の頭文字のアルファベットです)

S = N / 1000
H = (N – S * 1000) / 100
J = (N – S * 1000 – H * 100) / 10
I = N % 10

例えばN = 1234 だった場合、以下のようになります。

S = 1234 / 1000 = 1.234 ⇒ 1(小数切り捨て)
H = (1234 – 1 * 1000) / 100 = 234 / 100 = 2.34 ⇒ 2(小数切り捨て)
J = (1234 – 1 * 1000 – 2 * 100) / 10 = 34 / 10 = 3.4 ⇒ 3(小数切り捨て)
I = 1234 % 10 = 4(1234を10で割った余り)

この書き方で間違いは無いですがちょっと長くてややこしいですね。
以下のように書くともう少し短くてシンプルになるので、こちらの方がおすすめです。


S = N / 1000
H = N % 1000 / 100
J = N % 100 / 10
I = N % 10

例えばN = 1234 だった場合、以下のようになります。

S = 1234 / 1000 = 1.234 ⇒ 1(小数切り捨て)
H = 1234 % 1000 / 100 = 234 / 100 ⇒ 2(小数切り捨て)
J = 1234 % 100 / 10 = 34 / 10 = 3.4 ⇒ 3(小数切り捨て)
I = 1234 % 10 = 4(1234を10で割った余り)

1.06.ABC問題(A – Good Integer):解答1
#include <bits/stdc++.h>
using namespace std;

int main() {
  int N , S , H , J , I;
  cin >> N;
  S = N / 1000;
  H = N % 1000 / 100;
  J = N % 100 / 10;
  I = N % 10;
  if(S == H && H == J){
    cout << "Yes" << endl;
  }else if(H == J && J == I){
    cout << "Yes" << endl;
  }else{
    cout << "No" << endl;
  }
}

【パターン2】
先ほどのパターン1では4桁の数字を1桁ずつバラバラにしましたが、今度はバラバラにしない解き方を考えてみましょう。
「左3桁または右3桁が同じ数字」というのは、言い換えると「左3桁または右3桁の数字が111で割り切れる」となり、さらに言い換えると「左3桁または右3桁の数字を111で割った余りがゼロ」ということです。
そして左3桁とは4桁の数字を10で割って小数を切り捨てた値、右3桁とは4桁の数字を1000で割った余りの値のことです。

1.06.ABC問題(A – Good Integer):解答2
#include <bits/stdc++.h>
using namespace std;

int main() {
  int N;
  cin >> N;
  if(N / 10 % 111 == 0){
    cout << "Yes" << endl;
  }else if(N % 1000 % 111 == 0){
    cout << "Yes" << endl;
  }else{
    cout << "No" << endl;
  }
}

以上で1.06は終わりです。
最後の問題(A – Good Integer)のパターン2の解き方はなかなかトリッキーで思いつきにくいと思いますが、プログラミングの楽しいところは答えが必ずしも1つではなく、アイデア次第で全く異なる解決方法が見つかるところだと思いますので、皆さんも柔軟な頭で問題を解けるよう工夫してみましょう。
それでは今回はここまでにして、次回は「1.07.条件式の結果とbool型」から続きを進めて行きましょう。
お疲れさまでした。

<<1つ前の記事  1つ後の記事>>

コメント

タイトルとURLをコピーしました