Zamień przebiegi liter i cyfr

14

Biorąc pod uwagę ciąg wejściowy zawierający tylko alfanumeryczne znaki ASCII i rozpoczynający się na literę, zamień każdą kolejną literę na następną cyfrę.

Prowadzony jest ciągiem następujących po sobie liter lub cyfr. Zauważ, że w przypadku, gdy ciąg wejściowy kończy się ciągiem liter, bieg ten pozostaje nietknięty.

Przykład przejścia

Na przykład, biorąc pod uwagę ciąg wejściowy uV5Pt3I0:

  1. Oddzielne serie liter i cyfry: uV 5 Pt 3 I 0
  2. Zidentyfikuj pary przebiegów: (uV 5) (Pt 3) (I 0)
  3. Zamień pary biegów: (5 uV) (3 Pt) (0 I)
  4. Powiązać: 5uV3Pt0I

Przykłady

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

To jest więc wygrywa najkrótsza odpowiedź w bajtach. Wyjaśnienia są zachęcane.

Jim
źródło

Odpowiedzi:

9

Galaretka , 9 bajtów

~ṠŒg⁸ṁṭ2/

Wypróbuj online!

Jak to działa

~ṠŒ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.
Dennis
źródło
15

Siatkówka , 15 bajtów

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

Zastępuje regex (\D+)(\d+)z $2$1. Rozbijmy to, jeśli nie wiesz, co to znaczy.

Zawodnik \Doznacza „meczu wszystko, co nie jest liczbą”. \doznacza „dopasuj wszystko, co jest liczbą”. Te +środki znak „pasuje do tego co najmniej raz, ale starają się dopasować go tyle razy, ile to możliwe”. Nawiasy definiują grupę. Pierwsza grupa jest, (\D+)a druga jest(\d+)

W drugim wierszu mówimy, że chcemy umieścić wszystko, co pasowało do drugiej grupy, a następnie wszystko, co pasowało do pierwszej grupy. To skutecznie zamienia biegi liter i cyfr.

Wypróbuj online!

Okx
źródło
7

Haskell , 58 56 bajtów

Thanks to @Laikoni for shaving off 2 bytes

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

Try it online!

Ungolfed:

f "" = ""
f string | (letters, afterLetters) <- span (> '9') string
         , (numbers, afterNumbers) <- span (< ':') afterLetters
         = numbers ++ letters ++ f afterNumbers
Julian Wolf
źródło
Save two bytes with (a,(b,y))<-span(<':')<$>span(>'9')s.
Laikoni
1
Save even more with (a,(b,y):_)<-lex<$>span(>'9')s: Try it online!
Laikoni
@Laikoni: Thanks for the tip! I'm not really clear on how lex works, so I'm gonna refrain from including that for now. In any case, good to know that there's something like that in Prelude
Julian Wolf
7

JavaScript (ES6), 34 bytes

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

Try it

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>

Shaggy
źródło
6

Pyth, 15 bytes

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

Explanation

     :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

Test suite.

Leaky Nun
źródło
6

Python 2, 49 bytes

Every non-regex solution I tried was longer. :P

lambda s:re.sub('(\D+)(\d+)',r'\2\1',s)
import re

Try it online!

totallyhuman
źródło
6

Japt (v2.0a0), 16 bytes

