БЫСТРО ЭТО ТРИСФ ДНА ТАСЛ СЕТТЕРЛ ФО ХАС ДОРВ


30

Или «поменять местами первые и последние буквы каждого слова»

Ваша задача состоит в том, чтобы, учитывая строку алфавитных символов ASCII, а также еще один символ, используемый в качестве разделителя (для разделения каждого слова), поменять местами первые и последние буквы каждого слова. Если есть односимвольное слово, оставьте его в покое.

В примерах / тестовых случаях в качестве разделителя используются строчные буквы и пробел.

Вам не нужно обрабатывать знаки препинания; все входные данные будут состоять только из букв от a до z, разделенных разделителем, все в одном регистре.

Например, со строкой «Привет, мир»:

Input string: "hello world"
Identify each word: "[hello] [world]"
Identify the first and last letters of each word: "[[h]ell[o]] [[w]orl[d]]"
Swap the first letters of each word: "[[o]ell[h]] [[d]orl[w]]"
Final string: "oellh dorlw"

ПРИМЕЧАНИЕ: разделитель не нужно вводить отдельно. Разделитель - это просто символ, используемый для разделения слов. Это может быть что угодно. Я хотел оставить варианты открытыми для творческих игроков в гольф, поэтому я не хотел ограничивать это только пробелами или новыми линиями. Разделитель - это просто символ, который разделяет слова во входной строке.

Тестовые случаи:

"swap the first and last letters of each word" -> "pwas eht tirsf dna tasl setterl fo hace dorw"
"hello world" -> "oellh dorlw"
"test cases" -> "test sasec"
"programming puzzles and code golf" -> "grogramminp suzzlep dna eodc folg"
"in a green meadow" -> "ni a nreeg weadom"
"yay racecar" -> "yay racecar"

3
Как лечить пунктуацию? Hello, world!становится ,elloH !orldw(заменяя пунктуацию буквой) или oellH, dorlw!(сохраняя пунктуацию на месте)?
Фелипе Олейник

3
@PhelypeOleinik Вам не нужно обрабатывать знаки препинания; все входные данные будут состоять только из букв от a до z и всех одинаковых регистров.
Товарищ SparklePony

4
Второй абзац читает, а также еще один символ для использования в качестве разделителя, а четвертый - через пробел . Который из них?
Адам

@ Adám Любой не алфавитный символ. Я отредактирую, чтобы уточнить.
Товарищ SparklePony

1
@BenjaminUrquhart Да. Вы можете принять входные данные в качестве аргумента функции, если хотите.
Товарищ SparklePony

Ответы:


59

TeX, 216 байт (4 строки по 54 символа в каждой)

Потому что речь идет не о количестве байтов, а о качестве вывода на наборе :-)

{\let~\catcode~`A13 \defA#1{~`#113\gdef}AGG#1{~`#1 13%
\global\let}GFF\elseGHH\fiAQQ{Q}AII{\ifxQ}AEE#1#2#3|{%
I#3#2#1FE{#1#2}#3|H}ADD#1#2|{I#1FE{}#1#2|H}ACC#1#2|{D%
#2Q|#1 }ABBH#1 {HI#1FC#1|BH}\gdef\S#1{\iftrueBH#1 Q }}

Попробуйте онлайн! (На обороте; не уверен, как это работает)

Полный тестовый файл:

{\let~\catcode~`A13 \defA#1{~`#113\gdef}AGG#1{~`#1 13%
\global\let}GFF\elseGHH\fiAQQ{Q}AII{\ifxQ}AEE#1#2#3|{%
I#3#2#1FE{#1#2}#3|H}ADD#1#2|{I#1FE{}#1#2|H}ACC#1#2|{D%
#2Q|#1 }ABBH#1 {HI#1FC#1|BH}\gdef\S#1{\iftrueBH#1 Q }}

\S{swap the a first and last letters of each word}

pwas eht a tirsf dna tasl setterl fo hace dorw

\S{SWAP THE A FIRST AND LAST LETTERS OF EACH WORD}

\bye

Выход:

введите описание изображения здесь


Для LaTeX вам просто нужен шаблон:

\documentclass{article}
\begin{document}

{\let~\catcode~`A13 \defA#1{~`#113\gdef}AGG#1{~`#1 13%
\global\let}GFF\elseGHH\fiAQQ{Q}AII{\ifxQ}AEE#1#2#3|{%
I#3#2#1FE{#1#2}#3|H}ADD#1#2|{I#1FE{}#1#2|H}ACC#1#2|{D%
#2Q|#1 }ABBH#1 {HI#1FC#1|BH}\gdef\S#1{\iftrueBH#1 Q }}

\S{swap the a first and last letters of each word}

pwas eht a tirsf dna tasl setterl fo hace dorw

\S{SWAP THE A FIRST AND LAST LETTERS OF EACH WORD}

\end{document}

объяснение

TeX странный зверь. Чтение нормального кода и его понимание само по себе является подвигом. Понимание запутанного кода TeX делает несколько шагов дальше. Я постараюсь сделать это понятным для людей, которые также не знают TeX, поэтому перед тем, как мы начнем, вот несколько понятий о TeX, чтобы упростить понимание:

