れとろのメモ置場

とあるSEのメモ置場

GPUを使ってOpen-Interpreterを動かすコンテナを作ろうとしたら苦労した話

DockerコンテナでOpen-Interpreterを動かせるようになったけどどうやらCPUだけで処理してるみたいだったので、GPUを使って動かせるようにするために四苦八苦したことをメモしておこうと思う。

前提

  • Dockerでコンテナを作ってその中でOpen-Interpreterを動かす。
  • Docker Desktopを動かしているマシンは、OSがWindows11、グラボは載せてある。

やりたいこと

  • コンテナにGPUを認識させる
  • Open-Interpreterの実行時にCPUじゃなくてGPUを使わせる。

やったこと

  1. コンテナにGPUを認識させる
  2. コンテナにCUDAをインストールする
  3. 公式のドキュメントをみながらllama-cpp-pythonをインストールする

コンテナにGPUを認識させる

少し前?にコンテナにGPUを共有するオプションができたらしく、コンテナにGPUを認識させること自体は簡単だった。 コンテナを作るときに--gpusというオプションをつけるだけで良いらしい。 gpusの後ろはどれくらいリソースをコンテナに渡すかのパラメータらしい。とりあえずallとつけておけばPCについているGPUを全部コンテナと共有できる。

docker run --gpus all -it イメージ名 bash

コンテナにCUDAをインストールする

正直やり方がはっきりせず結構大変だった。
公式のインストール方法を試すのが1番正解な気がしたけど、コンテナのOSにではwgetがインストールされていないし、インストールしようとしてもエラーが出てインストールできなかった…
CUDA Toolkit 12.2 Update 2 Downloads | NVIDIA Developer

最終的にNvidiaが公式に用意しているcudaがインストール済みのコンテナイメージを使って、すでにCUDAがインストールされているコンテナを使うことにした。
たぶんこれが1番早い。

https://hub.docker.com/r/nvidia/cuda

公式のドキュメントをみながらllama-cpp-pythonをインストールする

open-interpretrのgithubをみてみるとGPU.mdっていういかにもGPU使って動かしたい人向けのreadme的なものがあったので見てみた。
内容はwindows環境でGPUを使ってopen-interpreterを動かす手順についてで、結論としては

python -c "from llama_cpp import GGML_USE_CUBLAS; print(GGML_USE_CUBLAS)"

を実行したときにTrueが返ってくるように、色々設定しながらでllama-cpp-pythonをインストールすれば良いっぽい。

https://github.com/KillianLucas/open-interpreter/blob/main/docs/GPU.md

python -c "from llama_cpp import GGML_USE_CUBLAS; print(GGML_USE_CUBLAS)"がTrueになるかどうかでOpen-interpreterGPUを使ってくれるかどうかが決まるみたい。 ドキュメントで紹介されている手順の流れとしては以下の通り。

  1. CUDAをインストールする
  2. 環境変数を設定しつつllama-cpp-pythonをインストールする
  3. python -c "from llama_cpp import GGML_USE_CUBLAS; print(GGML_USE_CUBLAS)"でインストールが上手くできているかを確認

その他

コンテナはNvidiaが用意したCUDAインストール済みのイメージを使ったので、Pythonがちょっと古かった。 そこでここをみながらPythonのバージョンアップをした。

それでもpip install open-interpreterを実行するとERROR: Could not find a version that satisfies the requirement open-interpreter (from versions: none)とエラーが出てうまくインストールできなかった。 色々調べてると下のサイトに辿り着いてその中で書かれているpip install open-interpreter --ignore-requires-pythonを実行するとインストールができた。

Could not find a version that satisfies the requirement open-interpreter · Issue #38 · KillianLucas/open-interpreter · GitHub

おまけ

とりあえずopen-interpretrがGPUを使ってくれるようにはなった。でもクエリを投げてもエラーで落ちててうまく動いてない。
エラーの内容的に古い方のPythonを使っているっぽいのでaliasの設定がうまくできてないのかなあ…

追記

現時点で最新のopen-interpreterだと起きるバグっぽい…