q/(\d+/ ò mw c q

Test it online!

Note: this is an unstable alpha, so if this link breaks, you can use a slightly longer version in v1.4.4: Test it online!

Explanation

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
ETHproductions
źródło
Was trying to figure out if there was a way to do it with ò.
Shaggy
5

CJam, 32 30 28 bytes

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

CJam has no regex and no "split into digits and letters" or whatnot, so this was kind of painful.

Try it online!

Explanation

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.
Business Cat
źródło
4

Gema, 11 characters

<L><D>=$2$1

Sample run:

bash-4.4$ gema '<L><D>=$2$1' <<< 'Em5sA55Ve777Rien'
5Em55sA777VeRien
manatwork
źródło
So...short. I mean, it's not a golfing language and just 11? Wow.
Erik the Outgolfer
Yeah, but only for tasks which not require touching the same input twice. Then it becomes nightmare. ☹
manatwork
Found Gema through one of your other posts... cool language. Just how obscure would you say Gema is?
Jonah
@Jonah, I would say its only obscure part is the domain. Though that is partially because the feature is underdocumented. Otherwise the language is a collection of great but painfully limited features. (For example the recognizers rocks, but they would be much powerful if could be combined like the regular expression character classes.)
manatwork
how popular was gema in the 90s? and does it have any modern counterparts / competitors? do you use it for work or just found it for fun?
Jonah
3

Java 8, 38 bytes

s->s.replaceAll("(\\D+)(\\d+)","$2$1")

Not much to explain. Uses the same method as @Okx's Retina answer, which can't be any shorter in Java.

Try it here.

Kevin Cruijssen
źródło
2

Japt, 18 bytes

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

Test it

Shaggy
źródło
Can you add the explanation?
Jim
@Jim, it's just a port of my JS solution (Japt transpiles to JS), which should be pretty self-explanatory. If not, see the explanation in Okx's Retina solution; both of mine do the exact same thing.
Shaggy
4
??? @Downvoter: please provide feedback.
Shaggy
@Shaggy you said it yourself, it's basically copy paste of Okx's solution and then you took it one step further to a language which compiles to the exact same code as your other answer. So I downvoted because this wasn't a unique solution, which doesn't use any interesting golfing techniques or ingenuity; rather a translation of another answer
Downgoat
1
@Downgoat, thanks for commenting. However, I did not say I copied Okx's solution, I simply directed Jim there for the explanation. If you check the timestamps, you'll see that I posted my JS solution at almost the same time as Okx (I may even have been first, but I can't see exact timestamps on mobile). I then ported my own solution to another language, which happens all the time here so, unless you're downvoting all ports, I don't understand why you've singled this one out.
Shaggy
2

Sed, 29 bytes

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

Run with -r.

Uses capture groups and replaces them in the opposite order.

It Guy
źródło
You can shorten [A-Za-z] to [^0-9]. However, you have to count the flag as part of your code.
Dennis
How much does the flag count as?
It Guy
The difference between sed <command> and sed -r <command>, so three bytes.
Dennis
@Dennis, it's the difference between sed -f filename and sed -rf filename (or between sed -e 'command' and sed -re 'command'): a single byte.
Toby Speight
I missed the key phrase ("starting with a letter") in the question, so had s/([a-z]+)([0-9]+)|([0-9]+)([a-z]+)/\2\1\4\3/gi at 48 bytes. Otherwise, much the same.
Toby Speight
2

Jelly, 12 bytes

e€ØDŒg⁸ṁs2Ṛ€

Try it online!

Explanation:

e€ØDŒg⁸ṁs2Ṛ€ Accepts a string
eۯD         Check if each char is in ['0'..'9']
    Œg       Split runs of 0s and 1s (respectively letter and digit runs)
      ⁸ṁ     Replace with input, keeping the split
        s2   Get pairs of runs, last left alone if letter run
          Ṛ€ Swap each pair
Erik the Outgolfer
źródło
2
Can you add the explanation?
Jim
@Jim Added explanaion.
Erik the Outgolfer
2

PHP, no regex, 73 bytes

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

Run as pipe with -nR or test it online.

breakdown

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
Titus
źródło
I mean you can use ~ instead of a&
Jörg Hülsermann
1

C#, 71 bytes

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

Just a shame regular expressions are so long in C#.

Try it online!

Full/Formatted version:

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();
    }
}
TheLethalCoder
źródło
Can you add a link to TIO?
Jim
@Jim Done. I'm usually too lazy to add it initially, especially whilst I'm still looking for any improvements.
TheLethalCoder
1

Clojure, 104 88 bytes

Oh regex is really handy... anyway (TIO):

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

partition-by splits into consecutive runs based on the return value of that function, partition-all splits into partitions of 2 (the pairs we'll be swapping), map reverse reverses them, flatten gets rid of nested list structure and finally we'll output a string. If partition was used instead of partition-all and we had odd number of chunks then the last one would be discarded.

Original used verbose but fun (juxt second first) and (set"0123456789") instead of reverse and ASCII integer ranges.

#(apply str(flatten(map(juxt second first)(partition-all 2(partition-by(comp not(set"0123456789"))%)))))
NikoNyrh
źródło
Can you add a link to TIO and an explanation?
Jim
1

QuadR, 15 bytes

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

Try it online!

Explanation blatantly stolen from Okx:

This replaces the regex (\D+)(\d+) with \2\1. Let's break that down if you don't know what that means.

The \D means 'match anything that isn't a number'. \d means 'match everything that is a number'. The + sign means 'match this at least once but try to match it as many times as possible'. The brackets define a group. The first group is (\D+) and the second is (\d+)

In the second line we say that we want to put whatever was matched by the second group, followed by whatever was matched by the first group. This effectively swaps the letter and digit runs.

Adám
źródło
1

PowerShell, 40 bytes

$args|%{$_ -replace '(\D+)(\d+)','$2$1'}

Try it online!


PowerShell is pretty ideal for this, seeing that it supports regex search-and-replace out of box. Props go to @Okx for the regex solution.

Jeff Freeman
źródło
1

Pip, 17 bytes

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

Takes input as a command-line argument. Try it online!

Explanation

This uses the standard regex-replacement strategy, somewhat golfed.

The regex is -C+XL.C+XD, which evaluates to `(?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+)`

The replacement is {c.b}, a callback function that concatenates the second group (c) and the first group (b). (The first argument to the function, a, contains the whole match.)

This is three bytes shorter than the naive aR`(\D+)(\d+)``\2\1`.

DLosc
źródło
1

brainfuck, 98 bytes

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

Try it online!

Explanation

This program maintains a queue of letters than haven't been output yet, and outputs them when appropriate.

The key to this program is >>----[---->+<<<-[>]>]. The three cells right of the input cell start out at zero. If the input is a code point between 1 and 63 inclusive, this moves the pointer one space right and places the input two spaces right of this new position. Otherwise, the pointer moves two spaces right, the cell one space right of the new position becomes 63, and the same 63 is subtracted from the input cell. This neatly divides the input into letters (65-122) and digits (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
Nitrodon
źródło
Congratulation for having a brainfuck answer which is not the longest of the answers!
Jim
0

Mathematica, 129 bytes

(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)&
J42161217
źródło
Can you add an explanation / ungolfed version?
Jim
nothing much to explain...detects NumberString divides into 2 sets and riffles.Plus some "If" conditions in order to work perfectly
J42161217