Запаліть розбійника


14

Давши дошку, напишіть найкоротшу програму або функцію, щоб відобразити або повернути, які символи видно гравця. Персонаж видно, якщо можливо провести лінію між ним та гравцем, не перетинаючи жодних символів, які блокують зір.

Вхід:

  • @представляє позицію гравця. Буде лише одна з них у вході.
  • будь-який символ, який відповідає регексу, [#A-Z]блокує зір.
  • будь-який персонаж, який відповідає, [ a-z]дозволяє бачити.
  • недійсних символів не буде
  • вам гарантовано прямокутний вхід

Рядки визначаються наступним чином:

  • визначають вектор за величиною та напрямком
  • напрямок - один із N, NE, E, SE, S, SW, W, NW
  • величина - скільки знаків по цьому напрямку рахувати
  • нехай початковий вектор називається d 1 ; другий вектор називається d 2
  • один з d 1 або d 2 повинен мати величину 1; інший може мати будь-яку величину
  • d 1 'напрямок повинен бути суміжним із напрямком d 2 (наприклад: N і NE)

Рядок визначається як усі символи вздовж шляху, позначеного застосуванням d 1 , потім d 2 , d 1 , d 2 ....

Зразок лінії (заданий .s):
d 1 = (величина: 4, напрямок: E)
d 2 = (величина: 1, напрямок NE)

               .....
          .....
     .....
@.... 

Вихід:

  • кожен видимий символ у правильному положенні .замінює пробіл.
  • Пробіл для кожного невидимого символу.

Зразок введення:

@         
    K     
 J        

    L   




         o

Відповідний вихід:

@.........
....K.....
.J.....   
..........
.. .L.....
..  . ....
... .. ...
...  .. ..
...   .  .
....  ..  

Зразок введення:

 B###M#  by 
 #Q   # Zmpq
 # # aaa    
@  m #      
# ##P#      
# ####      
# ####      
#M ###      
######      

Відповідний вихід:

.B  #M      
.# ..   Z pq
.#.#.aaa..  
@..m.#      
#.##P#      
 .#         
 .#         
 M.         
  #         

Зразок введення:

  w                 

     O  l   gg  rT  
   QQL      Ag  #b  
   qqqqq         XqQ
 x     V# f@aa      
   Y        aaa     
   uU  E  l TaKK    
  e  dd  FF d opi   
   e       d        

Відповідний вихід:

   ..........  .....
    ......... ..... 
     O..l...gg..rT  
...QQL......Ag..#b..
...qqqqq.........XqQ
        #.f@aa......
   Y........aaa.....
...uU..E..l.TaKK....
      d..FF.d.op    
     .... .d. ...   

3
Гаразд ... кажани, всілякі фунгі, цвілі та змії та навіть гніди блокують точку зору, але гігантські міміки, гірки-орки, мастодонти, всілякі інші істоти чи навіть вогневі вихори ні?
Джон Дворак

@JanDvorak Я лінувався і вибирав великі літери для блокування. На зразок типу TALL монстрів проти коротких монстрів; що ви могли б побачити понад. Так що так.
Джастін

1
Я не знаю про квантову механіку, але летюча миша та матуся-гном може бути легкою справою. Міміка, можливо, ще більше ускладнить справи. Крім того, ці три мурахи можуть бути веселими, і велика група різноманітних монстрів на північному сході, можливо, вже знає про вас. Так ... це може бути неприємно. Щодо №3 - де мій прокрутка телепортації? Ой, це було знищення броні.
Джон Дворак

3
Просто цікаве спостереження, але якщо я зрозумів ваше визначення "лінії" правильно, схоже, є квадрат, який не буде видно навіть без жодних перешкод. Наприклад, якщо гравець знаходиться на (0, 0), то квадрат у (5, 12) не може бути досягнутий жодною лінією. Можливо, було б доцільніше, скажімо, вказати деяку канонічну реалізацію алгоритму лінійки Брезенама для нанесення лінії між будь-якими двома точками та визначити квадрат як затемнений, якщо лінія між ним та гравцем перетинає перешкоду.
Ільмарі Каронен

1
@IlmariKaronen Ви абсолютно праві. Саме так мені подобається. :-).
Джастін

