RLE Brainfuck dialect

14

RLE Brainfuck

(related to BF-RLE)

The hypothetical RLE (Run-Length Encoding) dialect of Brainfuck accepts the symbols for the 8 commands and also accepts digits. The digits are used to represent the number of successive repetitions of a command, thus allowing run-length encoding of the source code.

8> is equal to >>>>>>>>.

The length is always on the left side of the command.

Your task is to write the shortest program/function that translates the input string (RLE Brainfuck fragment) into a regular Brainfuck program.

For example:

Input:

10+[>+>3+>7+>10+4<-]3>2+.>+.7+2.3+.2<2+.>15+.>.3+.6-.8-.2<+.<.

Ouptut:

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

The shortest code in byte count in each language will win.

Galen Ivanov

Posted 2017-11-02T12:54:46.157

Reputation: 13 815

I'm confused. Is the goal to output the fixed string corresponding to translating the given string? – xnor – 2017-11-02T12:57:53.817

Is the program given as input, or should we hardcode it? – user202729 – 2017-11-02T12:57:56.977

Your task is to write the shortest program/function that translates the following RLE Brainfuck fragment into regular Brainfuck program - Should our submissions work for any valid Brainfuck code or just that piece of code? You should also include the desired output by the way. – Mr. Xcoder – 2017-11-02T12:58:04.620

