pwaS eht tirsf dna tasl setterl fo hace dorw


30

または、「各単語の最初と最後の文字を入れ替える」

あなたの課題は、アルファベットのASCII文字列と、区切り文字として使用する他の1文字(各単語を区切る)を指定して、各単語の最初と最後の文字を入れ替えることです。1文字の単語がある場合は、そのままにします。

サンプル/テストケースでは、小文字とスペースを区切り文字として使用します。

句読点を処理する必要はありません。すべての入力は、デリミタで区切られたa〜zの文字のみで構成され、すべてが大文字です。

たとえば、文字列「hello world」の場合:

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!(場所に句読点を維持しますか)?
Phelype Oleinik

3
@PhelypeOleinik句読点を処理する必要はありません。すべての入力は、a〜zの文字のみで構成され、すべて大文字と小文字が区別されます。
同志SparklePony

4
2番目の段落は区切り文字として使用する他の1文字と同様に読み取りますが、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

出力:

enter image description here


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はマクロ拡張言語です。例として、TeXを印刷するように定義\def\sayhello#1{Hello, #1!}してから書き込む\sayhello{Code Golfists}ことができますHello, Code Golfists!。これは「無制限のマクロ」と呼ばれ、最初の(この場合のみ)パラメーターにフィードするには、波括弧で囲みます。TeXは、マクロが引数を取得するときにこれらの中括弧を削除します。あなたは9つのまでのパラメータを使用することができます。\def\say#1#2{#1, #2!}それから\say{Good news}{everyone}

  • 区切られていないマクロの対応物は、当然のことながら、区切られたマクロです:)前の定義を少し意味的にすることができます:\def\say #1 to #2.{#1, #2!}。この場合、パラメーターの後に、いわゆるパラメーターテキストが続きます。このようなパラメーターテキストは、マクロの引数を#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 11は、制御シーケンス(マクロの高級名)を構成できるトークンを定義します。デフォルトでは、すべての文字[a-zA-Z]はcatcode 11であるため\hello、1つの単一の制御シーケンスである、2つの文字が続く\he11o制御シーケンス、文字が続く\he1oので、1場合catcode 11ないI didは\catcode`1=11、その時点から\he11o1つの制御シーケンスになります。1つの重要なことは、TeXが手元にある文字を最初に見たときにcatcodeが設定され、そのようなcatcodeが凍結されることです... 永遠に!(利用規約が適用される場合があります)

    • catcode 12など、他のほとんどの文字0"!@*(?,.-+/です。これらは、紙の上に物を書くためだけに役立つため、最も特別なタイプのcatcodeです。しかし、ちょっと、誰が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別の操作です)は、その割り当てがグローバルでない限り、グループが開始される前の状態に復元されます。グループを開始するにはいくつかの方法がありますが、そのうちの1つはcatcode 1および2文字を使用する方法です(ああ、catcodesを再度使用します)。デフォルトで{は、catcode 1、つまりbegin-group、}catcode 2、またはend-groupです。例:\def\a{1} \a{\def\a{2} \a} \aこれはを出力し1 2 1ます。グループ外\a1で、内部はに再定義され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は改行をスペースとして理解します。複数の単語の間に空行ではなく改行を挿入してみてください。次に%、これらの行の最後にa を追加します。これらの行末スペースを「コメントアウト」していたようです。それでおしまい :)

(並べ替え)コードのアンゴルフ

その長方形を(おそらく)わかりやすいものにしましょう:

{
\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 }
}

各ステップの説明

各行には1つの命令が含まれます。それらを1つずつ分析していきましょう。

