Pythonメモ1-3

本日解いた問題を全部載せて、感想などを設けるだけのメモです。

 

 

レッドコーダーが教える、競プロ・AtCoder上達のガイドライン【初級編:競プロを始めよう】 - Qiita

1.5の条件4に記されている問題は今日中に全部解く気持ちでやりました。

かなり易しい問題が多く、歯応えはあまりありませんでしたが、基礎を学ぶ上では非常に丁度良かったです。勉強し甲斐がありました。

 

 

B - Papers, Please

 

まずはコードから。

 

  1. n=int(input())
  2. a=list(map(int,input().split()))
  3. c=0
  4. d=0
  5. for i in a:
  6.   if i % 2 == 0:
  7.     c +=1
  8.     if i % 3 ==0 or i % 5 ==0:
  9.       d +=1
  10. if c == d:
  11.   print("APPROVED")
  12. else:
  13.   print("DENIED")

 

 

N個の整数 A1,A2,...,AN をリストに内蔵し、リスト内の全ての整数において、2で割り切れるものがあるとき、それらが全て3or5で割り切れたら APPROVED、そうでなければ DENIED で出力する。と考えました。(他の方の解答を拝見すると自分の解答が回りくどい考え方なのが伺えて悲しい;;)

 

・リスト内の全ての整数において、2で割り切れる整数の個数を c,その整数の中で3or5で割り切れるものの個数を d とし、c の数を d の数が一致、すなわち c=d ならば APPROVED です。

 

・for文とif文を組み合わせる問題はある程度慣れましたが、if文にif文を組み合わせるのはまともに解いたのはこれが初めてかもしれません。新鮮な感覚を味わうことができました。

 

ということで、問題文の要求通りのコードを書いたら一発AC通ってくれました。ありがたい。

 

 

感想:連続for文は全探索で童貞卒業済みですが、本問の連続if文は童貞を奪われました。

 

 

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

 

 

次。

 

B - I miss you...

 

