n-knuu's logs

憧れ駆動。だいたい競プロ

HackerRank Pythonist

HackerRankのPythonistに参加しました。www.hackerrank.com
Pythonのいい練習になったのでメモを残しておきます。

コードはpython3で書きました。

Sort Data

問題

N要素を持つデータがM個与えられる。K番目の要素が昇順になるように出力せよ。
K番目の要素で異なる行に同じ値がある場合は、入力で現れた順に表示せよ。

解法

sortメソッドでもsorted関数でもどちらでも良いので引数にkey=lambda data: data[K]とすればよい。
pythonのソートは安定ソートなので、sortメソッドもしくはsorted関数を使っていれば問題ない。
pythonのソートで困った時はここ(ソート HOW TO — Python 3.4.2 ドキュメント)を見よう

コード

N, M = map(int, input().split())
data = [list(map(int, input().split())) for i in range(N)]
K = int(input())
data.sort(key=lambda x: x[K])
for d in data:
    print(' '.join([str(num) for num in d]))

感想

やるだけ


String Formatting

問題

数字Nが与えられる。1からNまで、その数の10進数、8進数、16進数、2進数を1行ずつに表示せよ。
ただし、表示幅はNの2進数表記の幅に合わせて表示せよ。

解法

format関数を使うのだろうと思ってリファレンスを調べていたら、答えが見つかってしまった。6.1. string — 一般的な文字列操作 — Python 3.4.2 ドキュメントの一番下の例を見ればよい。

コード

N = int(input())
width = len(format(N, 'b'))
for num in range(1,N+1): 
    for base in 'doXb':
        print('{0:{width}{base}}'.format(num, base=base, width=width), end=' ')
    print()

感想

format関数の{}の中にネストして{}を書く方法が分からなかったので勉強になった。
Emacsのflycheckだとネストして{}を書くとinvalid syntax扱いになるらしい。


Triangle Quest

問題

正整数N(1<=N<=10)が与えられる。以下のようなtriangleを1つのforループとprint文/関数とarithmetic operationsのみで2行以内のコードで出力せよ。

1
22
333
4444
.....

解法

111111111を用意しておいて、forループに合わせてそれを10^(9-i)で割って、それにiを掛ける。

コード

for i in range(1,int(input())):
    print(111111111*i//(10**(9-i)))

感想

最初、問題文をよく読んでいなくてforループでprint(str(i) * i)としていたが、途中で「文字列に関連する操作をすると0ptだよ」と書いてあることに気がついて修正した。
Nが小さいのでやっつけでコードを書いたら通った。なにか他にいい案ないのだろうか...


Time Delta

問題

時間が以下の形で与えられる。

Day dd Mon yyyy hh:mm:ss +xxxx

2つの時間が与えられたとき、2つの秒数の差の絶対値を出力せよ。

解法

datetimeモジュールを使う。(8.1. datetime — 基本的な日付型および時間型 — Python 3.4.2 ドキュメント)
入力の分解にはstrptime関数を使う。(http://docs.python.jp/3.4/library/datetime.html#datetime.date.strftime)
あとは2つを引き算して、total_secondsメソッドを使えばよい。

コード

import datetime
T = int(input())
for _ in range(T):
    t1 = datetime.datetime.strptime(input(), '%a %d %b %Y %H:%M:%S %z')
    t2 = datetime.datetime.strptime(input(), '%a %d %b %Y %H:%M:%S %z')
    delta = t1 - t2
    print(abs(int(delta.total_seconds())))

感想

datetimeモジュール便利。


Validating Email Addresses With a Filter

問題

正整数NとN行のメールアドレスが文字列が与えられる。
username@websitename.extensionの形になっているメールアドレスを辞書順してにリストとして出力せよ。
ただし、usernameは英数字、-、_のみを含み、websitenameは英数字のみ、extensionは3文字以内とする。

コード

import re
N = int(input())
valid = re.compile(r'^[a-zA-Z0-9_-]+@[a-zA-Z0-9]+\.[a-zA-Z0-9]{1,3}$')
l = [input() for _ in range(N)]
print(sorted(list(filter(lambda x: valid.match(x) != None, l))))

感想

正規表現は使わないと忘れそうになるので危ない。
conceptを読んでいるとfilter関数を使って欲しいみたいだから使った。
usernameもwebsitenameもextensionも、0文字以上であることが書いてないけど、そこは競プロと違うからそんなものだろうか。


Regex: Validating phone numbers

問題

正整数NとN個の携帯電話の番号が文字列として与えられる。それぞれの携帯電話の番号が有効なものかどうか確かめよ。
ただし携帯電話の番号は、7-9で始まる10桁の数字とする。

解法

正規表現を使う。

コード

import re
N = int(input())
valid = re.compile(r"^[7-9]\d{9}$")
for _ in range(N):
    test = input()
    ans = valid.match(test)
    if ans is None:
        print('NO')
    else:
        print('YES')

感想

正規表現を使うのはこの問題からだったらしい。


Regex: Validating Roman Numerals

問題

ローマ数字が文字列で与えられる。それが有効なものか調べよ。

解法

どのローマ数字が有効なのか書いてない...
→ググったらこんなの(正規表現 - Dive Into Python 3 日本語版)が出てきたので貼り付けた。

コード

import re
N = input()
valid = re.compile(r'^M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$')
ans = valid.match(N)
print(ans != None)

感想

有効なローマ数字の定義を示して欲しかった...
Dive Into Python 3もちゃんと一度読みたい


Classes: Dealing with Complex Numbers

問題

2つの複素数が与えられるので、和、差、積、商、それぞれの絶対値を出力せよ。
ただし、出力は決められた形式(説明略)で出力せよ。

解法

conceptを読むと、classを作って欲しかったみたいだけど、complexが使えるのでそちらを使った。

コード

def cprint(c):
    r, i = c.real, c.imag
    if r != 0:
        if i > 0:
            print('{:.2f} + {:.2f}i'.format(r, i))
        elif i < 0:
            print('{:.2f} - {:.2f}i'.format(r, abs(i)))
        else:
            print('{:.2f}'.format(r))
    else:
        if i != 0:
            print('{:.2f}i'.format(i))
        else:
            print('{:.2f}'.format(0))
                
            
cr, ci = map(float, input().split())
dr, di = map(float, input().split())
c = complex(cr, ci)
d = complex(dr, di)
cprint(c+d)
cprint(c-d)
cprint(c*d)
cprint(c/d)
print('{0:.2f}'.format(abs(c)))
print('{0:.2f}'.format(abs(d)))

終わりに

これからは競技プログラミング参戦記的なものも書いていこうと思います。