{
最初にグループを開始して、いくつかの変更(つまりcatcodeの変更)をローカルに保持し、入力テキストが混乱しないようにします。

\let~\catcode
基本的に、すべての TeX難読化コードはこの命令で始まります。デフォルトでは、プレーンTeXとLaTeXの両方で、~文字は、さらに使用するためにマクロにすることができる1つのアクティブな文字です。また、TeXコードを変なものにするための最適なツールはcatcodeの変更なので、これが一般的に最良の選択です。代わりに、\catcode`A=13次のように書くことができます~`A13(これ=はオプションです):

~`A13
これでレターAはアクティブなキャラクターになりました。これを定義して何かを行うことができます。

\defA#1{~`#113\gdef}
A現在、1つの引数(別の文字である必要があります)を取るマクロです。最初に、引数のcatcodeを13に変更してアクティブにします~`#113~by \catcodeを置き換えてan =を追加すると、次のようになります\catcode`#1=13)。最後に、入力ストリームに\gdef(global \def)を残します。つまり、A別のキャラクターをアクティブにし、その定義を開始します。試してみよう:

AGG#1{~`#113\global\let}
AG最初に「アクティブ化」G\gdef、「次」に続いGて定義を開始します。の定義はの定義Gと非常に似ていますがA、代わりにを実行\gdefする点が異なります\global\let(の\gletようなものはありません\gdef)。要するに、Gキャラクターを活性化し、それを別のものにする。後で使用する2つのコマンドのショートカットを作成しましょう。

GFF\else
GHH\fi
今の代わりに\else\fi、私たちは簡単に使用することができるFH。はるかに短い:)

AQQ{Q}
ここでA再び別のマクロを定義するために使用しますQ。上記のステートメントは基本的に(あまり難読化されていない言語で)行い\def\Q{\Q}ます。これはそれほど興味深い定義ではありませんが、興味深い機能があります。何らかのコードを壊したい場合を除き、展開されるマクロQQそれ自体だけなので、一意のマーカーのように機能します(クォークと呼ばれます)。\ifx条件を使用して、マクロの引数がそのようなクォークであるかどうかをテストできます\ifx Q#1

AII{\ifxQ}
そのため、そのようなマーカーを見つけたことを確信できます。この定義では、私は間にスペースを削除していることに注意してください\ifxQ。通常、これはエラーになります(構文のハイライトはそれ\ifxQを1つのことと考えていることに注意してください)が、現在Qはcatcode 13であるため、制御シーケンスを形成できません。ただし、このクォークを展開しないように注意してください。Q展開すると、Qどの展開先Qがどの展開先になり、無限ループに陥ります。

準備が完了したので、適切なアルゴリズムに進んでeht setterlを実行できます。TeXのトークン化により、アルゴリズムは逆方向に記述されなければなりません。これは、定義を行うときに、TeXが現在の設定を使用して定義内の文字をトークン化する(catcodesを割り当てる)ためです。

\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が変更される前に定義内の文字(catcode 11)としてトークン化されたため、常にletterになるためEです。ただし、2番目の例では、E最初にアクティブ\oneにされてから定義されたので、定義にはEに展開されるcatcode 13 が含まれてい1ます。

ただし、この事実を見落として、定義を論理的な(ただし機能しない)順序に並べ替えます。以下の段落では、文字と仮定することができBCD、および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はないではない削除\fiH)条件が評価された後まで、代わりにそれはそこにそれを残し\fiている、実際に拡大しました。今、Bマクロが展開されます。

ABBH#1 {HI#1FC#1|BH}
Bは、パラメータテキストがである区切りマクロであるH#1␣ため、引数はHスペースとスペースの間にあるものです。前の拡張への入力ストリーム上の例を続けるとB、IS BHhello world Q␣Bに続いHてが必要で(そうでない場合はTeXがエラーを発生させます)、次のスペースはとの間にhelloありworld#1単語もそうですhello。ここで、入力テキストをスペースで分割する必要がありました。イェーイ:Dの拡大Bにより、入力ストリームと置き換えから最初のスペースに削除し、すべてのアップHI#1FC#1|BH#1あることhelloHIhelloFChello|BHworld Q␣BH入力ストリームの後半に新しいものがあることに注意してください。B後の単語を処理します。この単語が処理Bされた後、処理対象の単語がクォークになるまで次の単語が処理されますQ。後の最後のスペースがQ区切られたマクロがあるため必要とされているB 必要があり、引数の最後に1を。以前のバージョン(編集履歴を参照)では、使用するとコードが正しく動作しませんでし\S{hello world}abc abcた(abcs 間のスペースがなくなります)。

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␣。別のもの|がそこに置かれ、その後にhof helloが置かれることに注意してください。スワッピングの半分が完了しました。最初の文字は最後にあります。TeXでは、トークンリストの最初のトークンを簡単に取得できます。\def\first#1#2|{#1}を使用すると、単純なマクロが最初の文字を取得します\first hello|。最後の1つは問題です。TeXは常に「最小の、おそらく空の」トークンリストを引数として取得するため、いくつかの回避策が必要です。トークンリストの次の項目は次のとおりですD

