[Python] paizaプログラミング練習問題 長テーブルのうなぎ屋 (paizaランク B 相当)


paizaの練習問題をPython3でプログラミングします。

問題

長テーブルのうなぎ屋 (paizaランク B 相当)
https://paiza.jp/learning/long-table

ポイント

  • 円卓なので、最後の席まで座ったら1番目の席に戻ること
  • グループ全員が連続して座れること

解答

unagi.py
# coding: UTF-8 

# ①入力処理:値取得、テーブル座席の配列準備
nm_array = input().split(" ")
seat_num = int(nm_array[0])
group_num = int(nm_array[1])
# print("シート数:", seat_num)
# print("グループ数;", group_num)

# 空席を0にする
seat = [0] * seat_num

count = 0
# ②グループ毎に空席確認
# グループ分のループ
for i in range(group_num):
    group_array = input().split(" ")
    group_person_num = int(group_array[0])
    sit_point = int(group_array[1])

    # インデックスのため-1する
    sit_point -= 1
    # print("グループの人数:", group_person_num)
    # print("着席開始位置:", sit_point)

    # グループ人数分のループ、空席確認
    empty_flg = True;
    for j in range(sit_point, sit_point+group_person_num):
        # 円卓処理
        if j >= seat_num:
            search_point = j - seat_num
        else:
            search_point = j
        # 空席確認
        if(seat[search_point] > 0):
            empty_flg = False
            break

    # ③席が空いていたら座る処理
    if empty_flg == True:
        # グループの人数分のループ、着席処理
        for j in range(sit_point,sit_point+group_person_num):
            # 円卓処理
            if j >= seat_num:
                search_point = j - seat_num
            else:
                search_point = j
            # print(search_point)
            # 着席処理
            seat[search_point] = 1
        # 座った人の人数を合算
        count += group_person_num

# 出力処理:座った人の人数を出力
print(count)

2018/10/21 追記
コメントをいただいたので、シンプルな別解を追記しました。

unagi2.py
def sit(n, m):
    """長テーブルのうなぎ屋の関数

    Arguments:
        n {int} -- シート数
        m {int} -- グループ数
    """
    # 空席をTrueとする
    sitable = [True] * n
    # グループ分のループ
    for _ in range(m):  
        people, seat = map(int, input().split())
        # 着席位置
        seats = range(seat, seat + people)
        # 空席確認(全員が座れるか確認)
        if all(sitable[seat % n] for seat in seats):
            # 座れた人数を報告
            yield people
            # 着席処理
            for seat in seats:
                sitable[seat % n] = False

# 出力処理:グループ毎に座れた人数を合計して出力
print(sum(sit(*map(int, input().split()))))
  • for _ in range(m)_(アンダースコア)は変数名を置き換えただけで、変数を使っていないことを表す。

  • yieldを実行すると、値を返却しつつ、現在の処理を中断したまま保持する。

  • all(sitable[seat % n] for seat in seats)all関数は引数内で指定した条件が全て満たされている場合、Trueを返す。

  • sit(*map(int, input().split()))*(アスタリスク)はリストはタプルや分解して渡し、sum関数で合計する。

感想

アルゴリズム以前にPythonでリストの初期化方法を知りませんでした。
円卓処理のif文(座席数を超えたら最初に戻る)や、ループ処理の開始と終了(グループの1人目からグループの人数分)をどうすればいいかで悩みました。
うなぎ屋ではなく、回転寿司屋だと思って途中まで解いていました。

関連

[ネタばれ] 長テーブルのうなぎ屋 (paizaランク B 相当)
アルゴリズム問題 paiza練習問題 長テーブルのうなぎ屋