オフラインリアルタイムどう書く E27の参考問題「灯りと鏡」の実装例を、python3 で。
※ 手元の環境は Python 3.5.2 :: Anaconda 4.2.0 (x86_64)
問題 : http://nabetani.sakura.ne.jp/hena/orde27ligmir/
実装リンク集 : https://qiita.com/Nabetani/items/0b2f459ec128c89948f4
ruby 版を python3 に移植した。
import json
N=5
class State:
def __init__( self, pos, dir ):
self._pos = pos
self._dir = dir
def pos(self):
return self._pos[:]
def advance(self):
for i in range(2):
self._pos[i] += self._dir[i]
def inbound(self):
return self._pos[0] in range(N) and self._pos[1] in range(N)
def x(self):
return self._pos[0]
def y(self):
return self._pos[1]
def reflect(self,p):
self._dir = [ p*self._dir[1], p*self._dir[0] ]
def impl(map, s):
visited=[s.pos()]
for _ in range(2*N*N):
s.advance()
if not s.inbound():
break
if map[s.y()][s.x()]=="x":
break
visited.append( s.pos() )
cell = map[s.y()][s.x()]
if cell=="0":
s.reflect(1)
if cell=="1":
s.reflect(-1)
return visited
def solve(src):
xy = list(reversed(divmod( src.find("Y"), 6 )))
map = src.split("/")
visited = impl( map, State(xy,[0,-1]) )
return "".join(sorted(list(set([
chr(xy[0]+xy[1]*N+ord('a')) for xy in visited
] ) ) ) )
with open('data.json') as f:
data = json.load(f)
for r in data["test_data"]:
actual = solve(r["src"])
ok = actual == r["expected"]
print( " ".join( [
str(r["number"]),
("ok" if ok else "**NG**" ),
r["src"],
actual,
r["expected"]] ) )
python ではソースコードの末尾に JSON を埋める簡単な方法がないようなので、別ファイルにした。
{"event_id":"E27","event_url":"https://yhpg.doorkeeper.jp/events/79705","test_data":[
{"number":0,"src":"x...x/.1.0./..0../.Y.../0..x.","expected":"ghilnqs"},
{"number":1,"src":"..Y../...../...../...../.....","expected":"c"},
{"number":2,"src":"..x../..Y../...../...../.....","expected":"h"},
{"number":3,"src":"..Y.x/..1x0/11.../....0/1..1.","expected":"c"},
{"number":4,"src":"....1/....Y/...../...../.....","expected":"ej"},
{"number":5,"src":".10../x.1../x.1x./.Y.1./...0.","expected":"bcghlq"},
{"number":6,"src":"0.x10/00..x/x0x.0/....0/...Y1","expected":"deinsx"},
{"number":7,"src":"1.01./01Y.1/..1.1/..10./0.0..","expected":"abcfgh"},
{"number":8,"src":"x..../x1x../0...0/....Y/.1..0","expected":"klmnot"},
{"number":9,"src":"...../..10./.1Y1./.01../.....","expected":"hilmnqr"},
{"number":10,"src":"...../..10./x.11./...../..Y..","expected":"hilmnrw"},
{"number":11,"src":"...../x.10x/...../x.Y1x/.....","expected":"himnqrs"},
{"number":12,"src":"..010/...Y1/..0../0.x../.....","expected":"defghij"},
{"number":13,"src":"1.0../...../.0x../Y.1x./..1..","expected":"abcfhkp"},
{"number":14,"src":"...../101../0.0../..Y../.....","expected":"fgklmqrv"},
{"number":15,"src":"1.0../00.../.x..0/0.Y1./...10","expected":"abcfghmr"},
{"number":16,"src":"x101./1..../.Y.x./..01./.00.1","expected":"bcghlmrs"},
{"number":17,"src":"x11../x.x../.0.01/..x../...Y.","expected":"bcglmnsx"},
{"number":18,"src":"..1.0/x0.x./0.0../x...Y/.10.1","expected":"cdehjmnot"},
{"number":19,"src":"..x.0/.0.../1..0x/1..1./Y.00.","expected":"klmnpqrsu"},
{"number":20,"src":"0.1.0/.0.xY/0...0/01..1/x00.x","expected":"cdehjmrwx"},
{"number":21,"src":"...0./.0.0./..101/...10/..01Y","expected":"mnpqrstwxy"},
{"number":22,"src":"10..0/.Y.0./0..1./....x/000..","expected":"abfghiklmn"},
{"number":23,"src":"10..1/...../.1010/110.1/x..Yx","expected":"lmnopqrstx"},
{"number":24,"src":"110../....1/x1..x/0.0.0/....Y","expected":"bcghlmrsty"},
{"number":25,"src":"x.101/1..../..001/010Yx/..1.1","expected":"cdehijmnos"},
{"number":26,"src":"x.111/x10../...0./00.1x/x.Y.1","expected":"ghklmnqrsw"},
{"number":27,"src":"11.../....0/11..1/1.1../.Y..1","expected":"fghijlmnoqv"},
{"number":28,"src":"...x1/.1.0./11.1./.01../Y..x.","expected":"cghiklmnpqru"},
{"number":29,"src":".0.../110x./11..0/01.x./..Y.x","expected":"ghklmnopqrtw"},
{"number":30,"src":".01.0/.110x/0...0/.01Y./x.1x.","expected":"cdeghilmnqrs"},
{"number":31,"src":".1100/..1.0/1.11Y/0..1./.0..0","expected":"hijklmnopqrs"},
{"number":32,"src":"1..00/..11./.100./1..Y1/.....","expected":"abcdfhikmnps"},
{"number":33,"src":"1.0../.11x0/.00.x/Y.10./.10x0","expected":"abcfghklmpqr"},
{"number":34,"src":"11110/11.../.x.../.0111/0.Y0.","expected":"deijnorstwxy"},
{"number":35,"src":"...1./.1.0x/10..0/0Y.11/.0.x0","expected":"ghiklmnopqrst"},
{"number":36,"src":"...10/x111./0x.11/.0.../0.0Y.","expected":"dehijmnorswxy"},
{"number":37,"src":".1x../.x1.0/0x.x./x11.1/x0Y.1","expected":"hijmoqrstvwxy"},
{"number":38,"src":"x.x../x110./1.1.0/0.Y.1/0.00x","expected":"hiklmnopqrstx"},
{"number":39,"src":"...0./11.00/10..x/..0.1/Y0.10","expected":"ghiklmnpqsuvwx"},
{"number":40,"src":".110./....0/x..../.0001/11.Y.","expected":"cdfghijmnorstx"},
{"number":41,"src":"1.00./....1/.1.../0...0/0..1Y","expected":"abcfhkmpqrstwy"},
{"number":42,"src":".1.01/..x../..100/..Y../...01","expected":"bcdgilmnoqrstvxy"},
{"number":43,"src":"1...0/Y..../...../...../0...1","expected":"abcdefjkoptuvwxy"},
{"number":44,"src":"x1..0/1..0./.Yx../0...1/.0.1.","expected":"bcdefghijklnopqrstvwx"},
{"number":45,"src":"1...0/.1.0./..1../..01./Y0..1","expected":"abcdefghijklmnopqrstuvwxy"}]}
python 力はあまり高くないし、なれない class を使っているので適切なコードになっているかどうかあまり自信がない。
"".join(sorted(list(set(略))))
の辺りが美しくない気もするし、仕方ない気もする。
実装方針は ruby版とほぼ同じ。
終了条件も for _ in range(50):
といういい加減なもの。
とはいえ全く同じでは面白くないので、座標を複素数じゃなくて整数の配列にした。
python の複素数が 1+2j
のように j を使うことを知って驚いた。
あと。
この記事を書くにあたって、「ruby でこう書くのは、python ならこう書く、のメモ」をちょっと更新した。
イベントの本番( see https://yhpg.doorkeeper.jp/events/79705 )では python の人は最近少ないけど、python での参加も大歓迎です。