特斯拉脱氧核糖核酸


30

或者,“交换每个单词的首字母和尾字母”

您面临的挑战是,给定一串字母ASCII字符以及一个用作分隔符(分隔每个单词)的其他字符,交换每个单词的第一个和最后一个字母。如果有一个字符的单词,请不要理会。

示例/测试用例使用小写字母和空格作为分隔符。

您不需要处理标点符号。所有输入将仅由字母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
第二段和另一个字符都用作分隔符,而第四段则以空格分隔。哪一个?
阿达姆(Adám)

@Adám任何非字母字符。我将进行澄清。
SparklePony同志

1
@BenjaminUrquhart是的。如果需要,也可以将输入作为函数参数。
SparklePony同志

Answers:


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是一种宏扩展语言。作为示例,您可以定义\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!}。在这种情况下,参数后跟所谓的参数文本。这样的参数文本#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读取一个字符(由“字符代码”定义)时,它将为该字符分配一个“类别代码”(类别代码,对于朋友:),该字符定义了该字符的含义。字符代码和类别代码的这种组合构成了令牌(例如,此处有更多内容)。我们这里感兴趣的基本上是:

    • 目录代码11,它定义可以组成控制序列的标记(宏的宏伟名称)。默认情况下,所有字母[a-zA-Z]都为catcode 11,因此我可以编写\hello,这是一个单一的控制序列,而\he11o该控制序列\he后面是两个字符1,然后是字母o,因为1它不是catcode 11。从那时\catcode`1=11起,\he11o将是一个控制序列。重要的一点是,当TeX第一次看到手边的字符时,就设置了Catcode,并且这样的Catcode被冻结了 ……永远!(条款和条件可能适用)

    • 目录代码12,是大多数其他字符,例如0"!@*(?,.-+/等等。它们是Catcode 的特殊类型,因为它们仅用于在纸上书写内容。但是,嘿,谁用TeX编写文字?!(同样,条款和条件可能适用)

    • 目录代码13,这真是地狱:)真的。停止阅读,去做一些你毕生无法做的事情。您不想知道类别代码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在代码中编写一个!这就是目录代码13。我很平静!让我们继续前进。

  • 好的,现在分组。这很简单。不论分配(\def是分配操作,\let除非分配是全局的,否则在组中完成的(我们将进行介绍)是另一个)都将恢复为该组开始之前的状态。有几种开始组的方法,其中一种是使用类别1和2个字符(哦,再次使用类别代码)。默认{是目录1,或开始组,目录}2,或结束组。例如:\def\a{1} \a{\def\a{2} \a} \a打印1 2 1。外组\a1,那里面它被重新解释2,当组结束时,就恢复了1

  • \let操作是另一个分配操作,例如\def,但有所不同。随着\def定义的宏将扩展到东西,与\let你创造的已经存在的事物的副本。之后\let\blub=\def=可选),您可以将e示例的开头从上面的目录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 }
}

每个步骤的说明

每行包含一条指令。让我们一一剖析一下:

{
首先,我们开始一个小组,以将一些更改(即Catcode更改)保留在本地,以使它们不会弄乱输入文本。

\let~\catcode
基本上所有 TeX混淆代码都以该指令开头。默认情况下,在普通TeX和LaTeX中,该~字符都是一个活动字符,可以将其设置为宏以供进一步使用。修改TeX代码的最佳工具是更改Catcode,因此通常是最佳选择。现在代替\catcode`A=13我们可以写~`A13=是可选的):

~`A13
现在,字母A是一个活动字符,我们可以定义它来执行以下操作:

