4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

「俺の許嫁と幼なじみが修羅場すぎる」で学ぶワンライナー

Posted at

背景

python歴数年だけど、普段はlambdaやreduceやmap関数なんてあまり使わない。
せっかくなのでpaizaでいまやってる『俺の許嫁と幼なじみが修羅場すぎる』を
pythonのワンライナー縛りで解いていって勉強してみよう!

ワンライナーとは

複数行をまとめて1行で書ききること。書いていると楽しくなる ʅ(◔౪◔ ) ʃ

# 偶数の合計を出力
r = 0
for x in xrange(100):
  if x % 2 == 0:
    r += x
print r
> 2450

# ワンライナーで偶数の合計を出力
print sum([x for x in xrange(100) if x % 2 == 0])
> 2450

1問目

問題文はこれ

文字列から奇数の文字だけ抜き出してprintすればいいみたい

# まずは普通に解いてみる
input_lines = raw_input()
result = ''
count = 1
for s in input_lines:
    if count % 2 == 1:
        result += s
    count +=1
print result

OneLineにするために使えそうな関数を調査してみる

# 変数のrを利用しない方法だと、1文字ずつのListにして連結すればよさそうだ
print ''.join(['o', 'h', 'a', 'y', 'o'])
> ohayo

# 変数count邪魔すぎい...
# djangoのforloop counterみたいに自動でカウントできる関数ないか調べてみたら
# enumerateを使うと良いみたいだ。
for idx, x in enumerate(xrange(100, 103)):
  print idx, x
>0 100
>1 101
>2 102

# 以上の関数を使って変数2つを消す
l = []
for idx, x in enumerate(raw_input()):
  if idx % 2 == 0:
    l.append(x)
print ''.join([str(_l) for _l in l])

# for文をOneLineにする
l = []
[l.append(x) for idx, x in enumerate(raw_input()) if idx % 2 == 0]
print ''.join([str(_l) for _l in l])

# lを使わないように書き換えると完成!
print ''.join([s for i, s in enumerate(raw_input()) if i % 2 == 0])


無事テストケース通過

スクリーンショット 2015-04-14 19.06.58.png

可読性がめっちゃ悪い。メンテしたくないプログラムが完成

2問目

問題文はこれ

改行区切りのtextを週毎にサマリーすればいいみたい

# まずは普通に解いてみる
from collections import defaultdict
d = defaultdict(int)
for i in xrange(int(raw_input())):
    d[i % 7] += int(raw_input()) 
for key in d:
    print d[key]

そして詰む

1時間考えても方法が出てこない。。。俺のOneLine力はこの程度なのか。。。
raw_input()で取得できる値が1行目がファイル全体の行数で
2行目以降がサマリーすべき値なのでどう扱えばいいか悩む

# default dictなしに書き換える
l = [0 for x in xrange(7)]
for i in xrange(int(raw_input())):
    l[i % 7] += int(raw_input()) 
print '\n'.join([str(x) for x in l])


# lambda式使うために、リストの初期化を廃止してif,elseで書いてみる
from collections import defaultdict
l= []
for i in xrange(int(raw_input())):
  if i >= 7:
    l[i % 7] += int(raw_input())
  else:
    l.append(int(raw_input()))
print '\n'.join([str(x) for x in l])

# raw_input()部分を分離して考えるために、その部分だけOneLineにする
l = [int(raw_input()) for x in xrange(int(raw_input()))]

# zipとiterで1次元配列を7区切りの2次元配列にする
# 変換前: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
# 変換後: [(1, 2, 3, 4, 5, 6, 7), (8, 9, 10, 11, 12, 13, 14)]
l = [int(raw_input()) for x in xrange(int(raw_input()))]
seven = zip(*[iter(l)]*7)

# zipで行と列を反転する
# 変換前: [(1, 2, 3, 4, 5, 6, 7), (8, 9, 10, 11, 12, 13, 14)]
# 変換後: [(1, 8), (2, 9), (3, 10), (4, 11), (5, 12), (6, 13), (7, 14)]
l = [int(raw_input()) for x in xrange(int(raw_input()))]
seven = zip(*[iter(l)]*7)
r = zip(*seven)
# 出力
print '\n'.join([str(sum(_r)) for _r in r])


# これをとりまとめると。
print '\n'.join([str(sum(_r)) for _r in zip(*zip(*[iter([int(raw_input()) for x in xrange(int(raw_input()))])]*7))])

無事テストケース通過

スクリーンショット 2015-04-14 19.35.11.png

自身を混乱させるraw_input()部分を、思い切って1行で書ききったところがブレイクスルー。
その後はスルスル解けました。難解な要素を切り離して考えることが大事みたいです。

いままでiter関数なんて一度も使ったことが無かったのですが、こんな使い方するんですね。
Pythonの組み込み関数を初めてちゃんと読みました。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?