Стрибки та біг


18

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

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

Вхідні дані

Введення задається як один рядок на стандартному вході, закінчується розривом рядка. Лінія складається або з тире ( -), або з підкресленнями ( _), що представляє собою землю або метр отвору відповідно. Приклад зразка може бути:

----__--___---

Даний ландшафт довжиною принаймні один і не більше 30 метрів і завжди починається з землі.

Вихід

Вихід дається на стандартному виході і являє собою ряд команд руху до Метью, або run ( R), або jump ( J). Як зазначалося вище, команда з бігу змушує Метью бігти на один метр, а стрибки переносять його вперед рівно на чотири метри. Для наведеного вище прикладу можливий наступний рух:

RRJRJRR

яка виглядає приблизно так:

Ілюстрація руху RRJRJRR

Якщо через пейзаж немає безпечного шляху, то !слід надрукувати єдиний знак оклику ( ).

Зразки входів

--------
----__--___---
-_______
-_-_-_-_-_-
-

Зразки виходів

JRRR
RRJRJRR
!
!

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

Примітка

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

Додатковий вихід при стандартній помилці ігнорується.

Умова виграшу

Найкоротший код виграє, як це прийнято в гольфі. У разі вирівнювання виграє раніше рішення.

Тестові справи

Є два сценарії тестів, що містять однакові тестові випадки:

Закликання є в обох випадках: <test script> <my program> [arguments]наприклад, ./test ruby jumprun.rbабо ./test.ps1 ./jumprun.exe.

Ще одна примітка

Це завдання було частиною змагань з гольфу, які проводилися в моєму університеті протягом 2011 -24. Оцінки та мови наших учасників конкурсу були такими:

  • 104 - Хаскелл
  • 131 - Хаскелл
  • 154 - С
  • 170 - С
  • 275 - VB.NET
  • 286 - Лист звичайний

Наші власні рішення були

  •   92 - Рубі
  • 124 - PowerShell

@Joey Я отримую помилку при спробі запустити test.sh з ./test.sh perl jump.pl- ./test.sh: line 42: syntax error near unexpected token 'done', під баш 3.2.48
swilliams

@Joey Я очистив кеш, перезавантажився і він зараз чудово працює. Спасибі.
swilliams

Дивлячись на рішення, це було, мабуть, занадто банально. Вибачення.
Joey

1
Я припускаю, що назад / стрибки не дозволяється? Якби це було, це зробило б ландшафти на зразок - - - вирішуваним.
Кіт Рендалл

Кіт: трохи пізно зараз, щоб змінити завдання, я думаю.
Joey

Відповіді:


7

Perl, 53 символи

s/-...(?=(-|-...)*-$)/J/g;y/-/R/;/_/?$_="!":s/.$//

Виконати це за допомогою perl -p jumpnrun.pl. Я порахував 3 символи для -pпараметра, що є різницею довжини між perl jumpnrun.plта perl -p jumpnrun.pl.

Я не так добре володію Perl, тому я впевнений, що це можна скоротити. Для цього використовується регулярний вираз, подібний до рішення Говарда .


3

Рубі, 93 90 79 70 символів

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

puts gets.gsub(/-...(?=(-|-...)*-$)/,?J).tr(?-,?R)=~/^([JR]*)R$/?$1:?!

Він проходить всі тести для поданого сценарію.

Збережено кілька символів порівняно з попереднім сценарієм (зараз достатньо одного дзвінка до gsub).

Edit 1: Змінено puts z!=?-??!:''до z!=?-&&$><<?!після тестового сценарію дозволило не вихід для тесту 1.

Редагувати 2: попередня версія була

z=gets.chop
z.chars{z.sub!(/^(-|-...)((-|-...)*-)$/){$><<($1==?-??R:?J);$2}}
z!=?-&&$><<?!

Моя первісна ідея полягала в тому, щоб замінити персонажів, використовуючи стратегію огляду та випередження на зразок такої ^(?<=[RJ]*)(-|-...)(?=(-|-...)*-$). На жаль, Ruby не дозволяє оглядатись із змінною довжиною, і інша група захоплення першої частини зробила код ще довшим.