\defA#1{~`#113\gdef}
A现在是一个带有一个参数(应该是另一个字符)的宏。首先,将参数的catcode更改为13以使其处于活动状态:(~`#113替换~by \catcode并添加an =和you have:)\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我们可以简单地使用FH。矮得多 :)

AQQ{Q}
现在,我们A再次使用定义另一个宏Q。上面的声明基本上是这样做的(用一种不太混淆的语言)\def\Q{\Q}。这不是一个非常有趣的定义,但是它具有有趣的功能。除非你想打破一些代码,唯一的宏扩展为QQ本身,因此它就像一个特殊的标记(它被称为夸克)。您可以使用\ifx条件语句来测试宏的参数是否为夸克\ifx Q#1

AII{\ifxQ}
因此,您可以肯定地找到了这样的标记。请注意,在此定义中,我删除了\ifx和之间的空格Q。通常,这将导致错误(请注意语法突出显示认为这\ifxQ是一回事),但是由于现在Q是catcode 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中,定义更改之前,定义中的标记为字母(目录代码11),因此它将始终为letter E。但是,在第二个示例中,E首先将其激活,然后\one才对其进行定义,现在该定义包含目录代码13E变为扩展为的目录代码1

但是,我将忽略这一事实,并对定义重新排序以使其具有逻辑顺序(但不起作用)。在下面的段落,你可以假设信件BCD,和E活跃。

\gdef\S#1{\iftrueBH#1 Q }
(请注意,以前的版本中有一个小错误,上面的定义中没有包含最后的空格。我只是在编写本文时才注意到它。继续阅读,您将了解为什么我们需要那个来正确终止宏。 )
首先,我们定义用户级宏\S。该字符不应该是具有友好(?)语法的活动字符,因此gwappins setterl的宏是\S。宏以始终为true的条件开头\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和之间是空格。在扩展Bis 之前,在输入流之上继续该示例BHhello world Q␣B后面紧跟着H它(应该是TeX会引发错误),然后下一个空格在helloand 之间world#1单词也是hello。在这里,我们必须在空格处分割输入文本。耶:的d的扩展B中移除了一切到从输入流和替换第一空间通过HI#1FC#1|BH#1helloHIhelloFChello|BHworld Q␣。请注意,这里有一个新BH输入流中稍后,可以对B并处理以后的单词。B处理完该单词后,处理下一个单词,直到要处理的单词是夸克为止QQ需要最后一个空格,因为定界宏在参数末尾B 需要一个空格。在以前的版本中(请参阅编辑历史记录),如果您使用该代码,则行为会不正确\S{hello world}abc abcabcs 之间的空格将消失)。

OK,回到输入流:HIhelloFChello|BHworld Q␣。首先是H\fi)完成了initial \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(with #1=h#2=ello)展开后,输入流为:DelloQ|h BHworld Q␣。请注意,另一个|放置在此处,hof 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,它将看到参数为quark并将中断执行,仅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=lloQIlloQeFE{e}lloQ|HHh BHworld Q␣。另一个I...F...H块检查夸克(其看到l并返回false): E{e}lloQ|HHh BHworld Q␣。现在E再次膨胀(与#1=e空,#2=l#3=loQIloQleFE{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␣。ew

哦,等等,这些是什么?正常字母?好家伙!终于找到了字母,TeX写下了oell,然后找到了H\fi)一堆并展开(没有内容),输入流带有:oellh BHworld Q␣。现在,第一个单词交换了第一个和最后一个字母,而TeX接下来找到的是另一个B重复下一个单词的整个过程。

}
最终,我们结束了从该小组开始的小组,以便撤消所有本地任务。本地分配是字母的catcode变化ABC,...它作了宏,让他们回到自己的正常字母的含义,并可以在文本中安全地使用。就是这样。现在\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

很抱歉(可能也是如此)罗explanation的解释。我也尝试使非TeXies也尽可能清楚:)

急躁的总结

巨集\S会在输入端加上一个主动字元B,该字元会撷取以最后一个空格分隔的标记清单,并将它们传递给CC获取该列表中的第一个令牌并将其移至令牌列表的末尾,然后扩展D剩余的令牌。D检查“剩下的”是否为空,在这种情况下,找到一个字母,然后什么也不做;否则扩展EE循环遍历令牌列表,直到找到单词中的最后一个字母,当找到单词时,它离开最后一个字母,然后是单词的中间,然后是令牌流末尾剩下的第一个字母,即C


2
我希望对此有完整的解释。我很好奇它是如何工作的!
LambdaBeta

1
@LambdaBeta我可以,但是现在不能。稍等,待会我会
通知

1
@LambdaBeta完成!抱歉,有时我太
罗word了

13

JavaScript(ES6), 39  36字节

@FryAmTheEggman节省了3个字节

使用换行符作为分隔符。

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

在线尝试!


5
(.)(.*)(.)这是“全面召回”图释吗?
MikeTheLiar

1
我猜@MikeTheLiar有点。:D
Arnauld的

分配指定包含分隔符的字符串。
Cees Timmerman

@CeesTimmerman我不确定您的意思。此代码期望将换行符用作分隔符,因此将带有换行符的字符串作为输入。(TIO链接的页脚将空格转换为换行符,然后再转换回空格以提高可读性。)
Arnauld

“给出了一串字母ASCII字符以及一个用作分隔符(以分隔每个单词)的其他字符 ”-Nm,我认为这是一个单独的参数。
Cees Timmerman,

11

视网膜8 5字节

,V,,`

在线尝试!

多亏了Kevin Cruijssen,节省了3个字节!

使用换行符作为分隔符。我们利用了视网膜的反向阶段和一些限制。第一个限制是要应用冲销的匹配项,因此我们选择,。然后,我们希望交换每个匹配项的第一个和最后一个字母,因此我们将范围内的每个字母,,转换为从开始到结束的范围,步长为零。


Dangit,我只是在文档中搜索类似的内容来更新我的答案,但是您击败了我。我知道V,但不知道它可以与这样的索引一起使用1,-2。好东西!
凯文·克鲁伊森

1
@KevinCruijssen我作弊了一点,回顾了限制范围在沙箱中的工作原理:)我仍然觉得应该有一个比反转范围更好的方法,但是我找不到更短的方法。
FryAmTheEggman

