1
\$\begingroup\$

For a story I'm writing, I needed to convert 101⅐ (101 + 1/7 if that doesn’t show up for you) into base 47.

Expressing an integer in some base brings back memories of first learning how to program back in the days of 8-bit systems; it’s a fairly easy exercise. Doing so using a floating-point format is a bit harder, though. The final twist, identifying the repeating digits, is more challenging to do elegantly.

So I thought I’d do it in a different language from what I’m used to, just for fun and learning the new dialect. And I thought it would be good to share, so here I am. The vast majority of the posts here are (char or byte of source) code golf, but I’m more interested in an elegant expression in the target language. Cyclomatic complexity isn’t a category, but is pretty close.


The program should take a rational number in a natural way, such as supplying three integers on the command line of the script invocation or standard input. This does not count towards the score (nor does the error checking and defaults if you give it one value only). The function (or part that is counted for score) should receive the three values; e.g. 101,1,7 for the example above.

The output is a sequence of code points that are transliterated into text output as follows:

  • digits 0 through 9 inclusive: ‘0’ through ‘9’ in the normal way
  • digits 10 through 46: express as ‘[10]’ through ‘[46]’
  • negative sign: the normal ASCII ‘-’
  • separator: ‘:’
  • prefix: ‘#’

A number starts with the prefix ‘#’ and has up to three parts, separated by ‘:’. Leading parts are omitted if zero.

The basic natural number (BNN) is encoded using the digits in base 47, outputted in little-endian. That is, 99181 = 11×470 + 42×471 + 44×472 so the digits, in order output, are [11][42][44].

The last (possibly only) part of a number is an integer, which is a leading ‘-’ if the value is negative, followed by the digits of the BNN. So, 99181 would be encoded as #[11][42][44] and −99181 would be encoded as #-[11][42][44].

The middle part, if needed, is an exponent as for scientific notation. It states which power of the base (position) is the first digit listed. In the case of integers, this is 470 so the 0-valued part is omitted.

Suppose you divide that by 47, shifting the radix point by one. That is, 99181 ÷ 47 is the same digits but starting with 47−1; that is, 11×47−1 + 42×470 + 44×471, and the output becomes #-1:[11][42][44]. There are two parts, the first is the encoding for the integer −1, and the second is the digits as before.

Now it comes out so neat only if you divide by some power of 47. Normally, a rational number made of small components will end up with a repeating sequence of digits. In decimal, for example, ⅓ is .3333… and ⅐ (1/7) is .142857142857142857… in the first case one digit repeats, in the second case 6 digits repeat.

In the alien real number format, the first part, if present, states how many digits are to be repeated. So, the number 8½ would have a single digit [23] repeating forever, so we just encode one of them and state that 1 repeats: #1:-1:[23]8. The first part is 1 (the encoded BNN for the value 1) which means that one digit is to be repeated. The second part (negative sign and BNN) indicates that the first digit given is the 47-1 position. The third part is the two digits needed: 26×47-1 + 8×470.


Somebody should check my results, but I think the correct output for (101 1 7) is:
#6:-6:[20][13][40][26][33]672.

\$\endgroup\$
  • \$\begingroup\$ What counts as an "atom"? Are you using the description in the tag wiki? \$\endgroup\$ – Rɪᴋᴇʀ Mar 9 '17 at 1:58
  • \$\begingroup\$ I'm new here. I'm using the established conventions. So yes, I mean what was stated in the tag wiki. \$\endgroup\$ – JDługosz Mar 9 '17 at 2:00
  • 3
    \$\begingroup\$ You might want to make output a bit less stringent. I personally feel that restrictive output formats make the answers more about the output formatter than the actual algorithm. \$\endgroup\$ – Wheat Wizard Mar 9 '17 at 2:56
  • 4
    \$\begingroup\$ I am also not sure why you chose atomic-code-golf over plain old code-golf. It seems a bit random in the context of the entire question. \$\endgroup\$ – Wheat Wizard Mar 9 '17 at 2:57
  • \$\begingroup\$ Welcome to the site! As WheatWizard has said we encourage looser I/O specs. Other than that it would be good idea to include a table of example inputs and outputs to help people with testing their code. \$\endgroup\$ – 0 ' Mar 9 '17 at 3:17
3
\$\begingroup\$

Batch, 531 bytes

@echo off
set q=
set s=
set m=
if %1 lss 0 set m=-
set/ai=%m%%1,n=%2,d=%3,p=0
:i
set/ar=i%%47,i/=47
if %r% gtr 9 set r=[%r%]
set s=%s%%r%
if %i% gtr 0 goto i
:p
if %n%==0 goto n
set/ao=n,g=d%%47
if %g% gtr 0 goto g
set/ap+=1,d/=47,r=n/d,n%%=d
if %r% gtr 9 set r=[%r%]
set s=%r%%s%
goto p
:g
set/aq+=1,p+=1,r=n*47/d,n=n*47%%d
if %r% gtr 9 set r=[%r%]
set s=%r%%s%
if %n% neq %o% goto g
if %q% gtr 9 set q=[%q%]
set q=%q%:
:n
if %p% gtr 9 (set q=%q%-[%p%]:)else if %p% gtr 0 set q=%q%-%p%:
echo #%q%%m%%s%

Takes three parameters, whole number, numerator, denominator representing a mixed number in its lowest terms.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.