ADD#1#2|{I#1FE{}#1#2|H}
このDマクロは回避策の1つであり、単語が1文字の場合にのみ役立ちます。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=lloQIeFE{}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}
ここでは、パラメータのテキストは非常によく似ているCD。最初と2番目の引数は区切られず、最後の引数はで区切られ|ます。このような入力ストリームルックス:E{}elloQ|Hh BHworld Q␣、その後、E(で展開し#1、空#2=e、および#3=lloQ): IlloQeFE{e}lloQ|HHh BHworld Q␣。別のI...F...Hブロックがクォークをチェックしlます(これはを見て返しますfalseE{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、次の単語に対してプロセス全体を繰り返すもう1 つの単語です。

}
最後に、すべてのローカル割り当てが取り消されるように、そこから開始されたグループを終了します。地元の割り当ては、文字のcatcodeの変化であるABC、...マクロが行われたので、彼らは彼らの通常の文字の意味に戻っていることを安全にテキストで使用することができます。以上です。ここで\S定義されたマクロは、上記のようにテキストの処理をトリガーします。

このコードの興味深い点の1つは、完全に拡張可能であることです。つまり、爆発することを心配することなく、引数を移動する際に安全に使用できます。コードを使用して、\ifテストの単語の最後の文字が2番目の文字と同じであるかどうか(何らかの理由で必要な場合)を確認することもできます。

\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「残っているもの」が空であるかどうかをチェックします。その場合、1文字の単語が見つかった場合、何もしません。それ以外の場合は展開されEます。E単語の最後の文字が見つかるまでトークンリストをループし、見つかった場合はその最後の文字を残し、その後に単語の中央が続き、トークンストリームの最後に最初の文字が続きますC


2
これについての完全な説明が欲しいです。私はそれがどのように機能するかについて非常に興味があります!
ラムダベータ

1
@LambdaBetaできますが、今はできません。
ちょっと待っ

1
@LambdaBeta完了!申し訳ありませんが、私は時々あまりにも
冗長

13

JavaScript(ES6)、 39  36バイト

@FryAmTheEggmanのおかげで3バイト節約

区切り文字として改行を使用します。

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

オンラインでお試しください!


5
(.)(.*)(.)Total Recallの絵文字ですか?
MikeTheLiar

1
@MikeTheLiarの種類、私は推測する。:D
アーナウド

割り当ては、区切り文字を含む文字列を指定します。
Cees Timmerman

@CeesTimmermanどういう意味かわかりません。このコードは区切り文字として改行を想定しているため、入力として改行を含む文字列を受け取ります。(TIOリンクのフッターはスペースを改行に変換し、読みやすくするためにスペースに戻します。)
Arnauld

「アルファベットのASCII文字列と、区切り文字として使用する他の文字(各単語を区切る)を指定すると」-Nm、それは別のパラメーターだと思いました。
Cees Timmerman

11

網膜8 5バイト

