【Pythonメモ2-2】解いた問題を復習する。

・最近更新していなかったので。

・バイトが急に忙しくなって最近Pythonをやる時間が少ないです。あと帰ってすぐ寝たりとかして時間を失ったりとかが多いのもあって、やれてないです。

・若干モチベも下がっている。

 

・ABCを解く際に、C問題から知らないと解けない、難しい、といった問題が多くなり、焦って様々なアルゴリズムを勉強しないといけない、実装できなければならない、といった煽りを受けているとモチベーションが下がったりもする。

 

・例えば、幅優先探索深さ優先探索といった言葉を多々目にしたことがあり、試しにと思って幅優先探索を勉強したことがあるが、それ以前に配列の勉強(二次元配列やそれの取り扱いに苦手意識を持たないなど)などといった基礎のきにあたる勉強を怠っていた。

 

・その影響で、B問題のちょっとした問題をスピーディーに解くことができなかったり、分からないことがあって検索エンジンに手を伸ばしたりすることが多々あって、確かにABC本番時に焦るわなと改めてしまう。

 

・そこで今回は今まで解いた問題を総復習してみようと思う。

 

 

 

 

 

B - Do you know the second highest mountain?

atcoder.jp

  1. n = int(input())
    yama = []

    for _ in range(n):
    a, b = input().split()
    yama.append*1

    yama.sort() # int の昇順になる
    print(yama[-2][1]) # [x][y] 左からx番目, 左からy番目の要素を出力

Submission #24996256 - Mynavi Programming Contest 2021(AtCoder Beginner Contest 201)

 

 

山の情報として、山の名前(str)、山の高さ(int)の2つが付与される。

・これらを二次元配列に収め、intについてsortし、2番目に高い山の出力は[-2]などと書けばよさそうだ。

 

・故に、本問を解くにあたって必要な知識は単なる配列ではなく、二次元配列も大丈夫ですかというジャブ攻撃に耐えれるかどうかである。

・ちなみにぼくは二次元配列はあまり分からず、取り扱ったことも全く無かったのもあり、文法知識として勉強になった。

 

▼例えば以下のようなもの

  1. li =
    a,b=input().split()
    li.append((int(b), a))
    li.sort()

 

・本来はfor文でa,bを指定回数だけ配列liに格納するのだが、便宜上として簡素にかいた。

・3行目のappendの括弧の中身に注目。先にint(b)を書いているのだが、これをsortしたらint(b)についての昇順になるだろうか?aについての昇順になるだろうか?

 

・答えは先に書いたint(b)についての昇順になる。

 

▼故に、このコードの出力結果は下のようになるのだ

  1. n = int(input())
    list =[]

    for _ in range(n):
      a, b = input().split()
      list.append((int(b), a))

    list.sort() # int の昇順になる
    print(*list)

入力:

4
a 4
b 10
c 1
d 7

 

出力:

(1, 'c') (4, 'a') (7, 'd') (10, 'b')

 

・さて、ここで初心者の人ほど疑問に思うことがあるだろう。

list.apend(a,int(b)) のように、先にaを入力したらどうなるだろうか?

・実は文字aの昇順になるのだ。なので、上の入力をすると出力結果は以下のようになる。

 

出力:

('a', 4) ('b', 10) ('c', 1) ('d', 7)

 

・ここまでできたら後はlist[-2][1]の意味もわかるだろう。

・全体の要素のうち、右から2番目、その要素の各々に対して2番目が該当する、というのを意味している。

 

 

B - 180°

atcoder.jp

  1. s=list(input())
    li=s[::-
    1] # [::-1], 或いは s.reverse() で逆順にできる.)
    for i in range(len(s)):
      if li[i] == "6":
        li[i] =
    "9" # 予めslist宣言をしていることで、listの値を更新できる.
      elif li[i] == "9": # s=str(input()) とすると,格納用listappendするしかない.
        li[i] = "6"
    print(''.join(li))

Submission #24995324 - AISing Programming Contest 2021(AtCoder Beginner Contest 202)

 

・配列の順序を逆順にする、joinを使える、といった基本的なことができていると楽な問題。

・逆順にしたことが今までなかったので、以下の様なinsertを使ったコードを組んだが、実行時間がギリギリだったため大変よろしくない。

Submission #24995115 - AISing Programming Contest 2021(AtCoder Beginner Contest 202)

 

・本問においては他に難しいところはなく、ちょっとした知識のジャブ攻撃ゲーだった。

・配列を逆順にしたあとは配列の要素を左からfor文で条件を満たすものがあればif文でちょこちょこ手を加えるだけなので、まさにB問題の流れそのもの。

・あとは配列を用いることでlistの値を更新できるのが配列のつよみかな。あーいう使い方は結構好みです。

 

 

B - ATCoder

atcoder.jp

  1. a=str(input())
    ans=
    0
    count=0
    for i in a:
      if i in "A" "C" "G" "T":
        count +=
    1
      else:
        count=
    0
      ans=max(count,ans)
    print(ans)

Submission #24897516 - AtCoder Beginner Contest 122

 