Для (не очень) абсолютных новичков TeX

  • Первый и самый важный пункт в этом списке: код не обязательно должен быть в форме прямоугольника, хотя поп-культура может заставить вас так думать .

  • TeX - это язык расширения макросов. В качестве примера вы можете определить, \def\sayhello#1{Hello, #1!}а затем написать, \sayhello{Code Golfists}чтобы заставить TeX печатать Hello, Code Golfists!. Это называется «неопределенным макросом», и для подачи его в первый (и единственный, в данном случае) параметр вы заключаете его в фигурные скобки. TeX удаляет эти скобки, когда макрос захватывает аргумент. Вы можете использовать до 9 параметров: \def\say#1#2{#1, #2!}затем \say{Good news}{everyone}.

  • Аналог неделимитированных макросов, что не удивительно, разделители из них :) Вы можете сделать предыдущее определение чуть более семантическим : \def\say #1 to #2.{#1, #2!}. В этом случае за параметрами следует так называемый текст параметра . Такой параметр text ограничивает аргумент макроса ( #1разграничивается ␣to␣, включая пробелы, и #2разграничивается .). После этого определения вы можете написать \say Good news to everyone., что будет расширяться до Good news, everyone!. Хорошо, не правда ли? :) Однако разделители аргумент (цитируя . Произведет странное предложение В этом случае вам нужно «скрыть» первый с : . TeXbook ) «самая короткая (возможно, пустая) последовательность токенов с правильно вложенными {...}группами, за которой следует ввод этого конкретного списка непараметрических токенов». Это означает, что расширение\say Let's go to the mall to Martin␣to␣{...}\say {Let's go to the mall} to Martin

  • Все идет нормально. Теперь все становится странным. Когда TeX читает символ (который определяется «кодом символа»), он назначает этому символу «код категории» (catcode, для друзей :), который определяет, что этот символ будет означать. Эта комбинация символа и кода категории создает токен (подробнее об этом здесь , например). Вот те, которые представляют для нас интерес:

    • catcode 11 , который определяет токены, которые могут составлять управляющую последовательность (шикарное имя для макроса). По умолчанию все буквы [a-zA-Z] являются катодом 11, поэтому я могу написать \hello, что является одной последовательностью управления, в то время \he11oкак последовательность управления \heсопровождается двумя символами 1, за которыми следует буква o, потому что 1это не катод 11. Если я сделал \catcode`1=11, с этого момента \he11oбудет одна контрольная последовательность. Одна важная вещь заключается в том, что катокоды устанавливаются, когда TeX впервые видит символ под рукой, и такой каткод замораживается ... НАВСЕГДА! (условия могут применяться)

    • catcode 12 , которые являются большинством других символов, таких как 0"!@*(?,.-+/и так далее. Они являются наименее специальным типом кат-кода, поскольку они служат только для написания материала на бумаге. Но кто же использует TeX для записи?!? (опять же, условия могут применяться)

    • Catcode 13 , который ад :) Действительно. Хватит читать и иди делай что-нибудь из своей жизни. Вы не хотите знать, что такое catcode 13. Вы когда-нибудь слышали о пятницу 13-го? Угадай, откуда он получил свое имя! Продолжайте на свой страх и риск! Символ catcode 13, также называемый «активным» символом, больше не просто символ, а сам макрос! Вы можете определить его так, чтобы он имел параметры и расширился до того, что мы видели выше. После того, как \catcode`e=13вы думаете, вы можете сделать \def e{I am the letter e!}, НО. ТЫ. НЕ МОГУТ! eэто уже не письмо, так \defчто не \defвы знаете, это так \d e f! О, выбери еще одну букву? Хорошо! \catcode`R=13 \def R{I am an ARRR!}, Хорошо, Джимми, попробуй! Смею вас сделать это и написать Rв своем коде! Вот что такое catcode 13. Я СПОКОЕН! Давайте двигаться дальше.

  • Хорошо, теперь группировка. Это довольно просто. Независимо от того, какие назначения ( \defэто операция присваивания, \let(мы будем в нее входить), это другое), выполненные в группе, восстанавливаются до того, чем они были до того, как эта группа была запущена, если это назначение не является глобальным. Существует несколько способов запуска групп, один из которых - с кодами catcode 1 и 2 (опять же, catcodes). По умолчанию {это catcode 1, или begin-group, и }это catcode 2, или end-group. Пример: \def\a{1} \a{\def\a{2} \a} \aэто печатает 1 2 1. Снаружи группа \aбыла 1, затем внутри она была переопределена 2, и когда группа закончилась, она была восстановлена 1.

  • Эта \letоперация похожа на другую операцию присваивания \def, но отличается от нее. С \defвами вы определяете макросы, которые будут расширяться, а \letвы создаете копии уже существующих вещей. После \let\blub=\def( =опционально) вы можете изменить начало eпримера с элемента catcode 13, приведенного выше, \blub e{...и повеселиться с ним. Или лучше, вместо того , чтобы ломать вещи можно исправить (вы посмотрите на это!) На Rпример: \let\newr=R \catcode`R=13 \def R{I am an A\newr\newr\newr!}. Быстрый вопрос: не могли бы вы переименовать в \newR?

  • Наконец, так называемые «паразитные пространства». Это своего рода запретная тема, потому что есть люди, которые утверждают, что репутация, заработанная в TeX - LaTeX Stack Exchange , отвечая на вопросы о «ложных местах», не должна рассматриваться, в то время как другие искренне не согласны. С кем вы согласны? Делайте ваши ставки! Между тем: TeX понимает разрыв строки как пробел. Попробуйте написать несколько слов с разрывом строки (не пустой строкой ) между ними. Теперь добавьте %в конце этих строк. Как будто вы «закомментировали» эти пробелы в конце строки. Это оно :)

(Вроде) разглаживание кода

Давайте сделаем этот прямоугольник во что-то (возможно) более понятным:

