==================
== Madhav Kumar ==
==================

30

I turn 30 today. To celebrate, I thought it would be fun to write a script that ouputs the number 30 in the first 30 bases.



convert_base.sh#

 0
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#! /bin/sh

if [ "$2" = 1 ]; then
    result=$(printf "%0.s1" $(seq 1 $1))
    echo "$result"
    exit 0
fi

number=$1
base=$2
result=""
while [ $number -gt 0 ]; do
    remainder=$(( number % base ))
    if [ $remainder -lt 10 ]; then
        result="$remainder$result"
    else
        letter=$(printf "\\$(printf '%03o' $(( remainder + 55 )) )")
        result="$letter$result"
    fi
    number=$(( number / base ))
done

echo "$result"

Explanation#

A couple of things worth noting:

0
1
2
3
4
if [ "$2" = 1 ]; then
    result=$(printf "%0.s1" $(seq 1 $1))
    echo "$result"
    exit 0
fi

This handles the special case of base 1. (N)10 is represented by 1 repeated N times in base 1.

letter=$(printf "\\$(printf '%03o' $(( remainder + 55 )) )")

This converts a number into a digit represented by a letter in the English alphabet. For example, 10 is (A)16.

There are three components to this:

  1. remainder + 55
  2. printf '%03o' $(...)
  3. printf "\\$(...)"

In this case, if we’re converting N to base B, then 10 <= remainder <= B-1. Therefore, 65 <= remainder+55 <= B+54. Since the max base we want to support is 361, we know 65 <= remainder+55 <= 90.

We then use printf '%03o' to convert that into a 3 digit octal. Our range of values then is (101)8 to (132)8.

Finally, we use printf "\\$(...)" to output the byte with that octal value which will render the corresponding ASCII character. Looking at an ASCII table, we can see that (101)8 to (132)8 represents A to Z.

With that script in convert_base.sh, we can run this2 in the terminal to display 30 in bases 1 to 30:

seq 1 30 | xargs -i{} echo "sh convert_base.sh 30 {} | xargs printf 'Base %b ---> %s\n' {}" | sh

Final Result#

Base 1 ---> 111111111111111111111111111111
Base 2 ---> 11110
Base 3 ---> 1010
Base 4 ---> 132
Base 5 ---> 110
Base 6 ---> 50
Base 7 ---> 42
Base 8 ---> 36
Base 9 ---> 33
Base 10 ---> 30
Base 11 ---> 28
Base 12 ---> 26
Base 13 ---> 24
Base 14 ---> 22
Base 15 ---> 20
Base 16 ---> 1E
Base 17 ---> 1D
Base 18 ---> 1C
Base 19 ---> 1B
Base 20 ---> 1A
Base 21 ---> 19
Base 22 ---> 18
Base 23 ---> 17
Base 24 ---> 16
Base 25 ---> 15
Base 26 ---> 14
Base 27 ---> 13
Base 28 ---> 12
Base 29 ---> 11
Base 30 ---> 10

  1. Why 36? Well there are 26 letters in the english alphabet and we want to represent numbers greater than 10. 26 + 10 = 36. We could extend this to use lowercase letters to gain an additional 26 digits, but it’s my birthday and I didn’t feel like it. ↩︎

  2. I actually added | xclip -selection clipboard so I could paste the output into this post. ↩︎