Чи вдарить промінь?


31

Лазер стріляє прямим променем в одному з чотирьох ортогональних напрямків, позначених символом <>^v. Визначте, чи вдарить він у ціль Oпрямокутної сітки.

Кожен із них потрапить (True):

.....
...O.
.....
...^.
.....

>O.
...

v....
O....

...........
...........
O.........<
...........

Вони будуть пропускати (помилково):

......
......
.^..O.

......
.....>
O.....
......
......


.O.
...
.v.

.....<.
..O....

Вхід: прямокутна сітка .розміром принаймні 2х2, рівно одна мішень Oта один лазер <>^v. Рядки можуть представляти собою список рядків, двовимірний масив або вкладений список символів або окремий розділений рядком нового рядка з необов'язковим заднім рядком.

Вихід : Послідовне значення, якщо лазерний промінь потрапляє в ціль, і стійке хибне значення, якщо воно не вистачає.

Я буду розглядати подання, які не використовують регулярні вирази (або вбудоване узгодження рядків на основі шаблону) як окрему категорію. Якщо ви введете (no regex)після назви мови, ваша відповідь з’явиться окремо в таблиці лідерів.



6
Я сподівався, що ви включите дзеркала з /та \ . Можливо, для іншого питання ...
vsz

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

2
@Mego Я не згоден; за цією логікою, звичайний привіт світовий виклик - це копія десятків інших викликів одночасно. У будь-якому випадку, дякую, що сповістили мене про потужність, яку мені зараз доводиться закривати / відновлювати виклики коду для гольфу, я цього не знав.
aditsu

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

Відповіді:


27

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

\>|\<l|\^u|\vd).,\O

Специфікація для цього може бути реалізована максимально буквально, не потрібно думати.


6
Чи можете ви додати пояснення, як це працює?
Фонд позову Моніки

5
@QPaysTaxes Доки feersum не обійдеться, сподіваємось, це допоможе: Равлики - це двовимірна мова, що відповідає мові. udlrвстановити напрямок равлики вгору / вниз / вліво / вправо. |працює так, як це робиться в регулярному регулярному вираженні, і )не потребує відповідних відкритих дужок. Отже, код досить безпосередньо перекладається на "Знайти один із них v<>^та встановити напрямок відповідним чином, а потім спробувати знайти О в цьому напрямку".
FryAmTheEggman

Так, що сказав Еггман. Єдине, що ,схоже на *регулярний вираз.
feersum

13

Сітківка, 56 52 42 38 31 30 байт

Збережено 1 байт завдяки @ MartinBüttner

O.*<|>.*O|[vO](.*¶)[^O]*[O^]\1

Зловживає властивостями прямокутників. Потрібен вхід, щоб мати зворотний новий рядок.

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

Пояснення

Це працює в трьох частинах:

  • Узгодження >
  • Узгодження <
  • Узгодження ^і vце тому , що логіка ^і vдійсно те ж саме, тільки персонажі.

Перевірка <

Це просто:

O.*<

Це збігається з O, необов'язково, після чого символами не-нового рядка, а<

Перевірка >

Це майже те саме, що і попередній спосіб, за винятком навпаки. Спочатку >збігається а, потімO

Підтвердження ^таv

Це було важко для гольфу, і реклама рекламних даних завжди була дійсною. По- перше, ми зіставляємо це vабо O:

[vO]

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

(.*\n)

Далі це може поділитися на дві частини, я розкрию першу:

Отже, по-перше, ми підходимо до наступного O, використовуючи:

[^O]*O

Це необов'язково відповідає всім не Oсимволам, поки Oне зустрінеться ан , якщо це успішно, то воно продовжується ... якщо ні, то відбувається наступне ...

Тепер він намагається знайти ^:

[^^]*\^

^є спеціальним символом у регулярному виразі, тому його потрібно уникати. [^^]відповідає всім символам, за винятком того ^, що це працює так само, як і вище, якщо це вдається, то відбувається наступне ...

Отже, зараз одне з вищезазначених успішно збігається, \1перевіряє і бачить, чи група захоплення раніше (.*\n), ця група захоплення зберігала кількість .s, яке було після того vчи Oраніше, тому тепер \1просто перевіряє, чи кількість крапок у те саме.


