はじめに
おぉ、勇者よ!
その目を見れば分かるぞ!そなたからは凄まじい意志を感じる……!コード書きたい、プログラミングしたいという熱い思いがひしひしと伝わってくるようじゃ……
さぁ!立ち向かえ勇者よ!
かの阿智暴虐の魔王を倒す旅に出るのじゃ!!!
チートシート
野村部長が作ってくれたチートシートです。困ったら見てみようsuper_python_Reiwa.md
問題1
問題文
12 月 30 日の M 時から次の年になるまでは何時間か、求めてください。
制約
- 1≦M≦23
- 入力は全て整数
入力
入力は以下の形式で標準入力から与えられる。
M
出力
12 月 30 日の M 時から次の年になるまでが x 時間のとき、x を出力せよ。
解答例
m = int(input())
print(48-m)
プログラム解説
1: 変数mに入力(数値M)を受け取る
2: 「48−m」を出力する
解説
分からなかったらまずは場合分けしてみるといいかも。
まず、Mが0の時を考えてみましょう。この時、12月30日0時〜1月1日0時なので、答えは48時間。
と、いうことは。Mが1なら始まりが1時間早まっただけなので答えは47時間。
Mが0の時48、Mが1の時47。つまり、48からMの数を引けば答えになります。
よって答えは48−Mです。
問題2
問題文
英小文字からなる文字列Sが与えられます。
Sの先頭からa文字目とb文字目を入れ替えて得られる文字列を出力してください。
制約
- Sは英小数字からなる文字列
- Sの長さ∣S∣は、2≤∣S∣≤10を満たす
- 1≤a≤b≤∣S∣
- a,bは整数
入力
入力は以下の形式で標準入力から与えられる。
S
a b
出力
答えを出力せよ。
解答例
s = input()
a, b = map(int, input().split())
a = a - 1
b = b - 1
print(s[: a] + s[b] + s[a + 1 : b] + s[a] + s[b + 1 :])
プログラム解説
1: 変数sに入力(文字列S)を受け取る
2: 変数aと変数bにそれぞれ入力(数値a,数値b)を受け取る
3: aの数値を1減らす
4: bの数値を1減らす
5: 「〜a番目のs + b番目のs + a+1番目〜b番目のs + a番目のs + b+1番目〜のs」を出力
解説
入力の仕方に○=int(input)以外のものが出てきました。2行目のmap(int,input().spilit())という形ですね。これらは入力の形により区別されます。
例:
S //のように、一行に1つならint(input)
a b //のように、一行に2つ以上ならmap(int,input().spilit())
詳しくはチートシートを参照してください。
さて、5行目がぱっと見た感じ意味不明ですよね。そう、この問題を解くためには、「スライス」の知識がないといけません。
しかし、「スライスは、シーケンス型オブジェクトの要素の範囲を指定して、新しくオブジェクトを作ることが出来る機能」…だなんて言われても(主に私が)わかるわけないので、ざっと説明します。
飽くまでもざっとなので正確性に欠けているかもしれません。許して。 そん時はだれか間違い報告よろしく
スライスのざっとした説明
例えば、s= [A, B, C, D, E]という配列があったとします。
この時、Bを表す場合はs[1]とできます。
sは配列の名前、[]の中には配列の順番が入ります。左から数え0スタートです。
配列 s= [A, B, C, D, E]
順番 s= [0, 1, 2, 3, 4]
なので、Cならs[2]です。
しかし、例えば「ABCD」を出力したいとなったとき、s[0]+s[1]+s[2]…とするのは大変です。この配列sならば簡単でしょうが、配列が長かったり長さが不明だったりすると厳しくなってきます。この問題2も長さは不明ですよね。
そんな時に使うのがスライスです。
「〇~〇まで」という、いわば配列の範囲指定ができます。
例えば、「ABC」を出力したい場合はs[0:3]とすればよきです。0~3番目という意味です。…あれ?おかしくない?0~3ならABCDになっちゃうじゃん!
そう。ここで注意すべき点があります。
実は、この時の[]の中身は配列の順番ではありません。
アイエエエ!?順番!? 順番ナンデ!?コワイ!
…簡単に言うと、スライス――つまりは[]の中に「:」を使う場合は区切った後の、その仕切りの順番が[]に入ります。
可視化するとこうです。
配列 s= [A, B, C, D, E] を区切る↓
区切ったとき s= [| A | B | C | D | E |]
区切った順番 s= [0 A 1 B 2 C 3 D 4 E 5]
この|の順番が[]に入ります。なので、s[0:3]が0~3の区切りなのでA~Cが当てはまるという訳です。
また、上限・下限なしでも使えます。例えばDEを表したい場合は3~なのでs [3:]、ABCDなら~4なのでs[:4]といった風に。
要するに「:」が「~」だと思えば大丈夫です。
スライスのざっとした説明を踏まえて
5行目の print(s[: a] + s[b] + s[a + 1 : b] + s[a] + s[b + 1 :]) について。
問題はsのa番目とb番目を交換しろというものでしたよね。なので一回sの配列をs[a]とs[b]を基準にして区切ります。
s = […… | a | …… | b | ……]
のような形になるのがわかるでしょうか。ここで、区切ったところの順番をつけます。
s = […… a a a+1 …… b b b+1 ……]
よって、〜a + a + a+1〜b + b + b+1〜 という風にsを表せるので、
s = s[〜a] + s[a] + s[a+1〜b] + s[b] + s[b+1〜] とできます。
赤下線部は配列の中の、青下線部はスライスの順番が[]の中に入るので注意。
これの~を:に直すと
s[: a] + s[a] + s[a + 1 : b] + s[b] + s[b + 1 :]となります。
問題ではs[a]とs[b]を入れ替えればよいので、答えは
s[: a] + s[b] + s[a + 1 : b] + s[a] + s[b + 1 :] だ!!
…と、思いますよね?よく見てください、解答例の3、4行目。aとbを1ずつ減らしてますよね?
そう、配列は0から数える。忘れてませんか?私は忘れてました。
a番目の文字とb番目の文字を、と言っているので実際にはこの数字をあらかじめ-1しておかなくてはいけません。(例えば、5番目の文字は数列の順番だと5-1=4番目。とてもややこしい。)
これを忘れたままやると、数が1つずれてしまうので、ちゃんとこの数え方は覚えておきましょう。(1敗) あと、スライスの時の数え方も。(5敗)
解答例2
s = int(input())
a,b = map(int,input().spilit())
print(s[: a-1] + s[b-1] + s[a : b-1] + s[a-1] + s[b :])
すごいコンパクト!ですが、あとで見直した時にわからなくなる可能性があるのであまりおすすめはしません。答えは同じなのでお好みでどうぞ。
問題3
問題文
3 つの正の整数 A,B,C が与えられる.
このうちある 1 つの値がそれ以外の 2 つの値の和になっているなら 1 を,そうでないなら 0を出力せよ.
制約
- 1≦A≦100.
- 1≦B≦100.
- 1≦C≦100.
- 入力される値はすべて整数である.
入力
入力は以下の形式で与えられる.
A
B
C
出力
ある 1 つの値がそれ以外の 2 つの値の和になっているなら 1 を,そうでないなら 0 を出力せよ.
結果以外は何も出力しないこと.(入力を促す文章なども出力しないこと.)
解答例
a = int(input())
b = int(input())
c = int(input())
if a == b+c or b == a+c or c == a+b:
print(1)
else:
print(0)
プログラム解説
1: 変数aに入力(数値A)を受け取る
2: 変数bに入力(数値B)を受け取る
3: 変数cに入力(数値C)を受け取る
4: 《もし「a=b+c」か「b=a+c」 か「c=a+b」なら》
5: 「1」を出力
6: 《そうでないなら》
7: 「0」を出力
解説
解説いるかな……?
答えはプログラム解説のままです。1つの数字が他の2つの和になっているかif文で確認しているだけです。注意すべき点があるとするならば、if文での同値は=ではなく==なところとか、and と or の間違いくらいかな…?
問題4
問題文
整数 A,B が与えられます。 AB の値を出力してください。
制約
- 1≤A , B≤9
- 入力はすべて整数
入力
入力は以下の形式で標準入力から与えられる。
A B
出力
答えを出力せよ。
解答例
a,b = map(int,input().split())
print(a ** b)
プログラム解説
1: 変数aと変数bにそれぞれ入力(数値A,数値B)を受け取る
2: 「ab」を出力
解説
解説いるぅ…?
一応。べき乗は「**」です。チートシートに他の特殊な演算子も載ってるので詳しくはそちらをば
ラスボス
問題文
JOI アイスクリーム店は,非常に高さのあるアイスクリームタワーが名物のアイスクリーム店である.アイスクリームタワーとは,ベースとなるアイスクリームの上に,追加のアイスクリームを0個以上積み重ねたものである.
ベースとなるアイスクリームの金額は 250 円で,高さはAcmである.追加のアイスクリームは 個につき 100 円で,1 個追加するごとにアイスクリームタワーの高さが Bcm 増える.
あなたは,この店で高さが Scm 以上のアイスクリームタワーを買いたい.高さが Scm 以上のアイスクリームタワーを買うために必要な金額の最小値を求めよ.
制約
- 1≦S≦100.
- 1≦A≦100.
- 1≦B≦100.
- 入力される値はすべて整数である.
入力
入力は以下の形式で標準入力から与えられる.
S
A
B
出力
高さ Scm 以上のアイスクリームタワーを買うために必要な金額の最小値を,単位 (円) を省いて出力せよ.
解答例
s = int(input())
a = int(input())
b = int(input())
if s <= a:
print(250)
elif (s - a) % b == 0:
print((s - a) // b * 100 + 250)
else:
print((((s - a) // B) + 1) * 100 + 250)
プログラム解説
1: 変数sに入力(数値S)を受け取る
2: 変数aに入力(数値A)を受け取る
3: 変数bに入力(数値B)を受け取る
4: 《 もし「s≦a」なら》
5: 「250」を出力
6: 《そうでなく、「(s–a)%b=0」なら》
7: 「(s – a) // b * 100 + 250」を出力
8: 《これら全てが当てはらないのなら》
9: 「(((s – a) // b) + 1) * 100 + 250」を出力
解説
まずは問題文の理解から。
- 【最初】高さ:A 値段:250
- 【追加】高さ:+B 値段:+100
- 【目標】高さ:S 値段:??
なんとなくどんな問題かわかったら場合分けをしていきましょう。
(ⅰ) s≦aの時
初めにSがA以下のときを考えましょう。
この時、最初の時点で目標を達成しているので追加料金はなし。
よって、初期費用のみで250円。
(ⅱ) (ⅰ)でないかつ (s – a) % b == 0の時
次に、S-AがBで割り切れるとき。
言い換えると、AからSまでの距離がBで割り切れる場合。
例えば、Aが10、Bが20、Sが50の時。
この時、AからSまでの距離は50-10で40。40は20で割ると2で割り切れるので追加料金は2×100で200円。これに初期費用の250円を足して合計で450円です。
よって、割り切れた場合は「S-AをBで割り切った数×100 + 250」円
(ⅲ) (ⅰ)でないかつ(ⅱ)でない時
最後に、S-AがBで割り切れないとき。
例えば、Aが5、Bが10、Sが49の時。
この時、AからSまでの距離は49-5で44。44は10で割ると4あまり4なので、まだSには届きません。なので+1の5回追加しなくてはいけません。追加料金は5×100で500円。これに初期費用の250円を足して合計で750円です。
よって、割り切れなかった場合は「(S-AをBで割った数+1)×100 + 250」円
最後に
おぉ、勇者よ!よくぞ魔王を倒した!
ここまでは長く苦しい戦いだったじゃろう…しかし、戦いはまだ終わっていない。まだ見ぬ世界がそなたを待ちうけておるのじゃ!
さぁ!立ち向かえ勇者よ!
再び、阿智暴虐の魔王を倒す旅に出るのじゃ!!!
ーto be continued?ー
コメント