github.com

参考

コンテナ内で GPU を使う (Windows 環境) – すらりん日記

Dockerで計算用途で使うときのオプションのまとめ - Qiita

Windows 11のWSLとDocker DesktopとGPUを使用したDeepLearning環境の構築方法(超便利になった!!) - Qiita

open-interpreter/docs/GPU.md at main · KillianLucas/open-interpreter · GitHub

UbuntuにインストールされているPythonをアップデートする - 自動化無しに生活無し

Could not find a version that satisfies the requirement open-interpreter · Issue #38 · KillianLucas/open-interpreter · GitHub

ERROR: Could not find a version that satisfies the requirement open-interpreter (from versions: none) · Issue #170 · KillianLucas/open-interpreter · GitHub

サントリープログラミングコンテスト2023(AtCoder Beginner Contest 321)

サントリープログラミングコンテスト2023(AtCoder Beginner Contest 321)に参加しました。

結果

A,B,C,Dの4問正解でした。

C問題でそこそこ時間を使ったのが痛かった。 E問題はちょっとしか時間が取れなかったから解ききれなかった。

A - 321-like Checker

与えられた数値の各桁が狭義単調減少になっているかどうかを判定する問題。

数値を文字列として受け取って上から1桁目から順番に次の桁の値と比較して判定していった。
charで'0'から'9'のどれかだから上からx桁目とx+1桁目を直接比較しても問題ないと思うし、数値にしたいならcharの値から'0'を引いてあげれば0~9の数値に変換できる。

数値として処理したいなら、2桁以上の場合は 10で割った余り(下から1桁目)と100で割った余りを10で割ったもの(下から2桁目)を比較してみて、OKなら元々の数を10で割ってまた比較をするって具合に繰り返していけば良い。

B - Cutoff

数値がN個ある時、ソート済みの数列の最初と最後以外を足した値(スコア)について考える。 N個中のN-1まで数列が与えられたときにN個目の値はいくつ以上ならスコアがX以上になるかどうかを答える問題。

N個目の値が取りうる値は最大でも100程度なので0の時から100の時まで全通り探索して答えを求めれば良い。

値によって以下の3パターンが考えられるので、どれに該当するか判定して最終的なスコアを計算する。

  • 最小値を更新する
  • 最大値を更新する
  • 最大値、最小値に影響しない

計算したスコアがXを超えれば、その時考えているN個目の値が解の候補になる。

スコアの計算用に、N-1個の数列をソートしたものの最初と最後以外の値を合計しておけば、N個目の値を決めたときのスコア計算が楽になる。

C - 321-like Searcher

A問題でみた各桁が狭義単調減少となっている数値の中からK番目に小さいものを答える問題。

TLEとかMLEとかCEとかいろいろエラーになってその度に解き方の方針を考え直した。

案1

  • 考える範囲は最大でも9876543210なので1から順番に条件を満たすかどうか判定して、条件を満たすもののK番目を探す。

最大値が10 ^ {9}なので、そこまで探索することになるならTLEするだろうなと思いつつ提出したらTLEになった。

案2
案1から無駄な部分を削ぎ落とそうとした。

  • 案1同様1から順番に全探索する。
  • ある値が条件を満たすかどうかの判定は、上記A問題の数値として処理したい場合の考え方の方針で実装する。
  • 1度条件を満たさないとなったものはメモしておき、10で割った後に下1桁目と2桁目を求めて判定を始める前にその値がメモにあるかどうかを確認する。メモに登録のある値ならそれ以降の桁の判定は時間の無駄なので省略する。

メモ用にサイズが9876543210の配列をboolで用意しようとしたらメモリを使いすぎてMLEになったり、コンパイルエラーになったりした。

案3

  • 条件を満たすある値があるとして、条件を満たすように1桁追加したものをqueue/stackに追加していく幅優先探索深さ優先探索を行う。条件を満たす値すべてを洗い出した後にソートし、K番目のものを答える。

最初に0~9をqueueに入れてそれらを初期として幅優先探索を行った。 とりあえずこの方針で解けた。