{
\let~\catcode
~`A13
\defA#1{~`#113\gdef}
AGG#1{~`#113\global\let}
GFF\else
GHH\fi
AQQ{Q}
AII{\ifxQ}
AEE#1#2#3|{I#3#2#1FE{#1#2}#3|H}
ADD#1#2#3|{I#2FE{#1}#2#3|H}
ACC#1#2|{D{}#2Q|#1 }
ABBH#1 {HI#1FC#1|BH}
\gdef\S#1{\iftrueBH#1 Q }
}

Объяснение каждого шага

каждая строка содержит одну единственную инструкцию. Давайте пойдем один за другим, разбирая их:

{
Сначала мы запускаем группу, чтобы некоторые изменения (а именно, изменения кода) были локальными, чтобы они не испортили введенный текст.

\let~\catcode
В основном все коды запутывания TeX начинаются с этой инструкции. По умолчанию, как в обычном TeX, так и в LaTeX, этот ~символ является одним активным символом, который можно преобразовать в макрос для дальнейшего использования. И лучший инструмент для странного кодирования TeX - это изменение кода, так что это, как правило, лучший выбор. Теперь вместо \catcode`A=13мы можем написать ~`A13( =необязательно):

~`A13
Теперь буква Aявляется активным символом, и мы можем определить, что он делает:

\defA#1{~`#113\gdef}
Aтеперь макрос, который принимает один аргумент (который должен быть другим символом). Сначала catcode аргумента изменяется на 13 , чтобы сделать его активным: ~`#113(заменить ~на \catcodeи добавить =и у вас есть: \catcode`#1=13). Наконец, он оставляет \gdef(глобальный \def) во входном потоке. Короче говоря, Aактивизирует другого персонажа и начинает его определение. Давай попробуем:

AGG#1{~`#113\global\let}
AGСначала «активирует» Gи делает \gdef, после чего следует следующее Gзапускает определение. Определение Gочень схоже с определением A, за исключением того, что вместо \gdefнего \global\let(а не \gletкак \gdef). Короче говоря, Gактивирует персонажа и делает его чем-то другим. Давайте сделаем ярлыки для двух команд, которые мы будем использовать позже:

GFF\else
GHH\fi
Теперь вместо \elseи \fiмы можем просто использовать Fи H. Короче :)

AQQ{Q}
Теперь мы используем A снова для определения другого макроса Q. Вышеупомянутое утверждение в основном делает (на менее запутанном языке) \def\Q{\Q}. Это не очень интересное определение, но у него есть интересная особенность. Если вы не хотите нарушать какой-либо код, единственный макрос, который расширяется, Qэто Qсам по себе, поэтому он действует как уникальный маркер (он называется кварком ). Вы можете использовать \ifxусловное выражение для проверки, является ли аргумент макроса таким кварком с \ifx Q#1:

AII{\ifxQ}
так что вы можете быть уверены, что нашли такой маркер. Обратите внимание, что в этом определении я удалил пробел между \ifxи Q. Обычно это приводит к ошибке (обратите внимание, что выделение синтаксиса думает, что \ifxQэто одно), но так как теперь Qэто код 13, он не может сформировать управляющую последовательность. Однако будьте осторожны, чтобы не расширять этот кварк, иначе вы застрянете в бесконечном цикле, потому что Qрасширяется в Qкоторый расширяется в Qкакой ...

Теперь, когда предварительные выводы завершены, мы можем перейти к правильному алгоритму для установки. Из-за токенизации TeX алгоритм должен быть написан задом наперед. Это связано с тем, что в то время, когда вы выполняете определение, TeX будет токенизировать (присваивать катокоды) символам в определении, используя текущие настройки, например, если я это сделаю:

\def\one{E}
\catcode`E=13\def E{1}
\one E

выходной E1, тогда как, если я изменю порядок определений:

\catcode`E=13\def E{1}
\def\one{E}
\one E

выход есть 11. Это связано с тем, что в первом примере Eв определении был токенизирован как буква (catcode 11) перед изменением catcode, так что это всегда будет букваE . Во втором примере, однако, Eсначала был сделан активным, и только потом \oneбыл определен, и теперь определение содержит код 13, Eкоторый расширяется до1 .

Я, однако, пропущу этот факт и переупорядочу определения, чтобы иметь логический (но не работающий) порядок. В следующих параграфах вы можете предположить, что буквы B,C , Dи Eявляются активными.

\gdef\S#1{\iftrueBH#1 Q }
(обратите внимание, что в предыдущей версии была небольшая ошибка, она не содержала заключительного пробела в приведенном выше определении. Я заметил это только во время написания этого. Читайте дальше, и вы поймете, зачем нам это нужно для правильного завершения макроса. )
Сначала мы определим макрос уровня пользователя \S. Этот не должен быть активным символом, чтобы иметь дружественный (?) Синтаксис, поэтому макрос для gwappins eht setterl есть \S. Макрос начинается с всегда истинного условия \iftrue(скоро станет понятно, почему), а затем вызывает Bмакрос, за которым следует H(который мы определили ранее \fi) для соответствия \iftrue. Затем мы оставляем аргумент макроса, #1за которым следует пробел и кварк Q. Предположим, мы используем \S{hello world}, то входной поток должны выглядеть следующим образом:\iftrue BHhello world Q␣(Я заменил последний пробел на так, чтобы рендеринг сайта его не съел, как я делал в предыдущей версии кода). \iftrueэто правда, поэтому он расширяется, и мы остались с не расширяется. Теперь макрос расширен:BHhello world Q␣, TeX делает удалить \fi( H) после того , как условно оценивается, вместо этого она оставляет его там до тех пор , \fiпока на самом делеB