Although this is a valid challenge, it received 2 VTC (at the time of writing this comment) as unclear (up to the site's standard). You can try the Sandbox next time.

– user202729 – 2017-11-02T13:01:55.743

Hi, I edited the description. The program should work for any valid RLE BF code and display the translated program. – Galen Ivanov – 2017-11-02T13:02:03.880

10Hi, I downvoted this question because I feel that it's going to be dominated by one or two RLE-based regex algorithms that are then just copied to each language's individual regex formatting. There's very little room to golf anything here. – AdmBorkBork – 2017-11-02T13:04:15.197

13

This looks a lot like a generic run-length decoding challenge. The difference here is that multidigit numbers are supported. I think it's still a dupe, but I won't hammer it.

– xnor – 2017-11-02T13:04:18.353

@user202729 Thanks, I'll use it next time. – Galen Ivanov – 2017-11-02T13:13:34.253

@AdmBorkBork Hi, Thanks for the feedback. Now I understand that my idea was stupid. – Galen Ivanov – 2017-11-02T13:34:05.837

Hi, I added clarification that the shortest code in each language wins. – Galen Ivanov – 2017-11-02T13:42:45.193

4@xnor The other difference is that digits are not always present — this form of RLE guarantees far less structure, and IMO can lead to interesting techniques (compare my Python answer here with the one in the linked challenge!) – Lynn – 2017-11-02T14:22:09.817

@GalenIvanov Can the input contain things like 0<? – Lynn – 2017-11-02T14:22:37.803

1@Lynn I haven't explicitly described this, but as is seen in the example, 1 is ommited; adding 0 doesn't make the string shorter, so the answer is no, no zeroes can prepend a command. – Galen Ivanov – 2017-11-02T14:45:19.840

6The other direction would be more interesting, I think (i.e. transform a brainfuck programm in the shortest equivalent RLE brainfuck program). – Paŭlo Ebermann – 2017-11-02T22:04:49.760

I kinda sorta implemented this language awhile ago if anyone's interested.

– Carcigenicate – 2017-11-04T23:11:56.490

@PaŭloEbermann It'd be really difficult to prove that it was the shortest equivalent. You'd need to recognize that, e.g., >+++<[>++++<-] is equivalent to 12+, but only if the second cell is 0 always 0 when the code is executed, which requires some serious static analysis if it appears inside any looping/branching structures. And since in the general case, pretty much any interesting static analysis is going to reduce to the halting problem, it may actually be impossible to prove optimality. Converting to an equivalent RLE-BF program would be possible, though. – Ray – 2017-11-06T14:53:15.120

1@Ray I meant some "weaker" form of equivalence, basically the one implemented by this challenge (i.e. two RLE brainfuck programs are equivalent if they expand to the same brainfuck program). Finding the shortest (or one of the shortest, as ++ and +2 have the same length) from such a family should be easily decidable. The general equivalence in the computer science meaning is non-decidable, of course. – Paŭlo Ebermann – 2017-11-06T20:17:18.847

Answers

24

Python 2, 62 61 bytes

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

Try it online!

The regex substitution expands 3<2+- into the string:

+1*3*1*"<"+1*2*1*"+"+1**1*"-"

which is then evaled. (Note how when \1 is empty, we get 1**1 = 1.) The first + is a unary operator which binds to the first number, and the other +s are string concatenation. This beats the more obvious

lambda s:re.sub('(\d+)(.)',lambda m:int(m.group(1))*m.group(2),s)
import re

by 14 bytes. Ordinarily "\2" wouldn’t always work, but thankfully \ and " aren’t brainfuck commands.


xnor saved a byte, supplying the 1*\1*1 trick. Previously I had \1L in the regex, and defined L=1 as a lambda argument, which is also pretty cool: 3L is a long int literal and L is a variable.

Lynn

Posted 2017-11-02T12:54:46.157

Reputation: 55 648

1That's a slick use of L to handle the empty string. There's a shorter way though, r'+1*\1*1*"\2"'. – xnor – 2017-11-02T14:51:27.460

3...Why is import re below the lambda? – Fund Monica's Lawsuit – 2017-11-03T21:51:03.790

1Putting the lambda first means I can use tio.run's Header/Footer feature to show off how the code is supposed to be invoked (I put f=\ in the Header — now the lambda has a name!) – Lynn – 2017-11-05T13:36:16.960

18

Pyth, 2 bytes

r9

Try it here!

How it works

r9  - Full program receiving the String from STDIN.

r   - Pyth's set of extended string operations.
 9  - The ninth command of that set (run-length decode). This supports multi-digit numbers.

Mr. Xcoder

Posted 2017-11-02T12:54:46.157

Reputation: 39 774

Darn, Jelly RLD borks :( :P – HyperNeutrino – 2017-11-02T13:06:02.867

31

Necessary reminder: Stop upvoting trivial solutions (like this one).

– Mr. Xcoder – 2017-11-02T13:18:36.193

4It's not so trivial to know about that command, and to know it works when numbers are missing – Luis Mendo – 2017-11-02T14:28:13.213

1@Mr.Xcoder Wait, what? Isn't the entire point of code golf to have the lowest byte count? – Deacon – 2017-11-02T15:01:16.910

@Deacon It is, but trivial answers shouldn't be upvoted too much in my opinion, since they (might) discourage new users that don't know of these golfing languages. – Mr. Xcoder – 2017-11-02T15:02:39.057

4@Deacon yes, but a golfed Python answer is usually a lot harder to make and more interesting than a 2-byte golflang answer. – Stephen – 2017-11-02T15:59:54.567

1@Mr.Xcoder People can certainly upvote if they wish. – NoOneIsHere – 2017-11-02T16:04:45.490

@Stephen Yeah, but this doesn't have a popularity-contest tag, it has a code-golf tag. – Deacon – 2017-11-02T16:40:37.493

8@Deacon Upvoting isn't just about upvoting short solutions. Users are generally encouraged to upvote solutions that are interesting and creative as opposed to trivial short solutions in golfing languages. – LyricLy – 2017-11-02T20:50:09.927

17

Lua, 65 64 63 Bytes

Great ! For once, Lua beats Python !

Edit: Saved one byte thanks to @Jarhmander, thanks to him for the useful trick to force a single result

print(((...):gsub("(%d+)(.)",function(a,b)return b:rep(a)end)))

Try it online!

Explanations

print)((...):gsub(             -- iterate over the argument and replace the strings
            "(%d+)(.)",       -- matching this pattern (at least one digit and a non-digit)
            function(a,b)     -- capture the digit and non-digit parts in separate variables
              return b:rep(a) -- repeat the non-digit a times, a being the digit part
            end)))                    

Katenkyo

Posted 2017-11-02T12:54:46.157

Reputation: 2 857

1Beat you! :) – Lynn – 2017-11-02T14:19:25.500

@Lynn One byte down, 3 more to go! – Katenkyo – 2017-11-02T14:31:21.100