最初に思いついた方針だと全然だめだったので少し遠回りしたのが時間的に痛かった。

D - Set Menu

N個あるA _ {i}とM個ある B _ {j}全通りの組み合わせで足し算をして  min(A _ {i} + B _ {j}, P)の総和を求める問題。

足すのはPじゃなくてA _ {i} + B _ {j}として手元で計算してみると各A _ {i} はM回足されていて、各 B _ {j}はN回足されていると気づいた。

このM回、N回のうちの何回かが代わりにPになる。

A _ {i}に対してM個ある B _ {j}のいくつが足したときにP以上になるのかを数えていき、 P以上にならない回数だけA _ {i} B _ {j}を足して、最後に数えていたPになる回数分Pを足した。

 B _ {j}をソートしておけば二分探索でP以上になる B _ {j}の境目が高速に探索できる。

話題のOpen Interpreter用にDockerでコンテナを作ろうとしたら詰まった話

最近すごいらしいと噂を聞くOpen Interpreterを触って見ようと思ったので、コンテナを作ってそこで動かしてみようとしてみた。
Dockerfileを作ってビルドして、いざコンテナを作って接続しようとするとすぐにステータスがExitedになってうまくいかなくて困ったなとなったので、原因とかトラブルシューティングに役立ったものをメモしておこうと思う。

とりあえず結論

同じ問題にまた遭遇してとりあえず対処法だけ知りたい時用に最初に直し方を書いておく。
結論としては、以下を実行してコンテナを作成する。

docker run -ti イメージ名

コンテナ名も指定したい場合は
docker run --name コンテナ名 -ti イメージ名

Docker Desktopのイメージ一覧横にある再生ボタン的なのを押してコンテナが作れたと思ったけど、今回やってみるとうまく行かなかった。

イメージからコンテナを作る時はCUIのコマンドからじゃないとできないのかな?
Dockerは業務も含めてでほとんど触ったこと無いからよく分からないや…

症状

  • Docker Desktopのイメージ一覧横にある再生ボタン的なのをおしてコンテナを作ったつもりだったけど、ステータスが即Exitedになってコンテナがうまく動かない
  • コンソールからコマンド実行でコンテナを作ってるつもりだけど、同じく即ステータスがExitedになる。

参考

おまけ Open Interpreterをちょろっと触ってみた感想

Open Interpreterすごいという記事が多いのでどんなものかなと思ったけど、 軽く触った所感だとそこまですごいとは感じなかった。

たしかに、エージェントにローカルのファイルを渡せたりするっぽいのはすごく便利だし、そのファイルを解析とかしてくれるのは使い方次第で化けるとは思う。
けど、それってChatGPT-4でもできることだし、ChatGPT-4じゃないLLMをローカルにダウンロードして動かすパターンだと、まあLLMってこのくらいのことしかできないよなって思う程度の性能だった。

世の中のOpen Interpreterすごいって記事はChatGPT-4を使っている記事ばかりな気がするので、正しくはChatGPT-4すごいってことなんだと思う。

デスクトップPCを自作してみた

数ヶ月前にPCを自作してみたのでまとめて見ようと思います。
自作するのはこれが2回目で、1回目に作ったPCのスペックがちょっと物足りないなとなってきたのでできる限りパーツを流用して1台目の自作PCを作り替えてみました。

パーツ

今回作ったPCのパーツはこんな感じです。ほぼどれにするかは決めておいてからツクモに行って買いました。

候補がいくつかあってどうしようかなと思っている部分は店員さんに相談して決めました。店員さんの説明は丁寧だったし説明自体も下調べしていた内容と相違なかったので、相談したかった部分やちょっとした質問の回答もかなり信用できた。 個人的にはPCショップの中だとツクモが好き。

型番 備考
CPU i5-13600K
マザーボード ASRock Z790 Pro RS/D4
CPUクーラー DeepCool AK400
ストレージ SSD 1TB+旧PCからの流用
グラフィックボード RTX3070 旧PCからの流用
メモリ DDR4 32GB
電源 旧PCからの流用
ケース Fractal Design Core2500 旧PCからの流用
OS Windows11

