naruの日記

いい記事を書きます。あと、日記ではないです。

なんとも言えないテクニックまとめ (2)

LRUキャッシュ

計算時間を短縮したいときに使えるテクニック。

ある引数に対する計算結果を保存しておいて、同じ引数の計算を行うときに以前の計算結果を再利用することを言うらしい。
メモ化再帰と同じことかな?

from functools import lru_cache
#上手くいかない時は下
# from functools32 import lru_cache 

@lru_cache(None)
def ~~:

@ってつけるところが可愛いので今後使っていきたい。

小数点の計算が怖い時

ABC169のC問題で以下の問題が出題された。


ABC169-C

A\times Bの小数点以下を切り捨て、結果を整数として出力してください。


制約

  • 0\leq A \leq 10^{15}
  • 0\leq B < 10
  • Aは整数
  • Bは小数第2位まで与えられる

おいおい舐められたもんだぜ、と口笛を吹きながら提出するとWAだった。

小数点の計算による誤差が原因である。よし、じゃあ整数に直して計算すればいいんだなと以下のコードを提出した。

a,b=map(float,input().split())

a=int(a)
b=int(100*b)

print(a*b//100)

再びWAになってしまった。どうやらbを100倍にする計算にて誤差が出ていたようだ。

#例えば
9.79*100
#出力:978.9999999999999

コンピュータが9.79という数を正確に表現する術を持たないことが誤差の原因である。

100倍に直す計算にも注意を払った結果が以下のコードである。

a,b=map(str,input().split())

a=int(a)
b=100*int(b[0])+10*int(b[2])+1*int(b[3])

print((a*b)//100)

これでACとなった。文字列として受け取り、小数点だけ除くというやり方は新しいと感じました。

リストをスペース開けながらいい感じに表示したい時

これでいける。

A=[2,4,6,3,5,1]

print(" ".join(map(str, A)))

#出力:2 4 6 3 5 1

たまにこういう形式での出力を要求されるので、覚えておきたい。

(追記)
以下のコードで十分なことを知った。

A=[2,4,6,3,5,1]

print(*A)

#出力:2 4 6 3 5 1

革命的だ。

小数とか文字とかを組み合わせていい感じに表示したい時

pythonで出力を指定する時、代表的に以下の2つの書き方がある。

a = 123

b = 'abc'

print('{} and {}'.format(a, b)) #文字列メソッドの利用
# 123 and abc

print(f'{a} and {b}') #f文字列の利用
# 123 and abc

こんな感じで数値の有効桁も指定できたりする。

x = 12.3456

print(f'digit(decimal): {x:.3f}')
print(f'digit(all)    : {x:.3g}')
# digit(decimal): 12.346
# digit(all)    : 12.3

割り算した結果がものすごく小さな数である時などは、勝手に指数表示になることもあるので、こういう表記を上手く使っていこう。

アルファベットを使ってなんかしたい時

かつては自分でa,b,c,...と打ってリストを作ったりしていたが、そんなことをする必要はないらしい。

import string
print(list(string.ascii_lowercase))

print([chr(ord("a")+i) for i in range(26)])

print([chr(i) for i in range(97, 97+26)])

上のどのコードに対しても出力は

['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']

となる。アルファベットのリストが得られるわけだ。特に

import string
alphabet=list(string.ascii_lowercase)

Alphabet=list(string.ascii_uppercase)

とすると、アルファベットの小文字、大文字それぞれのリストが得られるので覚えておくと良いだろう。

なんでみんな受け取る時"sys"使うん?

AtCoderをやってきて、入力受け取りは全てをinput()で済ませてきた。しかし、ネット上のコードを見るとその多くがimport sysから始め、入力受け取りにsysモジュールを利用している。

何が便利なんだと不思議に思ってきたが、先日sysモジュールを利用しなければならない場面に遭遇した。入力が複数行にわたり、さらにその行数が指定されていない場合である。

おそらくsysモジュールを使わなくともその入力を受け取る方法はあったのだが、sysモジュールを使うと便利だったのでここに軽くまとめておく。

import sys

#1行の入力を1つの文字列として受け取る
#入力が複数行にわたる場合も始めの1行のみ受け取る
a=sys.stdin.readline() 

#複数行の入力をリストとして受け取る
#リストの要素は各行を(改行\nも含めて)文字列として受け取ったもの
a=sys.stdin.readlines()

#複数行の入力を文字列として受け取る
a=sys.stdin.read()

まあたまには使ってやっても良いな、という気持ちになった。





...もう終わりだよ、終わり!
はやいとこおうちに帰んな!