成長観察日記

競プロとかPythonとかに関しての成長記録

茶コーダーが競プロ知識だけでやってみた!シリーズ〜バチャを半自動で立てられるPythonを改変し、Twitter投稿用テキストも生成してみた話〜

1日2本のバチャを手動で立てているのはアホすぎたので、心がぶっ壊れたのを機にやってみた(人生 いろいろ〜)




はじめに…大感謝 KowerKoint さん

AtCoder Problems Contest Builder という、バチャを立てている人間にとって、喉から手が出るほど欲しかったツール…。
こちらのステキツール、ツールの素敵さだけでなく、なんとまあコードの読みやすいこと読みやすいこと。
そして「動いたあやったあ!」とツイートした瞬間「わからないことあったら聞いてくださいね」とリプをくださる菩薩的人間性

All perfect…足を向けて眠れません。本当に、だいだいだいかんしゃ!です!

こちらのステキツールを、ABCなにか仕様に変更する過程が、今回の記事内容です。



私の事前知識

  • Pythonで競プロをやっている(底を擦ってる茶)
  • 競プロ以外だと、テキストファイルに出力するやり方は知っている
  • Web知識は人並みくらい

以上!!!!!



ABCなにかとは

元々、私が個人的に精進するために立て始めた、35分のバチャ(バーチャルコンテスト)です。

  • 平日14:00〜14:35、21:00〜21:35で開催
  • コンセプトは「早解き力を鍛える!35分でA〜D問題まで辿り着けるようになろう(できたら解けるようになろう)」
  • 毎晩21時の頭を冴えさせるために、平日に立てている

短い時間でしっかり集中できること、何が出てくるかわからないガチャ感、懐かしい回に出会った時の望郷感(?)、〜緑レートまでは本来の目的で、青以上は1st RTA狙いで…など、いろいろな方にお楽しみいただけています。うれしい



やりたいこと

  • diff範囲指定など、使わない機能を横に置く
  • ARC / AGCなにかを追加にあたり、ABC, ARC, AGCそれぞれのコンテスト指定範囲から乱数を生成
  • ABCはA〜D, ARCはA〜C, AGCはA〜Bの問題をセット
  • 生成したURLを、告知botツイート用にテキストファイルへ出力



やったこと

トークンってどうすりゃ手に入れられるんだ?を調べる

AtCoder Problems Contest Builder の README.mdに記載のある

トークンはAtCoder Problemsにログインしたブラウザに保存されているCookieから確認してコピペします。

の意味や、やり方が、永遠にわからなくて挫けそうになったんだぜ?
が、すでに崩れ落ちているむりおでんことわたくし(2023/05/27(土)現在)は、一味違うんだぜ?なので、得意のググり力でたどり着いた答えが chrome拡張機能のEditThisCookie でした。

拡張機能を起動して出てくるこいつをゲット!コピペだあ!!

無事にトークンとやらをゲットしました(まだふんわりとしかわかってない)



コードを読み、わからない部分を整理してママに聞く

業プロ的Pythonを読むのはまだ2回めなので、目が枯れるまで読みながら、コメントアウトをつけていく。

その後、いつもお世話になっているママことimaimaiさん、開発ができすぎてもう何がすごいのかよくわからないすごさ。あ、生み出しているからママなのか…?!?!
前回の大宴会スクレイピングに引き続き、助けを乞いました…いつもありがとう

ここからはぜひ、AtCoder Problems Contest Builder の main.py も開きながら読んでいただけると、よさそうです。

質問したことは以下です。

  • やりたいこと

    • ランダムに数字を生成して、abc{}a,〜dを追加した問題名で、問題セットを作りたい
  • わかった

    • problem_jsonで持ってきてる問題セットは、keyが問題名になっている
  • わからない

    • 54行目〜、きっと問題を設定している部分のfor文がまだ読解できてない…そこをどうにかすればできる…?
    • 83行目のtokenに直接書き込んでも良いのか…?
    • 全体的に、実験の仕方がわからない



いやあ。なんて素晴らしい質問の仕方なんだ。自画自賛するしかない。しない選択肢がない。

返答していただいた内容は

  • 54行目からは、config.pyで設定した内容から、問題の候補を絞っている
  • config.pyのproblem_infosの各オブジェクトに、問題名を設定するkeyを追加し、それをもとに問題を絞れそう
  • tokenは、他者に公開しない(githubなどに上げない)のであれば、直接書き込んでOK
  • 実験は、89行目以降のrequests.post以降をコメントアウトし、所々でprintデバックでOK

とのことで、満を持し、いじいじしはじめる

変更した箇所

config.py

ABC, ARC or AGCを1日2回開催するデータをセットするために、配列自体を増殖
diff設定などは適当にし、残しておきました(結果的に、のちほどmain.pyのfor文の中で設定しちゃったため)
いつか綺麗にしてあげたい…


# コンテストセット一覧
# abc用
contest_sets_abc = [
    {
        'name': '☀️🍰ABCなにか(Dまで)!',
        'title': '☀️🍰ABCなにか(Dまで)!',
        'memo': 'だれでも参加してください!早解き練習にどうぞ / ABCD問題を35分間走るバチャ / ABC126〜最新-10までのなにかがランダムで出現 / 通知bot https://twitter.com/abc_nanica',
        'everyday_start_time': '14:00',
        'duration_second': 2100,
        'penalty_second': 300,
        'problem_infos': [
            {
                'difficulty_range': (0, 1500),
                'point': 1,
                'include_experimental': True,
                'duplicate_remove_days': 60,
            }
        ]
    },
    {
        'name': '🌙🍰ABCなにか(Dまで)!',
        'title': '🌙🍰ABCなにか(Dまで)!',
        'memo': 'だれでも参加してください!早解き練習にどうぞ / ABCD問題を35分間走るバチャ / ABC126〜最新-10までのなにかがランダムで出現 / 通知bot https://twitter.com/abc_nanica',
        'everyday_start_time': '21:00',
        'duration_second': 2100,
        'penalty_second': 300,
        'problem_infos': [
            {
                'difficulty_range': (0, 1500),
                'point': 1,
                'include_experimental': True,
                'duplicate_remove_days': 60
            }
        ]
    }
]



# arc用
contest_sets_arc = [
    {
        'name': '☀️🍘ARCなにか(Cまで)!',
        'title': '☀️🍘ARCなにか(Cまで)!',
        'memo': 'だれでも参加してください!早解き練習にどうぞ / ABC問題を55分間走るバチャ / ARC104〜最新-2までのなにかがランダムで出現 / 通知bot https://twitter.com/abc_nanica',
        'everyday_start_time': '15:00',
        'duration_second': 3300,
        'penalty_second': 300,
        'problem_infos': [
            {
                'difficulty_range': (0, 4000),
                'point': 1,
                'include_experimental': True,
                'duplicate_remove_days': 60,
            }
        ]
    },
    {
        'name': '🌙🍘ARCなにか(Cまで)!',
        'title': '🌙🍘ARCなにか(Cまで)!',
        'memo': 'だれでも参加してください!早解き練習にどうぞ / ABC問題を55分間走るバチャ / ARC104〜最新-2までのなにかがランダムで出現 / 通知bot https://twitter.com/abc_nanica',
        'everyday_start_time': '22:00',
        'duration_second': 3300,
        'penalty_second': 300,
        'problem_infos': [
            {
                'difficulty_range': (0, 4000),
                'point': 1,
                'include_experimental': True,
                'duplicate_remove_days': 60
            }
        ]
    }
]



# agc用
contest_sets_agc = [
    {
        'name': '☀️🌶AGCなにか(Bまで)!',
        'title': '☀️🌶AGCなにか(Bまで)!',
        'memo': 'だれでも参加してください!早解き練習にどうぞ / AB問題を55分間走るバチャ / AGC001〜最新-2までのなにかがランダムで出現 / 通知bot https://twitter.com/abc_nanica',
        'everyday_start_time': '15:00',
        'duration_second': 3300,
        'penalty_second': 300,
        'problem_infos': [
            {
                'difficulty_range': (0, 10000),
                'point': 1,
                'include_experimental': True,
                'duplicate_remove_days': 60,
            }
        ]
    },
    {
        'name': '🌙🌶AGCなにか(Bまで)!',
        'title': '🌙🌶AGCなにか(Bまで)!',
        'memo': 'だれでも参加してください!早解き練習にどうぞ / AB問題を55分間走るバチャ / AGC001〜最新-2までのなにかがランダムで出現 / 通知bot https://twitter.com/abc_nanica',
        'everyday_start_time': '22:00',
        'duration_second': 3300,
        'penalty_second': 300,
        'problem_infos': [
            {
                'difficulty_range': (0, 10000),
                'point': 1,
                'include_experimental': True,
                'duplicate_remove_days': 60
            }
        ]
    }
]




main.py

どのバチャを立てるか、を入力で受け取る

14行目付近に打ち込みました。ドドパーン!
contest_typeという変数を作り、ターミナルで入力した「abc」または「arc」または「agc」を代入しています。
上記三種類以外の文字が入力されたら、ここで終了するようにしている。

ところで、いつも競プロでは「exit(print('hoge'))」って書いているので、同じ書き方をしそうになった、が、他の部分と合わせて0を返すようにした。
どうして0を返すのかはまだわかっていない…

print('どのバチャをたてる?')
contest_type = input()

if contest_type == 'abc':
    contest_sets = config.contest_sets_abc
elif contest_type == 'arc':
    contest_sets = config.contest_sets_arc
elif contest_type == 'agc':
    contest_sets = config.contest_sets_agc
else:
    print('打ち間違いだよ')
    exit(0)



バチャの日付設定のYYYY(西暦)を打たなくていいようにする

36, 45行目のinput前に'2023' + を書き加え、月日だけ入力すればOKにしました。来年になったら変えるぞ(どなたか、今年のクリスマスくらいに、私にプレゼントとして思い出させてください…)

date = '2023-' + input('開催日を入力してね(MM-DD): ')



指定コンテスト以外の問題は弾く

59行目の、for文内if条件文を書き換え
冒頭で作ったcontest_typeの文字列が入ってない問題は、さようならします

        if not contest_type in problem_id:
            continue



各コンテストにおける問題数の設定

75行目に追加

  • 途中から問題の傾向や、問題の数が変更になっているので、適切な範囲に設定
  • 最後の数字を手動で変えなきゃいけないのが若干めんどい。が、おそらくconfig.pyの設定ではじいてるから、適当なでか数字入れておけば良いのかも…
  • agcはzfillをするのを諦めてしまっているのがバレるぜ。3桁になったらちゃんとやる…
    if contest_type == 'abc':
        problem_id = f'abc{str(random.randint(126, 300))}_'
        problem_type = ['a', 'b', 'c', 'd']
    elif contest_type == 'arc':
        problem_id = f'arc{str(random.randint(104, 158))}_'
        problem_type = ['a', 'b', 'c']
    else:
        problem_id = f'agc0{str(random.randint(10, 60))}_'
        problem_type = ['a', 'b']
    
    
    for d in problem_type:
        problems.append({
            'id': problem_id + d,
            'point': problem_info['point'],
            'order': i
        })



tokenの記述

83行目の値を変更

token = 'gho_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

ご自身のトークンに置き換えてくださいませ。xの数はかなりてきとうっす



生成したURLをテキストに書き出し、ツイート用文章作成

103行目に追加

だいたい何をやっているかというと

  • ツイート生成用のテキストファイルを4つ作成
  • contest_type別にアイコンと、テキストファイルの名前を設定
  • 昼か夜か別に、ツイート用の文字列と、テキストファイルの名前を設定
  • datetimeから曜日を持ってきて、数値を日本語表記へ変換
  • 一覧用ツイート(【たてたよ】)と、通知用ツイート(今日の〇〇のぶん!)をセット。日付部分だけ抜き出しのスライスがなんか大変だった
# 通知ツート生成
if contest_type == 'abc':
    icon = '🍰'
    text_name = 'tweet_list_abc_'
elif contest_type == 'arc':
    icon = '🍘'
    text_name = 'argc_'
elif contest_type == 'tweet_list_argc':
    icon = '🌶'
    text_name = 'tweet_list_argc_'

if contest_index == 0:
    contest_time = 'おひる'
    text_name += 'day.txt'
else:
    contest_time = 'よる'
    text_name += 'night.txt'

day = start_dt.weekday()
day_of_week = {0: '(月)', 1: '(火)', 2: '(水)', 3: '(木)', 4: '(金)'}

