Чи може гравітаційний хлопець встигнути?


27

Gravity Guy - гра, де єдиним вводом користувача є окрема клавіша, яка перевертає напрямок тяжіння. З огляду на рівень мистецтва ASCII, визначте, чи можливо Gravity Guy досягти кінця.


Правила

  • Початковий напрямок сили тяжіння вниз .
  • Перший стовпець вводу завжди буде містити лише один # , який починає Gravity Guy зверху.
  • Кожну ітерацію він рухає до персонажа прямо праворуч .
  • Якщо його шлях заблокований, і він рухається в a #, гравець програє .
  • Після переміщення гравець може за бажанням перемикати гравітацію вниз або вгору.
  • Гравітаційний хлопець потім переходить до наступного# (у поточному напрямку сили тяжіння).
  • Якщо немає #до кого потрапити, і він випаде з сітки , гравець програє .
  • Якщо Gravity Guy відсувається від правої частини вхідної сітки, гравець виграє .

Приклад

Якщо це вхідна сітка:

  ### 

#  # #
 ###  

Гравітаційний Хлопець починав xби з цих позицій після кожної ітерації. ^= переключити гравітацію вгору і v= переключити гравітацію вниз.

v                        ^                               v
-------------------------------------------------------------
  ###   |    ###   |    ###   |    ###   |    ###   |    ### 
x       |          |    x     |     x    |      x   |        
#  #    |  #x #    |  #  #    |  #  #    |  #  #    |  #  # x
 ### #  |   ### #  |   ### #  |   ### #  |   ### #  |   ### #

Як бачимо, перемикання сили тяжіння в цей час Gravity Guy доходить до кінця, тож цей вхід поверне тривале значення.

Технічні умови

  • Сітка для введення може бути у будь-якому відповідному форматі "сітка" (багаторядковий рядок з пробілами, масив рядкових рядків, масив масивів символів тощо).
  • Якщо це можливо для гравця , щоб виграти рівень, виводити truthyзначення. Якщо ні, виведіть falseyзначення.
  • Ширина та висота сітки становитимуть не більше 50символів.
  • Це , можливо найкоротший код у байтах виграє!

Випробування

(кожен випадок розділений ----------пробілами, будь-які порожні рядки також повинні бути прокладені пробілами)

Правда

 #########   ########      ######     ######    
          #  #       #    #      #   #      #   
###    #   # #    #   #  #       #  #        #  
  #    ##  # #    ##  # #     # #  #      ##    
  #    #   # #    #   # #    #     #     #######
  #       #  #       #  #     ###  #          # 
  #    ##    #    ##     #       #  #         # 
  #    #          #              #        #   # 
  #    ####################################   # 
  #                                           # 
  ############################################# 

----------


###

----------

   #####

####    

----------

 #####
 # # #

# # # 
 #####

----------

   ############   

######      ######

   ############   

----------

  ###   ###  
     # #     
####  #  ####
    #   #    
     # #     
      #      

----------

    ######  
   #        
 ##         
     #######
###     #   
   #    #   
    #####   


----------

    #####   
   #    #   
 ##     #   
     #######
###         
   #        
    ######  

----------

  ### 

#  # #
 ###  

----------

  ###  ###

###     ##
   #    # 
    ##### 

----------

  #        
     #   # 
       #   
#   #     #
        #  
   #       
      #    
 #         

----------

    ##### ####   
   #     #    #  
  #   # #  ##  # 
             #  #
#####  ####   #  
               # 
     #########   

----------

 ########################### 
 #   #   #   #     #   #   # 
 # # # #   #   # #   #   # # 
 # # # ######### ########### 
 # # # #  #       #     #  # 
   # # # ## ##### ### #      
## #   #    #          ## ###
 # ##### #### ###########  # 
 # #     #  #     #     ## # 
 # # #####  ### # # # # #  # 
 #              #   # #   ## 
 ########################### 

помилковий

 ###
   #
####

----------


### ###

----------

    #   
 ### ###

#### ###
    #   

----------

  ###     ###  
     # # #     
####  # #  ####
    #     #    
     #   #     
      # #      
       #       

----------

  ####### 
  #     # 
 ## ##### 

### ######
  #     # 
  ####### 

----------

 ########################### 
 #   #   #   #  #  #   #   # 
 # # # #   #   # #   #   # # 
 # # # ######### ########### 
 # # # #  #       #     #  # 
   # # # ## ##### ### #      
## #   #    #          ## ###
 # ##### #### ###########  # 
 # #     #  #     #     ## # 
 # # #####  ### # # # # #  # 
 #              #   # #   ## 
 ########################### 

Чи дозволено нам сітку в стовпчастому форматі?
Ніл