Ви можете зберегти байт, скориставшись замість \n(Retina може обробляти вихідний код у ISO 8859-1.)
Martin Ender

@ MartinBüttner думав, що заміни є лише \ n, дякую за пораду!
Пуховик

ні, він не працює ніде у вихідному коді. Після розбиття файлу на рядки, перше, що робить Retina, - це замінити всюди, перш ніж робити подальший аналіз.
Мартін Ендер

9

Java (без регулярного вираження), 413 412 246 242 212 211 209 198 байт

Змагатися у гольф-викликах з використанням Java має менше сенсу, ніж брати участь у гонках на велосипеді Формули-1, але я не завжди займаюся думками, які мають сенс.

Ось моє надзвичайно довге java рішення Golfed версія

boolean l(char[][]w){int[]t={},l={};for(int y=0;y<w.length;y++)for(int x=0;x<w[0].length;x++){if(w[y][x]=='O')t=new int[]{x,y};if(w[y][x]=='<')l=new int[]{x,y,1};if(w[y][x]=='>')l=new int[]{x,y,2};if(w[y][x]=='v')l=new int[]{x,y,3};if(w[y][x]=='^')l=new int[]{x,y,4};};return(l[2]==1&&l[1]==t[1]&&l[0]>t[0])||(l[2]==2&&l[1]==t[1]&&l[0]<t[0])||(l[2]==3&&l[0]==t[0]&&l[1]<t[1])||(l[2]==4&&l[0]==t[0]&&l[1]>t[1]);}

і невольф

boolean l(char[][] w) {
    int[] t = {}, l = {};
    for (int y = 0; y < w.length; y++)
        for (int x = 0; x < w[0].length; x++) {
            if (w[y][x] == 'O')
                t = new int[] { x, y };
            if (w[y][x] == '<')
                l = new int[] { x, y, 1 };
            if (w[y][x] == '>')
                l = new int[] { x, y, 2 };
            if (w[y][x] == 'v')
                l = new int[] { x, y, 3 };
            if (w[y][x] == '^')
                l = new int[] { x, y, 4 };
        }
    ;
    return (l[2] == 1 && l[1] == t[1] && l[0] > t[0])
            || (l[2] == 2 && l[1] == t[1] && l[0] < t[0])
            || (l[2] == 3 && l[0] == t[0] && l[1] < t[1])
            || (l[2] == 4 && l[0] == t[0] && l[1] > t[1]);
}

Здається, моя вся концепція була неправильною, ось моє коротше рішення

boolean z(char[][]w){int x=0,y=0,i=0,a=w.length,b=w[0].length;for(;w[y][x]!=79;)if(++y==a){y=0;x++;}for(;i<(a<b?b:a);)if(i<b&w[y][i]==(i<x?62:60)|i<a&w[i][x]==(i++<y?'v':94))return 1<2;return 1>2;}

і безгольова версія

oolean z(char[][] w) {
        int x = 0, y = 0, i = 0, a = w.length, b = w[0].length;
        for (; w[y][x] != 79;)
            if (++y == a) {
                y = 0;
                x++;
            }
        for (; i < (a < b ? b : a);)
            if (i < b & w[y][i] == (i < x ? 62 : 60) | i < a
                    & w[i][x] == (i++ < y ? 'v' : 94))
                return 1 < 2;
        return 1 > 2;
    }

EDIT Я переписав код для пошуку "O", тепер він містить один цикл набагато коротший, і я також використав пропозицію @Frozn, щоб замінити деякі символи на їх значення ascii.

В результаті ще 30 байт кусає пил.

Ще одна пропозиція від @Frozn, і ми на пару байтів ближче до рішення Python

Ще перезапишіть один цикл і об'єднайте два, якщо заяви


1
+1 Однак ви можете видалити пробіл між returnі (зберегти байт. Пробіл не потрібен, коли ваше повернене значення знаходиться в дужках (або лапки для Strings). Джерело з порад з коду Java для гольфу.
Кевін Круїссен

@KevinCruijssen не економить багато, але дякую :)
user902383

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