パーツ決めの方針

前のCPUがi5-7500で、ゲームとかマルチタスクとかしてると性能が足りないな感じたりコア足りてないから全体がちょっと止まってるみたいなことがチラホラあったので、主にCPUのスペックアップを軸としてミドルレンジくらいのスペックを目指してパーツを選びました。

もともとCPUを新しくしたいだけだったけど、CPUが変わるとソケットが変わるからマザーボードも買うことになり、CPUにはCPUクーラーが付属しないのでCPUクーラーを買い、あとはOSのライセンスだったり、旧PCのOSはバックアップ用に残しておきたいからOS用にストレージを買ったり、結局新規に1台自作するのとさほど変わらない程度のパーツを買うことになった。

CPU

ホントはハイエンドにしたいなと思ったけど、13世代i-7以上だとCPUクーラーは水冷じゃないと排熱が追いつかないらしいしPCケース的に水冷はちょっと厳しそうだったので空冷でもぎり使える13世代i-5にしました。
HDDがなかったら水冷も使えるらしいけど旧PCのデータやバックアップをHDDに入れてるから水冷は諦めた。

CPUクーラー

最近のCPUクーラー界隈は空冷ならDeepCool一択という風潮らしい。コスパ良いし空冷の中ではよく冷えるらしい。
あと、ノベルティ?かなにかでDeepCoolのロゴが入ったTシャツが貰えた。

公開されているヒートシンクの高さとPCケースのどれくらいの高さのCPUクーラーに対応しているかを確認して候補をいくつか選んでいたけど、 CPUクーラー全体の高さってヒートシンクのサイズ+ヒートシンクとCPUとの接触面との距離部分になるから、単純にヒートシンクの高さだけみてるとケースに収まりきらないかもしれない。 ヒートシンクとCPUとの接触面との距離のことはすっかり忘れてたから危うくCPUクーラー買い直しか、ケースの蓋を常時開いておかないと行けないところだった。 指摘してくれた店員さんに感謝。

メモリ

メモリは旧PCのものを流用しようと思っていたけどPCショップの店員さん曰く、同じDDR4でもクロック数が数年前よりも上がっているので、できれば最近のクロック数高めのものにしたほうが良い。後で買い足すなどによりクロック数がぜんぜん違う新旧のメモリで複数枚刺しすると不具合が起きる可能性があるとのことだったので、旧PC流用+物足りなかったら買い足しの予定だったのを新しく2枚買うに変更しました。

マザーボード

マザーボードは、ストレージの大半を旧PCから流用する関係でSATAコネクタの数が最低いくつという基準があり、メモリもDDR4のものを流用するつもりでいたので、そのあたりの基準を満たすマザーボードいくつかに絞ってその中から選びました。PCショップに買いに行って店員さんに相談しながら最終的には決めました。

CPU用の電源回路周りのヒートシンクでっか!

組み立て

確かこんな手順で組みたっていった

  1. CPUの取り付け
  2. メモリの取り付け
  3. SSDの取り付け
  4. CPUクーラーの取り付け
  5. ケースに入れる
  6. 電源とかHDDとかの結線
  7. OSのインストール

CPUの取り付け

たぶん自作する時に1番緊張するところ。失敗してピンが曲がるとマザボがただのごみになる。

ここを

こうして

CPUの向きを気をつけて取り付けて

固定する。

メモリの取り付け

どのスロットにメモリを挿せばいいか確認して、ちょっと硬いかもしれないけどためらわずに力いっぱいメモリを挿し込む。
1台目自作した時はメモリが半挿しだったので、電源を入れても何も反応しなくて焦った。

マザボの説明書を読んで、どんなスロットの組み合わせで取り付けるか確認して、

マザボにも各スロットの番号が書かれてたから確認して

持っているメモリの枚数に合わせて取り付ける。

SSDの取り付け

SSDのスロットが3つあって、どこにつければいいのか悩んだ。マザボの説明書で説明しているところを探して、たぶんここって部分に取り付けた。