ABBH#1 {HI#1FC#1|BH}
Bявляется макросом с разделителями, чей параметр text является H#1␣, поэтому аргумент - это то, что находится между Hи пробелом. Продолжая приведенный выше пример входного потока перед расширением Bis BHhello world Q␣. Bзатем следует H, как и должно (в противном случае TeX вызовет ошибку), затем следующий пробел между helloи world, #1как и слово hello. И здесь мы должны разделить входной текст по пробелам. Ура: D экспансия . Последний пробел после необходим, потому что макрос с разделителями требуетB удаляет все вплоть до первого места из входного потока и заменяет на HI#1FC#1|BHс #1того hello: HIhelloFChello|BHworld Q␣. Обратите внимание, что BHпозже во входном потоке есть новое , чтобы выполнить хвостовую рекурсиюBи обработать более поздние слова. После обработки этого слова обрабатывается Bследующее слово, пока обрабатываемое слово не станет кварком один в конце аргумента. В предыдущей версии (см. Историю изменений) код будет некорректно работать, если вы используете (пробел между s исчезнет).QQB \S{hello world}abc abcabc

OK, обратно во входной поток: HIhelloFChello|BHworld Q␣. Сначала есть H( \fi), который завершает начальную \iftrue. Теперь у нас есть это (псевдокодирование):

I
  hello
F
  Chello|B
H
world Q␣

I...F...HДумают на самом деле \ifx Q...\else...\fiструктура. В \ifxтест проверяет , является ли (первый токен) слово схватил является Qкварк. Если нет ничего другого, и выполнение завершается, в противном случае что остается: Chello|BHworld Q␣. В настоящее времяC расширено:

ACC#1#2|{D#2Q|#1 }
Первый аргумент Cявляется не выделяются, так что если не приготовился будет один маркер, второй аргумент ограничен |, так что после расширения C#1=hи #2=ello) входной поток: DelloQ|h BHworld Q␣. Обратите внимание , что другой |ставятся там, и hиз helloставятся после этого. Половина обмена сделана; первая буква в конце. В TeX легко получить первый токен из списка токенов. Простой макрос \def\first#1#2|{#1}получает первую букву при использовании \first hello|. Последний является проблемой, потому что TeX всегда берет «самый маленький, возможно, пустой» список токенов в качестве аргумента, поэтому нам нужно несколько обходных путей. Следующий элемент в списке токенов D:

ADD#1#2|{I#1FE{}#1#2|H}
Этот Dмакрос является одним из обходных путей и полезен в единственном случае, когда слово имеет одну букву. Предположим, вместо helloнас x. В этом случае входной поток будет DQ|x, то Dбудет расширяться (с #1=Q, и #2опорожнить) к: IQFE{}Q|Hx. Это похоже на блок I...F...H( \ifx Q...\else...\fi) в B, который увидит, что аргумент является кварком, и прервет выполнение, оставив только xнабор текста. В других случаях (возвращение к helloпримеру), Dбудет расширяться (с #1=eи #2=lloQ) по адресу: IeFE{}elloQ|Hh BHworld Q␣. Опять же , I...F...Hбудет проверять , Qно потерпит неудачу и взять \elseвласть: E{}elloQ|Hh BHworld Q␣. Теперь последний кусок этой вещи,E макрос будет расширяться:

AEE#1#2#3|{I#3#2#1FE{#1#2}#3|H}
Текст параметра здесь очень похож на Cи D; первый и второй аргументы не ограничены, а последний ограничен |. Входной поток выглядит следующим образом : E{}elloQ|Hh BHworld Q␣, затем Eрасширяется (с #1пустым, #2=e, и #3=lloQ): IlloQeFE{e}lloQ|HHh BHworld Q␣. Другой I...F...Hблок проверяет кварк (который видит lи возвращается false): E{e}lloQ|HHh BHworld Q␣. Теперь Eснова расширяется (с #1=eпустым, #2=lи #3=loQ): IloQleFE{el}loQ|HHHh BHworld Q␣. И снова I...F...H. Макрос делает еще несколько итераций, пока, Qнаконец, не будет найден и trueветвь не берется: E{el}loQ|HHHh BHworld Q␣-> IoQlelFE{ell}oQ|HHHHh BHworld Q␣-> E{ell}oQ|HHHHh BHworld Q␣-> IQoellFE{ello}Q|HHHHHh BHworld Q␣. Теперь кварк найден и условные Раскрывается в: oellHHHHh BHworld Q␣. Уф.

Ой, подожди, что это? НОРМАЛЬНЫЕ ПИСЬМА? О, парень! Письма , наконец , нашли и TeX запишет oell, то связка H( \fi) будут найдены и расширены (ничего) , выходящий из входного потока с: oellh BHworld Q␣. Теперь в первом слове поменялись местами первая и последняя буквы, а TeX находит следующее, Bчтобы повторить весь процесс для следующего слова.

}
Наконец мы заканчиваем группу, начатую там, так что все локальные назначения отменяются. Местные назначения являются catcode изменения букв A, B, C, ... , которые были сделаны макросы так , что они возвращаются к своему нормальному значению буквы и может безопасно использоваться в тексте. Вот и все. Теперь \Sопределенный здесь макрос запустит обработку текста, как указано выше.

Одна интересная вещь об этом коде - то, что он полностью расширяем. То есть вы можете безопасно использовать его в движущихся аргументах, не опасаясь, что он взорвется. Вы даже можете использовать код, чтобы проверить, совпадает ли последняя буква слова со второй (по какой бы причине вам это не понадобилось) в \ifтесте:

\if\S{here} true\else false\fi % prints true (plus junk, which you would need to handle)
\if\S{test} true\else false\fi % prints false

Извините за (вероятно, слишком) многословное объяснение. Я постарался сделать это как можно более понятным для не TeXies :)

