メモ:ランチタイムCTFもくもく会 & 競プロランチ
最近は昼にCTFやりはじめて(今はpicoCTF2019やってる)、せっかくだし競プロランチとあわせてお昼休みのメモ残しとく。
CTF
caesar - Points: 100
ciphertext
の中身を見てみるとpicoCTF{dspttjohuifsvcjdpobqjtwtvk}
となってる。
問題名がcaesarだしシーザー暗号というやつっぽいので3つずらすのを試したら不正解だった。
結局26通り試してそれっぽいのを入力して通った。
dont-use-client-side - Points: 100
https://2019shell1.picoctf.com/problem/49886/
とりあえずソースを表示させたらpassを比較してるコードがあったのでそれを読んでパスを復元した。
logon - Points: 100
何も入力しないでSign In
してみるとログインはできるがFlagは表示されてない。cookieにadmin = False
という値があったのでこれをTrue
に変えてリロードしてみるとフラグをゲットできた。
strings it - Points: 100
strings strings | grep -i ctf
するとフラグがあった。
【 strings 】コマンド――バイナリファイルの可読部分を表示する:Linux基本コマンドTips(92) - @IT
vault-door-1 - Points: 100
ソースにあるcheckPassword
関数を見れば答えがわかった。
what’s a net cat? - Points: 100
netcatコマンドを使う。
$ nc 2019shell1.picoctf.com 49816
where are the robots - Points: 100
タイトル的にrobots.txtかなと思ってURLの最後に/robots.txtをつけてみたら
User-agent: *
Disallow: /0ecd0.html
こうなっていたので/0ecd0.html
にアクセスするとフラグがあった。
競プロ
A - Placing Marbles
1文字ずつ数値にして足したら光が見えた…。
提出 #10191239 - AtCoder Beginner Contest 081
puts gets.strip.chars.map(&:to_i).inject(:+)
B - Choose Integers
急に5000兆とかでてきて「は?欲しい」て感じだけど、足すのは常にAの倍数なので結局余りは周期的になるからb
を上限にして試してみれば光が見えた…。
提出 #10191425 - AtCoder Beginner Contest 060
a, b, c = gets.strip.split.map(&:to_i)
puts (1..b).any? {|i| i * a % b == c} ? "YES" : "NO"
これほんと、“Yes/No”で提出してて1WAくらった。これでぼくはまだビギナーですと胸を張って言える。なんかツールとか使ってたら防げるのかもしれないけど。使ってないのがばれてしまう。原始的にコピペしてサンプルケース試してるとかが。
C - Same Integers
まず+2
できるだけする。そのあとのパターンとしては、
- 一番大きな数より1小さいものが1つ
- 一番大きな数より1小さいものが2つ
- 3つとも同じになってる
のどれか。
最初の入力が1 6 3
だったとすると、できるだけ+2したあとは5 6 5
になってる。
このとき、上の1
のパターンで、ここから等しくするためには
5 6 5
↓ (+1 0 +1)
6 6 6
ということで、あと1回の操作でできる。
今度は最初の入力が2 6 3
だったときを考えると、できるだけ+2
したあとは6 6 5
になる。
このとき、上の2
のパターンで、ここから全て等しくするためには
6 6 5
↓ (+1 +1 0)
7 7 5
↓ (0 0 +2)
7 7 7
ということで、2回の操作が必要。
この2つのパターンをどう見分けるかがキモになる。
結局は、できるだけ+2
するという操作のあとでも偶奇は変わらないのがポイントで、一番大きい数と、それ以外の数(+2
する数)の偶奇の一致をみて、いくつ一致してるかによって場合分けすればおけ丸水産。はくつるです。
提出 #10191714 - AtCoder Beginner Contest 093
a, b, c = gets.strip.split.map(&:to_i)
min, mid, max = [a, b, c].sort
ans = (max - mid) / 2 + (max - min) / 2
p = [(max - mid) % 2, (max - min) % 2].inject(&:+)
if p == 1
puts ans + 2
elsif p == 2
puts ans + 1
else
puts ans
end
変数をp
とかやるのよくない。
あとこういう
p = [(max - mid) % 2, (max - min) % 2].inject(&:+)
雑に配列にしてsumするのよくやるけど行儀がよくないだろうなと思いながらも癖で書いてしまう。
C - Write and Erase
偶数回登場する数字は打ち消しあってカロリーゼロになるから、奇数個登場するやつを数えればいいような気がして、AC。
提出 #10196043 - AtCoder Beginner Contest 073
n = gets.to_i
an = n.times.map { gets.to_i }
puts an.group_by(&:itself).select { |k, v| v.size.odd? }.count
これなんかもっといい書き方あるのでは?という気もしてる。group_by
のコストいかほど?
ランチタイムにあんまりがんばるとお昼から余計に眠くなっちゃうから緩さを心がけたいけども思わず熱中しすぎて昼から脳が完全に沈黙することもありますここだけの話。