LoginSignup
1
0

More than 5 years have passed since last update.

オフラインリアルタイムどう書くE27の参考問題の実装例(ruby)

Posted at

オフラインリアルタイムどう書くE27の参考問題「灯りと鏡」の実装例を、まずは ruby で。

問題 : http://nabetani.sakura.ne.jp/hena/orde27ligmir/
実装リンク集 : https://qiita.com/Nabetani/items/0b2f459ec128c89948f4

10/6 のイベント : https://yhpg.doorkeeper.jp/events/79705

ruby2.5
require "json"

def reflect(x)
  case x
  when 0+1i; 1+0i
  when 0-1i; -1+0i
  when 1+0i; 0+1i
  when -1+0i; 0-1i
  end
end

def solve(map)
  you = Complex(*map.index("Y").divmod(5+1)) # +1 は「/」の分
  light = [you, -1+0i] # 位置と方向のペア
  visited = []
  (5*5*2).times do # 高々 5×5×2 しか進まない
    visited << light[0]
    newpos = light[0]+light[1]
    break unless (0...5)===newpos.real && (0...5)===newpos.imag
    cell = map[newpos.real*(5+1)+newpos.imag]
    case cell
    when ".", "Y"
      light=[newpos, light[1]]
    when "0"
      light=[newpos, reflect(light[1])]
    when "1"
      light=[newpos, -reflect(light[1])]
    when "x"
      break
    end
  end
  visited.map{ |c|
    ((c.real*5+c.imag)+?a.ord).chr
  }.sort.uniq.join
end

if $0==__FILE__
  data = JSON.parse(DATA.read, symbolize_names:true)
  data[:test_data].map{ | number:, src:, expected: |
    actual = solve( src )
    okay = actual == expected
    puts [ number, (okay ? "ok" : "**NG**"), actual, expected ].join(" ")
    okay
  }.all?.yield_self{ |x| puts( x ? "okay" : "SOMETHING WRONG" ) }
end

__END__
{"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"}
]}

たぶん方針は光の流れを素直にシミュレートするしかないと思う。
この実装では、地図の持ち方は文字列のまま。自分の位置は複素数で持つという方針にした。

悩みどころは終了条件をどうするか。
この実装の選択は、光は高々 2×5×5 マスしか進まないということを利用して、50.times で済ませた。
9番のケースなんかでだいぶ無駄な処理が進むことになるけど、気にしない方向で。

reflect メソッドをもう少し簡単にしたいところだけど、いい方法が思いつかなかった。
共役とか使えばシンプルになりそうな気もする。

テストを走らせるコードで

ruby2.5
  data[:test_data].map{ | number:, src:, expected: |
    #略
  }

とかけるのがちょっと嬉しかった。(シンタックスハイライト...)
@yancya さんありがとう( see https://qiita.com/yancya/items/c557864f307d429bbde4 )

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0