Розблокування секретів у 1-мірному лабіринті


41

Фон

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

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

Один вниз, ще багато ...

Виклик

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

Вхідним завданням цього завдання є лабіринт: одна рядок, що містить лише символи [A-Za-z^$ ]. Глосарій:

  • ^- Стартовий простір. Вхід буде містити рівно один ^.
  • $- Вихід (свобода!). Вхід буде містити рівно один $.
  • [A-Z]- Великі літери означають двері. Ви можете пройти через ці двері, лише якщо ви вже зібрали необхідний ключ.
  • [a-z]- Малі літери означають клавіші. Ви збираєте ці ключі, переходячи до місця, яке містить ключ.

Тут буде максимум одна з великих літер. Це означає, що загальна кількість дверей буде становити 0-26 включно.

Кожна заблокована двері [A-Z]матиме рівно один відповідний нижній ключ [a-z]. На вході може бути будь-яка кількість пробілів ( ).

Усі двері будуть праворуч від початку та ліворуч від виходу. Таким чином зайвих дверей не буде. Усі входи будуть вирішувані.

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

Алгоритм

Ваш методичний підхід до виходу з цього жалюгідного місця полягає в наступному:

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

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

Підрахунок

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

Приклади

У цих прикладах я залишив пробіли як підкреслення для читабельності людини.

Введення є _a_^_A__$__. Вихід є 11. Ви робите 1крок вперед, помічаєте, що у вас немає ключа від Aдверей, а потім про обличчя. Ви йдете назад, поки не займете простір, що містить a( 3кроки назад, тепер 4усього). Потім ви йдете вперед, поки не займете простір, що містить вихід ( 7кроки вперед, 11усього).

Введення є b__j^__a_AJB_$. Вихід - 41Ви робите дві окремі поїздки до задньої частини лабіринту, одну для отримання jключа, а наступну для отримання bключа.

Введення є __m__t_^__x_T_MX_$____. Вихід є 44. Ви не будете робити жодної додаткової поїздки, щоб отримати xключ, оскільки ви забрали його на шляху від початку до дверей T.

Введення є g_t_^G_T$. Вихід є 12. Ви не можете переміститись у Gпростір без клавіші та негайно навколо обличчя. Вам пощастило забрати tключ на шляху до gключа і тим самим відкрити обидві двері на шляху до свободи.

Введення є _^_____$. Вихід є 6. Це було легко.

Керівні принципи вводу / виводу та критерій виграшу

Застосовуються стандартні правила вводу / виводу. Це проблема з .


17
Окрім приємного виклику, я хотів би зазначити, наскільки добре формулювання та пояснення
Луїс Мендо

4
"Таким чином, зайвих дверей не буде". Я думаю , що Aв bA^aB$не буде зайвим ні. ;)
Мартін Ендер

4
@orlp Мені більше цікаво бачити, як люди гольфують за цим блукаючим у темряві алгоритмом. Мабуть, банально зробити оптимальне рішення: "йди, діставай усі ключі, потім відкрий усі двері".
турбулентність

2
@PeterTaylor і turbulencetoo Ні, це не хто, хто скаже, що всі клавіші знаходяться з лівого боку, а всі двері - з правого? І зайві ключі / двері теж будуть цікаві. Це було б досить цікаво, оскільки це означало б розв'язання графіка залежності.
orlp

5
У кожної двері є ключ. У кожного ключа є двері?
user2357112 підтримує Monica

Відповіді:


3

CJam, 45

1q_'$#<'^/~\W%:A;ee{~32+A#)_T>{:T+2*+}&]0=)}/

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

Пояснення:

1         initial step count; this 1 is actually for the last step :)
q_'$#<    read the input and only keep the part before the '$'
'^/~      split by '^' and dump the 2 pieces on the stack
\W%:A;    take the first piece, reverse it and store it in A
ee        enumerate the other piece (making [index char] pairs)
{…}/      for each [index char] pair
  ~32+    dump the index and character on the stack, and add 32 to the character;
           uppercase letters become lowercase and other chars become garbage
  A#)     find the index of this character in A and increment it (not found -> 0)
  _T>     check if this index (number of steps from '^' back to the key)
           is greater than T (which is initially 0)
  {…}&    if that's true (we need to go back), then
    :T    store that index in T (keeping track of how far we go back before '^')
    +     add to the other index (from the pair, number of steps we took after '^')
    2*    double the result (going back and forth)
    +     add it to the step count
  ]0=     keep only the first value from the bottom of the stack (step count)
           (if the condition above was false, we'd have 2 extra values)
  )       increment the step count (for the current step)

7

Pyth, 51 байт

JxQ"^"K-xQ"$"JVQI&}NrG1>JxQrN0=JxQrN0=+K*2t-xQNJ;pK

підсумовуйте відстань між дверима та її ключем (удвічі, щоб здійснити зворотну поїздку), ігноруючи "вкладені" клавіші та відстань від початку до кінця:

JxQ"^"                                              #Initialize the farther point with the starting position
      K-xQ"$"J                                      #Initialize the step counter with the difference between the exit and the start
              VQ                                    #iterate over the input
                I&}NrG1>JxQrN0                      #check if is upper and if the keys is father than one stored (to eliminate nested keys)
                              =JxQrN0               #update the farther key
                                     =+K*2t-xQNJ;   #update step counter with the round trip door<>key
                                                 pK #print the step counter

той самий алгоритм у python2.7:

lab=raw_input()
farther_key=lab.index('^')
steps = lab.index('$') - farther_key
for i in lab:
    if i.isupper():
        if farther_key> lab.index(i.lower()):
            farther_key=lab.index(i.lower())
            steps+=((lab.index(i) - farther_key)-1)*2
print steps

