Homeの3問目 (Cipher Map)
4掛け4のグリッドのマスにそれぞれ適当な文字を組み込んで、
同じ4掛け4サイズのグリッドの内4マス穴の空いたグリッドをかぶせて穴から覗く文字を取り出す、
90度ずつローテーションさせて合計16文字のパスワードを取り出す。
という暗号化の仕組みを解読するコードを書くという問題ですね。
とりあえず、2次元配列的な感じでやってみることに。
正直無駄な処理だらけではあるけれど、
def recall_password(cipher_grille, ciphered_password):
result = ''
grille_2d = [list(cipher_grille[0]),list(cipher_grille[1]),list(cipher_grille[2]),list(cipher_grille[3])]
password_2d = [list(ciphered_password[0]),list(ciphered_password[1]),list(ciphered_password[2]),list(ciphered_password[3])]
t = 0
while t < 4:
pickedchar = ''
for i,n in enumerate(grille_2d):
for j, m in enumerate(n):
if m == 'X' :
pickedchar += password_2d[i][j]
result += pickedchar
tmp_grille_2d=
grille_2d.reverse()
for a, b, c, d in zip(*grille_2d):
tmp_grille_2d.append([a, b, c, d])
grille_2d =
grille_2d = tmp_grille_2d
t += 1
return result
で一旦解けました。
リストをいちいち書くのは少し残念すぎる気がするのでforで回すようにして、
whileで残念な書き方になっていたところをfor ... in range()で置き換え。
def recall_password(cipher_grille, ciphered_password):
result = ''
grille_2d, password_2d = ,
for i, j in zip(cipher_grille,ciphered_password):
grille_2d.append(i)
password_2d.append(j)
for t in range(4):
pickedchar = ''
for i,n in enumerate(grille_2d):
for j, m in enumerate(n):
if m == 'X' :
pickedchar += password_2d[i][j]
result += pickedchar
tmp_grille_2d=
grille_2d.reverse()
for a, b, c, d in zip(*grille_2d):
tmp_grille_2d.append([a, b, c, d])
grille_2d =
grille_2d = tmp_grille_2d
return result
そもそも、いちいち配列にする必要ないような気がしたので、
書き換えようとしたものの回転させることができず下記でギブアップ
def recall_password(cipher_grille, ciphered_password):
result = ''
for i, j in zip(cipher_grille,ciphered_password):
for n, m in enumerate(i):
if m == 'X' :
print(j[n])
return result
最初に位置を出してあとは追ってくって感じで'X'の位置を座標に変換して回すとかどうだろうとか思ったけど、
読み出す順序を考えると結構無駄な処理が増えそうな気もする。。。
ということで、
def recall_password(cipher_grille, ciphered_password):
result = ''
grille_2d, password_2d = ,
for i, j in zip(cipher_grille,ciphered_password):
grille_2d.append(i)
password_2d.append(j)
for t in range(4):
for i,n in enumerate(grille_2d):
for j, m in enumerate(n):
if m == 'X' :
result += password_2d[i][j]
tmp_grille_2d=[]
grille_2d.reverse()
for a, b, c, d in zip(*grille_2d):
tmp_grille_2d.append([a, b, c, d])
grille_2d = tmp_grille_2d
return result
この辺が一旦落とし所でしょうか。。
さて、他の人の回答を見ると、
def recall_password(grill, cypher):
password = ""
for _ in grill: # must be of len 4
for grill_row, cypher_row in zip(grill, cypher):
for grill_letter, cypher_letter in zip(grill_row, cypher_row):
if grill_letter == 'X':
password += cypher_letter
row1, row2, row3, row4 = grill
grill = tuple(zip(row4, row3, row2, row1)) # rotate
return password
あー、後半の処理のところを逆に並べてzipするということなんですね。
でも、基本的には
row1, row2, row3, row4 = grill
を発想できませんでした。。
うむむむ。
def recall_password(cipher_grille, ciphered_password):
result = ''
for t in range(4):
for i, j in zip(cipher_grille,ciphered_password):
for n, m in enumerate(i):
if m == 'X' :
result += j[n]
a, b, c, d = cipher_grille
cipher_grille = tuple(zip(d, c, b, a))
return result
なるほどですね。