Тоді я зробив ітеративний підхід: якщо я можу почати з кроку або стрибка, ^(-|-...)після чого послідують ряд інших кроків або стрибків до останньої платформи, (-|-...)*-$тоді я надрукую відповідний лист, видаляю перший / чотири символи і починаю заново. Увімкнення може навіть налаштувати пріоритет RJ проти JR шляхом переключення варіантів виразу всередині виразу (в даний час він віддає перевагу RJ).

Редагування 3: Розщеплення однієї підстановки

puts (z=gets.chop.gsub(/(-...|-)(?=(-|-...)*-$)/){$1==?-??R:?J})=~/_/??!:z.chop

на два

puts (z=gets.chop.gsub(/-...(?=(-|-...)*-$)/,?J).tr(?-,?R))=~/_/??!:z.chop

дали ще кілька символів. Нарешті мені вдалося позбутися цієї проблеми в кінці рядка, але ціною: виявлення несправностей коштує ще кілька символів.


Ви можете зберегти 3 символи, змінивши останній рядок на z!=?-&&$><<?!. Крім цього, чудове рішення, +1!
Вентеро

@ Вентеро У мене було те, що ставити перший тест не вдалося через відсутність результатів для "-" ;-)
Говард

Гм, виявляється, що в моєму скрипті PowerShell крихітна помилка. Він, мабуть, не приймає жодних даних для тесту 2 і не приймає його до тесту 1. Це, мабуть, дивно. Я спробую виправити.
Joey

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

@Joey Danke Nun sind es 90 ;-)
Говард

1

Perl - 71 60

$_=<>;y/-/R/;s/R...(?=(R(...)?)*R$)/J/g;print/_/?"!":s/.$//r

Тепер проходить усі тести. :) Виявляється, я видалив останнього персонажа занадто рано ... і половина мого оригінального регулярного виразка була повністю зайвою.

$ _ = $ ARGV [0]; y / - / R /; s / (R ... (? = R)) (R * (? = R)) / J $ 2 / g; рубати; друкувати / /? "!": $ , $ /

Ще одне рішення для регулярного генерування, передає 5 тестових вікон на посаду.

Можна скоротити, працюючи як однолінійний з, -Eа sayне print, але тоді perl намагається інтерпретувати вхід як комутатор ... ( Unrecognized switch: -_-_-_-_-_-)


У запитанні зазначено, що введення подано на stdin. При зміні рішення для читання з stdin замість використання $ARGVвоно все ще не дає 108 тестових скринь з тестових сценаріїв.
Вентеро

@ Вентеро Ой, ой ... я думаю, я знаю, чому це робиться, я незабаром виправлю ... це те, що я отримую за те, щоб не пройти всі тести ...> _>
swilliams

Ну, намір сценаріїв полягав у тому, щоб дозволити людям легко перевірити правильність та відповідність специфікації :-)
Joey

@Joey Проблема полягала в тому, що мені якось вдалося переплутати 'тестовий скрипт' з 'опорною реалізацією', поки Вентеро не опублікував свій коментар :) ... сценарій зараз майже виправлений, хоча в даний час виходить лише 20, усі помилкові негативи
swilliams

1

Пітон - 89 93 97 93 символів

Лише тому що.

import re;i=re.sub('...(?<!---)-','J',input()[1:]);print('!'if'_'in i else re.sub('-','R',i))

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


Позичивши один з працюючих регексів, він закінчується як

import re;i=re.sub('-...(?=(-|-...)*-$)','J',input());print('!'if'_'in i else re.sub('-','R',i))

З 96 символами.


1
Проходить лише 728 тестових випадків. Насправді я поставив тестові сценарії не просто так.
Joey

@Joey: Схоже, я забув відрізати провідного персонажа з вхідних даних. Дурний мене. Зараз це виправлено.
JAB

Ще проходить лише 766/849 тестів.
Вентеро

1

Haskell, 90 символів:

Моє перше рішення - довге, але працює в лінійний час, використовуючи динамічне програмування. :) 150 символів :

x!y="!"
q '-'=max
q c=(!)
s i=r where r=zipWith3 q i(0&'R')$3&'J';n&c="":replicate n"!"++map(c#)r
c#"!"="!"
c#s=c:s
main=interact$reverse.last.s.init

Друге рішення - набагато повільніше (експоненційний час), але набагато коротше: 90 символів

s"-\n"=""
s('-':t)=max('R'#s t)$'J'#s(drop 3 t)
s _="!"
c#"!"="!"
c#s=c:s
main=interact s
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.