マザボによってはSATASSDスロットの信号線?が共通になっていて、このSSDスロットを使うとこのSATAコネクタは使えないとかある。 なので、どのSSDスロットを使うかはちゃんと確認して選ぶ。

CPUクーラーの取り付け

CPUクーラーの説明書をみながらバックパネルとかどのパーツを使って固定するとか確認してマザボに取り付けた。

思ったよりでっかかった。

ケースに入れる

本当はケースに入れる前に1度電源を繋いで起動確認したほうが良いのだけど、面倒だったので起動確認無しでケースに取り付けた。

電源とかHDDとかの結線

たぶん自作で1番面倒。
ただケースが小さいからやり辛いだけかもしれないけど。

OSのインストール

Windows11をインストールしました。 ネット環境とマイクロソフトアカウントが必須で面倒くさくなったなあと思った。

あと、しばらく使ってから気づいたけどドキュメントフォルダなどのデフォルトの場所がOneDrive内部になってて、知らず知らずの内にOneDriveのストレージを消費させられてた。
なんかヘイトを買うようなこと平気でするようになったんだとかなりがっかりした。

一応、従来どおりローカルストレージ上に設定変更する手順はネットで見つけられたので、フォルダの位置をOneDriveじゃなくてローカルのストレージ内に移動させておいた。
正直その手順もそこそこ面倒だった。マイクロソフトどんどん改悪していくなあ。

感想

久々に自作PCを組み立ててみると楽しいけどちょっと大変だったな。

1番楽しいのはパーツをどうしようかなと考えてる時だった。

最近はストレージにはHDDではなくSSDで全部済ます風潮らしいので、PCケースもHDDの取り付けは考えていない作りになっているらしい。 今までは早さはいらないデータの保存はHDDで済ませていたけど、ゆくゆくはSSDに入れ替えようかな。(今使っているHDDの処分方法に困るけど)

前に自作した時はなかったけど、今回は自作関係のパンフレット?がもらえた。 自作の組み立て手順的なものとかが説明されてて、親切になったなと思った。

トヨタ自動車プログラミングコンテスト2023#5(AtCoder Beginner Contest 320)

トヨタ自動車プログラミングコンテスト2023#5(AtCoder Beginner Contest 320)に参加しました。

結果

A,B,C,Eの4問正解でした。

D問題は問題文を斜め読みすると難しそうな気がしたので後に回して、Dより簡単そうに見えたE問題から解くことにした。

D問題自体も問題分をちゃんと読むと思ってたより難しくなさそうだった。

A - Leyland Number

指定されたとおりに数値計算する。

指数計算が必要なのでpowを使って楽に解いた。
powを知らなかったならループで頑張ってBをA回掛けたり、AをB回掛けたりすれば解ける。

ループと数値計算がわかっていれば解ける問題。

B - Longest Palindrome

文字列が与えられるので回文となっている部分の最長の文字数を答える問題。

文字列は100文字以下なので部分文字列全通りに対して回文かどうか確認しても処理時間的には余裕で間に合うので、全通り確認した。

具体的には、元の文字列に対して部分文字列の最初と最後はそれぞれ何文字目かで二重ループを回した。

部分文字列の最初と最後は元の文字列の何文字目かをもとに部分文字列を作って、別途用意しておいた、渡された文字列が回分かどうかを判定する関数で判定させた。

C - Slot Strategy 2 (Easy)

3つのリールのスロットがあるのですべてのリースを同じ目にするには最速何秒かかるかを答える問題。

どう解こうか悩んだ結果、全通り探索することにした。
複数のリールを同時に止めることはできないけど、運が悪くても最大3周するまでには全部のリールを止められる。 リールは最大でも長さが100なので、300秒以内のどこかに答えがある。

0秒から3*リールの長さの範囲での3重ループで探索した。 各ループはそれぞれのリールに対応していて、 それぞれのタイミングでそれぞれのリールを止めた時、3つが揃っているかどうかを確認して、揃っているなら1番最後にリールを止めた秒数が答えの候補になる。