Резюме для нетерпеливых

Макрос \Sдобавляет к вводу активный символ, Bкоторый захватывает списки токенов, разделенных конечным пробелом, и передает их C. Cберет первый токен в этом списке и перемещает его в конец списка токенов и расширяет Dс тем, что осталось. Dпроверяет, является ли «то, что осталось» пустым, и в этом случае было найдено однобуквенное слово, затем ничего не делает; в противном случае расширяется E. Eциклически перебирает список токенов до тех пор, пока не найдет последнюю букву в слове, когда он найден, он покидает последнюю букву, за которой следует середина слова, за которой следует первая буква, оставленная в конце потока токенов: C,


2
Я хотел бы полное объяснение этого. Мне очень любопытно, как это работает!
LambdaBeta

1
@LambdaBeta Я могу это сделать, но не сейчас. Держись, и я буду пинговать тебя, когда я это сделаю :)
Phelype Oleinik

1
@LambdaBeta Готово! Извините, иногда я слишком многословен :-)
Фелипе Олейник,

13

JavaScript (ES6),  39  36 байт

Сохранено 3 байта благодаря @FryAmTheEggman

Использует перевод строки в качестве разделителя.

s=>s.replace(/(.)(.*)(.)/g,'$3$2$1')

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


5
(.)(.*)(.)это смайлик Total Recall?
MikeTheLiar

1
@ MikeTheLiar Вроде как, наверное. : D
Арно

Присвоение указывает на строку, содержащую разделитель.
Сис Тиммерман

@CeesTimmerman Я не уверен, что ты имеешь в виду. Этот код ожидает перевод строки в качестве разделителя и, следовательно, принимает строки с переводами строки в качестве входных данных. (Нижний колонтитул ссылки TIO преобразует пробелы в переводы строки, а затем обратно в пробелы для удобства чтения.)
Арно

«дана строка буквенных символов ASCII, а также еще один символ для использования в качестве разделителя (для разделения каждого слова) » - Нм, я подумал, что это отдельный параметр.
Сис Тиммерман

11

Сетчатка ,8 5 байт

,V,,`

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

Сохранено 3 байта благодаря Кевину Круйссену !

Использует новую строку в качестве разделителя. Мы используем обратную стадию Retina и некоторые ограничения. Первый предел - это то, к чему относится обращение, поэтому мы выбираем их все ,. Затем мы хотим поменять местами первую и последнюю буквы каждого совпадения, поэтому мы берем каждую букву в диапазоне, ,,который переводится в диапазон от начала до конца с нулевым размером шага.


Дангит, я просто искал в документации что-то вроде этого, чтобы обновить мой ответ, но ты меня опередил. Я знал об этом V, но не знал, что его можно использовать с 1,-2такими показателями . Хороший!
Кевин Круйссен

1
@KevinCruijssen Я немного обманул и рассмотрел, как работают предельные диапазоны, пока это было в песочнице :) Я все еще чувствую, что должен быть лучший способ, чем инвертировать диапазон, но я не смог найти ничего более короткого.
FryAmTheEggman

2
Вы действительно правы в том, что он может быть короче без предельного диапазона, потому что кажется, что этот 5-байтовый код работает (приведен в качестве примера в нижней части Step Limits в документах).
Кевин Круйссен

@KevinCruijssen Отлично! Не могу поверить, что я пропустил это.
FryAmTheEggman

3
Итак, 5 байтов и только 3 разных символа? Это минималистский
Cœur

9

Пепе , 107 105 байт

REEeREeeEeeeeerEEreREEEeREEEEEEeREEEErEEREEEEEEEreererEEEeererEEEerEEeERrEEEeerEEeerereeerEEEEeEEEReEeree

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

Объяснение:

Обозначения комментариев: command-explanation -> (stack) // explanation

REEe # input -> (R)
REeeEeeeee # push space to last -> (R) // this prevents an infinite loop

rEE # create loop labeled 0 and automatically push 0 
  re # pop 0 -> (r)
  REEEe # go to last item -> (R)
  REEEEEEe # ...then copy the char to other stack
  REEEE # go to first item -> (R)

  rEE # create loop labeled 32 // detect space
    REEEEEEE # move item to other stack (R)
  ree # do this while char != 32

  re # pop 32 -> (r)
  rEEEee # push item (dup to end) -> (r)
  re # ...then pop -> (r)
  rEEEe rEEeE # go to 2nd to last item -> (r)
  RrEEEee # push the item (R flag: dup to first) -> (r)
  rEEee # go to next -> (r) //
  re # ...then pop -> (r)
  reee rEEEEeEEE # out all as char then clear -> (r)
  ReEe # out 32 as char -> (R)
ree # do this while stack != 0

Как это работает?
lirtosiast

Добавлено объяснение @lirtosiast
u_ndefined


6

laskelH , 71 байт

h=reverse
s(x:y:o)=a:h(x:r)where(a:r)=h$y:o
s o=o
f=unwords.map s.words

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

Пример в / output:

Swap the first and last letter in each word
This also works with single letter words like a

It is basically just a straight up implementation in which
I for words consisting of two or more letters cons the head
of the reversed tail on the reverse of the original head consed
on the reversed tail

Note that the rules say that we only have to support one kind
of separator - I am choosing spaces Technically it works with
other whitespace as well, but it will turn everything into spaces
in the end Line endings in this example usage are handled separately
to make the example output look nicer
pwaS eht tirsf dna tasl rettel ni hace dorw
shiT olsa sorkw hitw eingls rettel sordw eikl a

tI si yasicallb tusj a ttraighs pu nmplementatioi ni hhicw
I rof sordw gonsistinc fo owt ro eorm setterl sonc eht deah
fo eht deverser lait no eht eeversr fo eht lriginao deah donsec
no eht deverser lait

eotN that eht suler yas that ew ynlo eavh ot tuppors eno dink
fo reparatos - I ma ghoosinc spaces yechnicallT ti sorkw hitw
rtheo ehitespacw sa ,ellw tub ti lilw nurt gverythine onti spaces
ni eht dne einL sndinge ni shit example esagu era dandleh yeparatels
ot eakm eht example tutpuo kool ricen
```

