## Alien Numbers

### September 24, 2010

This task is very similar to the `digits`

and `undigits`

functions in the Standard Prelude. We will convert input from alien digit-strings to decimal numbers using the source language, then convert back to alien digit-strings for output using the target language. Here are `alien->number`

and its helper function `char->digit`

, which is curried for convenient use by `map`

:

`(define (char->digit lang)`

(lambda (c)

(let loop ((lang lang) (d 0))

(if (char=? (car lang) c) d

(loop (cdr lang) (+ d 1))))))

`(define (alien->number lang str)`

(let* ((lang (string->list lang))

(radix (length lang))

(str (string->list str)))

(undigits (map (char->digit lang) str) radix)))

And here is the translation back:

`(define (digit->char lang)`

(lambda (d)

(list-ref lang d)))

`(define (number->alien lang n)`

(let* ((lang (string->list lang))

(radix (length lang))

(num (digits n radix)))

(list->string (map (digit->char lang) num))))

`Translate`

takes an alien digit-string, a source language, and a target language, and perform the conversion from one to the other. Here is `translate`

with some examples showing its use; note the hex-to-binary conversion in the third example:

`(define (translate alien source target)`

(number->alien target (alien->number source alien)))

`> (translate "9" "0123456789" "oF8") ; (9*10^0 = 9)`

Foo

> (translate "Foo" "oF8" "0123456789") ; (1*3^2 + 0*3^1 + 0*3^0 = 9)

9

> (translate "13" "0123456789abcdef" "01") ; (1*16^1 + 3*16^0 = 19)

10011

> (translate "CODE" "O!CDE?" "A?JM!.") ; (2*6^3 + 0*6^2 + 3*6^1 + 4*6^0 = 454)

JAM!

Finally we process a file, fetching the input using `read-word`

from the Mark V. Shaney exercise:

`(define (do-file filename)`

(with-input-from-file filename

(lambda ()

(let ((n (string->number (read-word))))

(do ((i 1 (+ i 1))) ((< n i))

(let ((alien (read-word))

(source (read-word))

(target (read-word)))

(display "Case #")

(display i)

(display ": ")

(display (translate alien source target)))

(newline))))))

We used `digits`

and `undigits`

from the Standard Prelude. You can run the program at http://programmingpraxis.codepad.org/GPar0q3v.

Simple solution in haskell:

C# Solution

public static string sourceToDestination(string alianNumber, string sourceLanguage, string destinationLanguage)

{

int decimalValue = 0;

int product = 1;

int sourceRadix = sourceLanguage.Length;

int destinationRadix = destinationLanguage.Length;

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;

}

C# again copy paste does not like me

public static string sourceToDestination(string alianNumber, string sourceLanguage, string destinationLanguage)

{

int decimalValue = 0;

int product = 1;

int sourceRadix = sourceLanguage.Length;

int destinationRadix = destinationLanguage.Length;

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;`

}

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;

int sourceRadix = sourceLanguage.Length;

int destinationRadix = destinationLanguage.Length;

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;

}

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

Mine in F#

Here is mine in Clojure:

The full solution with tests is here.

My clojure generating data structures to meet the adequated functions:

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))

fcp #(remove leading-zero?

(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)))))

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