Відповіді:


5

GolfScript, 171 символ

.n?):L)[n*.]*1/:I'@'?{\+[{1$+}*]..{I=26,{65+}%"#
"+\?)}??)<}+{[L~.).)1L)L.(-1L~]>2<`{[.[~\]]{1/~2$*+L*.-1%}%\;~}+L,%~}8,%%{|}*`{1$?)I@=.n=@|\.' '={;'.'}*' 'if}+I,,%''*n%n*

Вхід повинен бути наданий на STDIN.

Вихід для наведених вище прикладів дещо відрізняється. Я перевірив відповіді вручну і вважаю, що вони правильні.

Приклад 1:

@.........
....K.....
.J.....   
..........
.. .L.....
..  . ....
... .. ...
...  .. ..
...   .  .
....  ..  

Приклад 2:

.B  #M      
.# ..   Z pq
.#.#.aaa..  
@..m.#      
#.##P#      
 .#         
 .#         
 M.         
  #         

Приклад 3:

   ..........  .....
    ......... ..... 
     O..l...gg..rT  
...QQL......Ag..#b..
...qqqqq.........XqQ
        #.f@aa......
   Y........aaa.....
...uU..E..l.TaKK....
      d..FF.d.op    
     .... .d. ...   

Здається, це не працює для однорядних входів (які є дійсними прямокутниками ...)
Джастін

@Quincunx Код передбачає, що ви доопрацюєте введення новим рядком. Крім того, додайте n+до коду.
Говард

4

Рубін - 510 символів

Досить мамонт; але це моя перша в історії спроба гольфу.

m=$<.read;w,s,o,p=m.index(?\n)+1,m.size,m.dup.gsub(/[^@\n]/,' '),m.index(?@);d=[-w,1-w,1,w+1,w,w-1,-1,-1-w];0.upto(7){|i|x=d[i];[i-1,i+1].each{|j|y=d[j%8];[1,nil].each{|l|t=0;catch(:a){loop{c,f,r=p,1,nil;catch(:b){loop{(l||r)&&(1.upto(t){|u|c+=x;n=!(0...s).include?(c)||m[c]==?\n;n&&throw(f ?:a: :b);o[c]=m[c]==" "??.: m[c];a=m[c]=~/[#A-Z]/;a&&throw(f ?:a: :b)};f=nil);r=1;c+=y;n=!(0...s).include?(c)||m[c]==?\n;n&&throw(f ?:a: :b);o[c]=m[c]==" "??.: m[c];a=m[c]=~/[#A-Z]/;a&&throw(f ?:a: :b)}};t+=1}}}}};$><<o

Введення - за файлом, вказаним як аргумент; Я вважаю, що вхідний файл повинен складатися з прямокутного блоку символів (значить, включені пробіли) і мати зворотний новий рядок.

Ця версія широко використовує catch-throw для виходу з глибоких циклів; Я, можливо, можу вдосконалити питання, замість цього перевіряються контури.

Нерозбірливий код:

# Read the map in
map = $<.read

# Determine its width and size
width = map.index("\n")+1
size = map.size

# Create a blank copy of the map to fill in with visible stuff
output = map.dup.gsub /[^@\n]/,' '

# Locate the player
player = map.index('@')

dirs = [
  -width,   # N
  1-width,  # NE
  1,        # E
  width+1,  # SE
  width,    # S
  width-1,  # SW
  -1,       # W
  -1-width  # NW
]

0.upto(7) do |i1|
  d1 = dirs[i1]
  [i1-1, i1+1].each do |i2|
    d2 = dirs[i2%8]

    # Stepping by 0,1,2... in d1, work along the line.
    # Write the cell value into the duplicate map, then break if it's
    # a "solid" character.
    #
    # Extensive use of catch-throw lets us exit deep loops.

    # For convenience of notation, instead of having either d1 or d2
    # be magnitude 1, and always doing d1,d2,d1... - I have d2 always
    # being magnitude 1, and doing either d1,d2,d1 or d2,d1,d2...

    # Loop twice - first with d1,d2,d1... second with d2,d1,d2...
    [true,false].each do |long_first|
      step = 0

      catch(:all_done) do
        # This loop increments step each iteration, being the magnitude of d1
        loop do
          cell = player
          first = true  # True until we've done the first d1
          later = false # True once we've done the first d2

          catch(:done) do
            # This loop repeatedly applies d1 and d2
            loop do
              if long_first || later  # Don't apply d1 first if starting with d2
                1.upto(step) do |dd1|
                  cell += d1 # Move one cell in d1
                  invalid = !(0...size).include?(cell) || map[cell]=="\n" # Out of range
                  throw :all_done if first && invalid # No point trying a longer step if the
                                                      # first application of d1 is out of range
                  throw :done if invalid # No point continuing with this step length

                  output[cell]=map[cell] == " " ? '.' : map[cell] # Transfer visble character
                  wall = map[cell]=~/[#A-Z]/  # Hit a wall?
                  throw :all_done if first && wall # Drop out as before
                  throw :done if wall
                end
                first = false
              end
              later=true

              # Now repeat above for the single d2 step
              cell += d2
              invalid = !(0...size).include?(cell) || map[cell]=="\n"
              throw :all_done if first && invalid
              throw :done if invalid
              output[cell]=map[cell] == " " ? '.' : map[cell]
              wall = map[cell]=~/[#A-Z]/
              throw :all_done if first && wall
              throw :done if wall
            end
          end
          step += 1
        end
      end
    end
  end
end

puts output

Редагувати

Ілмарі Каронен зазначає у коментарі запитання, що алгоритм бачення бачить не всі квадрати, навіть коли немає перешкод. Ось демонстрація цього, на відстані (40,40) від гравця.

@.......................................
........................................
........................................
........................................
........................................
............ ...........................
..............  ........................
............ ...   ..... ...............
.............. ...    .....  ...........
...............  ...     .....   .......
.................  ...      .....    ...
..................   ...       .....
..... . ............   ...        .....
.....................    ...         ...
...... . ..............    ...
...... .. ..............     ...
....... . ................     ...
....... .. ............. ..      ...
.......  .  .................      ...
........ .. ............... ..       ...
........  .  ............... ...       .
........  ..  ................ ..
.........  .  ................. ...
.........  ..  .................  ..
....... .   .   . ................ ...
..........  ..  ...................  ..
..........   .   ...................  ..
........ .   ..   . ..................
........ ..   .   .. ..................
...........   ..   .....................
......... .    .    . ..................
......... ..   ..   .. .................
......... ..    .    .. ................
.......... .    ..    . ................
.......... ..    .    .. ...............
.......... ..    ..    .. ..............
..........  .     .     .  .............
........... ..    ..    .. .............
........... ..     .     .. ............
...........  .     ..     .  ...........

Хм. Це не вдалося перевірити 3. Потребує налагодження.
Chowlett

ти впевнений? Я міг би помилитися ...
Джастін

Досить впевнений - я бачу V за стіною! Я думаю, що я не виявляю новий рядок після попереднього рядка.
Chowlett

Однозначно не слід бачити цього ...
Джастін

А, це була проблема з моїм вкладом; Після цього у мене з'явився додатковий простір XqQ. При цьому ваша відповідь на номер 3 взагалі не відповідає тестовій витримці - вона принаймні має додатковий рядок у верхній частині та лише один пробіл міжO і l.
Chowlett
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.