You can save a byte by removing ,"" and enclosing in parens the entire print argument. Expressions enclosed in parens are adjusted to one value in Lua (see https://www.lua.org/manual/5.3/manual.html#3.4).

– Jarhmander – 2017-11-03T16:02:43.460

11

Scala, 73 69 bytes

"(\\d+)(.)".r.replaceSomeIn(_:String,m=>Some("$2"*m.group(1).toInt))

Try it online!

oowekyala

Posted 2017-11-02T12:54:46.157

Reputation: 211

2This is a nice answer! Welcome to the site. :) – James – 2017-11-03T17:36:50.787

10

Perl 5, 18 bytes

17 bytes code + 1 for -p.

s/\d+(.)/$1x$&/ge

Try it online!

Dom Hastings

Posted 2017-11-02T12:54:46.157

Reputation: 16 415

8

vim, 29 25 23 22 16 bytes

:s/\D/a&<C-v><ESC>/g
D@"

<C-V> is 0x16, <ESC> is 0x1b.

It works by replacing each non-digit with a command that appends that character to the buffer. The counts are left alone and modify those commands. At this point, the buffer is a vimscript program that produces the desired Brainfuck program, so we pull it into a register and run it.

Try it online!

Edit: Size reductions thanks to suggestions: H.PWiz: 5, TheFamilyFroot: 5, DJMcMayhem: 1

Ray

Posted 2017-11-02T12:54:46.157

Reputation: 1 488

TheFamilyFroot had a nice golfing tip: you don't need to use a capturing group, you can just use group 0 (& or \0) instead with no parentheses. Also, a tip from me, not TheFamilyFroot is that you could use D instead of dd for -1 byte. – James – 2017-11-03T06:13:55.907

1Thanks for all the suggestions, H.PWiz, TheFamilyFroot, and DJMcMayhem. That brought it below the 18 byte Perl solution and into second place. Now we just need to find another 15 bytes we can get rid of and it'll beat the Pyth builtin. :-) – Ray – 2017-11-03T18:25:10.340

8

RLE Brainfuck, 204 bytes

-3>,[[->+>+<<]>>47-3<10+<->[-<+4>->+<[>-]>[3<+<[-]4>->]5<]3>57+[-]+<<[>>-<<[3>+3<-]]3>[3<+3>-]<[>>+7<+[->11-<+[-<+]->>+[-<[->10+<]>>+]<[-4>.4<]4>[-]-3<-<+7>-7<[8>+8<-]]8>[8<+8>-]<[3<.3<[-]-6>-]7<--5>-]<,]

As I understand it the specs for the brainfuck environment aren't super well-defined. This program assumes that the cells in the tape allow arbitrarily large positive and negative integers, with no overflow. This code will transcribe non-command comments as well, but it will expand the run-length encoding of comments (eg "see 3b" → "see bbb"). The resulting program should run the same, so I'm not too concerned.

I'm pretty sure I could still golf a few bytes off this but I'm exhausted from working with it.

Here's the custom interpreter + tests I've been using to test it. If you pass it input in the Standard Input box it should run against that input instead of running the tests.

My messy ungolfed workpad:

->>>,
[
  [->+>+<<]>>  clone 2 into 3 and 4
  if read char is between zero and nine
  (num buffer | max | is_digit | original char | read | temp0 | temp1)
                                                   ^
  47-
  <<<10+  set max
  <->  handle gross 0 case
  [  while max
    -  max minus one
    <+  buffer plus one
    >>>>-  read minus one
    IF STATEMENT : if read is 0
    >+<
    [>-]>[<
      <<+  is_digit = 1
      <[-]>>>  max = 0
    >->]<<  back to read
    <<<     back to max
  ]

  >>>57+[-]  reset `read` (need to add first to avoid infinite negative)

  +<<  check is_digit flag
  ( end marker | 0 | is_digit | original char | temp0 | temp1 | temp2 | temp3)
  x[  IF READ WAS DIGIT
    CODE 1a
    >>temp0 -<<x
    [>>>temp1 +<<<x-]
  ]
  >>>temp1 [<<<x+>>>temp1 -]
  <temp0 [
    START CODE 2a
    >>temp2 +
    7<y+[  IF THERE IS A NUMBER PREFIX
      -
      START CODE 1b
      >11-  end marker is negativeone
      <   on smallest digit
      +[-<+]->  find largest digit
      >+[  sum digits until we hit the end marker negativeone
        -
        <[->10+<]>  h1 = ten * h0; h0 = 0
        >
        +
      ]  leave the negativeone at zero though
      num | 0 | 0 | 0 | original char
            ^
      <num
      [->>>>.<<<<]  print `original char` `num` times
      >>>>[-]-  set `char` to negativeone
      <<<- last ditch guess
      END CODE 1b
      <y+
      7>temp2 -
      7<y[8>temp3 +8<y-]
    ]
    8>temp3 [8<y+8>temp3 -]
    <temp2 [
      CODE 2b
      <<<.  print original char
      <<<[-]-  set num buffer to new left edge
      >>>>>>temp2 -
    ]
    7<y--

    END CODE 2a
    5>temp0 -
  ]
  <
  ,
]

