Где я сейчас?

21

Где я сейчас?

Учитывая строку d, содержащую только буквы NSWE, определите координаты, которые я путешествовал (слева направо, жадно потребляя) и окончательную координату, где я живу.

Правила чтения координат слева направо:

  • Если следующий символ NилиS :
    • Если символ после Nили Sявляется другим NилиS :
      • Потребляйте только первое Nили S.
      • Выход [0,1] дляN
      • Выход [0,-1]дляS
    • Если символ после Nили Sявляется WилиE :
      • Потребляйте и Nили Sи Wили или E.
      • Выход [1,1]или [-1,1]для NEи NW, соответственно.
      • Выход [1,-1]или [-1,-1]для SEи SW, соответственно.
  • Если символ является Eили Wне предшествует SилиN :
    • Потреблять Eили W.
    • Выход [1,0]за E.
    • Выход [-1,0]за W.

Работал пример

NSWE

[0,1]   (North      N)
[-1,-1] (South-west SW)
[1,0]   (East       E)
[0,0]   (N+SW+E = Didn't actually move)

Обратите внимание, что это может быть в любом формате, вот другие примеры правильного вывода:

[[0,1],[-1,-1],[1,0],[0,0]]


[[[0,1],[-1,-1],[1,0]],[0,0]]


"0,1\n0,-1\n-1,0\n1,0\n0,0"

И т.д...


Больше примеров

SWSENNESWNE

[-1,-1]
[1,-1]
[0,1]
[1,1]
[-1,-1]
[1,1]
[1,0]

NNEESESSWWNW

[0,1]
[1,1]
[1,0]
[1,-1]
[0,-1]
[-1,-1]
[-1,0]
[-1,1]
[0,0]

NENENEE

[1,1]
[1,1]
[1,1]
[1,0]
[4,3]

NEN

[1,1]
[0,1]
[1,2]

EEE

[1,0]
[1,0]
[1,0]
[3,0]

правила

  • Вы можете выводить в любом удобном формате, который не нарушает лазейки.
  • Вы должны потреблять с жадностью, NWEникогда N,W,E, это всегда NW,E.
    • Это относится к: SW*, SE*, NW*, NE*.
    • Вы потребляете слева направо, жадно.
  • Это , выигрывает самый низкий счетчик байтов.
Урна волшебного осьминога
источник
«определите координаты, которые я путешествовал» : я не уверен, действительно ли это соответствует тому, что описано позже. Это больше похоже на «определить векторы всех моих ходов» . Только окончательный результат - фактические координаты.
Арнаулд
1
Тестовый пример, который приближается к этому [4, 3]или около того, сделает немного легче увидеть, что происходит в результатах теста.
Линн
3
Комплексные числа отформатированы как 1 , -1j, и (-1+1j)т.д. допустимый формат вывода?
Линн
2
Исходя из отсутствия этого случая в приведенных правилах и примерах, я предполагаю, что строка ввода никогда не будет заканчиваться на 'N' или 'S'?
Кевин Круйссен
1
Действительно ли жадное потребление отличается от этого? Так как NEэто просто N+Eне должно иметь значение?
Волшебник Пшеницы

Ответы:

7

Python 2 , 116 байт

import re
a=[(int(s,35)%5-3,('N'in s)-('S'in s))for s in re.findall('[NS][EW]?|.',input())]
print a,map(sum,zip(*a))

Попробуйте онлайн!

С выводом как [(3+4j), 1, -1j, …], 91 байт

lambda x:[sum(1j**(ord(c)%8%5)for c in s)for s in[x]+re.findall('[NS][EW]?|.',x)]
import re

Попробуйте онлайн!

Эта лямбда возвращает список гауссовых целых : первая - это конечная координата, а все остальные - шаги, необходимые для ее получения.

Линн
источник
5

Атташе , 80 байт

V#Sum##{Chop[1-ToBase[22260446188,3],2][Sum@Ords=>MatchAll[_,/"[NS][WE]|."]%11]}

Попробуйте онлайн!

Это анонимная функция, которая принимает один строковый аргумент.

объяснение

Первая задача - реализовать этап синтаксического анализа этого вопроса. Я нашел самое короткое использование простого регулярного выражения для разбора input ( _):

MatchAll[_,/"[NS][WE]|."]

Это соответствует всем вхождениям регулярного выражения [NS][WE]|., как видно из многих других ответов. Это жадно дает запрошенные направления.

Теперь мы собираемся применить хеш-функцию к каждому направлению. Мы берем кодовые точки каждого направления и суммируем их. Это дает следующее отображение:

Direction       Ord-sum
E               69
N               78
S               83
W               87
NE              147
SE              152
NW              165
SW              170

Мы попытаемся отобразить эти значения в меньшую область; Для этого полезно использовать модуль по модулю, и мы можем продемонстрировать, что наименьшее значение по модулю, которое приводит к уникальным значениям для всех заданных входных данных, равно 11. Сортировка по остаткам дает следующую таблицу:

Direction       Ord-sum         % 11
NW              165             0
N               78              1
E               69              3
NE              147             4
SW              170             5
S               83              6
SE              152             9
W               87              10

Теперь у нас есть входное соответствие, как кодировка Sum@Ords=>[...]%11. Далее мы должны преобразовать эти остатки в точки. Мы попытаемся получить другое отображение, которое означает, что вставка «разреженных значений» в хэши, которые не соответствуют направлениям, будет полезна:

Direction       Hash        Coordinates
NW              0           [-1, 1]
N               1           [0, 1]
--             (2)          [0, 0]
E               3           [1, 0]
NE              4           [1, 1]
SW              5           [-1, -1]
S               6           [0, -1]
--             (7)          [0, 0]
--             (8)          [0, 0]
SE              9           [1, -1]
W               10          [-1, 0]

В настоящее время у нас есть ряд точек, которые могут дать список, индексируемый по хешу:

[-1, 1] [0, 1] [0, 0] [1, 0] [1, 1] [-1, -1] [0, -1] [0, 0] [0, 0] [1, -1] [-1, 0]

Теперь мы сжимаем это, видя, как оно состоит только из -1s, 0s и 1s. Поскольку список представляет пары, мы можем сгладить список без потери данных. Затем, если мы возьмем каждое число xи вычислим 1-x, мы получим следующий список:

2 0 1 0 1 1 0 1 0 0 2 2 1 2 1 1 1 1 0 2 2 1

Мы можем преобразовать это в число 3 базы:

20101101002212111102213

Преобразование в базу 10:

20101101002212111102213 ≡ 2226044618810

Подводя итоги, мы взяли наши очки, развязали их, взяли каждый элемент, вычтенный из 1, и преобразовали из базы 3, дав нам 22260446188. Мы можем распаковать как таковой:

  1. Преобразовать в базу 3: ToBase[22260446188,3]
  2. Возьмите каждое число, вычтенное из единицы (самообращение): 1-ToBase[22260446188,3]
  3. Пересвязать список: Chop[1-ToBase[22260446188,3],2]

Это дает нам наш оригинальный набор пар. Затем мы можем выполнить вышеупомянутую индексацию следующим образом:

(chopped value)[hashes]

Поскольку в Attache индексирование по массиву возвращает все элементы, соответствующие этим индексам. (Итак,. [1,2,3,4][ [0,0,-1,1] ] = [1,1,4,2]) Теперь у нас есть направления пути, по которому прошел ОП. Осталось подсчитать сумму.

Таким образом, мы записываем этот результат в лямбду {...}и помещаем его как первую функцию в композицию функций ( a##b) со вторым существом V#Sum. Это форк, который с учетом входных данных xрасширяется до:

V[x, Sum[x]]

Sumпри задании 2D-массива происходит суммирование каждого столбца в массиве (в результате векторизованного суммирования). Таким образом, это соединяет направления с конечным пунктом назначения, и мы получаем наш конечный результат.

Конор О'Брайен
источник
4

JavaScript (ES6), 102 байта

Возвращает строку.

s=>s.replace(/[NS][EW]|./g,s=>(D=d=>!!s.match(d),x+=h=D`E`-D`W`,y+=v=D`N`-D`S`,[h,v]+`
`),x=y=0)+[x,y]

Попробуйте онлайн!

Arnauld
источник
Мне нравится использование шаблонных функций! : D
Конор О'Брайен
@ ConorO'Brien Да, они здесь очень удобны. Все заклинания хэширования колдовства, которые я вызывал, по крайней мере, немного длиннее.
Арнаулд
4

MATL , 45 байт

'NS' 'WE'Z*Z{2MhX{h'eklihfmj'X{YX9\3_2&YAqts

Попробуйте онлайн! Или проверьте все тестовые случаи .

Пояснение (с примером)

Рассмотрим ввод 'NSWE'в качестве примера.

'NS' 'WE'  % Push these two strings
           % STACK: 'NS', 'WE'
Z*         % Cartesian product. Gives a 4×2 char matrix
           % STACK: ['NW'; 'NE'; 'SW'; 'SE']
Z{         % Cell array of rows (strings)
           % STACK: {'NW', 'NE', 'SW', 'SE'}
2M         % Push again the inputs of the second-last function call
           % STACK: {'NW', 'NE', 'SW', 'SE'}, 'NS', 'WE'
h          % Concatenate horizontally
           % STACK: {'NW', 'NE', 'SW', 'SE'}, 'NSWE'
X{         % Cell array of individual elements (chars)
           % STACK: {'NW', 'NE', 'SW', 'SE'}, {'N', 'S', 'W', 'E'}
h          % Concatenate horizontally
           % STACK: {'NW', 'NE', 'SW', 'SE', 'N', 'S', 'W', 'E'}
'eklihfmj' % Push this string
           % STACK: {'NW', 'NE', 'SW', 'SE', 'N', 'S', 'W', 'E'}, 'eklihfmj'
X{         % Cell array of individual elements (chars)
           % STACK: {'NW','NE','SW','SE','N','S','W','E'},{'e','k','l','i','h','f','m','j'}
YX         % Implicit input. Regexp replace: replaces 'NW' by 'e', then 'NE' by 'k', etc.
           % Note that the two-letter combinations are replaced first, which implements
           % the greediness; and the target letters do not appear in the source, which
           % avoids unwanted interactions between replacements
           % STACK: 'hlj'
9\         % Modulo 9 (of codepoints), element-wise
           % STACK: [5, 0, 7]
3_2&YA     % Convert to base 3 with 2 digits. Gives a 2-column matrix
           % STACK: [1, 2; 0, 0; 2, 1]
q          % Subtract 1, element-wise
           % STACK: [0, -1; -1, -1; 1, 0]
tXs        % Duplicate. Sum of each column
           % STACK: [0, -1; -1, -1; 1, 0], [0, 0]
           % Implicit display
Луис Мендо
источник
4

Java (JDK 10) , 171 байт

s->{var r="";int i=0,l=s.length,c,x=0,y=0,Y,X;for(;i<l;X=c>1||i<l&&(c=~-s[i]/6%4)>1&&++i>0?c*2-5:0,r+=X+","+Y+" ",x+=X,y+=Y)Y=(c=~-s[i++]/6%4)<2?1-c*2:0;return r+x+","+y;}

Попробуйте онлайн!

Пояснения

Благодаря этому c=~-s[i]/6%4выполняется следующее отображение:

'N' -> ascii: 78 -> -1 = 77 -> /6 = 12 -> %4 = 0
'S' -> ascii: 83 -> -1 = 83 -> /6 = 13 -> %4 = 1
'W' -> ascii: 87 -> -1 = 86 -> /6 = 14 -> %4 = 2
'E' -> ascii: 69 -> -1 = 68 -> /6 = 11 -> %4 = 3
  • NSпроверяется с c<2и отображается на +1/ -1использование 1-c*2;
  • EWпроверяется с c>1и отображается на +1/ -1использование c*2-5.

кредиты

Оливье Грегуар
источник
Ах, вы опубликовали свой ответ на Java, пока я печатал объяснение. :) Поскольку мы оба используем совершенно разные подходы, я пока оставлю свой. Слишком плохие переменные, используемые в лямбда-выражениях, должны быть действительно окончательными, иначе вы могли бы вернуть String вместо List для сохранения байтов.
Кевин Круйссен
Спасибо, он сохранил только несколько байтов (4), но это лучше, чем ничего;)
Оливье Грегуар
@KevinCruijssen Спасибо, поначалу это казалось довольно очевидным, но я работал над другим подходом, который уменьшил мой счетчик байтов более чем на 30. «Разбор», а не «сопоставление».
Оливье Грегуар
1
Вздох .. 172 байта
Кевин Круйссен
1
@KevinCruijssen Извините, это беспорядок, объединяющий ваши изменения ... Я занят на работе, и я забываю обновить эту страницу ... В любом случае, спасибо всем ^^ 'Количество кредитов, скорее всего, ниже вашего фактического кредита. Извините за это тоже: s
Оливье Грегуар
3

Сетчатка 0.8.2 , 93 байта

.+
$&¶$&
\G[NS]?[EW]?
$&¶
G`.
W
J
%O`.
+`EJ|NS

m`^((J)?[EJ]*)((S)?[NS]*)
$#2$*-$.1,$#4$*-$.3

Попробуйте онлайн! Объяснение:

.+
$&¶$&

Дублируйте ввод.

\G[NS]?[EW]?
$&¶

Разделите первую копию на направления.

G`.

Удалите посторонние пустые строки, созданные вышеуказанным процессом.

W
J

Изменение Wв Jтак что она сортирует между Eи N. (Переход Eк между Sи Wбудет также работать.)

%O`.

Сортировка каждой строки в порядке.

+`EJ|NS

Удалите пары противоположных направлений (это влияет только на последнюю строку курса).

m`^((J)?[EJ]*)((S)?[NS]*)
$#2$*-$.1,$#4$*-$.3

Подсчитайте количество горизонтальных и вертикальных движений, добавляя знаки, где это необходимо.

Те из вас, кто знает разницу между Retina 0.8.2 и Retina 1, захотят указать, что я могу сохранить 2 байта в Retina 1, потому что он использует *вместо $*. Пока я был там, я пытался упростить процесс разделения, но я не смог еще больше уменьшить количество байтов, я смог сравнять его только с этим:

L$`$(?<=(.*))|[NS]?[EW]?
$&$1
Нил
источник
3

Java 10, 269 265 243 байта

s->{var r="";int x=0,y=0,t,X,Y,a;for(;!s.isEmpty();r+=X+"|"+Y+" ",s=s.substring(++t),x+=X,y+=Y){a=s.charAt(t=0);if(s.matches("[SN][WE].*")){X=s.charAt(1)<70?1:-1;Y=1-a%2*2;t++;}else{X=a<70?1:a>86?-1:0;Y=a>69&a<87?1-a%2*2:0;}}return r+x+"|"+y;}

Определенно не правильный язык для этого вызова ..

Попробуйте онлайн.

Объяснение:

s->{                  // Method with String as both parameter and return-type
  var r="";           //  Result-String, starting empty
  int x=0,            //  Ending `x`-coordinate, starting at 0
      y=0,            //  Ending `y`-coordinate, starting at 0
      t,X,Y,a;        //  Temp-integers
  for(;!s.isEmpty()   //  Loop as long as the input-String is not empty yet
      ;               //    After every iteration:
       r+=X+"|"+Y+" ",//     Append the current steps to the result-String
       s=s.substring(t),
                      //     Remove the first `t` characters from the input-String
       x+=X,y+=Y){   //      Append the ending `x`,`y` coordinates with the steps
    a=s.charAt(0);   //    Set `a` to the first character of the input-String to save bytes
    t=1;             //    Set `t` to 1
    if(s.matches("[SN][WE].*")){
                     //   Else-if the input-String starts with N/S followed by E/W:
      X=s.charAt(1)<70?1:-1;
                     //    Set `X` to 1 if 'E', -1 if 'W'
      Y=1-a%2*2;     //    Set `Y` to 1 if 'N', -1 if 'S'
      t++;}          //    Increase `t` by 1
    else{            //   Else:
      X=a<70?1:a>86?-1:0;
                     //    Set `X` to 1 if 'E', -1 if 'W', 0 if 'N' or 'S'
      Y=a>69&a<87?1-a%2*2:0;}}
                     //    Set `Y` 1 if 'N', -1 if 'S', 0 if 'E' or 'W'
  return r+x+"|"+y;} //  Append the ending coordinates, and return the result-String
Кевин Круйссен
источник
1
Ответы Java получают очки, хотя их получают все :).
Волшебная Урна Осьминога
@MagicOctopusUrn Правда. :) И я все еще наслаждаюсь игрой в гольф на Java, хотя ты никогда не будешь самым коротким ... Если только ты не один, кто ответит (получил два принятых ответа на Java ... XD). Однако для этой задачи ответ OlivierGrégoire на Java примерно на 70 байт короче, поэтому большинство голосов должно быть обращено к нему.
Кевин Круйссен
2

JavaScript (ES6), 102 байта

f=
s=>s.replace(/((N)|(S))?((E)|(W))?/g,(m,v,n,s,h,e,w)=>(x+=h=!w-!e,y+=v=!s-!n,m?[h,v]+`
`:[x,y]),x=y=0)
<input oninput=o.textContent=/[^NSEW]/.test(this.value)?``:f(this.value)><pre id=o>0,0

Возвращает строку.

Нил
источник
1

Рубин , 75 71 байт

->x{[*x.scan(/[NS][EW]?|./),x].map{|s|s.chars.sum{|c|1i**(c.ord%8%5)}}}

Попробуйте онлайн!

-4 байта благодаря benj2240.

Поскольку возвращение комплексных чисел выглядит приемлемым выходным форматом, я полагаю, что он не станет намного лучше, чем просто сделать порт очень приятного ответа Линн .

Кирилл Л.
источник
Очень хорошо. Вы можете сэкономить несколько байтов, пропустив внутренний map, передав его блок напрямую sum: Попробуйте онлайн!
benj2240
1

F # (моно) , 269 байтов

let f s=
 let l,h=(string s).Replace("NW","A").Replace("NE","B").Replace("SW","C").Replace("SE","D")|>Seq.map(function 'N'->0,1|'S'->0,-1|'W'-> -1,0|'E'->1,0|'A'-> -1,1|'B'->1,1|'C'-> -1,-1|'D'->1,-1)|>Seq.mapFold(fun(x,y) (s,t)->(s,t),(x+s,y+t))(0,0)
 Seq.append l [h]

Попробуйте онлайн!

Хенрик Хансен
источник
Привет, добро пожаловать в PPCG. К сожалению, вы пропустили последний элемент вашего вывода, который должен быть местом, где вы закончили. Так что для NSWEвас в данный момент выводится (0,1), (-1,-1), (1,0), а четвертый выход должен быть сумма этих координат, поэтому (0,0)(потому 0+-1+1 = 0и 1+-1+0 = 0).
Кевин Круйссен
@KevinCruijssen Хорошо, я этого не понял. Сделал обновление.
Хенрик Хансен
1
Кажется, теперь отлично работает, так что +1 от меня. Приятного пребывания! :) А в случае, если вы еще этого не видели, советы по игре в гольф на F # и советы по игре в гольф на <все языки> могут быть интересными для чтения.
Кевин Круйссен
1

сед, 125

В вольности с форматом вывода версии:

Оценка включает +1 для -rпараметра к sed.

s/(N|S)(E|W)/\L\2,\1 /g
s/N|S/,& /g
s/E|W/&, /g
s/N|E/A/gi
s/S|W/a/gi
p
:
s/(\S*),(\S*) (\S*),(\S*)/\1\3,\2\4/
t
s/Aa|aA//
t

Попробуйте онлайн .

Вывод следующий:

  • координатные элементы разделены запятыми
  • каждый набор координат разделен табуляцией
  • окончательная координата находится на новой строке
  • все числа в ℤ-одинарном:
    • строка Aсимволов представляет целое число + velen(string)
    • строка aсимволов представляет целое число -ve-len(string)
    • пустая строка представляет 0

Например:

  • , это [0,0]
  • ,AA это [0,2]
  • aaa, это [-3,0]

sed 4.2.2, включая расширение GNU exec , 147

Разумный формат вывода версии:

Оценка включает +1 для -rпараметра к sed.

s/(N|S)(E|W)/\L\2 \1\n/g
s/N|S/0 &\n/g
s/E|W/& 0\n/g
s/N|E/1/gi
s/S|W/-1/gi
p
:
s/(\S+) (\S+)\n(\S+) (\S+)/\1+\3 \2+\4/
t
s/\S+/$[&]/g
s/^/echo /e

Выходные данные даны как разделенные пробелом координаты, по одной на строку. Существует дополнительная новая строка между предпоследним и окончательным наборами координат - не уверен, проблематично это или нет.

Попробуйте онлайн!

Цифровая травма
источник
0

PHP, 153 байта

пусть регулярное выражение выполнит разбиение; перебрать совпадения, вывести и подвести промежуточные результаты:

preg_match_all("/[NS][EW]?|E|W/",$argn,$m);foreach($m[0]as$s){$x+=$p=strtr($s[-1],NEWS,1201)-1;$y+=$q=strtr($s[0],NEWS,2110)-1;echo"$p,$q
";}echo"$x,$y";

Запустите как трубу с -nRили попробуйте онлайн .

Titus
источник
0

C (gcc) , 173 байта

Интересно делать это на языке без поддержки регулярных выражений!

f(char*s){char*t="[%d,%d]\n";int x[4]={0},i;for(;*s;*x=x[1]=!printf(t,x[1],*x))for(i=-1;i<5;)if(*s=="S NW E"[++i]){x[i/3+2]+=x[i/3]=i%3-1;i+=2-i%3;s++;}printf(t,x[3],x[2]);}

Попробуйте онлайн!

ErikF
источник
164 байта
ceilingcat