1
Назначение в whereпредложении может быть перенесено в привязку для защиты 5 байтов: попробуйте онлайн!
Лайкони

1
Я вижу, что вы сделали там с именем "Haskell" в названии. Я сделал то же самое в своем ответе на PHP.
640KB

5

05AB1E , 10 байтов

#vyRćsRćðJ

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


-3 Спасибо @Kevin Cruijssen .

#           | Split into words.
 vy         | For each word...
   RćsRć    | Reverse, split head, swap, reverse, split tail
        ðJ  | Join by spaces.


1
@KevinCruijssen Я, честно говоря, хочу удалить это и дать вам, это было на 99% вашим умом при упорядочении аргументов, ха-ха.
Волшебная Урна Осьминога

1
Нашел 9-байтовый, но он работает только в устаревшей версии:|ʒRćsRćJ,
Кевин Круйссен

1
Жаль, что у нас нет loop_as_long_as_there_are_inputs, тогда я бы знал 8-байтовый: [RćsRćJ,этот 8-байтовый, используя[ никогда не выводит в теории, однако, только когда у вас не памяти или тайм-аут, как на TIO (и это требует трейлинг перевод строки во ввод, иначе он будет продолжать использовать последнее слово) ..
Кевин Круйссен

1
К сожалению вам нужно, так ð¡как ввод одного слова возможен, но ð¡εćsÁì}ðýтакже работает на 10 байтов.
Эминья

5

J , 23 17 байт

({:,1|.}:)&.>&.;:

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


Очень хороший трюк, чтобы поменять местами первые / последние буквы, вращая и применяя 1 A.!
Гален Иванов

1
1&A.&.(1&|.)-> ({:,1|.}:)а затем вы можете удалить::]
нгн

Удивительно, спасибо
FrownyFrog

Действительно удивительно! Я еще раз поражаюсь, насколько простым и элегантным может быть решение, но только после того, как я вижу, что оно сделано кем-то другим.
Гален Иванов

4

Рубин с -p, 42 41 29 байт

gsub /(\w)(\w*)(\w)/,'\3\2\1'

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



@ Шэгги, спасибо за внимание. Если вы посмотрите мою историю сообщений, это показывает, что я отсутствовал в течение 8 месяцев без каких-либо ответов, так что я, вероятно, пропустил несколько заметок за это время, ха-ха
Value Ink

Я уверен, что консенсус был изменен более 8 месяцев назад, но на тот случай, если вы его пропустили: «неконкурентность» также больше не вещь.
лохматый

Красиво сделано. Я думаю, что в соответствии с правилами вы можете использовать новые строки в качестве разделителя и заменить\w s на .s.
гистократ





3

Пробел , 179 байт

[N
S S S N
_Create_Label_OUTER_LOOP][S S S N
_Push_n=0][N
S S T   N
_Create_Label_INNER_LOOP][S N
S _Duplicate_n][S N
S _Duplicate_n][S N
S _Duplicate_n][T   N
T   S _Read_STDIN_as_character][T   T   T   _Retrieve_input][S S S T    S T T   N
_Push_11][T S S T   _Subtract_t=input-11][N
T   T   S S N
_If_t<0_jump_to_Label_PRINT][S S S T    N
_Push_1][T  S S S _Add_n=n+1][N
S N
T   N
_Jump_to_Label_INNER_LOOP][N
S S S S N
_Create_Label_PRINT][S S S T    N
_Push_1][T  S S T   _Subtract_n=n-1][S N
S _Duplicate_n][S N
S _Duplicate_n][N
T   S N
_If_n==0_jump_to_Label_PRINT_TRAILING][T    T   T   _Retrieve][T    N
S S _Print_as_character][S S S N
_Push_s=0][N
S S S T N
_Create_Label_PRINT_LOOP][S S S T   N
_Push_1][T  S S S _Add_s=s+1][S N
S _Duplicate_s][S T S S T   S N
_Copy_0-based_2nd_n][T  S S T   _Subtract_i=s-n][N
T   S N
_If_0_Jump_to_Label_PRINT_TRAILING][S N
S _Duplicate_s][T   T   T   _Retrieve][T    N
S S _Print_as_character][N
S T S T N
_Jump_to_Label_PRINT_LOOP][N
S S N
_Create_Label_PRINT_TRAILING][S S S N
_Push_0][T  T   T   _Retrieve][T    N
S S _Print_as_character][S S S T    S S T   N
_Push_9_tab][T  N
S S _Print_as_character][N
S N
S N
_Jump_to_Label_OUTER_LOOP]

Буквы S(пробел), T(табуляция) и N(новая строка) добавляются только как подсветка.
[..._some_action]добавлено только для пояснения.

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

Попробуйте онлайн (только с необработанными пробелами, вкладками и новыми строками).

