交换字母和数字


14

给定仅包含字母数字ASCII字符并以字母开头的输入字符串,请将每个字母运行与后面的数字运行交换。

一个运行是连续的字母或数字序列。注意,在输入字符串以字母结尾的情况下,该行程保持不变。

演练示例

例如,给定输入字符串uV5Pt3I0

  1. 字母和数字分开运行: uV 5 Pt 3 I 0
  2. 确定运行对: (uV 5) (Pt 3) (I 0)
  3. 交换运行对: (5 uV) (3 Pt) (0 I)
  4. 串联: 5uV3Pt0I

例子

uV5Pt3I0 -> 5uV3Pt0I
J0i0m8 -> 0J0i8m
abc256 -> 256abc
Hennebont56Fr -> 56HennebontFr
Em5sA55Ve777Rien -> 5Em55sA777VeRien
nOoP -> nOoP

这是因此最短的答案以字节为单位。鼓励解释。

Answers:


9

果冻,9字节

~ṠŒg⁸ṁṭ2/

在线尝试!

怎么运行的

~ṠŒg⁸ṁṭ2/  Main link. Argument: s (string)

~          Apply bitwise NOT.
           Bitwise operators attempt to cast to int, so if c is a digit, this
           yields ~int(c), a negative number.
           If c cannot be cast to int, ~ will yield 0.
 Ṡ         Take the sign.
           We've now mapped digits to -1, non-digits to 0.
  Œg       Group consecutive equal elements.
    ⁸ṁ     Mold s as the result, grouping run of digits and runs of non-digits.
       2/  Reduce all pairs of runs by...
      ṭ        tack, appending the first run of the pair to the second run.

15

视网膜,15字节

(\D+)(\d+)
$2$1

这将替换正则表达式(\D+)(\d+)$2$1。如果您不知道这意味着什么,让我们分解一下。

\D意思是“匹配任何不是一个数字”。\d意思是“匹配所有数字”。该+符号的意思是“至少匹配一次,但尝试匹配多次”。方括号定义了一个组。第一组是(\D+),第二组是(\d+)

在第二行中,我们说我们要放入第二组匹配的任何内容,然后放入第一组匹配的任何内容。这有效地交换了字母和数字的运行。

在线尝试!


7

Haskell58 56字节

感谢@Laikoni削减了2个字节

f""=""
f s|(a,(b,y))<-span(<':')<$>span(>'9')s=b++a++f y

在线尝试!

取消高尔夫:

f "" = ""
f string | (letters, afterLetters) <- span (> '9') string
         , (numbers, afterNumbers) <- span (< ':') afterLetters
         = numbers ++ letters ++ f afterNumbers

使用保存两个字节(a,(b,y))<-span(<':')<$>span(>'9')s
Laikoni'7

1
使用以下方法可以节省更多(a,(b,y):_)<-lex<$>span(>'9')s在线尝试!
Laikoni '17

@Laikoni:谢谢小费!我还不清楚如何lex运作,因此暂时不要加入。无论如何,很高兴知道序曲中有类似的内容
朱利安·沃尔夫

7

JavaScript(ES6),34个字节

s=>s.replace(/(\D+)(\d+)/g,"$2$1")

尝试一下

o.innerText=(f=
s=>s.replace(/(\D+)(\d+)/g,"$2$1")
)(i.value="uV5Pt3I0");oninput=_=>o.innerText=f(i.value)
<input id=i><pre id=o>


6

Pyth,15个字节

ss_Mc:z"(\d+)"3 2

说明

     :z"(\d+)"3      # Split the input z onto matches of numbers (\d+)
    c           2    # Split the resulting list in pieces of length 2
  _M                 # Reverse each pair
ss                   # Concatenate

测试套件



6

Japt(v2.0a0),16个字节

q/(\d+/ ò mw c q

在线测试!

注意:这是一个不稳定的Alpha,因此,如果此链接中断,则可以在v1.4.4中使用稍长的版本: 在线测试!

说明

q/(\d+/ ò mw c q  : Implicit input              "uV5Pt3I0"
q                 : Split input on
 /(\d+/           :   runs of digits, keeping each run. (This compiles to the regex /(\d+)/g)
                  : This gives                  ["uV","5","Pt","3","I","0",""]
        ò         : Take every pair of items.   [["uV","5"],["Pt","3"],["I","0"],[""]]
          m       : Map each pair by
           w      :   reversing.                [["5","uV"],["3","Pt"],["0","I"],[""]]
             c    : Flatten into one array.     ["5","uV","3","Pt","0","I",""]
               q  : Join into a single string.  "5uV3Pt0I"
                  : Implicit: output result of last expression

试图找出是否有解决办法ò
毛茸茸的

5

CJam32 30 28字节

q{i_64>X\:X^{])[}&c}/]]2/Wf%

CJam没有正则表达式,也没有“分成数字和字母”之类的东西,所以这有点痛苦。

在线尝试!

说明