・別に難しくはないけど、for文の最後にmaxで値を保持するところがたのしくて好き。C問題になると値を保持するタイプの問題が増えてくるのでB問題にしてはやっておいて損はない部類だと思った。わからんけど。

・コードを見る限り、結構汚いのがわかるのだが、例えば五行目の if i in "A" ~ 以降とか、思わず「そういうときこそ配列使えよ!」と突っ込みを入れてしまいたくなる。^^;

 

・4行目にあるfor文の for i in a(aは文字列や配列): という書き方って、ガチの初心者の頃だとやりづらいというか、あんまりできないイメージがある。

・あと5行目にあるif文もiがこの文字(str)や配列と一致するものがあるかの in もガチの初心者だとやりづらい印象がある。今も表記にそんなに慣れてないんですよねぇ・・・。

 

・まぁ、繰り返し写経したり解いとけばこれくらいの基本は慣れるでしょう!そう信じたい。

 

 

B - 0 or 1 Swap

atcoder.jp

  1. n = int(input())
    p =
    list(map(int, input().split()))
    P =
    sorted(p)
    cnt =
    0

    for i in range(n):
      if p[i] != P[i]:
        cnt +=
    1

    if cnt == 0 or cnt == 2:
      print("YES")
    else:
      print("NO")

Submission #24920215 - AtCoder Beginner Contest 135

 

・for文一個で解いた。O(N)相当の計算量なのでO(100)も実はない。結構気に入っている解法。

・もとの数列が昇順なので、sort用いて比較する方法が強い。

・もしももとの数列が昇順じゃなく、バラバラである場合は以下のような数列を入れ替えて、再度入れ替える二重for文ループを用いるとよい。

Submission #24920140 - AtCoder Beginner Contest 135

 

・特にといった感想はない。

 

 

B - 105

atcoder.jp

  1. n=int(input())
    ans=
    0
    for i in range(1,n+1,2):
      cnt=
    0
      for j in range(1,n+1):
        if i % j ==0:
          cnt +=
    1
      if cnt == 8:
        ans +=
    1
    print(ans)

Submission #24898280 - AtCoder Beginner Contest 106

 

・与えられる条件は複雑じゃなく、シンプルなのですらすらコーディングができるとたのしい。

・約数をもつという表現はカタい感じはするものの、単に割り切れればよい。

 

1.最初のfor文で1以上n以下の奇数iを設定する。(x,y,z)のzを2にするのを忘れないように。

2.その各々のfor文でつくった奇数に対し、またfor文で1以上n以下のjをつくり、iがjで割り切れれば1カウントする。

3.合計8カウント丁度になったら個数を1カウントする。

4.個数を出力する。

 

・以上4ステップで簡単に解ける。らくらく、さくさく実装できるようにしておきたい。

 

 

B - K-th Common Divisor

atcoder.jp

  1. a,b,k=map(int,input().split())
    c=

    for i in range(1,min(a,b)+1):
      if a % i == 0 and b % i == 0 :
        c.append(i)
    print(c[len(c)-k])

Submission #24898625 - AtCoder Beginner Contest 120

 

・for文でa,bをともに割り切れる数iを適当につくった配列に格納する。

・このとき、a,bの大小がわからないため、a,bのうち小さい方以下だけfor文を回せばよいので (1,min(a,b)+1) という書き方をした。勿論minはなくてもa,bを超えたiが出た時点で割り切れないから大丈夫だと思う。

 

・割り切れたら適当につくった配列に格納し、k番目に大きいものを出力したいので len(c)-k などと書いた。

・なぜこれで書けるのかは、配列cには既にソート化されているからである。

・iはfor文で小さい順から配列cに入るので、わざわざソート化する手間が省け、ソート化されているから len(c)-k として書けるのだ。これぞ一石二鳥。

 

 

B - Uneven Numbers

atcoder.jp

  1. n=int(input())
    ans=
    0
    for i in range(1,n+1):
      if len(str(i)) % 2 == 1:
        ans +=
    1
    print(ans)

Submission #24897900 - AtCoder Beginner Contest 136

 

・strは配列と似ていることについては以下の記事で書いたことがある。

volcano-tofu.hatenablog.com

 

・当時のぼくは、sum(map(list(map(int,str(i)))))の意味すら全然分からなかったが、改めてみると「見える、見えるぞ!」ってなってる(^^;

 

・例えば、s=str("a1b2") みたいな文字列を考えると、s[0]=a, len(s)=4 が返ってくるのだが、配列と似た性質であることがわかるだろう。

・ということは、桁数が奇数という条件は、長さlenを2で割った余りが1と同値なので、if文を用いて if len(str(i)) % 2 == 1: という書き方が可能なのがわかる。

・条件を満たすなら ans += 1 とかして ans を出力すればいい。

・あとはfor文で1以上n以下のjについて試せばいいだけ。

 

 

 

 

 

 

 

早く書き上げて早く寝ようと思ったのに、2時を超えてしまったじゃないか!もう寝るもん!

 

・明日はbit全探索、幅優先探索の問題を復習してみようと思う。ついでに記事も上げてみようかな?

 

お疲れさまでした。

*1:int(b), a