Ви можете замінити символи їх ASCII - значення: 'O' = 79, '>' = 62, '<' = 60, '^' = 94. Для 'v' це 118, але це не скорочує код.
Frozn

@Frozn, як сказав Кевін, у кожному байті.
user902383

7

MATL (без регулярного вираження), 26 25 24 22 байт

'>v<^'XJymfX!tZpYswJm)

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

Модифікована версія для всіх тестових випадків

Пояснення

        % Implicitly grab input
'>v<^'  % String literal indicating the direction chars
XJ      % Store in the J clipboard
y       % Copy the input from the bottom of the stack
m       % Check to see which of the direction chars is in the input. The
        % result is a 1 x 4 logical array with a 1 for the found direction char
f       % Get the 1-based index into '>v<^' of this character
X!      % Rotate the input board 90 degrees N times where N is the index. This
        % Way we rotate the board so that, regardless of the direction char,
        % the direction char should always be BELOW the target in the same column
t       % Duplicate
Zp      % Determine if any elements are prime ('O' is the only prime)
Ys      % Compute the cumulative sum of each column
w       % Flip the top two stack elements
J       % Grab '>v<^' from clipboard J
m       % Create a logical matrix the size of the input where it is 1 where
        % the direction char is and 0 otherwise
)       % Use this to index into the output of the cumulative sum. If the 
        % direction char is below 'O' in a column, this will yield a 1 and 0 otherwise
        % Implicitly display the result

@LuisMendo Тепер, щоб з’ясувати, як позбутисяJ
Suever

Я не знаю MATL, тому це може бути дурним питанням, але чому 0 прем'єр?
Ніл

3
@Neil Це лист 'O', а не номер 0. ASCII код для письма 'O'це79
Луїс Mendo

Тьфу, я думаю, я б все-таки обдурив, якби ти шукав непарні номери.
Ніл

5

CJam (без регулярного вираження), 25

Раніші версії були помилковими, це доведеться робити зараз:

q~_z]{'.-HbI%}f%[HF].&~+,

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

Пояснення:

q~         read and evaluate the input (given as an array of strings)
_z         copy and transpose
]          put the original grid and transposed grid in an array
{…}f%      map the block to each grid (applying it to each string in each grid)
  '.-      remove all dots (obtaining a string of 0 to 2 chars)
  Hb       convert to base H=17, e.g. ">O" -> 62*17+79=1133
  I%       calculate modulo I=18
[HF]       make an array [17 15]
.&         set-intersect the first array (mapped grid) with 17 and 2nd one with 15
~+         dump and concatenate the results
,          get the array length

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

"хорошими" рядками для вихідної сітки є "> O" і "O <", і вони дають результат 17
"хороших" рядків для перенесеної сітки "vO" і "O ^", і вони дають результат 15
"поганий" рядки для обох сіток: ">", "<", "^", "v", "O", "", "O>", "Ov", "<O", "^ O", і вони дають результати 8, 6, 4, 10, 7, 0, 1, 3, 1, 3


3

Python 3 (без регулярного вираження), 184 байти.

Ураг для злому евалу!

def f(a,o=0,d={},q=''):
 for r in a:
  i=0
  for c in r:d[c]=o,i;i+=1;q=(c,q)[c in'O.']
  o+=1
 z,y=d['O'];e,j=d[q];return eval("z%se and y%sj"%(('><'[q<'v'],'=='),('==',q))[q in'><'])

3

TSQL (sqlserver 2012) (без регулярного вираження), 358 байт

DECLARE @ varchar(1000)=
'......'+ CHAR(13)+CHAR(10)+
'......'+ CHAR(13)+CHAR(10)+
'...0..'+ CHAR(13)+CHAR(10)+
'...^..'+ CHAR(13)+CHAR(10)
;

WITH C as(SELECT
number n,SUBSTRING(@,number,1)a,1+min(IIF(SUBSTRING(@,number,1)=char(13),number,99))over()m
FROM master..spt_values
WHERE'P'=type and
SUBSTRING(@,number,1)in('>','<','^','v','0',char(13)))SELECT
IIF(c.n%c.m=d.n%c.m and c.a+d.a in('0^','v0')or
c.n/c.m=d.n/c.m and c.a+d.a in('>0','0<'),1,0)FROM c,c d
WHERE c.n<d.n and char(13)not in(c.a,d.a)

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

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