2
您确实是对的,可以没有限制范围地缩短它,因为看起来这是5乘的方法(例如,在文档中“步骤限制”的底部给出了示例)。
凯文·克鲁伊森

@KevinCruijssen不错!不敢相信我错过了。
FryAmTheEggman

3
那么,只有5个字节和3个不同的字符?极简主义。
心教堂

9

Pepe107105字节

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

在线尝试!

输入/输出示例:

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子句中的赋值可以移动到Guard中的绑定以节省5个字节:在线尝试!
Laikoni

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,
Kevin Cruijssen

1
不幸的是,我们没有loop_as_long_as_there_are_inputs,那么我会知道一个8位字节:[RćsRćJ,这种8位字节[从理论上讲从不输出,仅当您内存不足或像TIO那样超时时(这需要尾随)输入中的换行符,否则将继续使用最后一个单词。)
Kevin Cruijssen,

1
不幸的是,您可能需要ð¡输入单个单词,但ð¡εćsÁì}ðý也需要10个字节。
Emigna

5

J23 17字节

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

在线尝试!


通过旋转和应用来交换前一个/后一个字母的很好的技巧1 A.
Galen Ivanov

1
1&A.&.(1&|.)-> ({:,1|.}:)然后您可以删除::]
ngn


真的很棒!再一次让我感到惊讶的是,该解决方案多么简单和优雅,但是只有在看到其他人完成之后,我才感到惊奇。
Galen Ivanov

4

红宝石-p42 41 29个字节

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

在线尝试!



@Shaggy感谢您的注意。如果您查看我的发帖历史,它表明我已经离开了8个月而没有任何答案,所以我很可能错过了一些备忘录,哈哈
价值墨水

可以肯定的是,共识已在8个月前被更改,但以防万一您错过了共识:“不竞争”也不再是一回事。
毛茸茸的

做得很好。我认为,根据规则,您可以使用换行符作为分隔符,并将\ws 替换为.s。
历史学家





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.

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.