q      e# Read the input.
{      e# Do the following for every char c:
 i     e#  Get c's codepoint.
 64>   e#  Check if it's greater than 64 (i.e. if it's a letter), pushing 1 or 0.
 X     e#  Push X (variable predefined to 1).
 \:X   e#  Store whether c was a letter or digit into X.
 ^{    e#  If (old X) XOR (new X) is 1:
  ]    e#   Close the current array.
  )    e#   Pull out its last character.
  [    e#   Open a new array.
 }&    e#  (end if)
 c     e#  Turn the codepoint back into a character. This also shoves it into the new array, 
       e#  in case one was opened.
}/     e# (end for)
]      e# Close the final array, since it hasn't been closed yet.
]      e# Wrap the whole stack into an array.
2/     e# Split elements into groups of 2.
Wf%    e# Reverse each group.
       e# Implicitly flatten and print.

4

杰玛(Gema),11个字符

<L><D>=$2$1

样品运行:

bash-4.4$ gema '<L><D>=$2$1' <<< 'Em5sA55Ve777Rien'
5Em55sA777VeRien

所以...简短。我的意思是,这不是一种高尔夫语言,只有11种?哇。
暴民埃里克(Erik the Outgolfer)

是的,但仅适用于不需要两次触摸相同输入的任务。然后变成噩梦。☹
manatwork

通过您的其他帖子之一找到了Gema ...很酷的语言。您会说Gema多么晦涩?
乔纳

@Jonah,我想说的是它唯一晦涩的部分是域名。尽管部分原因是该功能文档不足。否则,该语言将是功能强大但功能有限的集合。(例如识别器摇晃,但如果可以像正则表达式字符类一样组合起来,它们的功能将非常强大。)
manatwork '18

在90年代,gema有多受欢迎?有没有现代的同行/竞争对手?您是用它来工作还是只是找乐子?
乔纳


2

Japt,18个字节

r"(%D+)(%d+)""$2$1

测试一下


您可以添加说明吗?
吉姆(Jim)

@Jim,这只是我的JS解决方案的一部分(Japt转为JS),这应该是不言而喻的。如果没有,请参见Okx的Retina解决方案中的说明;我两个都做完全相同的事情。
毛茸茸的

4
??? @Downvoter:请提供反馈。
毛茸茸的

@Shaggy是您自己说的,基本上是复制Okx解决方案的粘贴,然后您将其进一步发展为一种语言,该语言可编译为与其他答案完全相同的代码。我之所以投票,是因为这不是一个独特的解决方案,它没有使用任何有趣的高尔夫技术或独创性;而不是另一个答案的翻译
-Downgoat

1
@Downgoat,感谢您的评论。但是,我并没有说我复制了Okx的解决方案,我只是将Jim指示在那里。如果检查时间戳,您会发现我几乎在与Okx相同的时间发布了JS解决方案(我可能是第一个,但是我无法在移动设备上看到确切的时间戳)。然后,我将自己的解决方案移植到另一种语言,这种情况一直在这里发生,因此,除非您降低所有端口的投票率,否则我不明白您为什么要选择这种语言。
毛茸茸的

2

Sed,29个字节

s/([^0-9]+)([0-9]+)/\2\1/g

用-r运行。

使用捕获组并以相反的顺序替换它们。


您可以缩短[A-Za-z][^0-9]。但是,您必须将标志算作代码的一部分。
丹尼斯

标记计为多少?
It Guy

sed <command>和之间的差异sed -r <command>,因此为三个字节。
丹尼斯

@Dennis,它的之间的差sed -f filenamesed -rf filename(或之间sed -e 'command'sed -re 'command'):一个字节。
Toby Speight

我错过了问题中的关键短语(“ 以字母开头 ”),所以缺少了s/([a-z]+)([0-9]+)|([0-9]+)([a-z]+)/\2\1\4\3/gi48个字节。否则,大致相同。
Toby Speight


2

PHP,无正则表达式,73个字节

for(;a&$c=$argn[$i++];$p=$c)$c<A?print$c:$s=($p<A?!print$s:$s).$c;echo$s;

作为管道运行-nR在线测试

分解

for(;a&$c=$argn[$i++];  # loop through input
    $p=$c)                  # 2. remember character
    $c<A                    # 1. if digit
        ?print$c            # then print it
        :$s=($p<A           # else if previous character was digit
            ?!print$s           # then print and reset string
            :$s                 # else do nothing
        ).$c;                   # append current character to string
echo$s;                 # print remaining string

我的意思是你可以使用~的,而不是a&
约尔格Hülsermann


1

C#,71个字节

s=>System.Text.RegularExpressions.Regex.Replace(s,@"(\D+)(\d+)","$2$1")

在C#中,很遗憾的正则表达式很长。

在线尝试!

完整/格式化版本:

using System;

class P
{
    static void Main()
    {
        Func<string, string> f = s => System.Text.RegularExpressions.Regex.Replace(s, @"(\D+)(\d+)", "$2$1");

        Console.WriteLine(f("uV5Pt3I0"));
        Console.WriteLine(f("J0i0m8"));
        Console.WriteLine(f("abc256"));
        Console.WriteLine(f("Hennebont56Fr"));
        Console.WriteLine(f("Em5sA55Ve777Rien"));
        Console.WriteLine(f("nOoP"));

        Console.ReadLine();
    }
}

