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

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

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

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

目次

難易度B

精霊の村

問題

Hellテーブルから、属性名が「Air」、階級が「Boss」のレコードをすべて出力してください。なお、属性名はHellテーブルのelement_idを外部キーとしてElementテーブルを、階級はHellテーブルのgrade_idを外部キーとしてGradeテーブルをそれぞれ外部参照してください。レコードを出力する際に表示するカラムはHellテーブルのid, Hellテーブルのname, Elementテーブルのname, Gradeテーブルのnameとし、Elementテーブルのnameには「element」を、Gradeテーブルのnameには「grade」と名付けてください。

回答

回答その1_不正解

SELECT Hell.id, Hell.name, Element.name AS 'element', Grade.name AS 'grade'
FROM Hell
JOIN Element ON Hell.element_id = Element.id
JOIN Grade ON Hell.grade_id = Grade.id
WHERE Hell.element_id = 'Air' and Hell.grade_id = 'Boss';

回答その2

SELECT Hell.id, Hell.name, Element.name AS element, Grade.name AS grade
FROM Hell
JOIN Element ON Hell.element_id = Element.id
JOIN Grade ON Hell.grade_id = Grade.id
WHERE Element.name = 'Air' AND Grade.name = 'Boss';

参考

Hellテーブルから、属性名が「Air」、階級が「Boss」のレコードをすべて出力してください。

WHERE Hell.element_id = 'Air' and Hell.grade_id = 'Boss'

なお、属性名はHellテーブルのelement_idを外部キーとしてElementテーブルを、階級はHellテーブルのgrade_idを外部キーとしてGradeテーブルをそれぞれ外部参照してください。

JOIN Element ON Hell.element_id = Element.id
JOIN Grade ON Hell.grade_id = Grade.id

レコードを出力する際に表示するカラムはHellテーブルのid, Hellテーブルのname, Elementテーブルのname, Gradeテーブルのnameとし、Elementテーブルのnameには「element」を、Gradeテーブルのnameには「grade」と名付けてください。

SELECT Hell.id, Hell.name, Element.name AS 'element', Grade.name AS 'grade'

回答その1の問題

提供されたSQLクエリにはいくつかの問題が存在します:

  1. WHERE句の値:Hell.element_id = 'Air'およびHell.grade_id = 'Boss'では、element_idおよびgrade_idが文字列と比較されています。しかし、一般的にこれらのフィールドは数値型(たとえば整数)であり、文字列型ではありません。これらの値は恐らくElementテーブルとGradeテーブルの名前フィールドを指していると思われます。

正しいクエリは以下のようになるでしょう:

SELECT Hell.id, Hell.name, Element.name AS 'element', Grade.name AS 'grade'
FROM Hell
JOIN Element ON Hell.element_id = Element.id
JOIN Grade ON Hell.grade_id = Grade.id
WHERE Element.name = 'Air' AND Grade.name = 'Boss';
  1. シングルクォートでのエイリアス:ASの後に使用されるエイリアスは一般的にシングルクォート(' ')で囲まれません。ただし、一部のSQL実装(例えばMySQL)では許可されている場合もあります。しかし、一貫性と互換性を保つためには、エイリアスにはシングルクォートを使用せず、代わりにダブルクォート(" ")を使用するか、何も使用しないことが推奨されます。
SELECT Hell.id, Hell.name, Element.name AS element, Grade.name AS grade
...

これらの変更を行うと、SQLクエリは正しく動作し、期待される結果を提供するはずです。ただし、データベースの具体的な設定やテーブルの構造によっては、他の問題が存在する可能性もあります。

大海の渦

問題

手品の手順を詳しく述べると以下になります。1. 子供たちに好きな数だけ飴を取ってもらう。2. 子供たちに横一列に並んでもらう。3. それぞれの子供に、自分自身と両隣の子供の持っている飴の個数の和を言ってもらう。 ・両端の子供には、自分自身と隣の子供の持っている飴の個数の和を言ってもらう。4. 左端の子供の持っている飴の個数だけか、それぞれの子供の持っている飴の個数を当てる。あなたはこの手品をプログラムで再現しようと思いました。