D - Relative Position

時間が足りなくて解ききれなかった問題。

座標平面上に人がいて、この人からみてあの人はx軸正方向でX、y軸正方向でY離れているという情報が複数あるときに、それぞれの人の座標を答える問題。

最初に問題文を斜め読みした時は正方向というのを見逃していたので、人がいる候補が4つもあって特定するのは難しそうだなと思ってた。

実際は正方向なので一意に絞り込めるので、そこまで難しくなかった。

人1は原点にいるので、情報がある2人は繋がっている無向グラフとしみなして、 人1から深さ優先探索幅優先探索をしていけば解けそうと考えた。

E - Somen Nagashi

先頭の人が必ず全取りするけど、1度食べたらしばらく食べないと言う設定の流しそうめんで誰がどれくらい食べたかを答える問題。

設定は以下の通り。 - 人は番号順に並んでいる。 - 時刻T _ {i}にそうめんが流れてきて、食べるとS _ {i}秒後に戻ってくる。 - 列の先頭の人が全取りするけど、食べるとしばらく列から離れる。
戻ってくる時は列の元の位置に戻ってくる。

時間が10 ^ {9}秒後までありえるので1秒ずつのシミュレートでは時間がかかりすぎる。なので、イベントドリブンでシミュレートして解くことにした。

実装方針としては

  • 人の列は優先度付きキューで管理する。常に列の先頭の人がそうめんを全部食べるので。
  • イベントは発生する時間とイベントの種類(そうめんが流れるか人が列に戻ってくるか)、イベントの種類に応じた必要な情報(列に戻ってくる時間や流れてくるそうめんの量、列に戻ってくる人の番号)をタプルにして優先度付きキューに入れて時間別イベントの種類別にソートして管理する。

イベントドリブンのシミュレートを知っていれば多分簡単に解ける問題。

AtCoder Beginner Contest 319

AtCoder Beginner Contest 319に参加しました。

コロナに罹って1週間位寝込んでからの療養で2週間くらい体調を崩していたり、予定があって参加できなかったりで1ヶ月ぶりくらいのAtCoderでした。
久々で全体的に鈍ってる感がすごかった。あと、ここ1ヶ月くらい業務でPythonしか書いてないからC++の書き方忘れてた。 これはリハビリが必要そう。

結果

A,Bの2問正解でした。

久々でいろいろ鈍ってる感じはあるけど、C問題も解けなかったのがちょっとショック。

C問題がなんか難しかった。
D問題は2分探索を駆使すれば解けると思うけどちょっとバグらせてて、バグ取りで時間がなくなった。

A - Legendary Players

文字列が渡されるから、それに対応する数値を出力する問題。

Pythonだと辞書を使えば一発だなあと思いながら、普段のC++だとどう書いてたっけと思いながらif文を10個並べて解いた。

B - Measure

問題文のとおりに処理を実装して解く問題かなあ。

約数列挙が必要かなと思いきや9以下の約数だけが知りたいので、1~9でNを割り切れるものを探せばいい。
約数が一通り分かれば、0~Nの範囲でiがN/約数で割り切れるかどうかを確認して、 割り切れるならその中で最小の約数をiごとに保存しておく。 最後にiごとに結果を出力すればいい。

C - False Hope

ビンゴ?スロット?がテーマな問題。
3×3のマス目にランダムに数字が振られてて、縦横斜めで同じ数字が1列に揃うことはないときに、ランダムにマス目の内容が教えられ 2マス揃って3マス目は揃わなかったと言う状況にならないマスの開き方は何通りあるかを答える問題。

決して1列揃うことは無いのがちょっと悲しい…

9マスの開き方は9!通りでそれほど大きな値じゃないので多分全通りの確認ができる。 なので、ある順番でマス目を開いていくときに条件を満たすかどうかを判断していけば答えられそうだと思った。

条件を満たすかどうかの部分を関数に切り出して処理しようと思ったけど、うまく実装できなかった。
どこかでバグらせているのか、そもそも考え方が悪いのか…

D - Minimum Width