2

JavaScript (ES6), 78 байт

s=>s.match(`>.*O|O.*<|(?=v)([^]{${l=s.search`\n`+1}})+O|(?=O)([^]{${l}})+\\^`)

Зрозуміло. Виявилося в принципі подібним до відповіді Рубі.


2

Ruby, 71 55 54 байт

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

Повертає індексний номер (truthy), якщо є збіг.

Тепер з аналогічною хитрістю до відповіді @Downgoat Retina, одночасно збігаючи пучки вниз і вгору.

->m{m=~/>\.*O|O\.*<|(?=[vO])(.{#{??+m=~/\n/}})+[O^]/m}

2

JavaScript (ES6) (без регулярного вираження), 126 байт

s=>([n,o,l,r,u,d]=[..."\nO<>^"].map(c=>1+s.indexOf(c)),l>o&l-o<n&l%n>o%n||r&&r<o&o-r<n&r%n<o%n||u>o&u%n==o%n||d&&d<o&d%n==o%n)

Де \nпредставляє буквальний символ нового рядка.


2

Clojure (без регулярного вираження), 293 байт

(defn z[f](let[v(sort(keep-indexed(fn[i v](if(some #{v}[\v\>\<\^\O])[(if(= v\O)\& v)i]))f))l(+(.indexOf f"\n")1)d((nth v 1)0)q((nth v 1)1)p((nth v 0)1)r(=(quot p l)(quot q l))i(> q p)](cond(= d\^)(and i(=(mod(- q p)l)0))(= d\v)(and(not i)(=(mod(- p q)l)0))(= d\>)(and(not i)r):else(and i r))))

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

Ви можете спробувати тут https://ideone.com/m4f2ra


2

Python (без регулярного вираження), 105 байт

def f(s):t=s.strip('.\n');return not['\n'in t,len(t)%(s.find('\n')+1)!=1,1]['>O<vO^'.find(t[0]+t[-1])//3]

повертає істинне чи помилкове

По-перше, смужки "." і '\ n' з кінців, щоб символи, що цікавлять, '0 <> v ^', були першими та останніми символами.

'>O<vO^'.find(t[0]+t[-1])//3- перевіряє, чи символи є потенційно дійсним розташуванням. Оцінюється до 0 для '> O' або 'O <', до 1 для 'vO' або 'O ^', і до -1 для всього іншого.

'\n'in t- перевіряє, чи символи знаходяться в різних рядках,
len(t)%(s.find('\n')+1)!=1- перевіряє, чи знаходяться вони в різних стовпцях, і
1- є за замовчуванням

У notінвертує результат вибирається зі списку, так що returnвираз еквівалентно:

t[0]+t[-1] in '>0<' and '\n' not in t or t[0]+t[-1] in 'vO^' and len(t)%(s.find('\n')+1)==1

2

Юлія (без регексу), 98

a->(c=rotr90(a,findlast("i1Q/",sum(a-46)));
    f(n)=find(any(c.!='.',n));b=c[f(2),f(1)];
    (b'*b)[1]==97)

Функція, що працює на масиві символів, нормалізується обертанням, видаляючи рядки та стовпці, що містять лише крапки за допомогою індексації діапазону, і, нарешті, перевіряє місце розташування 'O' з урахуванням, якщо решта b - вектор стовпця або рядка за допомогою множення матриці.

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


1

Python 2 (без регулярного вираження), 268 байт

import numpy
def q(i):
 s=numpy.asmatrix(i)
 for n in s:
  n=n.tolist()[0]
  try:
   a=n.index("0")
   if n.index(">")<a or n.index("<")>a:return 1
  except:0
 for n in range(len(i)):
  c=[x[0] for x in s[:,n].tolist()]
  try:
   a=c.index("0")
   if c.index("v")<a or c.index("^")>a:return 1
  except:0
 return 0

Значення Truthy і Falsy, що повертаються функцією, дорівнюють 1 і 0 відповідно.

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

Будь-які пропозиції будуть дуже вдячні!


1

C # (без Regex), 282 байти

bool F(char[,]b){int k=0,l=1,m=1,n=0,o=0;for(int x=0;x<b.GetLength(0);x++)for(int y=0;y<b.GetLength(1);y++){char i=b[x,y];if(i=='O'){k=x;l=y;}if(new[]{'<','>','^','v'}.Contains(i)){m=x;n=y;o=i;}}return(o==60&&k==m&&l<n)||(o==62&&k==m&&l>n)||(o==94&&l==n&&k<m)||(o==118&&l==n&&k>m);}

Працює як версія java, але перекладається та зменшується

Розширено (пояснення включено):

bool F(char[,] b)
{
    // declare variables for goal x, goal y, laser x, laser y, and laser direction respectively (laser direction is char code for directions)
    int k = 0, l = 0, m = 0, n = 0, o = 0;
    // go through each cell
    for (int x = 0; x < b.GetLength(0); x++)
    {
        for (int y = 0; y < b.GetLength(1); y++)
        {
            // get cell contents
            char i = b[x, y];
            // set goal position if goal
            if (i == 'O')
            {
                k = x;
                l = y;
            }
            // set laser position and direction if laser
            if (new[]{ '<', '>', '^', 'v' }.Contains(i))
            {
                m = x;
                n = y;
                o = i;
            }
        }
    }
    // check everything is on the same line and in right direction
    return (o == 60 && k == m && l < n) ||
           (o == 62 && k == m && l > n) ||
           (o == 94 && l == n && k < m) ||
           (o == 118 && l == n && k > m);
}

0

C (ANSI) (Без регулярного вираження), 237 байт

#define l b[1][i]
main(i,b,c,d,x,y,z,p)char **b;{for(y=z=i=0,x=1;z<2&&(l==10?x=0,++y:1);i++,x++)if(l>46){if(l!=79)p=l;if(!z++)c=x,d=y;}i--;x--;z=(c==x)*((p=='v')*(l==79)+(p==94)*(l==p))+(d==y)*((p==60)*(l==p)+(p==62)*(l==79));return z;}

Розширено:

#define l b[1][i]
main(i,b,c,d,x,y,z,p)char **b;{
    for(y=z=i=0,x=1;z<2&&(l==10?x=0,++y:1);i++,x++)
        if(l>46){if(l!=79)p=l;if(!z++)c=x,d=y;}
    i--;x--;
    z=(c==x)*((p=='v')*(l==79)+(p==94)*(l==p))+(d==y)*((p==60)*(l==p)+(p==62)*(l==79));
    printf("%i\n",z);
    return z;
}

Я думаю, що тут я застосував гідно інший підхід порівняно з реалізацією Java або C #. Я отримав координати 'O' та стрілки ((c, d) та (x, y)), а потім порівняв їх, щоб побачити, чи стрілка вказує у правильному напрямку.

Повертає 0, якщо невірно і 1, якщо істинно


0

Grime v0.1 , 31 байт

n`\>.*a|a.*\<|\v/./*/a|a/./*/\^

Не дуже цікаве рішення. Принти 1для правдивих примірників і 0для хибних. Спробуйте в Інтернеті!

Пояснення

Ми просто шукаємо вхідний прямокутник для малюнка мінімального розміру (n × 1 або 1 × n), який містить лазер і ціль у правильному порядку. n`Прапор робить інтерпретатор друк кількості матчів, з яких завжди буде в основному один. Решта рядка складається з чотирьох шаблонів, розділених на |-символи, що означає логічний АБО: прямокутник узгоджується, якщо він відповідає одному з шаблонів. Шаблони працюють наступним чином:

\>.*a    Literal ">", horizontal row of any chars, one alphabetic char
a.*\<    One alphabetic char, horizontal row of any chars, literal "<"
\v/./*/a Literal "v", on top of vertical column of any chars, on top of one alphabetic char
a/./*/\^ One alphabetic char, on top of vertical column of any chars, on top of literal "^"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.