## Alien Numbers

### September 24, 2010

Today’s exercise comes to us from the Google Code Jam via Christian Harms’ blog:

Problem

The decimal numeral system is composed of ten digits, which we represent as “0123456789″ (the digits in a system are written from lowest to highest). Imagine you have discovered an alien numeral system composed of some number of digits, which may or may not be the same as those used in decimal. For example, if the alien numeral system were represented as “oF8″, then the numbers one through ten would be (F, 8, Fo, FF, F8, 8o, 8F, 88, Foo, FoF). We would like to be able to work with numbers in arbitrary alien systems. More generally, we want to be able to convert an arbitrary number that’s written in one alien system into a second alien system.

Input

The first line of input gives the number of cases, N. N test cases follow. Each case is a line formatted as

alien_number source_language target_language

Each language will be represented by a list of its digits, ordered from lowest to highest value. No digit will be repeated in any representation, all digits in the alien number will be present in the source language, and the first digit of the alien number will not be the lowest valued digit of the source language (in other words, the alien numbers have no leading zeroes). Each digit will either be a number 0-9, an uppercase or lowercase letter, or one of the following symbols !”#\$%&’()*+,-./:;?@[\]^_`{|}~

Output

For each test case, output one line containing “Case #x: ” followed by the alien number translated from the source language to the target language.

Your task is to write a program to solve the Google Code Jam. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

Pages: 1 2

### 10 Responses to “Alien Numbers”

1. Mithrandir said

alien number base1 base2 = map (fst . (b2 !!)) \$ reverse \$ undigits base10 l2
where
undigits 0 _ = []
undigits n b = (n `mod` b) : undigits (n `div` b) b
base10 = foldl ((+) . (* l1)) 0 digits
digits = map (\c -> find c b1) number
find c (x:xs) = if fst x == c then snd x else find c xs
b1 = zip base1 [0..]
b2 = zip base2 [0..]
l1 = length base1
l2 = length base2

2. Rodrigo Menezes said

C# Solution

public static string sourceToDestination(string alianNumber, string sourceLanguage, string destinationLanguage)
{
int decimalValue = 0;
int product = 1;
string newNumber = “”;

for (int i = alianNumber.Length – 1; i >= 0; i–, product = product * sourceRadix)
{
char numb = alianNumber[i];
int alianValue = -1;

for (int j = 0; j 0; decimalValue = decimalValue / destinationRadix)
{
newNumber = destinationLanguage[decimalValue % destinationRadix] + newNumber;
}

return newNumber;
}

3. Rodrigo Menezes said

C# again copy paste does not like me

public static string sourceToDestination(string alianNumber, string sourceLanguage, string destinationLanguage)
{
int decimalValue = 0;
int product = 1;
string newNumber = "";

for (int i = alianNumber.Length - 1; i >= 0; i--, product = product * sourceRadix)
{
char numb = alianNumber[i];
int alianValue = -1;

for (int j = 0; j 0; decimalValue = decimalValue / destinationRadix)
{
newNumber = destinationLanguage[decimalValue % destinationRadix] + newNumber;
}

return newNumber;
}

4. Rodrigo Menezes said

Actually wordpress doesn’t like me.
Hope it works this time and that someone can delete the failed attempts.

public static string sourceToDestination(string alianNumber, string sourceLanguage, string destinationLanguage)
{
int decimalValue = 0;
int product = 1;
string newNumber = "";

for (int i = alianNumber.Length – 1; i >= 0; i–, product = product * sourceRadix)
{
char numb = alianNumber[i];
int alianValue = -1;

for (int j = 0; j <= sourceLanguage.Length – 1; j++)
{
if (sourceLanguage[j] == numb)
{
alianValue = j;
break;
}
}

decimalValue += (alianValue * product);
}

for (; decimalValue > 0; decimalValue = decimalValue / destinationRadix)
{
newNumber = destinationLanguage[decimalValue % destinationRadix] + newNumber;
}

return newNumber;
}

5. [...] response of my article a scheme solution (and haskel as [...]

6. Khanh Nguyen said

Mine in F#

let human_numeric_value (n:string) (number_system:string) =
let pos = List.ofSeq n |> List.map (fun (c:char) -> number_system.IndexOf(c)) |> List.rev
let mutable v = 0
for i in [0..pos.Length - 1] do
v <- v + pos.[i] * (pown number_system.Length i)
v

let rec convert (n:int) (power_base:int) =
if (n / power_base < 1) then
[n]
else
(n % power_base) :: (convert (n / power_base) power_base)

let alien_number (n:string) (src_system:string) (dst_system:string) =
let tmp = convert (human_numeric_value n src_system) (dst_system.Length) |> List.rev

let ret = List.map (fun x -> dst_system.[x]) tmp
System.String.Concat(Array.ofList(ret))

alien_number "9" "0123456789" "oF8"
alien_number "Foo" "oF8" "0123456789"
alien_number "13" "0123456789abcdef" "01"

7. Here is mine in Clojure:

(defn decimal-to-lang
"Converts decimal-num to the equivalent number in lang as a string.
The algorithm was a translation of the algorithm by Rodrigo Menezes
in C# that he posted in the programming praxis site."
[decimal-num lang]
(loop [decimal-value decimal-num lang-num []]
(if (>= 0 decimal-value)
(apply str lang-num)
(concat [(nth lang (mod decimal-value lang-radix))] lang-num))))))

(defn digit-index
[digit lang]
(loop [i 0]
(if (= digit (nth lang i))
i
(recur (inc i)))))

(defn lang-to-decimal
[alien-num lang]
ralien-num (reverse alien-num)]
(loop [i 0 decimal-num 0 product 1]
(if (= i (count ralien-num))
decimal-num
(recur (inc i) (+ decimal-num (* (digit-index (nth ralien-num i) lang) product))

(defn convert-num
"Convert alien-num which is in source-lang into the same number in target-lang"
[alien-num source-lang target-lang]
(decimal-to-lang (lang-to-decimal alien-num source-lang) target-lang))

8. jneira said

My clojure generating data structures to meet the adequated functions:

9. jneira said

oops

(ns alien-nums
(:require (clojure.contrib [combinatorics :as comb :only cartesian-product]
[seq-utils :as seq-utils :only indexed])))

(defn generate-nums [lang]
(when-let [lst (seq lang)]
(let [leading-zero? #(= (first %) (first lang))
(map flatten
(comb/cartesian-product lst %1)))]
(apply concat (iterate fcp lst)))))

(defn get-index [nums num]
(first (some #(when (= (second %) (seq num)) %)
(seq-utils/indexed nums))))

(defn valid-num [lang num]
(every? (set lang) num))

(defn convert-num [alien-num from-lang to-lang]
(let [[from-nums to-nums]
(map generate-nums [from-lang to-lang])
idx (when (valid-num from-lang alien-num)
(get-index from-nums alien-num))]
(when idx (apply str (nth to-nums idx)))))

10. [...] response of my article a scheme solution (and haskel as [...]