N個の英単語を画面に表示させようとしている。M行で全部表示できた時、画面の横幅としてありえる最小値はいくつかを答える問題。

横幅が小さいうちはM行以上になって、ある閾値からはM行で表示できるようになるので、2分探索でその閾値を探せば良いと思う。 横幅を仮にXとした場合に、全部で何行で表示できるかを計算してM行以下にできるかどうかで2分探索の更新内容を判断すればよいかなと思った。

横幅をXとしたときに単語列を何行で表示できるかは競プロ典型90問でほぼ同じ問題( 001 - Yokan Party(★4))があったと思いながら、この部分だけを処理する関数を作って処理を分割しておいた。

一通り実装してみてサンプルを解いてみたけどすごく遅かった… 二分探索に二分探索を重ねているのが悪いのか、それとも何かの処理が遅いのか…

AtCoder Beginner Contest 314

AtCoder Beginner Contest 314に参加しました。

結果

A,B,C,Dの4問正解でした。 E問題は問題文を読んでDPっぽいなあと思いました。カテゴリ的には確率DPとか期待値DPとか呼ばれる分類の問題かなと思って、考え方をググってました…
期待値DP難しい。 E問題はdiffが水色くらいかなと思ったけど青くらいあるっぽい。

A - 3.14

小数第100位までの円周率が与えられているので、指定された小数第N位までを出力する問題。

小数第100位までを数値系の変数で管理するのは無理そうだと思ったので文字列で対応することにした。 (C++で解いてるけど、doubelを使っても誤差がでそう。)

文字列として考えると、3.以降のN文字を出力すれば良くなるので 先頭からN+2文字の部分文字列を出力するだけの問題に置き換わる。

B - Roulette

ルーレットでN人がそれぞれC _ {i}個の出目に賭けたから、当てた人のうち賭けた出目が最小の人を番号順に出力する問題。

map[人i][出目]=賭けた/賭けていない を管理して、 当てた人だけを対象に賭けた出目数の最小値を探して、 当てた人だけを対象に賭けた出目数=最小値となった人を順番に出力していけば良い。

C - Rotate Colored Subsequence

文字が何種類かの色で塗られている文字列があるので、同じ色の文字内で1文字ずらしてできる文字列を答える問題。
aXbcYZという文字列で赤青赤赤青青となっていれば 赤のabc内で1文字ずらしてcbaになって、青のXYZ内で1文字ずらしてZXYになって、答えるのはcZabXYになる。

色別に配列を用意して対応する文字を順番に入れていき、 文字列の色の順番に合わせて各配列の文字を順番に出力していった。 文字列を出力する際、この色は配列の何番目を出力するっていうインデックスを色別に管理しておいて、そこを参照して その色用の配列の何番目を出力するというのを制御していた。 インデックスの初期値を-1にしておいて、出力する際は(インデックス値+その色の文字数) mod その色の文字数ってすることで N個要素がある場合にN-1、0,1,・・・N-1、0,1,・・・と配列の最後から順番に循環して参照できるようになる。

D - LOWER

文字列が与えられるので1文字置き換えるか全部小文字にするか全部大文字にするかの操作をQ回繰り返した結果を出力する問題。

文字列を全部大文字/小文字にするのは処理が重そうで操作のたびに実行してたらTLEする気がした。 そもそも1回小文字に変換してもその後また小文字に置き換えたり大文字に置き換えたりするかもしれないので、最後の1回以外は無視しても大丈夫なので無視した。
最後に大文字/小文字に置き換える処理が何回目の処理なのかを探索して、
その回数までは1文字置き換える処理だけを実行し、
その段階の文字列を大文字/小文字に置き換えて、
そこから先の処理(1文字置き換えのみ)は指示通りに実施して、結果を出力した。

E - Roulettes

問題文を読んでDPだろうなあと思った。DPの中でも期待値DPとか呼ばれてた気がするジャンルの問題だと思って、 考え方をググって色々な記事を読んでた。 解き方がまだ理解しきれていないから後でゆっくりでも解いておきたい。