火山島でコーヒー
これは競技プログラミングだ
目次
難易度:C
火山島
問題
コーヒーメニューに記載される S, M, L サイズの値段と、その日に注文されたサイズが与えられるので、売上の合計を出力するプログラムを作ってください。
例:S=100,M=200,L=300
- SS 50
- S 100
- M 200
- L 300
- LL 600
入力される値
入力は標準入力にて以下のフォーマットで与えられます。
N S M L o_1 o_2 ... o_N
回答その1
n = int(input()) money_s, money_m, money_l = map(int, input().split()) money_2s = money_s // 2 money_2l = money_l * 2 sum = 0 for _ in range(n): order = input() if order == "SS": sum += money_2s elif order == "S": sum += money_s elif order == "M": sum += money_m elif order == "L": sum += money_l elif order == "LL": sum += money_2l print(sum)
回答その2
n = int(input()) small, medium, large = map(int, input().split()) prices = {"SS": small // 2, "S": small, "M": medium, "L": large, "LL": large * 2} total = 0 for _ in range(n): order = input() total += prices[order] print(total)
参考
map,split
Pythonで文字列から数値を取り出してそれぞれの変数に代入するには、以下のようにsplit()
関数と多重代入を使用します。
s = "100 200 300" a, b, c = map(int, s.split())
上記のコードでは、まずsplit()
関数を使って空白文字で文字列s
を分割しています。結果は文字列のリストになります。次に、map()
関数を使用して、このリストの各要素をint
関数で整数に変換します。最後に、多重代入を使用して、これらの値を変数a
、b
、c
にそれぞれ代入します。
この結果、a
は100、b
は200、c
は300になります。
以下に、Pythonのmap()
関数とsplit()
関数の説明、引数、および戻り値についてまとめた表を示します。
関数 | 説明 | 引数 | 戻り値 |
---|---|---|---|
map() |
この関数は、第一引数として指定された関数を、第二引数として指定されたイテラブル(リストやタプルなど)のすべての要素に適用します。 | 1.適用する関数 2.イテラブル | 適用された関数の結果を含むイテラブル(mapオブジェクト) |
split() |
この関数は、文字列を特定の区切り文字(デフォルトは空白)で分割します。 | 1.区切り文字(オプション) 2.分割数の最大値(オプション) | 分割された文字列のリスト |
map()
関数の例:
numbers = ["1", "2", "3"] numbers = list(map(int, numbers)) # [1, 2, 3]
split()
関数の例:
s = "Hello, world" words = s.split() # ["Hello,", "world"]
map()
関数はPythonの組み込み関数で、他の関数とイテラブルを引数に取り、そのイテラブルの各要素に対して関数を適用します。
split()
関数は文字列メソッドで、文字列を特定の区切り文字で分割し、その結果のリストを返します。
error ' '
エラーメッセージValueError: invalid literal for int() with base 10: ' '
は、Pythonが空白文字(' '
)を整数に変換しようとしたときに発生します。空白文字は整数ではないため、このエラーが発生します。
あなたが書いたコード:
n = int(input()) money_s, money_n, money_l = map(int, input()) print(n) print(money_s)
ここで、map(int, input())
は、ユーザーからの入力を取得し、それを空白で分割せずにmap
関数で整数に変換しようとします。しかし、ユーザーが空白を含む文字列(例えば"100 200 300"
)を入力すると、その入力全体を一つの整数に変換しようとするため、上記のValueError
が発生します。
この問題を解決するには、ユーザーからの入力を空白で分割してから整数に変換する必要があります。つまり、input().split()
を使用します。以下に修正したコードを示します:
n = int(input()) money_s, money_n, money_l = map(int, input().split()) print(n) print(money_s)
この修正により、ユーザーが"100 200 300"
のように空白で区切られた数値を入力すると、それらが適切に整数に変換され、それぞれの変数に割り当てられます。
ループのアンダースコア _
もしループ内で変数i
が必要ない場合、Pythonでは慣習的にアンダースコア _
を代わりに使うことがあります。このようにすることで、その変数がループ内で使われないことを明示的に示すことができます。
例えば、何かを5回繰り返すには次のように書きます:
for _ in range(5): print("Hello, world!")
このコードは"Hello, world!"を5回表示します。ここで _
はループカウンタとして機能しますが、ループ内で実際に使われることはありません。
この慣習は、ループ内でイテレータ変数が不要な場合、特にその変数を省略したいという時に有用です。
回答その1の改善点
以下、コードの改善点について述べます:
変数名の明示性:
money_s
,money_m
,money_l
などの変数名は少し抽象的です。可能であれば、これらの変数が何を表しているのかもっと明示的にすると良いでしょう。変数
sum
の命名: Pythonではsum
は組み込み関数であり、そのため一般的にはこの名前を変数に使用することは推奨されません。別の名前を選ぶことで、混乱を避けられます。ディクショナリの使用: 各
order
に対応する金額をディクショナリに保存すると、コードがより簡潔になります。if-elif
構造よりも効率的になることもあります。
以下に、これらの改善点を反映したコードを示します:
n = int(input()) small, medium, large = map(int, input().split()) prices = {"SS": small / 2, "S": small, "M": medium, "L": large, "LL": large * 2} total = 0 for _ in range(n): order = input() total += prices[order] print(total)
このコードでは、各注文の種類("SS"、"S"、"M"、"L"、"LL")をキーとし、その注文の金額を値とするディクショナリprices
を作成しています。ループ内では、このディクショナリを使って各注文の金額を直接取得し、合計金額に加算しています。
ディクショナリ
Pythonのディクショナリ(辞書)は、キーと値のペアを格納するデータ構造です。ディクショナリはハッシュマップまたは連想配列とも呼ばれ、キーを使用して値に迅速にアクセスすることができます。ディクショナリは中括弧 {}
を使用して定義され、キーと値はコロン :
で区切られます。
以下に、ディクショナリの作成と使用の基本的な例を示します:
# ディクショナリの作成 my_dict = {"apple": 1, "banana": 2, "cherry": 3} # 値のアクセス print(my_dict["apple"]) # 出力: 1 # 値の設定 my_dict["durian"] = 4 print(my_dict) # 出力: {'apple': 1, 'banana': 2, 'cherry': 3, 'durian': 4} # キーの存在確認 print("banana" in my_dict) # 出力: True print("mango" in my_dict) # 出力: False # キーと対応する値の削除 del my_dict["banana"] print(my_dict) # 出力: {'apple': 1, 'cherry': 3, 'durian': 4}
ディクショナリのキーは一意でなければならない点に注意してください。同じキーを持つ複数のエントリを作成しようとすると、以前のエントリが新しい値で上書きされます。
また、ディクショナリのキーは変更不可能(immutable)な型でなければならないため、例えば文字列や数値、タプルをキーとして使うことができますが、リストやディクショナリをキーとして使うことはできません。
砂漠のオアシス
問題
Hellテーブルから、costカラムの値が現在の魔力以下のレコードをすべて出力してください。レコードを出力する際に表示するカラムは「id, name, cost」としてください。現在の魔力は10とします。
回答
SELECT id, name, cost FROM Hell WHERE cost <= 10;
参考
SQLを使用して特定の条件を満たすレコードを抽出するには、WHERE
句を使用します。cost
が10以下のレコードを抽出する場合、次のようなSQL文を使用します:
SELECT * FROM your_table WHERE cost <= 10;
このSQL文では、your_table
という名前のテーブルからcost
が10以下のすべてのレコードを抽出しています。SELECT *
はすべての列を選択することを意味します。必要な列のみを選択する場合は、*
の代わりに列名を指定します。
SQL文中のテーブル名や列名は具体的な状況に応じて変更してください。
禁断の洞窟
問題
Hellテーブルから、属性名が「Earth」のレコードをすべて出力してください。なお、属性名はHellテーブルのelement_idを外部キーとしてElementテーブルを外部参照してください。レコードを出力する際に表示するカラムはHellテーブルのid, Hellテーブルのname, Elementテーブルのnameとし、Elementテーブルのnameには「element」と名付けてください。
回答
SELECT Hell.id, Hell.name, Element.name AS element FROM Hell JOIN Element ON Hell.element_id = Element.id WHERE Element.name = 'Earth';
参考
IN
この場合、Elementテーブルから属性名"Earth"に対応するelement_id
を取得し、それを用いてHellテーブルを検索する必要があります。これはサブクエリを使って実行することができます。
以下にそのSQL文を示します:
SELECT * FROM Hell WHERE element_id IN (SELECT id FROM Element WHERE name = 'Earth');
このSQL文では、まずサブクエリ (SELECT id FROM Element WHERE name = 'Earth')
でElementテーブルから属性名"Earth"に対応するid
を取得します。その後、IN
演算子を使ってHellテーブルのelement_id
が取得したid
に含まれる(一致する)レコードを抽出します。
SQL文中のテーブル名や列名は具体的な状況に応じて変更してください。
JOIN
ここでは、HellテーブルとElementテーブルを結合する必要があります。この結合はJOIN
を使用して行うことができます。そして、AS
を使用して列名のエイリアスを指定します。
以下にそのSQL文を示します:
SELECT Hell.id, Hell.name, Element.name AS element FROM Hell JOIN Element ON Hell.element_id = Element.id WHERE Element.name = 'Earth';
このSQL文では、まずJOIN
を用いてHellテーブルとElementテーブルを結合します。結合条件はON Hell.element_id = Element.id
で、これによりHellテーブルのelement_id
がElementテーブルのid
と一致するレコードを結合します。
次に、SELECT
句でHellテーブルのid
とname
列、そしてElementテーブルのname
列を選択します。ここで、Elementテーブルのname
列にはAS element
を使ってエイリアスを付けています。
最後に、WHERE
句でElementテーブルのname
が'Earth'のレコードを抽出します。
SQL文中のテーブル名や列名は具体的な状況に応じて変更してください。