# 一覧生成
f = open(text_name, 'a', encoding="utf-8")
f.write(str(start_dt)[8:10] + day_of_week[day] + '\n')
f.write('https://kenkoooo.com/atcoder/#/contest/show/' + contest_id + '\n\n')
f.close()


# 通知個別ツイート生成
f = open('tweet.txt', 'a', encoding="utf-8")
f.write(problem_id + '\n' + str(start_dt)[8:10] + day_of_week[day] + '\n')
f.write(f'{icon}今日の{contest_time}のぶん!' + '\n')
f.write('https://kenkoooo.com/atcoder/#/contest/show/' + contest_id + '\n\n')
f.close()

printの文言を変更

他、立てていてしあわせになれるよう、変えてみました。
プログラムが終了すると毎回「完了したよ!おつかれさま、いつもありがとう!」と言ってくれるの、愛着が深くなりすぎる…むふふ



こんな感じで立てられるようになったよ!

  • main.pyを実行し、立てたいコンテストを入力(abc, arc, agc
  • 昼か夜かを選ぶ
  • 立てたい日付を入力する(自動で前回立てた日の翌日になるので、違う場合は変更)


たったこれだけで!

自動的に問題がセットされて!

ツイート用の文章も作って!くれる!!

やばやばのやばで元気が出ました



今後どうにかしたいこと

  • 54行目のfor文をしっかり読解し、config.pyに無駄に設定してしまっている領域をすっきりさせたい…
  • if文がアホほど多い中学生コードなので、もうちょっと賢い業プロの書き方を知りたい



やってみて思ったこと

仕事以外で、自分のためにプログラミングをするのが初めてだったので、すごく楽しかったです。
今回はKowerKoint さんの素晴らしいベースから、自分仕様にいじいじしただけでしたが、いつか自分のためのツールを0から作ってみたいぞ!!と思いました。

そして、何より

「競プロで、Pythonを選んでよかった…」

これに尽きます…!
競プロ以外でPythonを使わなかったのですが、ほんとーにやっててよかったー!と心から思いました。
これを機に、Pythonで何かを作る、にもどんどんチャレンジしていきたいです。

読んでくださり、ありがとうございました!
ぜひ、ABCなにかで対よろです💪

発案から10日で107名の大宴会を開催した話(メール一括作成GASつき)

やっと書けた!! in 飛行機

基本的に、ずっと酒を飲んでいる話です。
おいしいお店を知りたい方はぜひぜひ読んでみてください。



前置き

3/18(土)、トヨタコン…
我々控えめレートコーダーには、夢のまた夢の話…

そんな夢の日の10日前、おにころくん a.k.a えてぃすさんが、こんなことを言っていました

そして、アンケートを取ったところ



「開催されるんだ!」の空気になってしまい、やべえ、と、とりあえず店を探すところからはじめました。

ちなみにわたしはこの期間中ずっと池袋と渋谷を勘違いしたり、足し算ができなかったり、自分を人数に入れ忘れたりなど、トップオブドジをかまし続けました。



お店を決める

翌日、すぐにお店を決めなければ…とぐーぐるおばけになりました。

  • 歓送迎会シーズン
  • 土曜日の渋谷
  • 1週間後

という3つが重なっているため、探すのはかなり難しいだろうなあ…と、とりあえずぐるなびにて「100名 宴会」と検索

  • 大手チェーン(安心と信頼の味と価格とサービス)
  • 駅近(泥酔者が出た場合、帰しやすくするため)
  • 飲み放題コース(代金を集めやすくするため、定額ぴったり3000円)

を条件に、電話をかけたところ、なんと1店舗めの土間土間 渋谷宮益坂店でHIT。空いてはいるが、店長さんから折り返しますとのことで、酒を飲みつつ待つ。

この日は東京ミート酒場 浅草橋店で友達と酒を飲んでいました。
ここはなんでもおいしいですが、特にミートソースパスタがやばいです。油そば的なスタイルで、チーズを練り込んだ麺だけでもおいしいのに、濃厚なミートソースを下からぐるりと掻き出した瞬間脳に刻まれるうまさは、走馬灯に出てくること間違いなし。

折り返し店長さんからお電話があり、仮予約をしました。

  • 確定を翌日20時にしてもよいか
  • 最大収容可能人数
  • 人数の最終確定日
  • 会場のテーブル割

を伺い、ひとまず仮押さえ状態をお許しいただきました。



そして、2軒目のダンダダン酒場 浅草橋店に移動。
ここは焼き餃子も水餃子もおいしいですが、おすすめは、餃子の皮を揚げたせんべいになんかうまい味噌がついてるやつ、です。紅茶ハイがあるのもポイント高いですね。



connpassで参加登録

規模と期間的にひとりでは絶対に無理なので、ゴリさんに協力していただき、相談しながら進めることにしました。
この時点でまだアンケートの匿名でしか人数把握ができておらず、ほんとうに100名規模になるか不明…

「誰が来るかわからないのに参加したくない」という意見を見つけ、たしかに会いたくない人とかいることもあるよなあ、と思い、Twitter連帯必須(誰だかわかる)状態でを条件に、connpassで参加登録をしていただくことにしました。

ゆるふわオンサイト開催の経験者であるゴリさんにconnpassページを立てていただき、わたしがちょろちょろいじりながら、まずは抽選で最大人数である147名をオープン状態で募集しました。
登録開始後2時間の時点で60名の参加登録があったため、お店に連絡をし「現状60名、今後100名になる可能性があります。予約確定でお願いします」と伝え、開催が現実になりました🎉



3/11(日)は月島のつくしやでもんじゃと酒をわははしてました。
こちらは年に1-2回、ほんとにだいじな友達を連れて行く、世界でいちばん好きなもんじゃ屋さんです。
店員さんが焼いてくれるタイプのお店で、すべてをプロの味で食べられますし、店員さんが下町!ってかんじで、めっちゃ居やすいです。居つきそうです。
心労で爆酔いして人生初財布なくしましたが、心優しい後藤さんという方が拾ってくださり、綺麗に帰ってきました。その節はたいへんご迷惑をおかけし、対処してくださりありがとうございました。

この酔い経験で、大宴会のリスク対策しっかりせんとな、と、胸に刻みました。



リスク対策

2名ではやはり無理(社会人、平日仕事マン)なのと、もう少し第三者な大人の意見が欲しかったため、きりさんに協力を仰ぎました。

この時点で、大きな懸念点が4つありました

  • 未成年飲酒防止対策
  • 飲酒時のトラブル対策
  • 代金の徴収方法
  • 飲み代のみ徴収のため、イベント系がなにもできない



未成年飲酒防止対策

こちらについては、chokudaiさんに相談させていただきました。というのも「トヨタコン懇親会でお酒出すから、そのまま酔っ払いが行くこともあるよー!」と教えていただいたからです。
どのように未成年判別をしますか、と伺ったところ「リストバンドで可視化するよ」とお答えいただき、こちらでも同様の方法を採択することにしました。

お店側や、参加者の方々に周知するため「赤は飲酒可能、青は飲酒不可だよ」を通達しましたが、一意性を持たせたかったため、すべてのリストバンドにねこを手描きしました。結果的によいお土産になったようでよかった…!

飲酒時のトラブル対策

未成年飲酒とも重なる部分もあるのですが、connpassで取れる情報(メールアドレスとハンドルネーム)では、例え顔が見える状態でも、何かトラブルがあった場合(最悪、意識を無くしたり、警察沙汰の喧嘩などが起こった場合)身元を確認できるものがないことが懸念点でした。
飲酒を希望される方には必ず身分証の提示をお願いすることで身分証持参を必須とさせていただき「最悪の場合は、財布から身分証引っこ抜いて確認できる、を担保しよう」という、アナログなリスク対策をしました。
また、ごりさんきりさんに泥酔する方の特徴や前触れなどを伝え、当日も会場を回りながら「ハッピー極まりそうだな」という方々を、周りの方にお水を飲ませるなどお願いしながら、できるだけアルコールオーバーフローを最低限におさえていました。たくさんの方々にご協力していただき、感謝です!

代金の徴収方法

「ドタキャン出たら俺が全部払うよ」ときりさんがおっしゃってくださいましたが、そんなことしたら末代まで花粉症がひどくなる的な呪いが降りかかりそうなため…めっちゃ考えました。
そもそも幹事経験はあるのですが、普段大学で顔を合わせいて家も本名も知ってる人々の飲み会企画と、インターネットで募り誰が来るかわからないアノニマスな飲み会企画では、同じ100名でもわけが違います。
また、受付時間と、お店での会計時間を最短にしたく、思いついたのが電子マネーでの事前集金でした。

この時意識したかったのが、あくまでもTwitterの匿名性というか、インターネットの人、の関係や距離感を保持することです。
あんまり個人情報をわたしに渡しすぎるのも、あれかなあ、と…

LINE payではLINEの交換の必要があるため、名前を好きに設定でき、友達追加の必要がない、かつ、お店が支払いに対応しているpaypayを採択しました。

大変だったのは

  • 集金URLの発行が、スマホアプリ上でしかできなかった
  • 送金時にメッセージを入れてもらわないと、誰かわからなかった
  • マネーライトとかなんだこれ?わからねえ(とりあえず大丈夫だった)

などなど…
おかげさまで、ぺいぺい集金ますたーぶりが生まれました。



飲み代のみ徴収のため、イベント系がなにもできない

これはけっこう、心苦しかったです。
いろんなご意見をいただくたび「やりたいけどお金と時間が…」ともがき苦しみました。
リストバンド代のみわたし負担でマイナスになった形でしたが、後から考えるとほんと、時間さえあれば色々やりたかったなあ…

名札を自作していただくのは結果的によかったようでなによりです!



参加者管理

受付終了後にconnpassからcsvで参加者一覧を落とし、スプレッドシートで管理しました。

主な項目は

  • 後述のアンケート内容
  • 入金履歴

です。
Googleなしでは、開催不可能でした。ありがとうGoogle

3/18(土)参加者管理(見本) - Google スプレッドシート



参加フォーム

上記3つの対策を叶えるために、connpass参加登録者さんたちにアンケートを取ることにしました。

内容は

  • メールアドレス
  • AtCoder ID
  • compass ID
  • 飲酒の希望
  • paypayの事前徴収に協力可能か

の5点。

connpassの一斉送信機能でGoogleフォームのURLを送るものの、迷惑メールに入ってることが多かったようで回収率が100%にならず…
また、Twitter連帯をされてなく、compass情報では誰だかわからない、compass IDを誤認されており、アンケートが来ても「これは誰だ」、AtCoder IDにTwitterが紐づいておらず「これは誰だ」、そもそもアンケートが回答されないこの人は誰だ…などなどで、泣きそうになったところ頭をよぎったのが、ツイ廃りゅーすけさんでした。 約10名のconnpass IDを送付したところ、ものの10分ほどで全員のTwitterを特定していただきました。おかげさまで全員と連絡が取れ、アンケートも無事に回収ができました!ありがとうコミュニケーションヤクザさん…!!



paypay集金

ご協力いただける方一人一人にURLを発行し、GASで作成したメールで一斉送信をしました。

  • 3000円のpaypay集金URLをiPhoneのpaypayアプリで発行、コピー
  • Apple ID連帯してあるMacBookスプレッドシートにペースト
  • 別シートにAtCoder ID、メールアドレス、URL、埋め込み変数を指定した本文(全て同一内容)の一覧を複製
  • GASでGmail下書きにメールを一括作成
  • 念の為さらりと確認しながら、送付

を、約70名分行いました。

一括下書き作成のGASコードはこちら。

function CreateDraft() {

  let ss = SpreadsheetApp.getActiveSpreadsheet();
  let sheet = ss.getActiveSheet(); // 現在選択してるスプレッドシート
  let range = sheet.getDataRange(); // データが入っている範囲
  let data = range.getValues(); // データの取得

  for(let i = 1; i < data.length; i++){

    let subject = 'PayPay支払いリンクのお知らせ'; // 件名

    let recipient = data[i][0]; // 宛先
    let name = data[i][1]; // 宛名
    let qr = data[i][2]; // QRリンク
    let body = data[i][3]; // 本文


    // 宛名の置き換え
    body = body.replace(/{{宛名}}/g,name);
    body = body.replace(/{{qr}}/g,qr);
    
    // 下書き作成
    GmailApp.createDraft(recipient,subject,body);

  };

}

iPhoneでコピーしたものをMacBookで貼り付けられる機能に本当に助けられました…あれがなかったら発狂していた
そして、GASってべんり!!JavaScriptがもずくレベルでもできてよかったー



お店下見

平日朝から晩まで働いていたので、2日前になってやっと行けました…あと、土間土間には経験則的に絶対的信頼感があったので、はい。

  • 予約時間、流れの確認
  • 支払い方法の再確認(paypayが先、残りを現金)
  • 受付場所の確認
  • 座席の確認、通し方の確認
  • 未成年飲酒対策のリストバンドの確認
  • 人数の最終確認

を行い、隣のおいしそうなステーキ屋さんに尾を引かれながら帰宅したら…深夜1:00でした。オォン



参加者情報のスクレイピング、考察

ココアサンは独特の洞察力を持ってらっしゃりだいすきなのですが(突然の告白)

おもしろそうだったのでさっそくDMしてお願いし、スクレイピングはハイパー開発マンいまいまいさんにお願いしました。

そちらの結果記事はこちらです。

qiita.com

何度見ても参加者さんたちが、すごい…本当にありがとうございます…!!



開催当日

30分前に幹事組(ごりさん、きりさん、ぜんじさん、えてぃすさん)とカフェに集まりました、が、わたしは遅刻しました。ごめんなさい。

競プロer大宴会のロゴ(?)を印刷し、クリアファイルに入れて看板代わりにし、ゴリさんとぜんじさんにお店までの誘導をお頼みしました。
chokudaiさんが「キャンセル待ちです〜」と来てくださったときは、自分をキャンセルにしてでもお招きしようとおもいました、が、店員さんが「いいよ」って入れてくださいました。土間土間にしてよかった。

受付を開始したところ、思ったよりも時間がかかりました。
特に

  • AtCoder IDの確認要員がわたしひとりであったこと
  • 赤色リストバンド(飲酒)の身分証チェックと巻く人がきりさんだけだったこと

が大きな遅れ要因になってしまい、大変申し訳なかったです。

座席の誘導をお手伝いしてくださったakira kanaiさん、ほんとうにありがとうございます!

けむにくくんが「名札忘れた!」と言ってたので、友達にアドバイスいただいた『養生テープに名前を書く』で対処しました。が、肝心の名前を書き忘れ、養生テープだけを貼った謎状態になってしまった。ごめんひつじさん。

そんなこんなで、予定していた20:15を30分オーバーし、20:45スタートに…
しかし、店長さんが「いまから120分にしたので」とイケメン対応をしてくださり、惚れました。本当に土間土間にしてよかった2。

宴会中はピッチャーシステムの伝達などで叫び狂っており、交流らしい交流ができませんでしたが、みなさん乾杯してくださりありがとうございました!
目立ったトラブルはなく、1.5名ほど泥酔者が出ましたが、そばにいてくださった方々の協力で無事家まで届けられました。

あの場にいてくださったひとりひとりの心優しさと配慮、賢さがなければ、無事に終えることはできませんでした。
ほんとうに、ほんとうにありがとうございました!



反省

  • 受付の並列処理を実施すべきだった
  • そもそもリストバンドを1種類にすれば良かったかもしれない(飲む人だけつける的な)
  • そもそもこういう規模は企業開催にお任せすべきだった
  • というか、せめて2ヶ月前から準備すべきだった。かなり無茶をした…珍しく、ほんとうに疲れた。ので、2次会に参加できなかった……

なので、半分やけになって行った翌日19(日)、函館空港のレストランで真っ昼間に飲んだガラナビールが、格別にウマかったです。

さいごに

改めて、参加してくださったみなさま、わたしの弱いところを支えてくださったみなさま、本当にありがとうございました!
どうか素敵なアルコールライフを!

よわよわ茶コーダー♀がはじめてオンサイト参加した話

3/4(土)のTUPCで、初のオンサイト参加を果たしました!

※「おまえだれやねん?」という方はこちらの記事を読むと、よわよわさがわかります…ぐへえ
 つまり、落ち込んでも寝たら忘れるタイプです。よろしくどうぞ!



経緯

けんちょんさんから「ぶりちゃんもTUPC参加しよう!」とリプが飛んできたことがはじまりでした。

フットワークが水素であることと、土日の一泊ならまあなんとか…ということで、ノリで参加登録!(この時点で、何もわかっていなかったのだった…)



TUPCとは?

AtCoderには

  • AtCoder主催のコンテスト
  • AtCoder以外が主催する、AtCoderのシステムを利用したコンテスト

の2種類があります

TUPCは、東北大学の競プロサークル「puzzleknot」が主催する、後者タイプのコンテストです。
他にも東京大学のUTPC、京都大学のKUPC、北海道大学のHUPCなどなど…いろんな大学がコンテストを主催されています。

特徴として

  • レーティングの変動がない
  • 時間が長い(今回はなんと4時間!)
  • チーム戦ができる
  • オンサイト(リアルコンテスト)が開催されることがある

などがあります。

今回わたしは

  • 初のAtCoder外主催コンテスト参加
  • 初のオンサイト参加
  • 初のチーム戦(学校に通ってなくて、集団戦に参加したことがない。協力プレー経験値マイナス)

というトリプルはじめてをしました!
しかも(おそらく)オンサイト参加勢で最弱…†

そんなもんだったので「オンサイトの手引き」としてお役に立てればうれしいなー、とおもい、筆をとらせていただいた次第です。



オンサイト参加までにやったこと

参加登録(オンサイト)

COMPASSにて、参加登録をしました。
TwitterのIDと連動しておくと、アイコンなどが自動反映されてよきよきです!
※わたしはアイコンで人を覚えているので「うお!こんな人が参加するのか!!」が一目でわかってしあわせでした



宿と交通手段の確保

今回は抽選だったので、確実に行くとわかるまでは、キャンセル料がかかる交通手段はひとまず放置。
日帰りで行ってもぎりぎり間に合ったのですが、どうせなら一泊して仙台をたのしみたいなあ…と、まず宿を探しました。
宿はだいたい前日までキャンセル無料のため、そこだけ確認したら軽率にとってOKです!

探した当初はえらい高かったので、確保はしつつも、直前キャンセルを狙ってました。
抽選通過したあと、結局は最初に取ってた宿をキャンセルし、JTBの新幹線&ホテルがセットになったツアーパッケージ(1人あたり22,000円。あれ?往復新幹線より安い…??)で、すてきな旅をしましたー!

余談ですが、ひとりで全国ふらふらする癖があるので

こういう手をよく知っています。
これからも積極的にシェアしていきたい所存です!



チーム決め

最初は誘ってくださったけんちょんさん、りゅうざきさんと組む予定でしたが「参加しようよー!PCも貸すよーー!!」と半強制的に巻き込んだけむにくくんしーふーどさん a.k.a ぷせうどさんと組むことになりました。

今回は、当初あったレーティング制限(チーム全員のレートを足したものの制限)がなくなったので、気軽に組めました!
…と言ってもわたしはよわよわ(当時411)なので、むしろ平均を引き下げる足枷要員なのですがな!ふはは!!

もちろん、個人で参加することもできますし、オンラインだけでも、オンラインとオンサイト勢を混ぜてのチームも可能です。
つまり、人数制限(今回は3人)さえ守れば、なんでもアリです!

規定はコンテストによって違ったり、最初のアナウンスと変わったりすることがあるので、要チェックなのです…!



チーム名決め & 参加登録(AtCoder

コンテストのページで、参加登録をしました。
チーム登録する場合は「チーム名」と「合言葉」が必要です。

チーム名を決める際には、とにかく思ったものを投げまくりましたが

「みんなけむにくくんを愛している」

ということで「けむにくくんを愛でる会」となりました。
合言葉は、みんなで同じものを入力します(つまり、同じチームの人は、チーム名と合言葉、同じものを入力します)



バチャ

本番前に、練習!ということで、チームでバチャをやりました。

  • discordのサーバーを立てる(けむにくくんがやってくれた)
  • 問題を選ぶ(ぷせうどさんがやってくれた)
    昨年のTUPC2021はAizu Online Judgeで開催されたことと、配点から見る難易度が今年とは差異がある(byぷせうどさん)ため、配点的に本番と難易度が近そうなKUPC2021をやりました

discordには問題ごとにチャンネルを作り、考えたことを投げる、というスタイルで行いました。

とはいえ、わたしが解けるのはせいぜいB問題までなので、戦略を以下の感じで決めました。

  • ぶり:A, B, C問題を読み、解けそうなものから解く。わからなかったら軽率に相談する。愚直解を書き、ランダムテストを回す
  • ぷせうどさん & けむにくくん:D問題以降を見て、解けそうなものから取り組む

そうして、はじめての5時間バチャがはじまりました…

結果:1時間延長し、A, B, C, D, Eの5完!!!

わたくし、Bから先はサンプルを図にすることしかできなかったので、実装をひたすらお願いする魚でした…

反省点と得たものは

  • discordにコードを投げる方法を知らず、学んだ(はてブと同じだった)
  • 提出コードに考察を書くと、他の人が見たときにわかりやすい
  • リーダブルコードを意識する
  • 考えたこと、思いついたことはもれなく伝える(例え間違っていても、正しい考察のヒントになるので)
  • ペナは気にせず、とりあえず投げる

でした。

自覚的にわたしは何も力になれず、むしろいることでチームの順位を下げることは明らかでした。
が、ぷせうどさん & けむにくくんが何度もはげましてくれ、具体的なやることを教えてくれたので(その節はお世話になりました)「今、自分ができることを精一杯やろう」と決意できました。ほんとうにありがとう…

個人的には、わからないときに「にゃーん!」「わーん!」「うえええわかんないよおおお!!」の合唱ができたのがたすかりました。
波長が似てる is あんしん!


そうして、あっという間に3/4(土)がやってきました。



持っていったものリスト

  • PC
  • iPad
  • 充電器類
  • モバイルバッテリー
  • めがね
  • 衣類(YNEOSスウェットなど。milkcoffeeさんに着てきて!と頼まれた)
  • 新幹線の切符
  • 財布
  • お菓子
  • 常備薬
  • 美容品
  • パジャマ(家の匂いでおちついて寝る用)
  • ひこにゃんの生首(コンテスト中もみもみしておちつく用)
  • 鹿本(サインをしてもらう用)

持っていけばよかったなあ、というもの

  • 筆記用具
    会場に紙はあったけれど、ペンがなかったため

わたしは考察を全てiPadと提出にコメントアウトで書くひとですが、何かとあるとよかった(サインしてもらうときとか)



コンテスト当日

まず、けむにくくんを鬼電で叩き起こしました。
そして、わたしは調子乗ってたら遅刻しました…ぷせうどさん、ひたすら保護者…

この日3人ともがお互いに初対面だったので、服の特徴など伝えつつ、東京駅のマクドナルド前で合流。

仙台へ向けて出発をしたのでした…!



ごはん(牛タンの補給)

けんちょんさん、りゅーざきさん、ゴリさんと合流して、6名で牛タンを補給!せっかく仙台に来たならばね!!

直前で思いついたことだったので、早めに着いた我々がよさげな牛タン屋を確保し、無事に補給できました。
が、そもそも開店時間が11:00〜と遅かったため、開会式にちょい遅刻をするというムーブをかましてしまいました…反省点そのいちです。



会場着

受付で、Twitter IDとアイコンが書いてある例の札を渡されました。もちろん、コダックもばっちり映ってました(実は、います)。
コンテスト開始まで25分しかなく、ちょっと慌ただしく準備をしながら、お手洗いの場所などを案内していただきました。

会場にはお菓子と飲み物類(お菓子は食べ放題、飲み物は1人1本まで)が用意されていました。
普段お水をいっぱい飲む人は、自分で持っていった方がよいです!

証明書の関係で学内Wi-Fiにうまく繋げられず、結局4時間フルでデザリングをしました…次はもっと早く会場に着くようにして、Wi-Fiをしっかり繋げよう。反省点そのに

2分前くらいにやっと整い、アルフォートをもぎもぎしながら、コンテスト開始を迎えました。



コンテスト

思っていたよりも、すっごく静かで話しづらかった…とにかく、あっという間の4時間でした…
わたしの担当したAと、ぷせうどさんが担当したFの2完。17秒後にBをACで悔やまれました。
あと20秒はやく相談していれば…くうう

でも、結果に関わらず、というか、結果が帳消しになるくらいにめっちゃ楽しかったです。
考え続けることがだいすきなので、4時間のコンテスト時間はすごくすごくうれしかった。
そして、なにもかもがよわっよわな自分がちょっとでもチームの力になれたことが、奇跡みたいだった。

解説の時間で、自力で通したA問題のdiffが、自分のレートより上の506だったことを知ったとき「成長したなあ」と泣きそうになりました。
C問題以降の解説は「ばなな!」だったので、解説を聞きつつ問題を見つつ「普段自分が解いてる問題はこんなふうにして作られているのかあ」と目をきらきらさせていたら、いつの間にか作問をしてました。
難易度の調整とか、解法から考えるとか、その逆とか、背景や過程を聞けてものすごくためになったし、楽しかった。



懇親会

そのまま会場でゆる〜っとお話タイム。
ふだんTwitterで見る文字や聞く声に生身がついている…という変な感覚でした。

緊張しながらいろんな方にご挨拶させていただき、特にこたつがめさんは緊張と尊敬とアイドル崇拝的感情が入り混じり、開口一番が「す、好きです」になってしまった(ばか)
そんなわたしに爽やかな笑顔で「ぶりおでんさんですよね、こたつがめです」と、topcoderTの腕部分に書かれている「kotatsugame」を示してくれたこたつがめさんは、やっぱり誰もが憧れるレッドコーダーでした。かっこよすぎ。。

個人的に絶対に挨拶しておきたいひとには、しっかり挨拶(敬礼含む)できたので、満足して終了。
チームメイトと温泉に行き、長い1日が終わりました。



反省点

上に挙げた2点

  • 時間には余裕を持ち、受付開始前くらいに着く勢いで行くこと
  • ネットワークに繋げることができない場合があるため、デザリングなどの用意は必ずすること(時間に余裕を持ち、困ったら質問できるようにすること)

の他に

  • コンテスト中はチーム内でも他人の提出は見られないので、discordにコードを送る練習などをしておくこと
  • 口頭で相談する派のチームだったので、もっと端っこに座り、しっかりと口頭で会話すること
  • 実装が手詰まりになった場合、相手に「今相談していいですか」をワンクッション挟んで、早めに相談すること
  • わたしはとても弱いので、次回はチームワークを具体的に、戦略的に構築すること(本当にこれ…申し訳なかった)
  • 他のチームがやっていることをもっと聞いて、良い方法を取り入れること
  • つよくなること

だなあ、と思っています。

ちなみに、女性はパッと見たところわたしひとりでしたが、特に不便や特殊事項は感じませんでした(性格のおかげかな)
お手洗いが占有できてラッキーって感じでした(!!)



そんな感じの、とってもたのしく学びばちばっちのオンサイト参加でした。

改めて、関わってくださったみなさま、TUPCの開催をしてくださった東北大学のみなさん、そして人生初のチームメイトのお二人…ほんとうにありがとうございました!

来年は絶対に4完する。

去年の1月に冪乗を知らなかった社会人がABC289で再入茶しました!ながい…

やったあ!また照り焼き色になれました!!

※前回の記事を読んでいない方はこちらから読めます

茶色になったあと、燃え尽き症候群やらガチ鬱やら仕事爆発だったりで、見事にレートが下がってしまいました。わはは

今回の記事はめちゃくちゃ個人的なことの羅列が多い、いわゆる巨大ポエムなので、タイトルが気になった方はむしろ前回記事の方がおもしろいかもしれません… とはいえ、精算や感謝を込めて、そしていずれ来るアニメ化のためにも(?)入茶小説第二弾を書き上げました!
ちなみに、書き上げの変換候補の第一はかき揚げでした。サクサクだ…おなかすいた。

再入茶までの推移

再入茶までに解いた問題

そういえば〜初回の茶色になるまでに会得したアルゴリズム

  • 貪欲法
    元々の考え方がけっこう怠惰で貪欲のため、知らずに会得してました…

  • 累積和
    E8さんの著書と、けんちょんさんの鹿本で会得しました。
    中学数学の度数分布表をやっていた時に「ペロッ。これは、累積和…!」となりました。学び方が逆!

  • BFS/DFS
    会得したとは言い難いですが、問題を見たときに「ペロッ。これは、BFS/DFSで解ける…!」となれるところまではいきました。

二分探索はこちらの記事、DPはアルゴ式で理解したつもりになっていましたが、いざ実装しようとすると ばなな になってしまいます。直近の課題はこの2つ…!!



コンテスト振り返り

ABC284 453→444(-9) 3完で冷える

Cで「コピペしたら通るコード」が出た回でした。 正しくは「コピペで通るが、入力が1-indexedなので0-indexedに直さねばならない」回…

燃え尽き症候群気味になっていたわたしは、ググって出てきた3つ(networkx、UnionFind、DFS)の0-indexedに気付けず、コピペコードでエラーを吐くターミナルを見つめ「もういいや、自力でBFS書こう」となったのでした。
そして、通りました(どうして?)

この時本番ではじめてBFSのコードを提出できて、かなりうれしかったです!

そしてレートの低下がはじまったのであった…



ARC153 444→398(-46) 0完入灰

ARCとABCの日程が入れかわり、出られなくなったABCの代わりに調子乗って出場し、0完。 ずっと繰り上がりの足し算と格闘していた…

仕事が膨大でメンタルと精進時間が削られていたので、仕方ないなあと思いつつもへこんだ。やさぐれて、以降めっちゃスペースに参加する人になってしまった…

でも、結果的にそれがよい方向に転んだ



ABC286 398→383(-15) ノーペナ2完 Aむずい

脳がMLEになるA問題でしたね。
ABCでこんなにがっつり冷やすということは相当脳がまわってないなー、と、しばらくコンテスト出るのやめて休もうかと思いました。

が、べつにレートが下がっても死ぬわけじゃないし、体重記録と同じで、自分の脳の状態を把握するために出続けよう!と決意。 結局まだCをあっぷそるぶできてないですね。ぐおお



ABC287 383→383(±0) ノーペナはやとき2完

レート低下をふんばれたことがすごくうれしかった! コンテスト後も奮闘している。よいですね。
カレンダー見たら前日にめちゃでか仕事が終わっているので、つまりそういうことだったようです。単純明快✨



ABC288 383→397(+14) ノーペナはやとき2完

はやときに助けられた!CとDがぬりかべみたいなつよつよの壁だった UnionFindをちゃんと整備すると決意(まだ決意しただけ…やりたい…)



ABC289 397→419(+22) ノーペナ3完 🎉再入茶🎉

at 北海道(旅行中)
Aで下手にbit反転使おうとしてかなり手間い、結局普通に1⇄0変換しおそめのAC
前だったらここでこころがしょぼんしてたし、Bのなっがあい、しかもグラフな問題文で「むり」ってなってるはずだった

…が、一度†落灰†をした者は一味違うんだぜ…??

実は何を隠そう、問題文を読みませんでした(わはは)

大学受験時に漢文のレ点だけは学習してて(漢文はえんぴつ転がしに任せたので、本当にレ点しかしらない)sample見る限り普通にレ点読みシミュレーションでいけそうだったので、stackしました。

ちなみに、この方法をstackと呼ぶことはあとから知りました…めっちゃ丁寧に教えてくださり、ありがとううにさん
抜けてる知識いっぱいありそうでこわいよー…!!

Cは…コンテスト直前まで、bit全探索の問題でうんうん唸って履修したのがまさかの奇跡爆発。 自分のバチャに自分で救われたのほんとうに運が良すぎた。

DはDPのD〜♪って踊ってたらおわった。うそです、履修してたら終わりました

そうして、私は 再びの照り焼き色 になったのです!!



再入茶までにやったこと

超絶鬱で精進をするあたまのちからがなかったため、それでも何かしらで競プロに関わっていたい…と、いろいろやってました。



リハビリ灰埋め

準備運動みたいな感じで、ARCやABC-likeの灰diffを埋めていました。
経験からしても、自分の実力よりも上の問題に取り組んだほうがよいのは自明だったのですが「解ける」という感覚を途切れさせないために、徐々に負荷をかけていく形にしました。



作問

鬼教官りゅーすけさんのスペースに参加していた際「buriodenさん、作問したら?」と無茶振りをされ…
ところがさくさくと3問作ることができ、作問才能をみつけていただきました。

これはいもす法で解けるらしい

これはよく覚えてない(?!)

こちらはNP困難のようです

スピードがえぐいですね。25分に1問…???
作問をしていると、いつも解いてる問題がどのようにして考えられているのか、想定解を見つけるための道筋を見つけやすくなったような、気が、します。まだそこまでの域には達せてないですが…いずれ…
そしてこの直後ひみつの企画が立ち上がり、1日で100問の作問種を出しました。こちらに関しては、私が緑になったときと、年末を楽しみにしていただければとおもいます…!!



新しくアルゴリズムを会得

  • いもす法/尺取法
    自然にやってたことを改めて落とし込みました。ながたかなさんの記事が本当にわかりやすくてすごいです!めちゃおすすめ

  • UnionFind
    そもそもプログラミングにおけるclassの概念が分からなかったのですが、こいつのおかげでわかりました…! まだ使いこなせてないですし、アレンジもしてないのでアルゴ式のものをコピのペしただけです。ゆっくりじっくり、わたし色に染め上げていきたいですねえ…ぐふふ

  • bit全探索
    ABCなにかですごく詰まった問題があり、bit全探索で解けるんだよ〜というフレンズさんのTwitter解説を見て(逃げていたことに、向き合わなければな…)と、北海道に向かう飛行機の中でけんちょんさんのアルゴリズム本を読みながら気絶して起きたり気絶したりしてたら、理解できました。
    2N個のYES/NO状態の全列挙をし、それぞれを入力から与えられる状態と比較していく、というやり方は、普段の生活で考えることとは逆の思考手順のため、すごくすごく衝撃的でした。

基本的に、ABCなにかか、コンテストで詰まった問題で使われているものを履修しただけです(グヌ)



人との交流

勉強会

えるさんとの勉強会は、 milkcoffeeさんのこちらのツイートがきっかけでした。

えるさんはレートが近いこともあり、以下の方針をたてました!

1.自分が解いており、相手が解いてない問題を2問ずつと、ふたりとも解いてない問題を3問、合計7問用意
2.期日を決めて5問、解説ACをせず解く(自分で解いてる2問は、やってもやらんでもOK)
3.専用のバチャを立てる
4.終わったあと、discordで解説会をやる

えるさんが投げてくださったものが幾何問題でうれしいことに歯が立たず、めっちゃしっかりがっつり解説していただきました…(わたしが投げた問題は、整数問題だったことと、解き方が一緒だったため何も解説ができませんでした。やはり、かしこい…)

反省点としては

  • 苦手分野や未履修アルゴリズムを把握し、diffよりもジャンルで問題を選べばよかった
  • 自分が解説をしっかりと用意してなかった(土下座)

本当に土下座案件なので、えるさんの試験期間が終わったら正しくリベンジをしたい所存であります。



鬼教官りゅーすけさんとは、毎週2〜3時間くらいの時間を設定し、わたしがHTML/CSSやらを、りゅーすけさんは競プロを、という感じで教え合いっこしてます。
とはいえまだ走り始めたばかりで1回しかやっていないのですが…とりあえず鬼です。通話中動悸がやばい。泣きそうになる。きらい!!
うそです。めっちゃだいすきだし、かんしゃしてます。



競プロ女子部設立

去年からわたしのことをご存知の方は既知かもですが、実は過去にとある事件に巻き込まれ、生活に支障があるレベルの重度男性恐怖症を患っていました。 競プロと一緒に、しばらく離れていたTwitterも勢いではじめたとき「び、美少女アイコンだらけで、性別がわからぬ」と身構えていたあの頃が懐かしい。

今では想像できないですが、リプを送ることすらおろか、いいねがくるだけでこわくて泣いてました。勇気を出してスペースを聞くも、自分の携帯から男性の声が聞こえるだけで過呼吸になって泣いてました(よくそこから復活したなあ。好きなことってすごい)
そんな状態にもかかわらず、やさぁ〜しく関わり続けてくださり「男の人は全員がこわいんじゃないんだ」を教えてくださった方々には本当に本当にかんしゃです。

さすがにそこまで極端な例はなさそうですが、もし、同じ気持ちを少しでも抱いてる方の力になれたらなあ…と。あと、単純に競プロの話できる女友達ほしいな、なんなら近所だとめっちゃうれしいな(楽観)というぽやぽやな願いを抱いていたところ、彗星のように現れたのが、fujikawaさんが設立に関わられている競プロゆんたく会でした。

「まあサーバー立てるだけだし、やってみるかあ」と立て、アイコンを描いただけです(本当にそう。チャンネルとかはほぼほぼおばけさんが作ってくれました。ありがてい…!!)

これからどう運用していくかなどぜんぜん考えられてないのですが、だからこそいろんな可能性があると思うので、引き続き†入会の番人†としておでんステッキ🍢持って門番をしていきます。

ご興味がある方はTwitterでわたしにDMをください!



ABCなにか(バチャ)に出る

何も食べられないくらいに鬱症状がひどかったときも、バチャを立てることだけはやめたくなくて…ありがたいことに単純作業だし、バチャの設定時にABC◯◯◯を決めるガチャを引くのはちょっと楽しかった。

参加して1完、2完しかできなくても、前に解いたときよりは確実に理解が進んでいたし「あ、これ全然解けなくて解説ACしたなあ」って問題がするっと解けた時のうれしさがすごかった。 それに、終わったあとすぐにTwitterでわからなかったところを復習できるのがありがたかったし、他の人の解法をひたすらもぐもぐできて、めちゃくちゃいいインプットになっている。

参加してくださっているみなさま、わたしの栄養になってくださりありがとうございます。じゅるり



競プロLINEスタンプ作り

ABC287で±0したときの成績表に :| がいて「かわいい」と思いらくがきしたのがきっかけでした。案を募ったらいろんな方からネタをいただけて、作りたくて作りたくてたまらなくなっちゃいました。

ちょうどその夜に理解のある友人らと飲酒会があり、みんながわいわい話している中でレモンサワーを煽りながらおえかきしまくり、その日のうちに完成。 まさか酔っ払いのらくがきがこんなにも反響をいただけると思っておらず、しあわせハッピーでした…!

第二弾はよりニッチなネタを攻めつつ、一般人も使いやすいような華麗なものに仕上げるという、自分への負荷をかけることで創作トレーニングちゅうです。乞うご期待!



その他、心境の変化

これはたいへんたいへんお恥ずかしい話なので読み飛ばしてください…

わたしは今まで、他人ではなく過去の自分と闘ったり、わかること自体がうれしい、という内発的動機付けで競プロをがんばっている つもり でいました。
でも、実際茶色になってみると、ずっとふわふわした気持ちでした。

その原因は、原点であり原動力であった競プロの神様にほめられなかったこと、です。
あんなに他者からの評価を気にしないつもりで競プロをやっていたのに、いろんな方からの「おめでとう!」「がんばった!」が募れば募るほど、心に穴が空くきもちでした。
うれしくなかったわけではなく、どちらかというと「実感がない」がいちばん近い感情でした。どんなにすごいと言われても、革命児(?)と言われても、ずっとずっとふわっふわしてました。

そんな折、マシュマロに「いま、一番ほしいものはなんですか」と質問が来たときに、う、となりました。
わたしは、たった一人からの「おめでとう」のために、ここまで頑張ってしまうバカだったということ。その一言がいただけなくてしょんぼりしてしまうほど単純だということ。
競プロでわたしを傷付けられるのは、わたしが競プロをはじめるきっかけをくれた神様だけだということ。

羞恥心と悔しさではちゃめちゃに泣いたり、落ち込んだり、抜け殻になったりしながら「競プロを続ける理由が欲しい」なんていう弱音を吐き続けました。そんな泣き言にも言葉をかけてくださった優しい方々を1日シャットアウトして、泣きじゃくったりするよわよわムーブをかましていました。
これ書いてて本当に恥ずかしいな…あの時は本当にごめんなさいでした。

シャットアウト中にいろいろ考えた結果「考えない」がベターアンサーだなと腑に落ち、またぬるぬる精進もTwitterも始めました。

昨日の夜、コンテスト前におふろぽちゃんしながら思ったことがあります。
あの時、競プロを続ける(緑を目指す)理由を探していたけれど、そもそも理由なんて最初からなかったし、今もない。
確かに強く憧れを感じたけれども「わたしもやってみよかな」のなんとなくではじめただけ。
その証拠?に、競プロをやらなくても死ぬことはないし、灰色に戻ったって叩かれて干されるみたいなこともなかった(どんだけ認知が歪んでたんでしょうね。鬱ってこわい)

でも、やる理由がないからこそ、趣味として思いっきり楽しめるんだな、と。

それに、灰色に戻っていた間、うれしいことがたくさんありました。
11月にレート100台の時、神様に「競プロも数学も、本当に楽しいです。きっかけをくださってありがとうございます」と、めちゃうまハンバーグを食べながらお礼を伝えたとき「実際に始めて、やり続けているのはあなたなので」と、謙遜された。

そのときに「風が吹かなきゃ桶屋は儲からないので」だか「種を蒔かなきゃ花は咲かないので」だか返したおぼえがあるのですが、ぜひ後者であってほしい。どうしていつもギャグチックになってしまうんだ…

そんな経緯があったからこそ、ながたかなさんrinrionさんのきっかけになれたことがすごく、すごく嬉しかった。

神様が蒔いた種をちゃんと他の方にも引き継げたことが、本当に、うれしくてたまらなかった。
うれしすぎてさっぽろ雪まつりが終わった後の会場を号泣しながら爆裂に散歩した。

引き続き競プロ女子部でも、Twitterでも、人生でも、誰かの何かになれたならば、とってもうれしいです!



さいごに…競プロを通じてお仕事をいただきました!

モノグサ株式会社さまで、コンテンツ作成のお仕事をさせていただくことになりました!
委託業務のため、作り終わったら解散!となる形ですが、まさか競プロを通じてお仕事をいただくことになるなんて夢にも思わなかったので、プルプルしてます。
がんばるぞーー!!!



今回は爆裂な自分語りになってしまいましたが、最後まで読んでくださってありがとうございました!
茶色で居続ける理由もないので、もろもろをもきもき精進して自分を更新していくぞ!!

今度こそ本当に、buriodenの次回作(入緑編)をおたのしみにです!!!!(翠富士の緑に、おれは成る…!!)

ABC283で入茶しました!〜成長日記〜

華麗なる右アッパー(©︎Ruteさん)で、ついに照り焼き色になりました〜!!!

すごい、どこもかしこも茶色でうれしい!!

うれしいので、わたしのAtCoder歴を辿る、成長観察日記をお届けすることにしました。
ひとりじゃ絶対無理だったーので、お礼も込めて、アカウント名を出したりしてしまってます…もしよろしくなかったら消すので、教えてください!

というわけで、お見苦しいところもある日記ですが、どうぞ行けるところまでお付き合いください



第一部

2021年

11月

伝来

プログラミングは、JavaScriptがちょっとできる。
学校行ってなかったから、算数は割り算も怪しい。

そんなぽやぽや社会人に、当時青色erの神より †きょうぷろ† の存在が伝えられる
やってる姿がかっこよすぎて憧れて、アカウント登録をする



12月

12/11(土) はじめてのAC、そしてはじめてのWA

チュートリアルをやってみる
はじめてのもんだいを、はじめてのC++でとく

Submission #27812359 - C++入門 AtCoder Programming Guide for beginners (APG4b)



にもんめ、はじめてのWA

Submission #27812427 - C++入門 AtCoder Programming Guide for beginners (APG4b)

AtCoder! って、hello world!のびっくりをとりわすれたんですね。おちゃめ


12/15(水)〜12月末

四則演算で電卓を使う始末、というか()かっこのある四則演算の存在を知らなかった。
やばい、このままじゃきょうぷろできない…と、6年分の算数をちびむすドリルで初履修


iPadでやる、という発想がなく、全て印刷し、12月末日までに無事履修完了。



2022年

1月

01/02(日)〜01/04(火)

2日間で20問ちょいのチュートリアルをすすめる。



01/08(土) はじめてのコンテスト はじめての0完

総AC29 チュートリアルEX11 まで進み、C++でのforとifを会得しいざコンテストへ!

さあ、いざコンテスト開始!ご覧ください!!
はじめてのA問題が、こちらっっ!!

A - Weird Function



burioden選手、100分間紙にひたすらfと()とxを書き続け、問題の理解すらできず、0完!!!


AtCoderって、プログラミングって、むずかしいんだなあ…(頬濡らす涙)」

この頃は他人の解答を見るとか、解説の存在も知らなくて、ただ枕を濡らすだけの日々を月末まで続けました。

後日、神から
「関数の中には、関数を入れられるのじゃ」
と教えていただき「そうだ関数じゃん!!」と、経験言語のJavaScriptでAC

アドバイスいただきJavaScriptでやることはせず、C++Pythonに完全移行
次のコンテストに向けて、アルゴ式でPython文法と基本的な計算を学びはじめました。



01/30(土) 2回目のコンテスト はじめてのコンテスト中AC

Pythonに切り替えてからはじめてのコンテスト
19分 1完

この時のA問題は…こちら!!!

A - Not Overflow

べき乗を知らず「なんだこの、ちっちゃい数字は…?」とググり、なんとか答えを導き出しAC

B問題は80分いすをあたため続ける
おそらくこの頃には解説の存在と、他の人の解答の見方を教えてもらったか学んで、コンテスト後にzipの存在を知り、無事にAC



2月

02/05(土) 3回目のABC はじめてのTLE 再びの0完


ん?A問題で3ペナなんてあるんでしょうかねえ?
実はですね、ご覧ください、この日のA問題!



A - Exponential or Quadratic

「この前やったべき乗ってやつだ!よおし、解けるー…あれ??TLEってなんだ??」

計算量を知らなかった魚、またしても数学に殺されるの巻



02/13(日) はじめてのARC

ABCとの違いがわからず無謀にも参加、A問題を開き唸り続けて気絶



02/19(土) 4回目のABC はじめての2完(ノーペナ)

すごいでしょう?!ノーペナで2完しました!
でも、A問題がえらい時間かかってますね…何を隠そう、この日のA問題はこちら!!


A - Horizon

何度でも言う。私は算数を学び終えたばかりである

「あ、この記号…あれだ…大学の時の統計学で出てきて、そして…寝たやつ……(フッ)」

となった後、意識を取り戻し、死ぬ気でググってAC

この日、B問題も数学チックだったので、綺麗に数学セットの回でした。よく解いたなあ

しかし、わたしの心は数学によりちゃっかりと折られ……



03/05(土) 5回目のABC

unrated未参加

04/09(日) 2回目のARC

unrated未参加

04/10(土) 6回目のABC

unrated未参加


そして、わたしは…競プロをあきらめました


〜終〜 ©︎BRI.



第二部

6月

06/17(金) 茶色宣言

神様とめっちゃ酒飲んだ。
どうやらこの時「茶色になる!!」を記憶の彼方で宣言したようです。
潜在意識に刷り込まれ、この後から急に予定を調整し、AtCoderのために土曜日を捧げる人になりました。

ちなみに翌日は…友達と旅行だったため、ABCには未参加



7月

07/02(土) 7回目のABC 復活

1完、Bは1回WAでタイムアップ

Twitterをはじめ、いっぱい泣いて、いっぱいこわがって、いっぱい悔しがるをはじめる



07/09(土) 8回目のABC 算数が、できぬ

算数ができず2ペナ1完



07/16(土) 9回目のABC B問題が、解けぬ

ノーペナ1完!



07/23(土) 10回目のABC なんとか、2完

1ペナ2完

7月は、全体的に「コンテストに出て、問題を解く」くらいしかできてなかった



8月

08/06(土) 11回目のABC 引っ越し疲れた1完

引っ越しを終えた後参加、疲労で2ペナ1完



08/13(土) 12回目のABC よし2完

1ペナ2完



08/21(土) 13回目のABC(Unrated)

1ペナ1完
Summer Sonic2022を観に行ったためUnrated
21時に宿に辿り着けなかったので、携帯でA問題だけ通す



08/27(土) 14回目のABC(Unrated)

1完 B問題はWA終わり。
Sweet Love Shower2022を観に行ったためUnrated
普通に参加するつもりだったけれど、宿がガチ山の中で、デザリングでも提出不可能だったためUnratedに変更
先週と同じく、携帯でコードを打って、提出した。

ところで、私はかなり本を読むタイプなのです。
E8さんのアルゴリズムx数学本は、数学がまだわからない私には計算量のところで挫折してしまった苦い思い出があり…
ところが、タイミングばっちりで出たけんちょんさんの鹿本は、読破することができて、とても自信になった。

そして月末、AtCoder ProblemsのA問題埋めにハマる。



9月

09/03(土) 15回目のABC 北海道飲酒事件

忘れもしない…
旭川で朝から3軒はしごして酒を飲み、夕方にイオンシネマ異動事例は音楽隊を観る。
ホテルにチェックインをして「よっしゃー仮眠取ってからABC出るぞお」と、目を閉じ、次の瞬間



夜中の2時でした。
レートは下がっていました。

そう…愚かなことに、Rated参加をしたまま、仮眠をしてしまったのです。

悔しさに身を委ねながら、100ACめの問題を解きました。ここでやっと辞書型を知ったようです。

以後、コンテストに出る日は絶対に飲酒をしない人になりました。
翌日のARCにRated参加して+6をするねずみおとこみたいなこともしました。



09/10(土) 16回目のABC(飲酒Unrated)


昼から終電まで、ビアガーデンで友達とすごくすごい飲酒をしたため不参加。
爆裂に酔っ払いながら携帯でA問題は通していた。
終了後順位表を見たら、神が黄色になっててうれしくて爆発し、HHKBを献上することに。



09/17(土) 17回目のABC 座標め、お前はどっちが列でどっちが行なんだ


1完。B問題は苦手な座標問題であったことと、zipをうまく取り扱えなかったようで死亡。



09/24(土) 18回目のABC 最高の0完

コンテスト前に総AC200を突破

神にHHKB献上ついでに、はじめていっしょにABCにチャレンジしたら…復活後初の0完

くやしすぎた
1問も解けないなんてかっこわるすぎた
めっちゃ泣きながら7km歩いて帰った
半分くらい飲み干したお酒も🤤(自主規制)した
ぎゃーぎゃー言ってたらRubyさんに「精進が足りないからですよ」と優しく厳しく諭していただき、精進グラフの存在を知った。

「なるほど、いっぱい問題解けばいいのか!」

そして †異常精進マン† は生まれたのであった…



10月

10/01(土) 19回目のABC つよくなりたい、でも、何からはじめよう

久しぶりのノーペナ2完。
今見てみると、解いた問題数は200問なのに、コンテストの成績としては2月とそう成長してないんですよね…そりゃ0完もするや。
茶色になるには国公立合格レベルの数学力が必要って見たことがあったため、数学力を上げることが必要だな、と、中学数学のテキストを進めることにした。
始めてみたら自分が無知すぎて恥ずかしくなって荒れた時、fujikawaさんからの「Twitterは恥を晒すところ」というお言葉に、大変元気付けられました…!ありがてえ
AtCoder ProblemsのTraning Boot camp for Beginners Easy埋めを主に、とにかくいろんな問題に触れることにした。



10/08(土) 20回目のABC はじめての3完

99:42っていう、超ギリギリで提出した3完がうれしすぎて踊った。このあたりから精進の結果が出始める。
るかごんくん主催のバチャが気になり、はじめて参加した。かなり大きな転機だった!
Discordにも参加したり、など、交流を少しずつがんばりはじめた。



10/15(土) 21回目のABC 偶数丸めの恐怖

かなしみの1完。
B問題でmath.roundの偶数丸めをこわがり使わず、結果失敗した。



10/22(土) 22回目のABC 早解が開花

2完だけど、C問題は3回提出できた
早解きが頭角を表し始め、2完なのにレートがわりと上がってよろこぶ。 企業コン、特にキーエンスは過去問を解いてて変なのが多くて身構えていた。けれど、自分的には納得いく感じでできた!



10/29(土) 23回目のABC はじめての茶パフォ

2完。C問題がむずすぎてD問題を開いたら「ん?これは解ける…?(勘違い)」をした。
が、秘技卍早解き卍のおかげではじめての茶パフォをとった!

結局10月は300問ほど解いて、総AC500を突破。



11月

11/05(土) 24回目のABC Pythonの挙動に苦しむ

1完…B問題がグラフで、連結リスト作ろうとした時に[[0]*n]と書き、数字が更新されなくて死んだ。[0]という配列をコピーしてるから、全て同じ値で更新されるという地獄を見た。
Pythonにはこういう挙動の謎があって、11月はそれでかなり苦しめられた月だった。
「絶対に動くコード」をスニペット登録、または常に隣に開いておける「使う.py」というアホファイルを置き、さらに早く解けるように整備し始めた。



11/12(土) 25回目のABC 2度目の茶パフォ

2度目の茶パフォ、早解き2完。



11/19(土) 26回目のABC 3度目の茶パフォ 2度目の3完

Cで2ペナしているのが痛いが、たしかに、なんだこの1ヶ月での急成長は?!?!



11/26(土) 27回目のABC 因縁のトヨタコン 3度目の3完

0完の悔しさをトヨタグループへ向けて放った結果、爆上がり!
安定して茶パフォ取れるようになってきたのは早解きのおかげ

11月は100問くらいしか解かなかったけれど、ただサクッと解ける問題が減っただけで…茶diffが自力ACできるようになった!
中学数学のテキストも、Boot campのEasyも終わって、いろんな解き方がわかるようになった。



12月

12/03(土) 28回目のABC 茶パフォ、3完の安定

1ペナ3完。この辺りから難易度傾斜が変わり、安定してD問題に進み椅子を温める人になる。
Twitterで「1いいねで何かしらをやりたいなあ」とつぶやいたら、鬼教官のRyusukeさんが「1いいねにつき1レート上げる」と返してくださり、震えた。おもしろそうだからやってみた。
ら、思いのほかいいねがめっちゃ来て(最終的に87)達成できるか不安になった…

でも、その不安が、火力になったんだぜ🔥

どうしたら達成できるかなーって考えながら温泉ぽちゃんしてて「おそらく自分の武器は早解きで、今日の難易度傾斜みたいな日にCまでをクレバーに速く通す練習、できたらいいな…あ、バチャ」と思いつき、Dまでの35minバチャを毎日立てるという暴挙に出る。



12/10(土) 29回目のABC ペナのデカさよ

Bで4ペナというひっどいことをして、久しぶりの灰パフォ…
個人的に300の壁は大きいなと思っていたので、目前にして失敗したのつらかったけれど、なんとか300には乗っていた。
早解きに助けられてばかりであるため、ペナは痛すぎるな、と学び、提出前に絶対見返す癖をつける。



12/17(土) 30回目のABC はじめてのノーペナ3完

ノーペナ、早解き、D問題もテストケースは通せて満足の飲酒!飲酒!!いんしゅ!!!
年内入茶が現実的になってきて、すこし怖気付き始める。
相変わらずいろんな方に勇気づけられて、がんばる。負けない。



12/24(土) 31回目のABC はじめてのノーペナ4完 \入茶/

いやあ、荒れましたね。荒れた回でしたね。
私も荒れてました。
Bまでを通した時点で、順位表を見に行ったら、いつも上にいるはずの黄色い神様の文字が…な、ない

え、まさか、クリスマスデートとかしてるから出てない、のか??!?
競プロはじめてからずっと、毎週欠かさず出てるって言ってたABCよりも、大切なものが…え、もう、一緒にコンテスト走れな…いっ…(目の前真っ暗)

1分間くらい、ひよこがぴよぴよと空を飛んでた

はっ と我に返り、そういや今のパフォは…?predictor、ん、あれ??APIエラー??
まあ、わかんない方が逆にノイズ減っていいか…いやでも、神様、えええ…とぐるぐるし始めてしまったので、友達に文章で泣きついて落ち着かせた。

ここまでで3分のロス。
深呼吸をして「そうだよ、こんな状況だからこそ、やるしかねえ!!」と、C問題に向き合うが、さっきまでの思考力と明らかに違う。問題文を読んでも、手からするすると、砂のように零れ落ちていく。
困った、もういいや、落ち込もう。と、友達に泣き言をびえびえと送りつける。結構やばい妄想レベルまで吐き出して真っ暗な世界に浸ったら すっ と冷静になって「よし」と、C問題に取り組む。

iPadに書いて実際にシミュレーションしたら、ただの文字列の長さ調整だったため、ちゃんと提出前に確認をし、AC。

9分5秒、よし。茶パフォは取れそう。
D問題に進む、たぶん解けないけど…

と、先ほどのショックが再び蘇る。問題文を読んでも頭に入らず、きつい、と、初めてコンテスト中にお花を摘みにいった。
コンテスト中に友達に連絡したのも、お手洗い(あ)行ったのも、はじめてだった。

初めて出た01/08(土)のコンテストからずっと、100分間諦めずに考え続けてきた。
1度だって、途中で離脱したことなんてなかった。

ここまで、よく頑張ったよ。
ここで抜けたって茶パフォは取れるから、レートは上がるよ。

って聞こえたのは天使の声だと思っていた。

でも

「は?ふざけんなよ、これくらいのショック、あの時の屈辱に比べたら…蚊に刺されたレベルだぜ」

私の中のインテリヤクザが、日本刀抱えて陰から顔を見せた。

「ねえねえ!次はどんな問題なの?はやく解きたいよー!」

私の中の幼女も、D問題を考えることを、何より楽しみにしてる。


そうだ、私は…今、戦っているんだ。
なんとしてでも、22:40までは戦い抜くんだ。絶対に

決心がつき、ちゃんと手を洗ってPCの前に戻る。


ここで運命の女神が私に微笑む。

いつもだったら見逃すはずのない、というか、見逃さないからこそ悩んで時間をかける箇所をすっ飛ばし、嘘解法でD問題を一発ACしてしまったのだ。
冷静なふりをするものの、やはりショックで頭が回ってなかったから、気づけなかった。

「気付かされなかった」と言ってもいいかもしれない。

そして私は、30:52でD問題を通してしまうという、とんでもないパフォーマンスを叩き出してしまった。

これは夢なのか…?と、ふわふわした気持ちでTwitterを見る。
ちなみに、コンテスト中にTwitterを見たのも初めて。

そして目に飛び込んでくる、何やらざわついたTL。これは…いや、今はいい。まだ私には闘うべき時間が60分も残っているんだ!!

と、そんな強い意志など実は持ってないので、不安を吐き出すだけ吐き出してE問題に突入する。
そういうクソなところも味だと思ってます。よろしくお願いします。

E問題は「bit反転かなあ」という気持ちで、テストケースは通るものは書けてよかった。
塗り潰せないかと、WAになったコードを数回回して、どこかのWAがとれるかの実験をして歴代最長コードを提出したら、波乱のABC283〜クリスマスイブ〜が終わりました。

そうして、私は 照り焼き色 になったのです。



ところで

実は、これくらいの精進は異常と思ってない

まだまだ頑張りが足りないなと思ってます。今でも。
精進量の権化である神の様子を見ちゃってることと、本当に一生懸命に頑張った!って実感がまだ、ないです。
「もう無理ー!」ってくらいに頑張りたい。だから、緑になるまでに、そういう日を積み重ねていきたいと思っています。



実は、今年最後のコンテストで茶色になる予感はしてた

半分トラウマみたいな話なのですが、以前いた職場の退職日に、過去最高の売り上げを叩き出して辞める、ってめっちゃかっけえことをしたことがあります。
溜まりに溜まってたマイナス感情が「売り上げ」という形で放出して、終わった後すぐに飲酒をしました。焼き鳥がめっちゃおいしかったです(なんか、ずっと酒飲んでますね)

ここ一週間その時のことが頭によぎることが多くて、もしかしたら、もしかするかもなーと思っていました。スピリチュアルは大嫌いだけれども、勘は当たるし運はいいから困った。

今回の緑パフォも、完全に運の力が大きいです。
だからこそ、実力で緑パフォが出せるまでは、成長を止めることなどできやしないんだぜ。

だから、これからも、たくさん教えてくれたら嬉しいです!
めざせ翠富士のみどりいろ〜!!!



最後まで読んでくださった方へ〜ささやかなクリスマスプレゼント〜

わたしのPythonはやときを支えてくれているVScodeスニペットたちです!
よろしければ、クリスマスプレゼントとしてお受け取りください。

{
    // 整数 1項 input
    "int(input())": {
        "prefix": "ii",
        "body": "int(input())",
 },
    "int n": {
        "prefix": "n=",
        "body": "n = int(input())",
 },
    "int q": {
        "prefix": "q=",
        "body": "q = int(input())",
 },
    "int d": {
        "prefix": "d=",
        "body": "d = int(input())",
 },
    "int r": {
        "prefix": "r=",
        "body": "r = int(input())",
 },
    "int k": {
        "prefix": "k=",
        "body": "k = int(input())",
 },
    "int x": {
        "prefix": "x=",
        "body": "x = int(input())",
 },
    "int m": {
        "prefix": "m=",
        "body": "m = int(input())",
 },
    
    // 整数 2項 input
    "int n,m": {
        "prefix": "nm=",
        "body": "n,m = map(int,input().split())",
 },
    "int n,q": {
        "prefix": "nq=",
        "body": "n,q = map(int,input().split())",
 },
    "int n,k": {
        "prefix": "nk=",
        "body": "n,k = map(int,input().split())",
 },
    "int n,x": {
        "prefix": "nx=",
        "body": "n,x = map(int,input().split())",
 },
    "int l,r": {
        "prefix": "lr=",
        "body": "l,r = map(int,input().split())",
 },
    "int a,b": {
        "prefix": "ab=",
        "body": "a,b = map(int,input().split())",
 },
    "int c,d": {
        "prefix": "cd=",
        "body": "c,d = map(int,input().split())",
 },
    "int h,w": {
        "prefix": "hw=",
        "body": "h,w = map(int,input().split())",
 },
    "int x,y": {
        "prefix": "x,y=",
        "body": "x,y = map(int,input().split())",
 },
    // 整数 3項 input
    "abc": {
        "prefix": "abc=",
        "body": "a,b,c = map(int, input().split())",
 },
    "xyz": {
        "prefix": "xyz=",
        "body": "x,y,z = map(int, input().split())",
 },
    // 整数 4項 input
    "abcd": {
        "prefix": "abcd=",
        "body": "a,b,c,d = map(int, input().split())",
 },
    // 整数 list in
    "int list 2項〜li": {
        "prefix": "a=",
        "body": "a = list(map(int,input().split()))",
 },
    "n行 int 1項リスト []": {
        "prefix": "ni1li=",
        "body": "n = int(input())\na = [int(input()) for _ in range(n)]",
 },
    "int 行 1項リスト []": {
        "prefix": "i1li=",
        "body": "a = [int(input()) for _ in range(n)]",
 },
    "n行 int 2項〜リスト [[]]": {
        "prefix": "nili2=",
        "body": "n = int(input())\na = [list(map(int, input().split())) for _ in range(n)]",
 },
    "int 2項〜リスト [[]]": {
        "prefix": "ili2=",
        "body": "a = [list(map(int, input().split())) for _ in range(n)]",
 },
    "n行 zip in": {
        "prefix": "nzip=",
        "body": "n = int(input())\nx, y = zip(*[map(int, input().split()) for _ in range(n)])",
 },
    "zip in": {
        "prefix": "zip=",
        "body": "x, y = zip(*[map(int, input().split()) for _ in range(n)])",
 },
    "int list sort": {
        "prefix": "ilis",
        "body": "a = sorted(list(map(int,input().split())))",
 },

    // 文字列 input
    "input()": {
        "prefix": "si",
        "body": "input()",
 },
    "str s in": {
        "prefix": "s=",
        "body": "s = input()",
 },
    "str t in": {
        "prefix": "t=",
        "body": "t = input()",
 },
    "str n in": {
        "prefix": "sn=",
        "body": "n = input()",
 },
    "str st 1行2項 in": {
        "prefix": "st1=",
        "body": "s,t = input().split()",
 },
    "str st 2行2項 in": {
        "prefix": "st2=",
        "body": "s = input()\nt = input()",
 },
    "intN strS in": {
        "prefix": "ns=",
        "body": "n = int(input())\ns = input()",
 },
    // str list in
    "str list 2項〜li": {
        "prefix": "sli=",
        "body": "a = list(input().split())",
 },
    "n行 str 1項リスト []": {
        "prefix": "ns1li=",
        "body": "n = int(input())\na = [input() for _ in range(n)]",
 },
    "str 改行 1項リスト []": {
        "prefix": "sbrli=",
        "body": "a = [input() for _ in range(n)]",
 },
    "n行 str 2項〜リスト [[]]": {
        "prefix": "nsli2=",
        "body": "n = int(input())\na = [list(input().split()) for _ in range(n)]",
 },
    "n行 str 1項リスト [[]]": {
            "prefix": "ns1li2=",
            "body": "n = int(input())\na = [input() for _ in range(n)]",
 },
    "str 2項〜リスト [[]]": {
        "prefix": "sli2=",
        "body": "a = [list(input().split()) for _ in range(n)]",
 },
    "str 1項 [[]]": {
            "prefix": "s1li2=",
            "body": "a = [input() for _ in range(n)]",
 },
    "str sort": {
        "prefix": "ssort",
        "body": "s = sorted(input())",
 },
    "str list sort": {
        "prefix": "slisort",
        "body": "s = sorted(list(input().split()))",
 },

    // 変数
    "cnt": {
        "prefix": "cnt",
        "body": "cnt = 0",
 },
    "ans": {
        "prefix": "ans",
        "body": "ans = 0",
 },
    "flag true": {
        "prefix": "flg1",
        "body": "flg = 1",
 },
    "flag false": {
        "prefix": "flg0",
        "body": "flg = 0",
 },
    "空list": {
        "prefix": "li",
        "body": "a = []",
 },
    "count-list 10": {
        "prefix": "cnt",
        "body": "cnt = [0]*9",
 },

    // for文
    "for i": {
        "prefix": "fori",
        "body": "for i in range(n):",
 },
    "for j/2": {
        "prefix": "forj",
        "body": "for j in range(n):",
 },
    "for k/3": {
        "prefix": "forkk",
        "body": "for k in range(n):",
 },
    "for l/4": {
        "prefix": "forl",
        "body": "for l in range(n):",
 },
    "for enumerate":{
        "prefix": "forie",
        "body": "for i,d in enumerate(a):",
 },
    "for reversed":{
        "prefix": "forir",
        "body": "for i in reversed(range(n)):",
 },
    "for i in a":{
        "prefix": "foria",
        "body": "for i in a:",
 },

    // print 出力系
    "print Yes": {
        "prefix": "priy",
        "body": "print('Yes')",
 },
    "print No": {
        "prefix": "prin",
        "body": "print('No')",
 },
    "print ans": {
        "prefix": "pria",
        "body": "print(ans)",
 },
    "print cnt": {
        "prefix": "pric",
        "body": "print(cnt)",
 },
    "print flg": {
        "prefix": "prif",
        "body": "print('Yes' if flg else 'No')",
 },
    "print list 改行": {
        "prefix": "priabr",
        "body": "print(*a, sep='\n')",
 },
    "print list 連結": {
        "prefix": "priaun",
        "body": "print(*a,sep='')",
 },
    "else print no": {
        "prefix": "elsen",
        "body": "else:\n\tprint('No')",
 },

    // リスト・辞書(初期)
    "int list": {
        "prefix": "ili",
        "body": "list(map(int,input().split()))",
 },
    "str list": {
        "prefix": "sli",
        "body": "list(input().split())",
 },
    "辞書": {
        "prefix": "dic",
        "body": "d = {'in': ans, 'in': ans, 'in': ans}",
 },

    // ライブラリ読み込む系
    "defaultdict": {
        "prefix": "dict",
        "body": "from collections import defaultdict\ndi=defaultdict()",
 },
    "sys.set": {
        "prefix": "sys",
        "body": "import sys\nsys.setrecursionlimit(10**5)",
 },
    "出現回数数える":{
        "prefix": "count",
        "body": "import collections\n\nc = collections.Counter(a)",
 },

    // inf mod
    "INF":{
        "prefix": "INF",
        "body": "INF = float('inf')",
 },
    "mod":{
        "prefix": "mod",
        "body": "mod = 998244353",
 },
    "MOD":{
        "prefix": "MOD",
        "body": "MOD = 1000000007",
 },

    // 高橋さんと青木さん
    "高橋": {
        "prefix": "ta",
        "body": "'Takahashi'",
 },
    "青木": {
        "prefix": "ao",
        "body": "'Aoki'",
 },

    // 小技系
    "重複抽出":{
        "prefix": "doub",
        "body": "l1 = []\nl2 = []\n\nl1_and_l2 = set(l1) & set(l2)\n\nl1_and_l2_set = list(l1_and_l2)\n\nprint(l1_and_l2_set)",
 },
    "素数判定":{
        "prefix": "prime",
        "body": "prime = 1\nif n == 1:\n\tprime = 0\nelse:\n\tfor i in range(2, n):\n\t\tif n % i == 0:\n\t\t\tprime = 0",
 },
    "約数判定":{
        "prefix": "div",
        "body": "for i in range(1, n+1):\n\tdiv = 0\n\tfor j in range(1, i+1):\n\t\tif i % j == 0:\n\t\t\tdiv = 1",
 },
    "約数出力":{
        "prefix": "divp",
        "body": "for i in range(1, n+1):\n\tif n % i == 0:\n\t\tprint(i)",
 },
    "回文判定":{
        "prefix": "loop",
        "body": "flg = 1\n\nfor i in range(n):\n\tif s[i] != s[(n-1)-i]:\n\t\tflg = 0",
 },
    "階乗":{
        "prefix": "fac",
        "body": "def fac(n):\n\tv = 1\n\tfor i in range(n, 1, -1):\n\t\tv *= i\n\treturn v",
 },
    "dicで条件分岐":{
        "prefix": "dicif",
        "body": "s = input()\nd = {'in': ans, 'in': ans, 'in': ans}\n\nif s in d:\n\tans = d[s]\n\nprint(ans)",
 },
    "累積和 a":{
        "prefix": "asum",
        "body": "for i in range(1, len(a)):\n\ta[i] += a[i-1]",
 },
    "各けた和":{
        "prefix": "11=2",
        "body": "a = []\n\nfor i in range(1, n+1):\n\tli.append(sum(map(int, str(i))))",
 },
    "差分を取る":{
        "prefix": "xor",
        "body": "s1 = []\ns2 = []\n\nans = set(s1) ^ set(s2)",
 },
    "平方判定":{
        "prefix": "sq",
        "body": "flg = 0\n\nfor i in range(1, n):\n\tif i*i == n:\n\t\tflag = 1\n\n",
 },
    "lambda i-1": {
        "prefix": "lai",
        "body": "lambda x:int(x)-1",
 },
}

茶色になるまでに関わってくださったみなさん、本当にありがとうございました!

ぶりの次回作(入緑)にご期待ください!

競プロ初心者がやらなくてもいいこと

こんにちは!さむいですか?さむいですね。
buriodenです。ぶりとおでんが好きです。いっしょに食べましょう!ほくほく



まえがき

「やってよかったこと」の記事はたくさんある。
けれども「やらなくてよかったこと」というネガ記事はあんまりない。
それならば、能天気マンによるネガ記事を書くぞ〜!と、筆を取らせていただいた次第です。
(来年は、みなさんのように技術記事を書けるようになりたいな…)

以下、私のスペックです。

  • 小中高の授業を受けたことがなく「九九…わかるよ!」のレベルから競プロをはじめた
  • JavaScriptPHPは少し書ける。HTML/CSSは寝てても書ける
  • 1年やってそろそろ茶色が見えてきた
  • 社会人。時間が取れるのは主に仕事の合間、仕事終わり、休日のみ
  • 茶色になりたい
  • リアル知り合い競プロerは1名(つよつよすぎて神様なので、気軽に質問できない…なかよくなりたい…)
  • 茶色になりたさすぎる
  • にゅうちゃしたい
  • 絶対に照り焼き色になる

この記事の対象者

  • 競プロはじめてみた!なひと
  • でも情報が多すぎて、ようわからん…なひと
  • プログラミングや数学の初心者だけど、できるのかな…?なひと
  • しかし、続けたいきもちがある。つよく!なりたい!!なひと
  • 暇つぶししたいひと(つよつよさんにはただの時間埋めにしかなりません…くう)

効いた度(おすすめ度)

  • ★★★ やらない方がいい
  • ★★ できればやらない方がいい
  •  人による

3段階に分けました!
※あくまで主観かつ、私のような数学やプログラミング初心者を対象にしてます

また、先輩先祖方の記事に倣い

  • 取り組み
  • 心持ち

のふたつに分けてお送りします!

やらなくてよかったこと〜取り組み〜

  • 「言語選択でゆらゆらする」をやらない ★★★

C++をやる。公式チュートリアルがあるため
C++の修得がきつかったらPython!または経験言語!
の流れでよいと思います!キツさが数学力のなさではなく、プログラミング言語のせいってのもあるので、やってダメだったら次!って心意気がよきよきです
ちなみに私は
C++(オーバーフローでつまづいた)→JavaScript(経験言語だが、数字の取り扱いについて悟空の修行的な苦しさを味わった)→ Python
の流れでした。Pythonマンになってよかった。そのぶん数学の勉強ができてます!

言及されてない数学知識が必要なことが多いです。
「わからぬ…」と無理して勉強する時間を、数学勉強に充てると、後々効いてくる感触があります。

  • 「自力で考え続ける」をやらない ★★★

知らないものは出てこない(にっこり)
精進時の自力は10-20分を目安にし、解説や他の方の解答を見て「インプット」に努めるのが楽しいです!
そして、コンテスト時は…Google依存症をしてます(調べまくるの意)

  • 「解説の理解に努める(解説ACにこだわる)」をやらない ★★

数学ができる方々の日本語は独特なので、慣れてないと「日本語なのに、わからない…」現象が起こることが多いです。
そんなとき、ご自身に近いレートの方のAC提出を見ると「読める、読めるぞ…!!」の主人公になれます!
プログラミングは噛み砕けば英語の文章であることと、レートが近い=経験値も近いことが多いため、腑に落ちる解き方を見つけることができます。
詳しくは→拡張機能について

  • 「ABC以外のコンテストに出る」をやらない ★★★

AtCoderのレートを上げたいなら、まずAtCoderをやるべし。
茶色になるまでは他の競プロサイトのコンテストには手を出さないのが無難です!
ABC以外の、ARC、AGCは神々のあそびで、AHCは…使う頭が違うまたちがう、神々のあそび

  • 「unrated参加」をやらない ★★★

万全でないなら無理して出ず、後日問題初見でバチャのほうが力つきます。その問題に初めて会える瞬間って、とってもだいじだとおもうのです。
ちなみに、いちばんやっちゃいけないのは、rated登録したあとにお酒飲んで「20:30には起きるう」って寝ることです!!(北海道の悲劇)

  • 「コンテスト中によりよい書き方、解き方を模索する」をやらない ★★★

競プロは!
綺麗で賢いコード書き選手権ではなく!
どんなトンデモスパゲティコードだとしても、1秒でも速くACした人が勝ち選手権!合ってりゃいい!!

  • 「ライブラリを使わず生コードで頑張って書く」をやらない ★★★

どうして?!(過去の自分への叱咤)
便利なものは使い方を学び、積極的に使うと楽しみが増します!

  • 「競プロ本を読破する」をやらない ★★

競プロ本は、辞書だもん!!

  • 「普段の精進を丁寧に記録する」をやらない ★★

よっぽど苦労したもの感動したもの以外は、丁寧に記録する時間を問題解く時間にあてたほうがよいかも…!
楽しいから書いちゃう、はガンガンやるとハッピーです!

  • 「ABC-AB埋め」をやらない 

「やらなきゃ…」と、プレッシャーになるタイプの方はやらないほうがよいかもです。
埋めないでも茶色以上になってる方々もいっぱいいらっしゃいます!
スタンプラリーだいすきなわたしは、こう…埋める快感に身を委ねてうふふふってしてたら、終わってました…

やらなくてよかったこと〜心持ち〜

  • 「競プロは何の役にたつか調べる」をやらない ★★

「役に立った」は個人的見解かつ結果論だから、やらなきゃわかんないよー

  • 「才能の有無で落ち込む」をやらない ★★★

経験と才能は掛け算だよ!って考え方がすきです
経験が0なら才能100でも、出力結果は0だ!ってことです…コワイ
肌感ですが、才能の壁は黄色くらいなのかなあ。逆に言えばそこまならめっちゃ経験を積めばいけそう…

  • 「streakをモチベにする」をやらない 

AtCoder Problemsのstreakという機能があります。「何日間連続でACしているか」を見せつけてくれる頼もしいやつです!
ところが、学ぶことの優先順位が、生きることよりも下になる時がどうしたってあるのです…切れた途端やる気が切れちゃって辞退はもったいないな、と思った時から、streakを知らないふりしはじめました。ちまちま毎日やるより、調子のいいときに思いっきり精進することを楽しめるようになりました!

  • 「他人とレートや精進量を比べる」をやらない 

ライバルいるとやる気出るタイプは除く
「はじめた時期、年齢、経験etcだけじゃ比べる基準にならない」と、この色変記事の著者に教えていただきました(泣きました)
他人と比較すると鬱になるけど、比較するのをやめられないよお…という頑張りやさんにおすすめなのは「過去の自分と勝負し続ける」です!過去の嫌いな自分を打ち負かすのたのしいですよーえへへへへ

  • 「寝ない」をやらない ★★★

寝ましょ



以上です!

でも「やってよかったこと」も気になりますよね…?ならないですか…??涙

あっ…なりますよね!!書きます!!!

いちお、やってよかったこと〜取り組み〜

  • ローカル環境構築 ★★★

online judge tools(問題のテストケースをローカルにダウンロードし、エディタ内でテスト→提出を完結できるツール)の導入を含みます
あ、でも…つらくなったらやめましょ!
環境構築に苦しんでた時代は、アルゴ式のてきとな問題ページをテストとして使ってました。AtCoderのコードテストよりも、いくらか動作が速い印象です

辞書登録ターミナルコマンドverです!
詳しくはこの記事にまとめてます。


VScode以外にもあると思います!辞書登録のコードverです。
確かに最初はフルで書いた方がいいけど…慣れてきたら、かんたんな入出力など、毎回擦るように書くものは登録するとキーボードの寿命が延びます

Pythonの文法は99%アルゴ式で勉強しました!
ちゅるっと学べるコンテンツがいっぱいで、気軽に取り組めます。競プロ本が辞書ならば、アルゴ式は単語帳ってイメージです。

色々あるので、こちらの記事を参考にしてください。
私のおすすめは、全ての提出一覧画面で、ユーザーネームの色をレートの色にしてくれる拡張機能です!
自力でACできなかった時、どの人の回答を見て勉強しようか?と選ぶ際に、めちゃ捗ります!

  • 中学数学を勉強する ★★★

連立方程式って知ってますか?あれを知らずに競プロやってた自分を殴った後に抱きしめたい
↓の本で問題解きながら勉強したら、見通しがかなり明るくなりました!



  • 「なぜこの解法になるのか?」ではなく「なぜこの解法を思いつくのか?」を考える ★★★

これ、正直何時間でもかけていいとおもいます!!
じっきーさんの色変記事で、この考え方を知って雷が落ちました。劇的成長しはじめたの、この後だったかも知れません

これは完全に私個人の話なのですが、先にお礼を伝えたくて…実は、ここ数年情熱大陸すぎて患った男性恐怖症が、Twitterでなおりました。息して外を歩けるようになったこと、何度感謝しても足りないです。
競プロerはツイ廃が多く(褒めてます)、わかんないです…!って質問すると、色んな方から色んな知見を教えていただけます
交流や考察を書いてくださっている方も多く、見ているだけで娯楽と勉強になります。あと、恥を晒すことにより、新しいことに向かっていける度量がついた気がします。
と考えると、メンタル面と取り組み面、どちらにも影響してますね。すげえや

いちお、やってよかったこと〜心持ち〜

  • 目標を1つ低く設定する ★★

ABC前に「今日はここまでいけそう」の1つ前段階を宣言してます。毎回越えられるから、やさしく元気です!

  • 頭の調子が悪い時の分析をする ★★★

暑いとダメなんだなとか、寝不足はダメなんだなとか…
自分の体調や気持ちに気付けないタイプなので、ちょっと頑張りました。
私の場合、部屋の温度と頭の回転におそろしいくらい相関があったため、何がなんでも適温環境で競プロをやることにしてます。



いかがでしたか?(これやりたかったー!!)

もし、あなたのなにかになれたらならば、とーってもうれしいです!
これからもがんばりますので、色々とよろしくお願いします…!

ABC281振り返り

3完は、した。が、今まででいちばんメンタルやられた回だった…
B問題4ペナて、ひよこです。ピヨ
300の壁あついよお なんか300になってました!!!!超えた!!!!!!!!



A問題

atcoder.jp

問題概要

nから0まで改行カウントダウンしてくれよな

考察

  • forでiをプリント 以上

コード

#入力
n = int(input())

#逆からfor
for i in reversed(range(n+1)):
  print(i)

感想

Ryusukeさん(鬼)に教えていただいたreversed(range())かなり効き始めている。ありがたや
45秒でA問題解けたのは最速だったんだけれど…しかし……

ちなみに、開始前にターミナルにoj d 前コンテストのA問題idを変えただけのやつ を打っておけば開始と同時にDLできるの知った。
というか、問題文を見ずにサンプル見て判断したことと、もう一つ気になるのが
私のPC、問題文の表示までとダウンロードがなんか遅い。chrome拡張機能starshipが影響している気もする。要研究。



B問題

atcoder.jp

問題概要

文字列Sが以下の条件を満たしているか判定してね。

  • そのいち:頭1文字が英語の大文字
  • そのに:真ん中が100000〜999999までの整数
  • そのさん:おしり一文字が英語の大文字

考察

  • if文を書きまくるやつだ
  • そのいち、そのさん、はisupper()で英語の大文字なのかを判断しよう
  • 真ん中は切り出して .isdigit()で全部整数なのかを判断し、OKだったら範囲をint()変換して見よう

コード

#入力
s = input()

f = s[0] #1文字目
e = s[-1] #最後の文字
n = len(s) #sの長さ
m = s[1:-1] #2文字目〜最後から2文字目(整数であってほしい部分)


#整数であってほしい部分の判定 Falseならその後の整数判定でバグるためNoを吐き出しプログラム終了
if m.isdigit() is False:
  print('No')
  exit()

#残りの条件判定
if n == 8: #8文字?
  if f.isupper(): #最初の文字は英語大文字?
    if e.isupper(): #最後の文字は英語大文字?
     if 100000 <= int(m) <= 999999: #整数部分はご指定の範囲内?ご注文はうさぎ??
        print('Yes') #よくぞここまで辿り着いたYes
        exit()

#全部違ったらNo
print('No')

感想

まさか4ペナするとはおもわなんだ。
手元でいろんなパターン書きまくってエラー原因見つける回だった。プログラミングが下手…でも、学べるものめっちゃ多かった。

  • 条件が複数の判定問題については、無理にandで条件を繋げず、ひとつずつ入れ子する。今回は f.isupper() and e.isupper() と書いてて、右項を判断しない問題でやられた
  • ifに対してelse:print("no")を連発するのではなく、print("Yes")したらexit()で処理
  • 指定範囲に文字列が含まれていた場合、int変換の時にエラーが出るので、丁寧に場合分けしてあげる
  • ちゃんとサンプルケースでREする原因を特定してから提出する。もうまぐれでRE解決するほどのレベルではない。いい意味で!
  • そして、REが解決したからとてWAが取れるわけではないため、WA原因を特定し修正してから提出するようにする(本当にこれ)

なんか書き出したら怒り(?)落ち着いた。自分に対して怒ってた…散歩しよう。良い散歩を。



C問題

atcoder.jp

問題概要

n曲のプレイリストがある。各曲の長さはaの数列で与える。では再生!無限ループをするぞ!!さて、t分経った時、何曲目の何秒を聞いてるでしょう。

考察

  • 好きなものが題材の問題、とてもほっとする。
  • 止まった時間(t)を合計で余剰計算すれば、何ループ目かは関係なく現時点にいるところは確定できる。
  • 確定できたら、頭から時間を引き算していこう。

コード

#入力
n,t = map(int,input().split())
a = list(map(int,input().split()))

s = sum(a) #合計秒数
now = t%s #止まった時間、合計秒数中のどこにいるか
track = 0 #何曲目かを足してく変数

#止まった時間(nowいま)がiよりでかかったらnowからiを引く。トラックナンバーを加算
for i in a:
  if now >= i:
    now -= i
    track += 1
  else:
    track += 1
    break

print(track,now)

感想

落ち着いて解けたからよかった。
悔しいけど、やっぱり音楽に救われてしまう…てへ


D問題

atcoder.jp

問題概要

nこの数字からmこを選び足した結果をxとす。dの倍数になる最大のxを探してね。

考察

  • ソートして上から順に貪欲しようとする。
  • しかしこれは組み合わせの数的に無理だ、あ、まさか、これは噂の…DP…か…

感想

DPのDだよね。それだけはわかったよ。漸化式?数Bだね。おいしそうだね。全菓子機
アルゴ式をがんばります!!!

来週のburiodenは

実はちょっとでかい仕事があるけれど、寝なければ終わるのでがんばります。
土日はなんもないぜ!!いえええええええい精進いええええええええええええええええい
DPとBFSに命を捧げようとおもいます!!!

って、テンションで乗り切ろうとしないようにね。丁寧に場合分け…(トラウマ)