5

Python 2, 155 154 134 128 байт

Редагувати: Дякую @ user2357112 та @loovjo за їх коментарі, які допомогли мені збрити ще 20 26 байт від мого рішення!

def f(l):
 i=l.index;b=i('^');t=i('$')-b
 for d in filter(str.isupper,l):
  k=i(d.lower())
  if k<b:b=k;t+=2*(i(d)-k-1)
 print t

1
Ви можете поєднати другий і третій рядки з комою з крапкою з комою, зберігаючи один байт. Крім того, змінна i здається непотрібною в циклі.
Loovjo

Домовились про 2-й та 3-й рядки @Loovjo, але чому ти вважаєш, що iце зайве? iвідслідковує положення двері, яка зараз обробляється, і потрібна, якщо її ключ ще не був підібраний (тобто якщо k- положення ключа - менше, ніж f- найдалі, з якого ми пішли - тоді нам потрібно додати 2*(i-k-1)кроки до нашої загальної (пішки ліворуч, щоб дістати ключ, і пішки праворуч до дверей) ...?
Кен 'Джоуї' Мошер

1
Але чи не iможна було замінити l.index(d)на п'ятому рядку, а призначення видалити на четвертому?
Loovjo

Окремі eта fзмінні виглядають зайвими. Також ви можете зберегти купу символів, зберігаючи l.indexзмінну.
user2357112 підтримує Моніку

@loovjo: Так, ти маєш рацію ... Спочатку я неправильно зрозумів ваш коментар. @ user2357112: абсолютно правильно. xє зайвим. Здогадайтесь, мій гольф нобі-інсе показує. :) Дякую за допомогу!
Ken 'Joey' Mosher

4

C, 136 байт

q,x,p[300],z,c,k;main(i){for(;p[c=getchar()]=++i,c-36;z&&(k+=(x=p[c+32])&&x<q?(q=q>x?x:q,2*i-2*x-1):1))z=p[94],q||(q=z);printf("%d",k);}

4

PHP 5.3, 123 байти

Це моє перше повідомлення про Code Golf, сподіваюся, це якість гольфу досить висока для першого посту. Однозначно веселий виклик та дивовижне запитання!

function n($m){while('$'!=$o=$m[$i++])$o=='^'?$b=$i+$c=0:$o>'Z'||$b<=$k=stripos($m,$o))?$c++:$c+=2*$i-3-2*$b=$k;return$c;}

Ця програма добре зловживає тим, що PHP не потребує того, щоб попередньо оголосити будь-які змінні, перш ніж використовувати їх.

Також у моєму остаточному рішенні виявилося на пару байт коротше, щоб почати з 0 і скинути кількість кроків, коли знайдеться символ запуску, а не починати з '^'.

Будь-які поради, безумовно, вітаються!


3

JavaScript (ES6), 110 байт

s=>(i=c=>s.indexOf(c),p=i`^`,l=i`$`-p,s.replace(/[A-Z]/g,(c,j)=>p>(t=i(c.toLowerCase()))?l+=j-(p=t)-1<<1:0),l)

Порт @ Роба відповідь Pyth.


2

Пітон 2.7, 234 199 179

a=raw_input()
x=a.index
v=x('^')
b=x('$')-v
l=filter(str.islower,a[:v])[::-1]
for i in filter(str.isupper,a):
 k=i.lower()
 if k in l:b+=(x(i)-x(k)-1)*2;l=l[l.index(k)+1:]
print b

1

AWK, 174 байт

func f(xmS){x+=S
c=a[x]
if(c~/^[A-Z]/&&!k[c]){C=c
S=-S
s--}else{c=toupper(c)
k[c]=1
s++
if(c==C){S=-S;C=9}}if(c=="$"){print s}else f(x,S)}{split($0,a,"")
f(index($0,"^"),1)}

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

Зверніть увагу, що я використовую gawk. Деякі реалізації файлу AWKможе не розділити рядок ""таким чином.


1

C #, 309 байт

class P{static void Main(string[]a){string m=Console.ReadLine(),k="";var f=true;char b,c=b=' ';int j=m.IndexOf('^'),t=0;for(;m[j]!='$';j+=f?1:-1){c=m[j];if(char.IsUpper(c)){if(k.IndexOf(char.ToLower(c))<0){f=!f;b=c;t--;}}if(char.IsLower(c)){k+=c;if(char.ToUpper(c)==b){f=!f;t--;}}t++;}Console.WriteLine(t);}}

Негольована версія:

    class P
{
    static void Main(string[] a)
    {
        string m = Console.ReadLine(), k = "";
        var f = true;
        char b, c = b = ' ';
        int j = m.IndexOf('^'), t = 0;
        for (; m[j] != '$'; j += f ? 1 : -1)
        {
            c = m[j];
            if (char.IsUpper(c))
            {
                if (k.IndexOf(char.ToLower(c)) < 0)
                {
                    f = !f; b = c; t--;
                }
            }

            if (char.IsLower(c))
            {
                k += c;
                if (char.ToUpper(c) == b) { f = !f; t--; }
            }


            t++;
        }
        Console.WriteLine(t);
        Console.ReadKey();

    }
}

Тут нічого фантазії, просто перейдіть через рядок і змініть напрямок, залежно від символу та того, чи міститься ключ у рядку ключів.

m = рядок лабіринту

k = рядок клавіш

f = напрямок (правда вперед у лабіринті)

b = ключ, який потрібно шукати під час зворотного відстеження

c = заповнювач місця для m [j], щоб зберегти деякі байти через часте використання

j = індекс char рядка, який потрібно переглянути

t = кількість

Ще відносно новачка в гольфі, тому якщо ви бачите десь, я можу зменшити це, дайте мені знати!

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