Revision 77bacd4f-ab25-40b3-b0f1-ff20e4eceb74 - Code Golf Stack Exchange

# [Retina](https://github.com/mbuettner/retina), <s>317</s> <s>139</s> <s>134</s> <s>132</s> <s>70</s> 63 bytes

<s>It's really about time I added some decimal-unary conversion feature to Retina...</s> I did! :)

<pre><code>
100$*1
\B
¶$`
\b(111)+\b
Fi;0ドル
\b(1{5})+\b
Bu;
;1*
zz
(1)+
$#1</code></pre>

Notice the leading empty line. The byte count assumes that the file is encoded as ISO 8859-1.

[Try it online!][1]

## Explanation

*(I'll update this later.)*

 ^
 1
 +`\b1{1,99}$
 0ドル¶10ドル

We start by writing a list of unary numbers from 1 to 100 into the empty input string. This is done by writing a single one with the first stage, and then adding the next number to the end, while the largest number is not more than 99. `¶` is placeholder for a linefeed. When Retina reads the source code it preprocesses the file to turn all pilcrows into linefeeds.

 1
 11
 111
 ... up to 99

Now the actual FizzBuzz:

 \b(111)+\b
 Fi;0ドル

Divisibility by `3` can easily be checked in unary: just test if the number can be written as a repetition of `111`. The word boundaries `\b` make sure we're not matching only part of a number. If this is the case, we prepend `Fi;` to the line. The semicolon is so that there is still a word boundary in front of the number for the next stage. If we turned the line into `Fizz111...` the position between `z` and `1` would not be considered a boundary, because regex treats both letters and digits as word characters. However, the semicolon also allows us to remove the `zz` duplication from `Fizz` and `Buzz`.

 \b(1{5})+\b
 Bu;

We do the exact same for divisibility by `5` and `Bu;`, although we don't need to keep the `1`s around this time. So we get a result like

 1
 11
 Fi;111
 1111
 Bu;
 Fi;111111
 ...
 Fi;Bu;
 ...

This makes it very easy to get rid of numbers only in those lines which contain `Fizz`, while also filling in the `zz`s:

 ;1*
 zz

That is, we turn each semicolon into `zz` but we also consume all the `1`s right after it. At this point we're done with FizzBuzz in unary. But the challenge wants decimal output.

I've used this general technique for unary-to-decimal conversion before, but I managed to golf it significantly using [balancing groups](http://stackoverflow.com/a/17004406/1633117).

 m`$
 ;:0123456789

We start by adding the second line to the end of each line in the string. We need this as a lookup table for the digits, because regex substitution can't conditional conjure up characters. The `:` is a marker so we can distinguish the lookup table from other numbers in the result. The `;` is another marker which indicates which part of the unary number has already been turned into decimal (everything to the right of it), and which parts still needs to be processed (everything to the left of it).

 +`\b(1*)1円{9}(1)+;(?=.*:(?<-2>.)*(.))
 1ドル;3ドル

This is the actual conversion, which builds up the decimal number from least to most significant digit. The first bit `(1*)1円{9}` matches the largest multiple of 10 it can find - i.e. everything not represented by the least significant digit. Then `(1)+` matches the remainder `R` of the number, while pushing `R` captures into group `2`. Notice that we ignore the case where `R = 0` - this saves a few bytes, and we can do this, because in the range `[1,100]` all numbers with 0-digits have been turned into `Buzz` or `FizzBuzz`.

Now that we have determined the next digit (as the size of stack `2`), we look up the correct character. To do so, we search for `:` in a lookahead. Then we match individual characters while popping from stack `2` with `(?<-2>.)*`. That is if the remainder was `4`, say, this matches `0123`. Once this stack is empty, `(?<-2>.)` fails and the regex engine moves on to the next part which is `(.)` and which captures the correct digit (`4` in this example) into group `3`.

The replacement string simply writes group 1 which happens to be our multiple of 10, but divided by 10, then the semicolon to indicate we've processed the new digit, and then the new digit.

<pre><code>;|:.*

</code></pre>

Finally, we clean up the string by removing all markers and lookup strings.

 [1]: http://retina.tryitonline.net/#code=CjEwMCQqMQpTX2AxKD88PSgxKykpClxiKDExMSkrXGIKRmk7JDAKXGIoMXs1fSkrXGIKQnU7CjsxKgp6egooMSkrCiQjMQ&input=

AltStyle によって変換されたページ (->オリジナル) /