カニゲーム攻略日記ブログ

beatmaniaIIDXやハースストーンなどのゲーム攻略日記。主にまったり勢。2016年にIIDX皆伝になった

エンジニア騎士とクエリの魔女 難易度C 攻略

火山島でコーヒー

これは競技プログラミング

目次

難易度: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関数で整数に変換します。最後に、多重代入を使用して、これらの値を変数abcにそれぞれ代入します。

この結果、aは100、bは200、cは300になります。

以下に、Pythonmap()関数と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の改善点

以下、コードの改善点について述べます:

  1. 変数名の明示性: money_s, money_m, money_lなどの変数名は少し抽象的です。可能であれば、これらの変数が何を表しているのかもっと明示的にすると良いでしょう。

  2. 変数sum命名: Pythonではsumは組み込み関数であり、そのため一般的にはこの名前を変数に使用することは推奨されません。別の名前を選ぶことで、混乱を避けられます。

  3. ディクショナリの使用: 各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テーブルのidname列、そしてElementテーブルのname列を選択します。ここで、Elementテーブルのname列にはAS elementを使ってエイリアスを付けています。

最後に、WHERE句でElementテーブルのnameが'Earth'のレコードを抽出します。

SQL文中のテーブル名や列名は具体的な状況に応じて変更してください。