,V,,`

オンラインでお試しください!

Kevin Cruijssenのおかげで3バイト節約できました

区切り文字として改行を使用します。Retinaのリバースステージといくつかの制限を利用します。最初の制限は、反転を適用するために一致するものであるため、すべてを選択し,ます。次に、各一致の最初と最後の文字を交換したいので,,、ステップサイズがゼロの先頭から末尾までの範囲に変換される範囲の各文字を取得します。


ダンギット、私はちょうど私のような答えを更新するためにこのような何かのためにドキュメントを検索していましたが、あなたはそれに私を打ち負かしました。私は知っていましたがV、その1,-2ようなインデックスで使用できることを知りませんでした。良いですね!
ケビンクルーッセン

1
@KevinCruijssen私は少しcheし、これがサンドボックスにある間に制限範囲がどのように機能するかをレビューしました:)私はまだ範囲を反転するよりも良い方法があるはずだと感じていますが、私はもっと短いものを見つけることができませんでした。
FryAmTheEggman

2
You're indeed right that it can be shorter without a limit-range, because it seems this 5-byter works (given as example at the bottom of the Step Limits in the docs).
Kevin Cruijssen

@KevinCruijssen Nice! Can't believe I missed that.
FryAmTheEggman

3
So, 5 bytes and only 3 different characters? That's minimalist.
Cœur

9

Pepe, 107 105 bytes

REEeREeeEeeeeerEEreREEEeREEEEEEeREEEErEEREEEEEEEreererEEEeererEEEerEEeERrEEEeerEEeerereeerEEEEeEEEReEeree

Try it online!

Explanation:

Notation on comments: 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

How does this work?
lirtosiast

@lirtosiast explanation added
u_ndefined


6

laskelH, 71 bytes

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

Try it online!

Example in/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
The assignment in the where clause can be moved to a binding in guard to save 5 bytes: Try it online!
Laikoni

1
I see what you did there with the name "Haskell" in the title. I did the same thing on my PHP answer.
640KB

5

05AB1E, 10 bytes

#vyRćsRćðJ

Try it online!


-3 Thanks to @Kevin Cruijssen.

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


1
@KevinCruijssen I honestly want to delete it and give it to you, that was 99% your brainpower on the ordering of the arguments haha.
Magic Octopus Urn

1
Found a 9-byter, but it only works in the legacy version: |ʒRćsRćJ,
Kevin Cruijssen

1
Too bad we don't have a loop_as_long_as_there_are_inputs, then I would have known an 8-byter: [RćsRćJ, This 8-byter using [ never outputs in theory however, only when you're out of memory or time out like on TIO (and it requires a trailing newline in the input, otherwise it will keep using the last word)..
Kevin Cruijssen

1
Unfortunately you need ð¡ as single word input is possible, but ð¡εćsÁì}ðý also works at 10 bytes.
Emigna

5

J, 23 17 bytes

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

Try it online!


Very nice trick to swap the first/last letters by rotating and applying 1 A. !
Galen Ivanov

1
1&A.&.(1&|.) -> ({:,1|.}:) and then you can remove the ::]
ngn

Amazing, thank you
FrownyFrog

Really amazing! Once again I'm amazed how simple and elegant can the solution be, but only after I see it done by someone else.
Galen Ivanov

4

Ruby with -p, 42 41 29 bytes

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

Try it online!



@Shaggy thanks for the heads up. If you look at my post history it shows I was away for 8 months without any answers, so I've likely missed a few memos during that time, haha
Value Ink

Pretty sure the consensus was changed more than 8 months ago but just in case you missed it: "non-competing" is also no longer a thing.
Shaggy

Nicely done. I think under the rules you can use newlines as your delimiter and replace the \ws with .s.
histocrat





3

Whitespace, 179 bytes

[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]

Letters S (space), T (tab), and N (new-line) added as highlighting only.
[..._some_action] added as explanation only.

Tab as delimiter. Input should contain a trailing newline (or tab), otherwise the program doesn't know when to stop, since taking input in Whitespace can only be done one character at a time.

Try it online (with raw spaces, tabs, and new-lines only).

Explanation in pseudo-code:

Whitespace only has a stack and a heap, where the heap is a map with a key and value (both integers). Inputs can only be read one integer or character at a time, which are always placed in the heap as integers, and can then be received and pushed to the stack with their defined heap-addresses (map-keys). In my approach I store the entire word at the heap-addresses (map-keys) [0,...,word_length], and then retrieve the characters to print one by one in the order we'd want after a tab (or newline) is encountered as delimiter.

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

The program terminates with an error when it tries to read a character when none is given in TIO (or it hangs waiting for an input in some Whitespace compilers like vii5ard).


3

Wolfram Language (Mathematica), 58 bytes

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

Try it online!

-22 bytes from @attinat

-12 bytes from @M.Stern


70 bytes using StringReplace with StringExpressions
attinat

1
64 bytes using StringTake instead of StringReplace: StringRiffle[StringSplit@##~StringTake~{{-1},{2,-2},{1}},#2,""]&
Roman

2
Here is a more direct approach: StringReplace[#, a : u ~~ w : u .. ~~ b : u :> b <> w <> a /. {u -> Except@#2}] &
M. Stern

1
{ and } are optional :)
M. Stern

1
55 bytes, also fixes 2-character words
attinat

2

QuadR, 20 bytes

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

Simply make three capturing groups consisting of 1, 0-or-more, and 1 word-characters, then reverses their order.

Try it online!



2

Japt -S, 10 bytes

Convinced there has to be a shorter approach (and I was right) but this'll do for now.

¸ËhJDg)hDÌ

Try it

¸Ë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

Much shorter than my 12 byter: ¸®Ì+Zs1J +Zg
Embodiment of Ignorance

@EmbodimentofIgnorance, that's where I started, too, but it would have failed on single character words. You could save a byte on that, though, with ¸®ÎiZÌ+Zs1J.
Shaggy

1
@EmbodimentofIgnorance Found a 7 byter
Oliver

2

sed, 64 bytes

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

Sure, we could use . instead of [[:alpha:]], but it would actually have to be [^ ], which reduces it to 43, but breaks on punctuation and such. Using [a-zA-Z] brings it up to 55, by which point I'm just hankering after those sweet, sweet human readable entities...
Rich

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. In other words, you don't need to worry about punctuation "breaking" your code and can just safely go for [^ ] ;)
Value Ink

@ValueInk Yeah, but then [^ ] should be [^[:space:]] which brings it to 67 chars.
Rich

"a delimiter" means you can ensure that the delimiter is always a regular space. Who uses tabs in a sentence anyways??
Value Ink

Okay. Seems like "code golf" is a game where you're meant to find ways to get a drone to drop the ball in the hole instead of actually doing the work. Thanks for the shitty welcome.
Rich

2

sed, 34 bytes

And presumably the pattern idea will work with most RE tools (and I do know there are differences between standard RE and extended RE).

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

Try it online!


1
Welcome to PPCG! Methinks that the greedy nature of regex matches means you can cut the \b from the match: Try it online!
Value Ink

Agreed @ValueInk -- but I was being accurate with the match. Removing the \b will lead to 30 bytes.
PJF

Use -E for advanced regex and you can use unescaped parentheses. Use . for the swapped chars and you can lose another two chars. This brings yours down to 26 bytes; one of the smallest readable solutions. s,\b(.)(\w*)(.)\b,\3\2\1,g
Rich

1
- nope, I'm wrong, you need the \ws at the ends. s,\b(\w)(\w*)(\w)\b,\3\2\1,g 28 chars.
Rich

Nice work @rich, but as I said I know about standard and extended RE. I just chose to make it standard and readable. The anchors would be required which I neglected to mention in my reply to ValueInk.
PJF

2

Ruby, 53 bytes

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

I tried it without regex. The output prints each word on a new line. If that's against the rules, let me know and I'll fix it.

Ungolfed:

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

Welcome to PPCG! Printing each word on a new line should be fine, but your old solution of p was no good because that added quotes to the output. You could always use puts instead since that one auto-appends the newline and is shorter than print! Also, if you call split with no arguments it automatically splits on spaces.
Value Ink

2

8088 Assembly, IBM PC DOS, 39 38 bytes

$ 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

Unassembled:

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 

Standalone PC DOS executable. Input via command line args, output to screen.

enter image description here

Download and test PWAS.COM.



1

Batch, 141 bytes

@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%

Takes input as command-line parameters. String manipulation is dire in Batch at best, and having to special-case single-letter words doesn't help.





1

Haskell, 75 74 bytes

Fixed a bug pointed at by Cubic and also golfed down 1 byte.

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

Try it online!


map g is shorter than (g<$>)
Cubic

1
Also, if you look at your test case you'll see it doesn't work for one letter words, it turns a into aa
Cubic

1

Scala, 100 bytes

(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 bytes

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

Input is via a pre-existing table t with varchar field v, per our IO standards.

Reading from back to front, STRING_SPLIT breaks a string into individual rows via a delimiter, STUFF modifies the characters at the specified positions, then STRING_AGG mashes them back together again.

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.