Объяснение в псевдокоде:

Пустое пространство имеет только стек и кучу, где куча - это карта с ключом и значением (оба целых числа). Входные данные могут быть прочитаны только одно целое число или символ за раз, которые всегда помещаются в кучу как целые числа, а затем могут быть получены и помещены в стек с их определенными адресами кучи (ключами карты). В моем подходе я храню все слово по куче-адресам (map-keys)[0,,,,,word_length]и затем извлекайте символы для печати по одному в том порядке, в котором мы хотели бы, чтобы после табуляции (или новой строки) встречался разделитель.

Start OUTER_LOOP:
  Integer n = 0
  Start INNER_LOOP:
    Character c = STDIN as character, saved at heap-address n
    If(c == '\t' OR c == '\n'):
      Jump to PRINT
    n = n + 1
    Go to next iteration of INNER_LOOP

  PRINT:
    n = n - 1
    If(n == 0): (this means it was a single-letter word)
      Jump to PRINT_TRAILING
    Character c = get character from heap-address n
    Print c as character
    Integer s = 0

    Start PRINT_LOOP:
      s = s + 1
      If(s - n == 0):
        Jump to PRINT_TRAILING
      Character c = get character from heap-address s
      Print c as character
      Go to next iteration of PRINT_LOOP

    PRINT_TRAILING:
      Character c = get character from heap-address 0
      Print c as character
      Print '\t'
      Go to next iteration of OUTER_LOOP

Программа завершается с ошибкой, когда она пытается прочитать символ, когда в TIO ничего не задано (или зависает в ожидании ввода в некоторых компиляторах пробельных символов, таких как vii5ard ).


3

Wolfram Language (Mathematica) , 58 байт

StringReplace[#,a:u~~w:u..~~b:u:>b<>w<>a/.{u->Except@#2}]&

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

-22 байта от @attinat

-12 байт от @ M.Stern


Использование 70 байтовStringReplace с StringExpressions
attinat

1
64 байт , используя StringTakeвместо StringReplace:StringRiffle[StringSplit@##~StringTake~{{-1},{2,-2},{1}},#2,""]&
Roman

2
Вот более прямой подход:StringReplace[#, a : u ~~ w : u .. ~~ b : u :> b <> w <> a /. {u -> Except@#2}] &
М. Штерн

1
{и} не являются обязательными :)
М. Стерн

1
55 байтов , также исправляет 2-х символьные слова
attinat

2

QuadR , 20 байтов

(\w)(\w*)(\w)
\3\2\1

Просто создайте три группы захвата, состоящие из 1, 0 или более и 1 слова-символов, а затем поменяйте местами их порядок.

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



2

Japt -S , 10 байт

Убежден, что должен быть более короткий подход (и я был прав ), но пока это подойдет .

¸ËhJDg)hDÌ

Попытайся

¸ËhJDg)hDÌ     :Implicit input of string
¸              :Split on spaces
 Ë             :Map each D
  h            :  Set the character at
   J           :    Index -1 to
    Dg         :    The first character in D
      )        :  End set
       h       :  Set the first character to
        DÌ     :    The last character in D
               :Implicit output, joined by spaces

Гораздо короче моего 12 байта:¸®Ì+Zs1J +Zg
Воплощение невежества

@EmbodimentofIgnorance, это то, с чего я тоже начал, но он потерпел бы неудачу на односимвольных словах. Вы можете сохранить байт на этом, хотя, с ¸®ÎiZÌ+Zs1J.
лохматый

1
@EmbodimentofIgnorance Нашел 7 байт
Оливер

2

sed, 64 байта

sed -E 's/\b([[:alpha:]])([[:alpha:]]*)([[:alpha:]])\b/\3\2\1/g'

Конечно, мы могли бы использовать . вместо [[:alpha:]], но это на самом деле должно быть [^ ], что уменьшает его до 43, но ломает на пунктуацию и тому подобное. Использование [a-zA-Z]доводит его до 55, и к этому моменту я просто жажду тех сладких, сладких, читаемых человеком сущностей ...
Рич

2
You do not need to handle punctuation; all of the inputs will only consist of the letters a through z, separated by a delimiter, all of a uniform case. Другими словами, вам не нужно беспокоиться о пунктуации, «ломающей» ваш код, и вы можете просто [^ ] ;)
Value Ink

@ValueInk Да, но тогда [^ ]должно быть[^[:space:]] что доводит его до 67 символов.
Богатый

«разделитель» означает, что вы можете убедиться, что разделитель всегда является регулярным пробелом. Кто использует табуляции в предложении?
Value Ink

Хорошо. Похоже, «Code Golf» - это игра, в которой вы должны найти способ заставить беспилотник бросить мяч в лунку вместо того, чтобы фактически выполнять работу. Спасибо за дерьмовый прием.
Рич

2

sed , 34 байта

И, вероятно, идея шаблона будет работать с большинством инструментов RE (и я знаю, что есть различия между стандартным RE и расширенным RE).

s,\b\(\w\)\(\w*\)\(\w\)\b,\3\2\1,g

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


1
Добро пожаловать в PPCG! Мне кажется, что жадная природа совпадений с регулярными выражениями означает, что вы можете отказаться \bот матча: попробуйте онлайн!
Value Ink

Договорились @ValueInk - но я был точен в матче. Удаление \bприведет к 30 байтам.
PJF

Используйте -E для расширенного регулярного выражения, и вы можете использовать неэкранированные скобки. Используйте .для обмененных символов, и вы можете потерять еще два символа. Это уменьшает ваш размер до 26 байт; одно из самых маленьких читаемых решений. s,\b(.)(\w*)(.)\b,\3\2\1,g
Богатый

