mery's Notes

めりーがプログラミングしたりします。

MENU

AtCoder Beginner Contest (ABC) 192 PythonでA,B,C問題解いてみた

前回解いたやつ

mery-kirokudayo.hateblo.jp

f:id:mery_poke:20211101225944p:plain


こんにちは。メリーです。

今日も今日とてAtCoder Beginner Contest (ABC) 192 を解いていきます。
言語はPython、提出はPyPyです。

今日はお昼ご飯を食べににラーメン屋さんに行きました。
スープがめちゃくちゃ美味しかったのですが、麺があまりスープと絡んでいなくて微妙でした。
スープがめちゃくちゃ美味かっただけに麺が残念でした。
今回は塩ラーメンを食べました。
北海道は味噌ラーメンが美味しいと言われますが、僕は味噌ラーメンが苦手なので・・・

↓のようなラーメンが美味しいって聞きますね。
僕はコレの醤油を好んで食べてるので、味噌もきっと美味しいんだと思います。

閑話休題それはさておき

目次

A問題

問題文

A - Star

あと何枚コインを集めたらボーナスがゲットできるかを表示する問題ですね。
100枚単位ということはきっとマリオの1UPを意識しているのでしょうね。

方針としては
1. 100で割った余りを出す
2. 100から1で求めたものを引く
3. 2の結果を表示する
というやりかたでできそうです。

実際にやったコードがこちら

x = int(input())
ans = 100 - (x%100)
print(ans)

このやり方でACもらえました。

B問題

問題文

B - uNrEaDaBlE sTrInG

タイトルが!!!!読みにくい!!!!!
可読性を!!!学べ!!!!

という感じのタイトルですね。
最初タイトルの文章読めなかった。

というわけで方針を。
1. ループをlen(s)で回す
2. 奇数番目の文字であれば小文字か判定
3. 偶数番目の文字であれば大文字か判定
4. 全部の文字の判定がOKならば"Yes"、NGがあれば"No"を出力
というやり方でやれそうです。

というわけでコードです。

s = input()
oomoji = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
komoji = "abcdefghijklmnopqrstuvwxyz"
flg = 1
for i in range(len(s)):
    if i%2 == 0: # 奇数番目の文字
        if not(s[i] in komoji):
            flg = 0
            break
    else: # 偶数番目の文字
        if not(s[i] in oomoji):
            flg = 0
            break

if flg:
    print("Yes")
else:
    print("No")

コードの解説していきます。

oomoji、komojiにはそれぞれ全種類の大文字の文字列と小文字の文字列が格納されています。
これは、大文字・小文字判定で使います。

flgに1を格納しているのは、最後に出力するYes、Noを管理するためのフラグです。

for 文では奇数偶数かをまず判定して、その後にそれぞれ処理をしていきます。
sの1文字目はs[0]で表されるので、
2で割った余りが0になる = iが偶数
のとき、文字列の奇数番目となります。

ここ、頭の中がごちゃごちゃになりそうなのでコメントでメモっておくと便利です。

奇数番目の文字列をチェックする場合は、komojiの文字列の中にs[i]が存在するかチェックします。
存在しなかった場合はflgを0にしてループを抜けてNoを表示して終わりです。
存在するなら続けます。

偶数番目の文字列をチェックする場合は、oomojiの文字列の中にs[i]が存在するかチェックします。
存在しなかった場合はflgを0にしてループを抜けてNoを表示して終わりです。
存在するなら続けます。

ループの途中で判定に引っかからなければflgは1のままなので、flgが1ならばYesを、0ならばNoを表示して終わりです。
※1はTrue、0はFalseと同値なので、

if flg:

で条件分岐ができます。

C問題

問題文

C - Kaprekar Number

タイトルを日本語にすると「カプレカー数」になるみたいですね。
wikiで調べると、

カプレカー数(カプレカーすう、Kaprekar Number)とは、次のいずれかで定義される整数である。

  1. 2乗して前の部分と後ろの部分に分けて和を取ったとき、元の値に等しくなるもの。
  2. 桁を並べ替えて最大にしたものから最小にしたものの差を取ったとき、元の値に等しくなるもの。

↓より引用
カプレカー数 - Wikipedia

今回の問題の言うカプレカー数というのは2の定義のようですね。
サンプルケースの3つ目の6174がカプレカー数だと思われます。

というわけで方針です。
漸化式を1からやっていくイメージですね。
1. ループをK回回す。
2. そのループでg1(i)、g2(i)、f(i)を求める。
3. 答えを追加、もしくは更新して記録する。
4. その答えを元に次のループを回す。

という方針でやっていきます。

それが以下のコードです。

n,k = input().split()
inN = int(n)
inK = int(k)
a = [n]
for i in range(1,inK+1):
    g1 = ''.join(sorted(n,reverse=True))
    g2 = ''.join(sorted(n))
    f = int(g1)-int(g2)
    a.append(f)
    n = str(f)
    if f == 0:
        break
print(a[-1])

N、Kをそれぞれ文字型と数値型にして変数に格納しました。
(結局数値型のNは使わなかったけど)

リストaにそのループの答えをどんどん格納して最後にa[-1]を出力するスタイルです。
a0 はNと同値なのでさっさとaにいれときました。

ループは1からKまで回すので

for i in range(1,inK+1):

です。

g1、g2を作る際に、そのままやると
['5','4','3']
みたいになるので

''.join

で結合することでその後でスムーズにintに変換できます。
※結合しないと、int変換するときにリスト型のデータは変換できないとエラーがでます。

全探索で間に合うとはおもいますが、(ループ回数が最大でも105なので)念のため、aiが0になったら終了するようにしてます。

最後に答えを格納してあるリストaの一番最後の値を出力して終了です。

今回の問題は全探索が使えたので楽だったのですが、全探索が使えない問題が全然解けないので、そういう問題を解けるようになりたいなと思いました。

ではまた!!