入力

N x_1
d_1 d_2 ... d_N

回答

N, x0 = map(int, input().split())

d_n = list(map(int, input().split()))

x = [x0]    # x0 = x0
for i in range(1, N):
    if i == 1:
        x.append(d_n[i-1] - x[i-1])   # x1 = d0 - x0
    else:
        x.append(d_n[i-1] - x[i-2] - x[i-1])    # x2 = d1 - x0 - x1

print(*x)

参考

計算式

d1 = x1 + x2  
d2 = x1 + x2  + x3
d3 = x2 + x3  + x4
d4 = x3 + x4  + x5
d5 = x4 + x5  
x1 = x1
x2 = d1 - x1
x3 = d2 - x1 - x2
x4 = d3 - x2 - x3
x5 = d4 - x3 - x4
x0 = x0
x1 = d0 - x0
x2 = d1 - x0 - x1
x3 = d2 - x1 - x2
x4 = d3 - x2 - x3

list

map(int, input().split())を使用すると、ユーザーからの入力を空白で分割し、各部分を整数に変換します。以下に、それを変数に代入する例を示します。

ユーザーから3つの入力値を取得するとしましょう。それぞれを別々の変数に代入することができます:

a, b, c = map(int, input().split())
print(a, b, c)

この場合、ユーザーが"10 20 30"と入力すると、それぞれの変数a, b, cには整数の10, 20, 30が代入されます。

入力値の数が固定されていない場合、結果をリストとして保存することができます:

numbers = list(map(int, input().split()))
print(numbers)

この場合、ユーザーが"10 20 30 40 50"と入力すると、numbersリストには[10, 20, 30, 40, 50]という値が格納されます。

append

与えられた問題は、連続する数値の差を取る操作を繰り返すことで解決できます。以下に、そのような操作をforループで処理する例を示します。

N, x1 = map(int, input().split())

d_n = list(map(int, input().split()))

print(N, x1)
print(d_n)

x = [x1]
for i in range(1, N):
    x.append(d_n[i-1] - sum(x))

print(*x)

このコードは以下のように動作します:

  1. ユーザーからNx1を入力として受け取ります。
  2. 次に、d_nという名前のリストを作成します。これにはN個の整数が含まれています。
  3. xという名前のリストを作成し、最初の値としてx1を追加します。
  4. forループを使って、リストd_nの各要素について処理を行います。各ステップで、d_nの現在の要素からリストxのすべての要素の和を引き、その結果をxに追加します。
  5. 最後に、print(*x)を使ってxのすべての要素を空白区切りで出力します。

この方法では、x2からx5までの計算を一つのforループで行うことができます。また、Nが変わってもこのループは正しく動作します。ただし、このコードはd_nN個の整数を含んでいることを前提としています。

変数の命名

明確で自己説明的な名前を使用することが、可読性と保守性の観点から推奨されます。

あなたのコードを見ると、Nは要素の数、x0は最初の値、d_nは差分のリスト、xは計算結果のリストを示しているようです。これらをより自己説明的に改善することができます:

num_elements, first_value = map(int, input().split())

difference_list = list(map(int, input().split()))

calculated_values = [first_value]
for i in range(1, num_elements):
    calculated_values.append(difference_list[i-1] - sum(calculated_values))

print(*calculated_values)

このコードでは:

  • Nnum_elements になっており、これは入力される要素の数を示しています。
  • x0first_value になっており、これは最初の値を示しています。
  • d_ndifference_list になっており、これは差分のリストを示しています。
  • xcalculated_values になっており、これは計算後の値のリストを示しています。

これらの名前は、その変数が何を表しているかをより明確に示しています。ただし、この例はあくまで一例であり、適切な変数名はその変数がどのように使われているかによります。