您可以添加指向TIO的链接吗?
吉姆(Jim)

@Jim Done。我通常懒得最初添加它,尤其是在我仍在寻找任何改进的时候。
TheLethalCoder

1

Clojure,104 88字节

哦,正则表达式真的很方便...无论如何(TIO):

#(apply str(flatten(map reverse(partition-all 2(partition-by(fn[i](< 47(int i)58))%)))))

partition-by根据该函数的返回值拆分为连续的运行,partition-all拆分为2的分区(我们将交换的对),map reverse反转它们,flatten摆脱嵌套列表结构,最后输出一个字符串。如果partition用代替partition-all而我们的块数为奇数,则最后一个将被丢弃。

原使用冗长,但乐趣(juxt second first)(set"0123456789"),而不是reverse和ASCII整数范围。

#(apply str(flatten(map(juxt second first)(partition-all 2(partition-by(comp not(set"0123456789"))%)))))

您可以添加指向TIO的链接和说明吗?
吉姆(Jim)

1

QuadR,15字节

(\D+)(\d+)
\2\1

在线尝试!

解释是从Okx偷来的

这将替换正则表达式(\D+)(\d+)\2\1。如果您不知道这意味着什么,让我们分解一下。

\D意思是“匹配任何不是一个数字”。\d意思是“匹配所有数字”。该+符号的意思是“至少匹配一次,但尝试匹配多次”。方括号定义了一个组。第一组是(\D+),第二组是(\d+)

在第二行中,我们说我们要放入第二组匹配的任何内容,然后放入第一组匹配的任何内容。这有效地交换了字母和数字的运行。



1

,17字节

aR-C+XL.C+XD{c.b}

将输入作为命令行参数。在线尝试!

说明

它使用标准的正则表达式替换策略,有些打高尔夫球。

正则表达式为-C+XL.C+XD,其计算结果为`(?i)([a-z]+)(\d+)`

   XL       Preset regex variable for lowercase letter: `[a-z]`
  +         Apply + to the regex: `[a-z]+`
 C          Wrap the regex in a capturing group: `([a-z]+)`
-           Apply the case-insensitive flag: `(?i)([a-z]+)`
        XD  Preset regex variable for digit: `\d`
       +    Apply + to the regex: `\d+`
      C     Wrap the regex in a capturing group: `(\d+)`
     .      Concatenate the two regexes: `(?i)([a-z]+)(\d+)`

替代方法是{c.b},一个回调函数将第二组(c)和第一组(b)连接起来。(函数的第一个参数a包含整个匹配项。)

这比天真短3个字节aR`(\D+)(\d+)``\2\1`


1

brainfuck,98个字节

,[>>----[---->+<<<-[>]>]>>[.[[-]<]<<[-]+>>]<[[-<<<+>>>]<<<<[-<[<]>[.[-]>]]>[-<+>]>],]<[-]<[<]>[.>]

在线尝试!

说明

该程序维护一个尚未输出的字母队列,并在适当时输出它们。

该程序的关键是>>----[---->+<<<-[>]>]。输入单元格右边的三个单元格从零开始。如果输入是1到63(含1和63)之间的代码点,则这会将指针向右移动一个空格,并将输入移到这个新位置的两个空格的右边。否则,指针将向右移动两个空格,新位置向右一个空格的单元格变为63,并从输入单元格中减去相同的63。这样可以将输入整齐地分为字母(65-122)和数字(48-57)。

,[                       Take first input byte and start main loop
  >>                     Move two cells to the right
  ----[---->+<<<-[>]>]   (See above)
  >>                     Move two cells to the right
                         This cell contains the input if it was a digit, and 0 if input was a letter
  [                      If input was a digit:
   .                     Output digit immediately
   [[-]<]                Zero out digit and working cell
   <<[-]+>>              Set flag so we know later that we've output a digit
  ]
  <                      Move one cell left
                         This cell contains 63 if input was a letter, and 0 if input was a digit
  [                      If input was a letter:
   [-<<<+>>>]            Add 63 back to input letter
   <<<<                  Move to flag
   [                     If a digit has been output since the last letter read:
    -                    Clear flag
    <[<]>                Move to start of queue
    [.[-]>]              Output and clear all queued letters
   ]
   >[-<+>]>              Move input to end of queue
  ]
,]                       Repeat until no input remains
<[-]                     Clear flag if present
<[<]>                    Move to start of queue
[.>]                     Output all queued letters

恭喜您得到了一个脑筋急转弯的答案,答案不是最长的答案!
吉姆(Jim)


0

Mathematica,129个字节

(n=NumberString;l=Length;s=Riffle[a=StringCases[#,n],b=StringSplit[#,n]];If[l@a==0,s=#,If[l@a<l@b,AppendTo[s,b[[-2;;]]]]];""<>s)&

您可以添加说明/非公开版本吗?
吉姆(Jim)2005年

没什么好解释的...检测NumberString分为2组和riffles.Plus一些“如果”条件以使其正常工作
J42161217
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.