1
- Нет, я ошибаюсь, вам нужно \ws на концах. s,\b(\w)(\w*)(\w)\b,\3\2\1,g28 символов
Богатый

Хорошая работа @rich, но, как я уже сказал, я знаю о стандартных и расширенных RE. Я просто решил сделать его стандартным и читабельным. Требуются якоря, о которых я не упомянул в своем ответе на ValueInk.
PJF

2

Рубин, 53 байта

gets.split(" ").map{|z|print z[-1]+z[1..-2]+z[0]," "}

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

Ungolfed:

gets.split(" ").map {|z|
    print z[-1] + z[1..-2] + z[0], " "
}

Добро пожаловать в PPCG! Печать каждого слова в новой строке должна быть в порядке, но ваше старое решение pне принесло пользы, поскольку это добавило к выводу кавычки. Вы всегда можете использовать putsвместо этого, так как этот автоматически добавляет символ новой строки и короче, чем print! Кроме того, если вы вызываете splitбез аргументов, он автоматически разделяется на пробелы.
Value Ink

2

8088 Assembly, IBM PC DOS, 39 38 байт

$ xxd pwas.com
00000000: d1ee ac8a c8fd 03f1 c604 244e 8bfe ac3c  ..........$N...<
00000010: 2075 098a 2586 6402 8825 8bfe e2f0 b409   u..%.d..%......
00000020: ba82 00cd 21c3

разобранное:

D1 EE       SHR  SI, 1          ; point SI to DOS PSP (080H) 
AC          LODSB               ; load string length into AL 
8A C8       MOV  CL, AL         ; load string length into CX for loop
FD          STD                 ; set LODSB to decrement 
03 F1       ADD  SI, CX         ; point SI to end of string 
C6 04 24    MOV  BYTE PTR[SI], '$' ; put a '$' DOS string terminator at end 
4E          DEC  SI             ; start at last char of word 
8B FE       MOV  DI, SI         ; point DI to last char of word 
        CHR_LOOP: 
AC          LODSB               ; load next (previous?) char into AL 
3C 20       CMP  AL, ' '        ; is it a space? 
75 0A       JNE  END_CHR        ; if so, continue loop 
8A 25       MOV  AH, [DI]       ; put last char in AH 
86 64 02    XCHG AH, [SI][2]    ; swap memory contents of first char with last 
                                ; (unfortunately XCHG cannot swap mem to mem)
88 25       MOV  [DI], AH       ; put first char value into last char position 
8B FE       MOV  DI, SI         ; point DI last char of word 
        END_CHR:
E2 EF       LOOP CHR_LOOP       ; continue loop 
B4 09       MOV  AH, 9          ; DOS display string function 
BA 0082     MOV  DX, 082H       ; output string is at memory address 82H 
CD 21       INT  21H            ; display string to screen 
C3          RET                 ; return to DOS 

Автономный исполняемый файл DOS для ПК. Ввод через аргументы командной строки, вывод на экран.

введите описание изображения здесь

Загрузите и протестируйте PWAS.COM .



1

Пакет, 141 байт

@set t=
@for %%w in (%*)do @call:c %%w
@echo%t%
@exit/b
:c
@set s=%1
@if not %s%==%s:~,1% set s=%s:~-1%%s:~1,-1%%s:~,1%
@set t=%t% %s%

Принимает ввод как параметры командной строки. Манипулирование строками в лучшем случае ужасно, и использование однобуквенных слов в специальном случае не помогает.


1

C # (интерактивный компилятор Visual C #) , 90 байт

n=>n.Split().Any(x=>WriteLine(x.Length<2?x:x.Last()+x.Substring(1,x.Length-2)+x[0])is int)

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

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


SelectMany (то есть map и flatten) для 84 байтов, но выводит один завершающий пробел. Попробуйте онлайн!
мое местоимение monicareinstate


1

Джава, 110 109 байт

-1 байт с помощью новой строки для делимера

s->{int l;for(var i:s.split("\n"))System.out.println(i.charAt(l=i.length()-1)+i.substring(1,l)+i.charAt(0));}

TIO


Это работает для однобуквенных слов?
Нейл

@ Нет, потому что я плохой. Я исправлю позже.
Бенджамин Уркхарт

109 с использованием новой строки в качестве разделителя
Воплощение невежества

1

Haskell , 75 74 байта

Исправлена ​​ошибка, на которую указывал Кубик, а также вносил в гольф 1 байт.

f=unwords.map(#v).words
x#g=g(r$tail x)++[x!!0]
r=reverse
v[]=[]
v x=r$x#r

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


map gкороче(g<$>)
Куб

1
Кроме того, если вы посмотрите на свой тестовый пример, вы увидите, что он не работает для однобуквенных слов, он превращается aвaa
Куб

1

Скала, 100 байт

(b:String,c:String)=>b.split(c)map(f=>f.tail.lastOption++:(f.drop(1).dropRight(1)+f.head))mkString c

1

T-SQL, 126 байт

SELECT STRING_AGG(STUFF(STUFF(value,1,1,RIGHT(value,1)),LEN(value),1,LEFT(value,1)),' ')
FROM STRING_SPLIT((SELECT*FROM t),' ')

Ввод осуществляется с уже существующей таблицей т с VARCHAR поля V , в соответствии с нашими стандартами IO .

При чтении задом наперед STRING_SPLITразбивает строку на отдельные строки через разделитель, STUFFизменяет символы в указанных позициях, а затем STRING_AGGснова объединяет их.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.