コードは以下の通り。

 

  1. print("x"*len((input()))

 

・パッと見listで解けそうでしたが、技量が足りず違う方針で考えました。

(for文を使い、list[i]=x みたいにおけば良さそうだと思いましたが、わかりませんでした。)

 

・そこで、本問は文字列 x の個数は与えられる文字数列と一致するので、単に文字 x に個数を書けるだけで済んでしまいました。

 

 

感想:変にリスト化して非効率なプログラムを組むぐらいなら、シンプルで効率的の方がよいことを改めさせられました。すーぐリストで考えようとする癖はよろしくないですね・・・。

 

 

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

 

 

次。

 

B - Comparing Strings

 

コードは以下の通り。

 
  1. a,b=map(int,input().split())
  2. if a<b:
  3.   print(str(a)*b)
  4. else:
  5.   print(str(b)*a)

 

・前問と大差はないものの、数値をstrを介して文字列化する一工夫が必要です。

(初心者過ぎてこれに気付くのに5分ぐらい奮闘しました・・・)

 

前問の毛が生えたような問題なので特にといった感想はありません。

 

 

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

 

 

次。

 

B - Strings with the Same Length

 

コードは以下の通り。

 

  1. n=int(input())
  2. s,t=list(map(str,input().split()))
  3.  
  4. for i in range(n):
  5.   print(s[i]+t[i],end='')

 

・今度こそlistが使えると確信したのでサクサク書けました。

 

・listにfor文を適用することで、新しく {s[0]+t[0]}, {s[1]+t[1]}, ..., {s[n-1]+t[n-1]} を作れるので、これにprint時に改行しない ,end='' を適用すればサクッと解けます。

 

 

感想:因みにend=" を用いたのは本問が初めて。つまり童貞を奪われたのである!

 

 

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

 

 

次。

 

B - ROT N

 

コードは以下の通り。

 

  1. n=int(input())
  2. s=input()
  3. for i in range(len(s)):
  4.   if ord(s[i])+n >90:
  5.     print(chr(ord(s[i])+n-26), end='')
  6.   else:
  7.     print(chr(ord(s[i])+n), end='')

 

・なにこれ?知識ゲー???気合で頑張れば解けなくはないが、より一般化した場合を考慮するなら知識を用いて練習した方がいいはず。

 

・本問を言い換えれば、シーザー信号を作成しなさい。という問題になります。

 

・どうやらUnicode上で色々いじくればよいらしいので、標準入力で与えられた文字列をord関数を通してUnicode数にします。

 

・ord("Z")=90 より、Z から A に返る/返らないに応じてif文を設けました。アルファベットは26文字なので、Z を超えた際は26文字分引けば元通りなので ord(s[i])+n-26 でprint。printする際は改行せず書きたいので同様に ,end='' を用います。

 

 

感想:初めて見たタイプの問題だったのか、苦戦して疲れました。もうやめたい。

 

 

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

 

 

次。

 

B - Achieve the Goal

 

コードは以下の通り。

 

  1. n,k,m=map(int,input().split())
  2. s=sum(list(map(int,input().split())))
  3. if k<n*m-s:
  4.   print("-1")
  5. else:
  6.   print(max(0,n*m-s))

 

ずっとぶっ続けでやっていたのもあり、こんな単純な計算すらできなくて超焦りました。

 

・A1+A2+...+A(N-1) の合計を s とすると、A1~AN までの平均は以下の不等式を満たせばok。

      (s+AN)/N>=M ―①

AN について解くと AN>=N*M'-s

 

・AN は K 以下の値を取るので、K<N*M-s となるような N,M,s が存在した時点で達成不可能になるので -1 を出力します。

 

・そうでなければ上記の不等式①を自動的に満たすので、AN が可能な最低点は等式を満たすことより、AN=N*M-s となれば大丈夫。

 

・しかし、s があまりにも大きすぎて AN = N*M-s < 0 を満たす場合があるので、その際は0を出力します。(if文でいちいち N*M-s < 0 の場合分けを書くより、max関数を用いる方が簡素だったため、maxを用いています。)

 

 

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

 

 

次。

 

B - Count ABC

 

コードは以下の通り。

 

  1. n=input()
  2. s=str(input())
  3. print(s.count("ABC"))

 

  1. n=int(input())
  2. s=str(input())
  3. c=0
  4.  
  5. for i in range(n-2):
  6. if s[i] == "A" and s[i+1] == "B" and s[i+2] == "C":
  7. c += 1
  8. print(c)

 

贅沢に、ふたつも書いてしまった。

ひとつめはcount関数を用いてシンプルに表記したものです。

ふたつめはfor文で故意的に長く書いたものです。

 

・strで文字列として認識させ、それをcount関数に介し、個数を出力して終わり。

 

・count関数以外にも、for文で条件を満たしたものを数えて出力しても可能。

 

 

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

 

 

次。

 

B - 81

 

コードは以下の通り。

 

  1. n=int(input())
  2. c=0
  3. for i in range(10):
  4.   for j in range(10):
  5.     if i*j == n:
  6.       c +=1
  7. if c>0:
  8.   print("Yes")
  9. else:
  10.   print("No")

 

  1. n=int(input())
    for i in range(10):
      for j in range(10):
        if i*j == n:
          print("Yes")
          exit()
    print("No")


またまたこちらも贅沢にふたつ作りました。

上はぱっと見で作成したもので、下は他の方のコードを参考にしたものです。(c += 1 が無駄すぎだが、どう省けばいいのかがわかってなかったので)

 

・for文n重ループは基本なのでサクッとできました。条件を満たすものがあればprintで出力し、exit() で終わらせてしまう。なければそのまま書いておしまい。

 

 

感想:for文3重ループは 

Pythonメモ1-1 - volcano-tofu’s blog ここでも取り扱っています。

 

 

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

 

 

ラスト。

 

B - TAKOYAKI FESTIVAL 2019

 

コードは以下の通り。

 

  1. n=int(input())
  2. d = list(map(int,input().split()))
  3. c=0
  4. for i in range(n):
  5.   for j in range(n):
  6.     c += d[i]*d[j]
  7. for i in range(n):
  8.   c=c-d[i]**2
  9.  
  10. print(c//2)

 

  1. n=int(input())
  2. d = list(map(int,input().split()))
  3. c=0
  4. for i in range(n):
  5.   for j in range(i+1,n):
  6.     c += d[i]*d[j]
  7. print(c)

 

・上記のコードはしたいことがうまくできず、総掛けして二乗引いて2で割って。。。という無駄オブ無駄のカスコードです。

 

・for i in range(n) まではよかったんですが、for j in range(i-1,n) みたいな書き方をして変な値が出力され、原因が分からずゴリ押ししたまでです。

 

・下記のコードは他の方のコードを参考にしました。for j in range(i+1,n) にしっかり治しました。。。。

 

 

感想:for文n重ループが見えるのでやりたいことがわかれば難しくはないですね・・・。

for文2重が見えるのでlistを使うのは言わずもがな。この程度のfor文2重3重ならまだしも、C問題になると途端にTLEになるのでこれがまたきついです。

 

 

 

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

 

 

結論:書くのに疲れる。でもメモはしておきたい・・・。お疲れさまでした。