@Neil Ви маєте на увазі перекладений / обернутий масив? Я збираюся сказати "ні", оскільки це змінює вхід. Але якщо у вашій мові є особливий columnтип, я думаю, це буде нормально.
користувач81655

Чи можливо, що #в першому стовпчику знаходиться в першому рядку?
feersum

@feersum Ні, ви можете припустити, що в сітку буде розміщений простір для "Гравітаційного хлопця", щоб "стояти".
user81655

Сором; транспозиція збільшує кількість байтів на 20%.
Ніл

Відповіді:


19

Равлики , 15 байт

Спробуйте в Інтернеті?

^
\ n\ ,=\#r}+~

0. ^- це варіант, який вимагає, щоб візерунок починався вгорі зліва.

  1. \ ​: відповідність місця

  2. n: Поверніть на 90 градусів в будь-яку сторону

  3. \ ,​: збігніть пробіл нульовий або більше разів

  4. =\#перевірте, чи є #перед нами

  5. r: встановити напрямок вправо

  6. }+: виконайте всі попередні один чи кілька разів

  7. ~ відповідати клітинці, яка знаходиться поза межами сітки


Це дає 0 для більшості справжніх тестових випадків
Bassdrop Cumberwubwubwub

@Bas Ви проклали порожні рядки з пробілами?
Мартін Ендер

@ MartinBüttner Я безпосередньо скопіював деякі входи, зробивши це дійсно видалив деякі пробіли. Це дійсно працює після додавання пробілів
Bassdrop Cumberwubwubwub

5
Оскільки це ще ніхто не сказав: Це дивовижно!
DLosc

9

Perl, 93 89 81 77 76 75 74 байт

Включає +2 для -0p

Запустіть схемою введення (з усім пробілом рядків, підкресленими однаковою довжиною) на STDIN:

gravity.pl < gravity.txt

gravity.pl:

#!/usr/bin/perl -0p
/
/;$n=".{@-}";s/#$n\K( $n)*\b |(^|w)([w ]$n)*\K $n#/w|$&/es&&redo;$_=m;w

Ця файлова версія потребує остаточного нового рядка, так що це дійсно 75 байт. Але версія, заснована на командному рядку, не потребує додаткового нового рядка, тому ця кількість нараховується як 74 байти:

perl -0pe '/
/;$n=".{@-}";s/#$n\K( $n)*\b |(^|w)([w ]$n)*\K $n#/w|$&/es&&redo;$_=m;w' < gravity.txt

Пояснення:

Це побудує рядок, у якому wв кожній позиції може досягти сила тяжіння. Отож, для другого останнього прихованого прикладу він побудує:

     #########   
    ##### ####   
   #wwwww#wwww#  
  #w  # #w ##ww# 
wwwww wwwwwww#ww#
#####  ####  w#ww
     wwwwwwwwww# 
     #########   

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

Кожна заміна буде такою формою

s/prefix \K space postfix/ w | $& /e

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

Припустимо, $nмістить регулярний вираз, який буде прогресувати достатньою мірою, щоб ліва і права сторона знаходилися рівно один під одним. Тоді відповідні регулярні вирази:

/^( $n)*\K $n#/       From the first position drop down as long as you
                      encounter spaces until you encounter a #. 
                      This puts gravity guy on his starting platform

/#$n\K( $n)*\b /      A space immediately below a # and if you (optionally)
                      go down further from there (as as the descent is
                      over spaces) you get to a space that follows a word
                      boundary. The only way to get a word boundary is if 
                      there is a w in front of that space. This selects the
                      position gravity guy ends up on if starting from that
                      w and gravity is up
/w([w ]$n)*\K $n#/    A w followed by a space (or w) and if you go down from
                      there as long as it is over spaces (or w) you finally
                      end up on a space directly above a #. This handles the
                      gravity down case. The test uses "space or w" instead
                      of just space to handle this case:

                       #
                      ww
                      #x  
                       #

                      Position x is currently a space and must be replaced by a
                      w but the gravity up regex has already put a w directly
                      after the w gravity guy takes off from. So for gravity
                      down we must handle w as if it is still a space. This
                      is not needed for gravity up because regex always matches
                      starting at the earliest possible character, so 
                      gravity up matches before gravity down

З цим не виходить програма просто:

#!/usr/bin/perl -0p   Slurp all of STDIN into $_, at the end print $_

/\n/                  Match the first newline (needed to measure the row
                      length)
$n=".{@-}"            $n effectively becomes rowlength-1 times ".". This
                      will be the regex that goes one step down a column

