python
1num = [i for i in map(int,input().split(" "))] #入力データの一行目取り出し [7, 3] 2 3date=[] 4uryo=[] 5for i in range(num[0]): #7回繰り返し 6 7 8 dater=[i for i in map(int,input().split(" "))] #入力データをリストとして取り出し 9 date.append(dater[0]) 10 uryo.append(dater[1]) 11 player_ans = {} 12 for h, p in zip(date, uryo): #取り出した入力データをリストに格納 13 player_ans[h] = p 14 15#上記6行に渡って、「入力データ取り出し ⇒ リスト ⇒辞書」としています。 16#下記の1行でできると思ったのですが、上手く動かなかったので、やむを得ず上記のコードとしています。 17#player_ans = {date:uryo for date,uryo in input().split(" ")} 動かない 18 19print(player_ans) #{1: 0, 2: 20, 3: 10, 4: 80, 5: 10, 6: 0, 7: 10} 20 21#入力データ 227 3 #7は下記入力データの数を表している。 3は連続する回数を表している。 ※詳しくは下記に。 231 0 242 20 253 10 264 80 275 10 286 0 297 10 30#希望する出力 5
『やりたいこと』
・入力データの2行目(1,0)からを対象に、右の数字(今回の場合は3個単位 ※最初の入力データの3をみる)を合計。
最も低い合計の行を出力したい。
今回の入力データの場合、まず
1 0
2 20
3 10
これらの右の数を合計(30)
次に
2 20
3 10
4 80
これらの右の数を合計(110)
3 10
4 80
5 10
これらの右の数を合計(100)
と、最後までみていき、
合計が最も低い行を出力したい。
今回の入力データでは、
5 10
6 0
7 10
が、合計20となるため、この合計値の先頭(5)を出力
・3個単位で合計を見る必要があるため、例えば先頭の(1,0)が最小(値0)ということで出力するのはNG
最後の(6,0 7,10)が最小(値10)ということで出力するのもNG(2行しかみていないため)
『考えたこと』
・辞書型にして、行をkeyに、値をvalueに、値を3個単位で合計して最小値を求めるのが楽かと思ったんですが、
どのようなコードで計算すればいいかつまづいてしまいました。
※載せているコードは、入力データを辞書化しただけです。
『ご質問』
・辞書型で解く方法、もしくは別なやり方がありましたら、ご教授いただきたいです。
・今回、入力データをリスト化して、辞書型としていますが、
もっと楽に辞書型にできるようでしたら、こちらもご教授いただきたいです。
ここまで長くなってごめんなさい。
よろしくお願いします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
回答3件
0
愚直だけど、こんな感じでもできるかもです。
積算値をキュー的に扱い(前の値を引き現在の値を足す)、計算量はO(n)でいけてると思います。
Python
1import random 2random.seed(110) 3cnt = 10 4l = [random.randrange(cnt*2) for i in range(cnt)] # rangeも個数に合わせる。(0が連続しないように) 5#print(l) 6span = 3 7 8# 0番目からspan個を足す。とりあえずこれを最小値とする。 9cur_sum = 0 10for i in range(span): 11 cur_sum += l[i] 12#print(cur_sum) 13cur_sub = l[0] 14min_sum = cur_sum 15min_pos = 0 16 17# 1番目から末尾を足すまで 18for i in range(1,cnt-span+1): 19 # 前の値を引いて、現在の値を足す=現在の積算値 20 cur_sum -= cur_sub 21 cur_add = l[i+span-1] 22 cur_sum += cur_add 23 #print('cur pos={} sub={} add={} sum={}'.format(i,cur_sub,cur_add, cur_sum)) # 24 cur_sub = l[i] 25 if cur_sum <= min_sum: 26 min_sum = cur_sum 27 min_pos = i 28 #print('min pos={} cur_min={}'.format(min_pos,min_sum)) 29 30print( 'total_min pos={} sum={}'.format(min_pos, min_sum))
境界値をちゃんと考慮できていないかも。
投稿2018/06/29 13:04
編集2018/06/29 13:10総合スコア0
0
回答の前にひとつアドバイスしますと、
python
1 player_ans = {} 2 for h, p in zip(date, uryo): #取り出した入力データをリストに格納 3 player_ans[h] = p
これをforの中に入れるのはやめましょうか(無駄だから)。
どうせ辞書に入れるなら、もうすこし旨味のある入れ方をした方が良いでしょう。
python
1# めんどいので入力周り省略 2num = [7, 3] 3date = [1,2,3,4,5,6,7] 4uryo = [0,20,10,80,10,0,10] 5 6dn, span = num # 扱いづらいのでunpack 7player_ans = {} 8for i in range(dn - span + 1): # このforループの意味は頭をひねって考えること 9 player_ans[date[i]] = uryo[i:i+span] 10 11# 以下3つは確認用のprint 12print(player_ans) # => {1: [0, 20, 10], 2: [20, 10, 80], 3: [10, 80, 10], 4: [80, 10, 0], 5: [10, 0, 10]} 13print(player_ans.items()) # => dict_items([(1, [0, 20, 10]), (2, [20, 10, 80]), (3, [10, 80, 10]), (4, [80, 10, 0]), (5, [10, 0, 10])]) 14print(min(player_ans.items(), key=lambda x:sum(x[1]))) # => (5, [10, 0, 10]) 15 16# 最終的にほしいもの 17print(min(player_ans.items(), key=lambda x:sum(x[1]))[0]) # => 5 18 19# こっちでもいいかなぁ 20print(min(player_ans, key=lambda x:sum(player_ans[x]))) # => 5
あるいは、
python
1for i in range(dn - span + 1): # このforループの意味は頭をひねって考えること 2 player_ans[date[i]] = sum(uryo[i:i+span])
で後ろのminのkeyが単純になります。後からリストを使わないのならこの方が良いかも。
投稿2018/06/29 11:38
編集2018/06/29 13:12総合スコア30945
0
ベストアンサー
個人的には、辞書を使わない方が書きやすい気がします。
解法の方針
0. 3個ずつ組にしたタプルのリストを作る
0. 最も合計値が小さいタプルのインデックスを調べる
Python
1n, span = map(int, input().split()) 2 3nums = [ 4 int(input().split()[-1]) for _ in range(n) 5] 6 7groups = zip(*[nums[s:] for s in range(span)]) 8indice = [ 9 index 10 for index, group in sorted( 11 enumerate(groups, start=1), 12 key=lambda ig: sum(ig[-1]) # (index, num_group) 13 ) 14] 15 16print(indice[0])
hayataka2049さんのご指摘を受けて修正したバージョン。
Python
1n, span = map(int, input().split()) 2 3nums = [ 4 int(input().split()[-1]) for _ in range(n) 5] 6 7groups = zip(*[nums[s:] for s in range(span)]) 8index, _ = min( 9 enumerate(groups, start=1), 10 key=lambda ig: sum(ig[-1]) # (index, num_group) 11) 12 13print(index)
せっかくなので
辞書を使った方法も書いてみた。
Python
1n, span = map(int, input().split()) 2 3nums = [ 4 int(input().split()[-1]) for _ in range(n) 5] 6 7sum_dict = { 8 i: 0 for i in range(n-span+1) 9} 10for key in sum_dict: 11 for i in range(span): 12 sum_dict[key] += nums[key+i] 13 14index = sorted(sum_dict.items(), key=lambda item: item[-1])[0][0] 15print(index+1)
コメントを受けて
enumerateなんですが、for文の際に使うもので、リストのインデックスをとるときに使用するものだと認識しておりますが、for文がありません。
ここでのenumerateは何をしているのでしょうか。。?
また、groupsは上記でタプルにされているデータをさしているのはわかるのですが、stard=1は何なのでしょうか?
for文で良く用いられるのは確かですが、その実態はジェネレータを返しているだけなのです。
また、キーワード引数startは、どの数値から順に付与するかを示します。
Python
1>>> abc = list('abcdefg') 2>>> abc 3['a', 'b', 'c', 'd', 'e', 'f', 'g'] 4>>> 5>>> enumerate(abc) 6<enumerate object at 0x00000270D21ED438> 7>>> 8>>> list(enumerate(abc)) 9[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e'), (5, 'f'), (6, 'g')] 10>>> 11>>> list(enumerate(abc, start=5)) 12[(5, 'a'), (6, 'b'), (7, 'c'), (8, 'd'), (9, 'e'), (10, 'f'), (11, 'g')]
key=lambda ig: sum(ig[-1])
lambdaは、引数、:の後に処理を記述すると認識しております。
min(enumerate(groups, start=1)この処理結果がigにはいって、sumして、keyに入って、それをindexと_に戻り値として渡される?という認識でよろしいでしょうか?
enumerate(groups, start=1)が返した各要素がigに入ります。
例えば一回目は(1, (0, 20, 10))が、二回目は(2, (20, 10, 80))がigに与えられるわけです。
keyは関数が『何をもって要素を比べるか』指定するために使います。
今回はsum(ig[-1])、つまり件の三個組の要素の合計を指標にしています。
minした結果をラムダで処理しているのではなく、minを求めるのにラムダを用いています。
minがどんな処理をしているか覗いてみたら、少しイメージが湧くかもしれません。
Python
1def my_min(it, key=None): 2 print('-' * 42) 3 if key is None: 4 key = lambda x: x # 恒等関数 5 6 ret = next(it) 7 ret_score = key(ret) 8 9 for e in it: 10 e_score = key(e) 11 print(f'{ret}[score={ret_score}] vs {e}[score={e_score}]', end='\t') 12 13 if ret_score > e_score: 14 print('latter wins') 15 ret, ret_score = e, e_score 16 else: 17 print('former wins') 18 19 print(f'smallest element is {ret}') 20 print('-' * 42) 21 return ret
実行結果 (minの代わりにmy_minを使用) Wandbox
plain
1------------------------------------------ 2(1, (0, 20, 10))[score=30] vs (2, (20, 10, 80))[score=110] former wins 3(1, (0, 20, 10))[score=30] vs (3, (10, 80, 10))[score=100] former wins 4(1, (0, 20, 10))[score=30] vs (4, (80, 10, 0))[score=90] former wins 5(1, (0, 20, 10))[score=30] vs (5, (10, 0, 10))[score=20] latter wins 6smallest element is (5, (10, 0, 10)) 7------------------------------------------ 85
註: 説明のために書いたコードであり、実際のminの実装を踏襲したものではありません。
前半部分「sorted(sum_dict.items()」は、辞書をソートされている。ここまではわかるのですが、
やはり、lambdaの処理が完璧に理解できません。(ソートした辞書をitemに渡す?)
辞書の各要素をタプルにしたシーケンスを作り、そいつをソートしています。
ソートした結果をラムダで処理しているのではなく、ソートするのにラムダを用いています。
Python
1>>> tmp_dict = {i: i**2 for i in range(10)} 2>>> tmp_dict 3{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81} 4>>> 5>>> tmp_dict.items() 6dict_items([(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25), (6, 36), (7, 49), (8, 64), (9, 81)])
回答いただいたのに、それに対しての質問ばかりでごめんなさい。
いえいえ、お気遣いなく。
投稿2018/06/29 11:21
編集2018/06/30 04:37総合スコア35682
2018/06/29 11:53 編集
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
2018/06/29 16:31