Orez

Posted 2017-11-02T12:54:46.157

Reputation: 471

Does the gross 0 case only refer to actual zero counts, or does it also happen when parsing, e.g. 10+? The OP clarified in a comment that count will always be greater than 0, so you might be able to shave some bytes off if it's the former. – Ray – 2017-11-06T14:57:06.913

Gross 0 case is for parsing any 0. Since the while max loop always runs at least once, and I'm unconditionally upping the buffer where I store the digit's value in that loop, I need to start that buffer at -1. I wonder if I could save some bytes by leaving that buffer logically at value+1 though – Orez – 2017-11-06T15:29:15.790

6

Stacked, 24 bytes

['(\d+)(.)'[\#~*]3/repl]

Try it online!

Explanation

['(\d+)(.)'[\#~*]3/repl]
[                      ]   anonymous function, taking string as argument
 '(\d+)(.)'                for all matches of this regex:
           [    ]3/repl      replace (stack = (whole match, digit, repetend))
            \#~              convert digit to number
               *             repeat the character by that digit

Conor O'Brien

Posted 2017-11-02T12:54:46.157

Reputation: 36 228

5

Retina, 28 23 bytes

thanks to @Leo for -5 bytes

\d+
$*
+`1(1\D)
$1$1
1

Try it online!

ovs

Posted 2017-11-02T12:54:46.157

Reputation: 21 408

Can you use \b in the second regex to only match one 1 per run of 1s? – Neil – 2017-11-02T20:23:44.087

Or you could do something like this

– Leo – 2017-11-02T23:19:44.210

5

TeX, 124 bytes

\newcount\n\def\b{\afterassignment\r\n0}\def\r#1{\ifx;#1\else\p#1\expandafter\b\fi
}\def\p#1{#1\ifnum\n>1\advance\n-1\p#1\fi}

(wrote in two lines to be visible, but the code can be written in one line)

This defines a macro \b that takes the input in the form \b<input>;, and prints the output wanted to the document.

Manuel

Posted 2017-11-02T12:54:46.157

Reputation: 291

4

Pyon, 66 bytes

print(re.sub("\d+.",lambda k:(int(k.group()[:-1])*k.group()[-1]),a

Try it online!

Pyon is pretty much just Python, but this is shorter because re is automatically imported when you use it, and a is automatically set to an argument or the input

-4 bytes thanks to Mr. Xcoder

HyperNeutrino

Posted 2017-11-02T12:54:46.157

Reputation: 26 575

You should change g[0] to g[:-1] (fails for the given test case or any number higher than 9). – Mr. Xcoder – 2017-11-02T13:23:22.997

Anyway why would you even need a lambda which actually wastes bytes? Golfed and corrected for 66 bytes

– Mr. Xcoder – 2017-11-02T13:27:23.363

@Mr.Xcoder whoops, not sure what I was thinking... thanks – HyperNeutrino – 2017-11-02T13:27:29.447

@Mr.Xcoder oh yeah I try to golf things a lot that end up being ungolfs xD – HyperNeutrino – 2017-11-02T13:27:55.133

4

Python 2, 100 93 89 bytes

-7 with thanks to Mr.Xcoder

n=b=""
for y in input():
 if"/"<y<":":n+=y
 elif""==n:b+=y
 else:b+=y*int(n);n=""
print b

Try it online!

ElPedro

Posted 2017-11-02T12:54:46.157

Reputation: 5 301

A few golfs for 93 bytes. It can be golfed further though.

– Mr. Xcoder – 2017-11-02T13:33:57.400

3

Haskell, 60 bytes

f(a:b)|[(c,d:e)]<-reads$a:b=(<$)d[1..c]++f e|1<2=a:f b
f a=a

Try it online!

Lynn

Posted 2017-11-02T12:54:46.157

Reputation: 55 648

3

R, 121 106 90 bytes

function(s,a=strsplit)cat(rep(el(a(gsub("\\d","",s),"")),pmax(el(a(s,"\\D")),"1")),sep="")

Try it online!

Saved 15 bytes by realising that rep() will coerce to numeric. Saved another 16 thanks to Giuseppe, mainly from the use of pmax to replace empty strings with 1

function(s) {
  x <- el(strsplit(s,"\\D")) # Split the string on anything that is not a digit...
  x <- pmax(x, "1")          # ... and replace any empty strings with 1. This gets us the numbers of repeats
  y <- gsub("\\d","",s)      # Remove all digits from the original string...
  y <- el(strsplit(y))       # ... and split into individual units. This gets us the symbols to repeat
  z <- rep(y, x)             # Implement the repeats. x is coerced to numeric
  cat(z, sep = "")           # Print without separators
}

user2390246

Posted 2017-11-02T12:54:46.157

Reputation: 1 391

very nice! I believe ifelse(x>"",x,1) is a byte shorter, and \\D is equivalent to [^\\d] and best of all, you don't need perl=T, so this is a sweet 99 bytes. I really didn't think this could be fewer than 100 bytes!

– Giuseppe – 2017-11-02T19:58:16.000

90 bytes with pmax – Giuseppe – 2017-11-02T20:00:14.857

@Giuseppe Very clever use of pmax giving a nice big improvement - thanks! – user2390246 – 2017-11-02T21:38:39.690

replace "1" with 1 as pmax will coerce to character for the comparison. – Giuseppe – 2019-07-26T15:24:03.110

85 bytes by changing the aliases – Giuseppe – 2019-07-26T15:24:33.927

2

PowerShell, 66 62 bytes

-join("$args"-split'\b'|%{(,$(,$_[0]*$n+$_))[!!($n=$($_-1))]})

Try it online!

Breakdown

What a mess!

Starting from $args, which is a single element array containing the RLE string, I'm forcing into an actual string by wrapping it quotes.

Then split it by word boundary (\b in regex). That will give me an array of strings, where each element is either a number or the BF token(s) that come after the number. So in the example, the first 4 elements of this split array are 10,+]>+>,3,+> (all are string).

Next, I pipe that into ForEach-Object (%) to deal with each element.

The middle is a well-known PowerShell golfism, with a twist; it's essentially a DIY ternary operator, in which you create a 2 element array then index into it using the boolean expression you want to test, whereby a false result gives you element 0 and a true result gives you element 1.

In this case, I actually create a single element array with the unary comma , operator, because I don't want output in the true case.

First let's look at the indexer, even though it gets executed later.

The idea of this is that $_ (the current element) could either be a valid number, or some other string. If it's a number, I want $n to be the value of that number minus 1 (as a number, not a string). If it's not, I want $n to be false-y.

PowerShell usually tries to coerce the right-hand value to the type of the left side, but it can depend on the operation. For addition, "10"+5 would give you a new string, "105", whereas 10+"5" will give you an integer (15).

But strings can't be subtracted so instead PowerShell can infer the numeric value automatically with a string on the left side of subtraction, therefore "10"-5 gives 5.

SO, I start with $_-1, which will give me the number I want when $_ is actually a number, but when it's not I get nothing. On the surface, "nothing" is falsey, but the problem is that is stops execution of that assignment, so $n will retain its previous value; not what I want!

If I wrap it in a subexpression, then when it fails, I get my falsey value: $($_-1).

That all gets assigned to $n and since that assignment is itself wrapped in parentheses, the value that was assigned to $n also gets passed through to the pipeline.

Since I'm using it in the indexer, and I want 1 if the conversion succeeded, I use two boolean-not expressions !! to convert this value to boolean. A successful number conversion ends up as true, while the falsey nothingness gives us that sweet, sweet 0 that allows for returning the only element in that fake ternary array.

Getting back to that array, the element is this: $("$($_[0])"*$n*$_) $(,$_[0]*$n+$_)

"$($_[0])" - this is an annoyingly long way of getting the first character of the current element (let's say, getting + from +[>+), but as a string and not as a [char] object. I need it to be a string because I can multiply a string by a number to duplicate it, but I can't do that with a character.

Actually I managed to save 4 characters by using a [char] array instead of a string (by using another unary comma ,), so I was able to remove the quotes and extra sub-expression. I can multiply an array to duplicate its elements. And since the entire result of this iteration ends up being an array anyway and needs to be -joined, using an array here incurs no additional cost.

Then, I multiply that string array by $n, to duplicate it $n times. Recall that $n could be $null or it could be the value of the preceding digits minus one.

Then +$_ adds the current element onto the end of the duplicated first character of that element. That's why $n is minus one.

This way, 10+[>+ ends up with $n equal to 9, then we make 9 +'s and add that back to the +[>+ string to get the requisite 10, plus the other single elements along for the ride.

The element is wrapped in a subexpression $() because when $n is $null, the entire expression fails, so creating the array fails, so the indexer never runs, so $n never gets assigned.

The reason I used this ternary trick is because of one of its peculiarities: unlike a real ternary operator, the expressions that define the elements do get evaluated whether or not they are "selected", and first for that matter.

Since I need to assign and then use $n on separate iterations, this is helpful. The ternary array element value gets evaluated with the previous iteration's $n value, then the indexer re-assigns $n for the current iteration.

So the ForEach-Object loops ends up outputting everything its supposed to (a bunch of errors we ignore), but as an array of new strings.

So that whole thing is wrapped in parentheses and then preceded by unary -join to give the output string.

briantist

Posted 2017-11-02T12:54:46.157

Reputation: 3 110

1Great explanation, that alone warrants an upvote already. – Mast – 2017-11-05T20:49:28.780

1Thanks @Mast, and because of your comment I looked over my answer again and realized how I could save 4 bytes. – briantist – 2017-11-05T21:29:03.513

2

QuadR, 17 bytes

\d+.
¯1((⍎↓)⍴↑)⍵M

Try it online!

Thanks to Adám for providing the correct version of the code.

How it works:

\d+.          ⍝ Regex to match any sequence of digits followed by a character.
¯1((⍎↓)⍴↑)⍵M  ⍝ Transformation line
¯1(      )⍵M  ⍝ Arguments: -1 and the matching expression
   ( ↓)       ⍝ 'Drop' the last item (-1) from the match (⍵M), yielding a string which is a sequence of digits.
    ⍎         ⍝ Execute. In this case, it transforms a string into a number.
        ↑     ⍝ 'Take' the last item (-1) from the match (⍵M), yielding a character.
       ⍴      ⍝ Reshape it. That will take the character resulting from the 'Take' operation and repeat it n times,
              ⍝ where n is the result from the 'Drop' and 'Execute' operations.

J. Sallé

Posted 2017-11-02T12:54:46.157

Reputation: 3 233

Equivalent to the APL function '\d+.'⎕R{¯1((⍎↓)⍴↑)⍵.Match}

– Adám – 2017-11-07T20:48:58.950

1

Proton, 50 bytes

x=>/\d+./.sub(k=>int((e=k.group())[to-1])*e[-1],x)

Try it online!

HyperNeutrino

Posted 2017-11-02T12:54:46.157

Reputation: 26 575

1

Java 8, 148 bytes

s->{for(s=s.format(s.replaceAll("(\\d+)","%1\\$0$1d"),0);!s.matches("\\D+");s=s.replaceAll("0(\\D)","$1$1"));return s.replaceAll("((.)+)\\2","$1");}

Gdamn Java regexes are so useless sometimes.. Last time it was lack of using the capture group "$1" for anything, now this.. I want to replace 3c with ccc or 000c with ccc as a one-liner, but unfortunately Java has no way of doing this without a loop. Ah well.

Explanation:

Try it here.

s->{                          // Method with String as both parameter and return-type
  for(s=s.format(s.replaceAll("(\\d+)","%1\\$0$1d"),0);
                              //  Replace every numbers of that many zeroes
                              //  (i.e. "3>2+" -> "000>00+")
      !s.matches("\\D+");     //  Loop as long as the String contains zeroes
    s=s.replaceAll("0(\\D)",  //   Replace every 0 followed by a non-0 character,
                   "$1$1")    //   with two times this captured non-0 character
  );                          //  End of loop
  return s.replaceAll("((.)+)\\2","$1");
                              //  Reduce every repeated character amount by 1,
                              //  and return this as result
}                             // End of method

Kevin Cruijssen

Posted 2017-11-02T12:54:46.157

Reputation: 67 575

1Hi Kevin, good to see you here, dealing with puzzles other than twisty :) – Galen Ivanov – 2017-11-02T15:14:26.547

@GalenIvanov Oh, hi! I had no idea you were active on PPCG as well. – Kevin Cruijssen – 2017-11-03T09:45:45.927

I wasn't until recently :) I'm learning J and decided that this is a good opportunity to test my skills. – Galen Ivanov – 2017-11-03T10:11:38.140

1

R, 151 bytes

Outgolfed by user2390246! This is now basically a garbage approach compared to that one, but I'll continue to improve it.

function(s,G=substr)for(i in el(strsplit(gsub("(\\d+.)","!\\1!",s),"!")))cat("if"(is.na(g<-as.double(G(i,1,(n=nchar(i))-1))),i,rep(G(i,n,n),g)),sep='')

Try it online!

Also outputs a bunch of warnings.

function(s){
s <- gsub("(\\d+.)","!\\1!",s)               # surround groups with !
X <- el(strsplit(s,"!"))                   # split to groups
for( i in X ){                             # iterate over groups
 n <- nchar(i)                             # length of group
 r <- substr(i,1,n-1)                      # potential number (first n-1 chars)
 d <- substr(i,n,n)                        # last character
 if( is.na(as.double(r)) ){                # if it's not a number
   cat(i)                                  # print out the whole string
  } else {
   cat(rep(d,as.double(r)),sep="")         # repeat d r times, and print with no separator
  }
 }
}

Next up, seeing if using a grep is more efficient than substr

Giuseppe

Posted 2017-11-02T12:54:46.157

Reputation: 21 077

A different approach – user2390246 – 2017-11-02T16:16:55.857

1

Haskell, 84 bytes

f s@(x:r)|(n:m,x:r)<-span(`elem`['0'..'9'])s=(x<$[1..read$n:m])++f r|1<3=x:f r
f e=e

Try it online!

Explanation:

span(`elem`['0'..'9'])s splits the given string s into a prefix of digits and the remainder. Matching on the result on the pattern (n:m,x:r) ensures that the digit prefix is non-empty and binds the character after the digits to x and the remainder to r. x<$[1..read$n:m] reads the string of digits n:m as number and repeats x that many times. The result is concatenated to the recursive treatment of the remaining string r.

Laikoni

Posted 2017-11-02T12:54:46.157

Reputation: 23 676

1

JavaScript (ES6), 46 bytes

a=>a.replace(/(\d+)(.)/g,(_,n,b)=>b.repeat(n))

Pretty straightforward explanation:

a=>a.replace(/(\d+)(.)/g,                      // Match globally the following: a number N followed by a character
                         (_,n,b)=>b.repeat(n)) // Replace each occurrence by the matched character repeated N times

XavCo7

Posted 2017-11-02T12:54:46.157

Reputation: 274

1

Ruby, 35 bytes

->s{s.gsub(/(\d+)(.)/){$2*$1.to_i}}

Try it online!

Alex

Posted 2017-11-02T12:54:46.157

Reputation: 371

1

C++, 239 235 bytes

-4 bytes thanks to Zacharý

#include<regex>
using s=std::string;std::regex m("[0-9]*[<>+.,\\[\\]-]");s t(s r){s d,h;std::sregex_iterator i(r.begin(),r.end(),m),e;while(i!=e){h=(*i)[0];int g=std::strtol(h.data(),NULL,10);g+=!g;d+=s(g,h[h.size()-1]);++i;}return d;}

HatsuPointerKun

Posted 2017-11-02T12:54:46.157

Reputation: 1 891

1Can you change g=(g?g:1) to g+=!g? If that doesn't work, can't you remove the parentheses around g?g:1 – Zacharý – 2017-11-07T19:03:58.273

208 bytes – ceilingcat – 2020-02-25T02:10:56.430

1

Untyped Lambda Calculus, 452 bytes

(λp.λq.(λb.λg.(λi.(λp.λq.λb.p q b)(q(λq.λj.λl.j((λq.λj.qλq.λl.(λu.g i j(λp.u)(g j(λq.λg.q(b(p(λp.λq.p q))(p(λp.λq.p(p q)))q g))(λp.u)(λu.u qλq.λu.g j i q(b l(p(λp.λq.p(p(p(p q)))))q u))))λp.p(λp.λb.q p((λp.λq.l(λp.l)(λp.λq.p q)(λq.p j q)q)p b))λp.λp.p)l q))(λp.p)(λp.p(λp.λp.p)λp.λp.p)(λp.λq.p)))(b(p(λp.λp.p))(p(λp.λq.p(p q)))))(λp.λq.λb.p(q b))λp.λq.q(λp.λq.λb.p(λp.λb.b(p q))(λp.b)λp.p)p)λp.λq.λb.q(q(q(q(q(q(p q b))))))

Input and output comprise of right-fold lists of church encoded character codes, for example the character code of a newline is 10 so the church encoding would be λf.λx.f(f(f(f(f(f(f(f(f(f x))))))))). Converting "ABCD" to a list looks like λf.λx.f 65 (f 66 (f 67 (f 68 x))) but with the numbers church-encoded.

Applying an encoded string to the program and reducing it all the way should give you an encoded output string with the RLE applied.

PixelToast

Posted 2017-11-02T12:54:46.157

Reputation: 11

1Hello and welcome to the site! This looks like an interesting solution but we do expect languages to have a valid interpreter, do you have one of Untyped Lambda Calculus? – Post Rock Garf Hunter – 2017-11-07T02:35:53.097

Also, what does the qλq notation mean? I've never seen that before. – Zacharý – 2017-11-07T19:28:32.283

1

Funky, 42 bytes

s=>s::gsub("(\\d+)(.)",(_,a,b)=>b::rep(a))

Try it online!

ATaco

Posted 2017-11-02T12:54:46.157

Reputation: 7 898

0

Dart, 78 bytes (with regex), 102 bytes (without regex)

With Regex:

(i)=>i.splitMapJoin(new RegExp(r"(\d+)(.)"),onMatch:(m)=>m[2]*int.parse(m[1]))

Without Regex:

(i,[n=0,d=0])=>i.codeUnits.map((c)=>i[d++]*((c-=48)>=0&&c<10?0*(n=n*10+c):n<1?1:(n=0*(c=n))+c)).join()

Both must be invoked like (<code here>)("input string").

Regex one is quite standard, but the regex-less one is quite special.

Regex-less abuses optional parameters to allocate local variables in "single return" function, otherwise you'd need to make a block and have the return keyword. For each code unit, if the code unit is between 0 and 9 it is accumulated to n and an empty string is returned. Otherwise, the the character is multiplied by the value of n (special cased if n == 0, in that case it will always emit 1 character) and n is set to 0. (n=0*(c=n))+c sets the char code argument to the value of n, multiplies n/c with 0, stores 0 to n, then adds c. This resets our n without being in a statement context.

Dwayne Slater

Posted 2017-11-02T12:54:46.157

Reputation: 111

0

Python3, 96 bytes

s,r=input(),""
while s:
 d=0
 while"/"<s[d]<":":d+=1
 r+=int(s[:d] or 1)*s[d];s=s[d+1:]
print(r)

I tried another implementation in Python, but i don't beat https://codegolf.stackexchange.com/a/146923/56846 :(

user285259

Posted 2017-11-02T12:54:46.157

Reputation: 201