s/#$n\K( $n)*\b |(^|w)([w ]$n)*\K $n#/w|$&/es

                     This is the 3 regexes shown above combined. The s 
                     modifier is needed so the . in $n also matches newline

    &&redo           Keep looping as long as w's keep getting added

$_=m;w\n;            Check if the last column contains a w: He made it!
                     The \n; at the end is not written. These 2 bytes sneakily
                     come from the -p option for the ; and the -e option
                     for the \n

3

JavaScript (ES6), 174 байти

a=>[...a[0]].map((_,i)=>[...t].map(x=>s[x]<'#'&&g(s.indexOf('#',x),-1)&&g(s.lastIndexOf('#',x),1),s=a.map(s=>s[i]),t=new Set),t=new Set([0]),g=(i,d)=>i<0||t.add(i+d))&&t.size

Бере горизонтальний масив рядків і повертає кількість точок виходу. Транспонування масиву коштує мені 29 байт. Безголівки:

function gravity(array) {
    var set = new Set;
    set.add(0); // starting point
    for (var i = 0; i < array[0].length; i++) {
        var s = array.map(s => s[i]); // transpose array
        var old = set;
        set = new Set;
        for (var x of old) {
            if (s[x] == '#') continue; // hit wall
            var j = s.indexOf('#', x); // try downward gravity
            if (j >= 0) set.add(j - 1);
            j = s.lastIndexOf('#', x); // try upward gravity
            if (j >= 0) set.add(j + 1);
        }
    }
    return set.size;
}

3

Піп , 85 68 62 59 + 1 = 60 байт

Використовує -rпрапор для читання всіх рядків stdin.

FcZg{YlFxiIc@xQsyPB(Jc@<x@?`# *$`)+1PB(c@>x@?'#)+x-1i:UQy}i

Спробуйте в Інтернеті!

Коротке пояснення

Стратегія - це по суті перший пошук. Ми переносимо вхід і цикл через рядки (стовпці), зберігаючи список y-позицій, до яких гравець може досягти у цьому стовпці. Результат після останнього стовпця - це не порожній список, якщо гравець може виграти, або порожній список (який друкується як лише кінцевий новий рядок), якщо програвач програє.

Повне пояснення

Вбудовані змінні , використовувані в цій програмі: i == 0, l == [], s == " ".

-rПрапор поміщає список ліній введення в g. FcZg{...}блискавки gта петлі над кожним стовпцем c. (Unary Z, коли застосовується до списку ітерабелів, діє як Python zip(*g), акуратно перекладаючи 2D масив.) Зауважте, що cце буде список, а не рядок.

Всередині циклу стовпців ми повертаємо yдо порожнього списку Yанкінгом l. Fxiпетлі i. У наступних ітераціях iбуде список y-координат, до яких гравцеві вдалося досягти у попередньому стовпчику. Перший раз, ми хочемо почати з просто 0(верхній лівий кут). Змінна попередньо ініціалізується до Скаляра 0, а не до списку [0], але Pip ітератує над ним просто добре.

Для кожної з дійсних позицій в останньому стовпчику Ic@xQsперевіряйте, чи є пробіл у цій позиції в поточному стовпчику. Якщо ні, гравець просто біг до стіни, і ми продовжуємо спробувати наступну можливість. Якщо так, то ми хочемо знайти позиції, на які гравець потрапить у цю колонку для кожного напрямку тяжіння, і додамо їх до списку yза допомогою оператора Push Back.

Гравітація піднімається вгору (зліва, у перекладеній версії):

(Jc@<x@?`# *$`)+1
  c@<x             Slice everything left of x in the column
 J                 Join into a string so we can do a regex search on it
      @?`# *$`     Find index of the last # in this string
(             )+1  The player's index is the space below/to the right of this #

Гравітація знижується (праворуч, у перекладеній версії):

(c@>x@?'#)+x-1
 c@>x              Slice everything right of x in the column
     @?'#          Find index of the first # in this list (no need to join into string)
(        )+x       Translate to index number in entire column
            -1     The player's index is the space above/to the left of this #

Якщо гравець випаде з сітки в певному напрямку, відповідна @?операція не знайде a #і дасть нуль. Це недійсний індекс, і він генерує деякі попередження в наступній ітерації - які, однак, не видно без -wпрапора. Для наших цілей ці справи по суті виключаються з розгляду.

Після внутрішнього циклу i:UQyприймає список yстворених нами позицій, виключає дублікати та присвоює його i. (Усунення дублікатів необхідно, оскільки в іншому випадку список повітряних кульок експоненціально.) Потім ми переходимо до наступного стовпця. Коли ми переглянемо всі стовпці, якщо був дійсний шлях до, iз'явиться не порожній список позицій (truthy); якщо ні, то це буде порожній список (фальси).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.