Rosetta Stone Challenge: Gene Mapping The goal of a Rosetta Stone Challenge is to write solutions in as many languages as possible. Show off your programming multilingualism!

The Challenge

Your challenge is to implement a program that will map some genes using cross-over frequencies, in as many programming languages as possible. You are allowed to use any sort of standard library function that your language has, since this is mostly a language showcase.

What is "gene mapping?"

Gene mapping is the process of locating the relative position of genes on chromosomes. This is done by measuring the crossing-over frequency of pairs of genes, equal to the percent of offspring in which that the pair is not inherited together.  Distance is measured in map units with one map unit equal to one percent of crossing over.  For example, if genes C &amp; D have a crossing-over frequency of 11%, then gene C is a distance of 11 map units away from gene D.

Gene mapping is performed with multiple pairs of genes to determine their relative order.  For example, the data (A,B,12) (D,B,7) (A,D,5) (D,H,2) (H,B,9) produces the following map:

A..H.D......B


You may have noticed that B......D.H..A is also a valid map.  This is true, because it is not possible to distinguish between mirror opposites.  Your program can pick which one to output.  Although the input may not include every possible pair, there will always be enough information to reconstruct the entire map (so there will never be more than 2 valid outputs).  In addition, the numbers will always work out (unlike actual biology), meaning that you won't have stuff like (A,B,3) (B,C,4) (A,C,13).

Input

Input will begin with a number n followed by a list of genes (uppercase letters).  There will then be n triplets of data.  Each set will consist of a pair of genes and their crossing over frequency (distance).

3,P,H,I
P,H,3
H,I,1
P,I,4

7,A,B,G,Q,U
B,Q,4
A,B,10
G,U,13
Q,U,10
A,G,9
G,Q,3
A,Q,6


Input is not rigidly defined, because different languages may have restrictions on what is feasible.  For example, you may change the delimiters to something other than commas and newlines.  Input formatting is largely up to you.

Output

Output will be a rendition of the gene map.  It will consist of the genes (capital letters) spaced out by periods such that the distances are accurately portrayed.  Here are the outputs for the above examples.

P..HI  *or*  IH..P

BG..Q.....A...U  *or*  U...A.....Q..GB


This also isn't a completely rigid requirement. For example you could use something other than periods, like commas or spaces.  

The Objective Winning Criterion

As for an objective winning criterion, here it is: Each language is a separate competition as to who can write the shortest entry, but the overall winner would be the person who wins the most of these sub-competitions. This means that a person who answers in many uncommon languages can gain an advantage. Code-golf is mostly a tiebreaker for when there is more than one solution in a language: the person with the shortest program gets credit for that language.

Rules, Restrictions, and Notes

Your program can be written in any language that existed prior to December 20th, 2013. I will also have to rely on the community to validate some responses written in some of the more uncommon/esoteric languages, since I am unlikely to be able to test them.



Current Leaderboard

This section will be periodically updated to show the number of languages and who is leading in each.


AutoHotkey (632) - Avi
dj (579) - rubik




Current User Rankings


Avi (1): AutoHotkey (632)
rubik (1): dj (579)
AutoHotkey (632)

f(i){
o:={},f:={},n:=0
loop,parse,i,`n
{
a:=A_LoopField
if A_index!=1
{
@:=Substr(a,1,1),#:=Substr(a,3,1),n+=($:=Substr(a,5))
if !IsObject(o[@])
o[@]:={}
if !IsObject(o[#])
o[#]:={}
o[@][#]:=o[#][@]:=$
}
}
f[n+1]:=@,f[@]:=n+1,a:=""
while !a
{
a:=0
for k,v in o
{
if !f[k]
{
c1:=c2:=s:=0
for k1,v1 in v
{
if f[k1]
if s
{
if (r1==f[k1]-v1)or(r1==f[k1]+v1)
c1:=r1
else r1:=c1:=""
if (r2==f[k1]-v1)or(r2==f[k1]+v1)
c2:=r2
else r2:=c2:=""
}
else
c1:=r1:=f[k1]+v1,c2:=r2:=f[k1]-v1,s:=1
}
if c1
f[c1]:=k,f[k]:=c1,a:=1
else if c2
f[c2]:=k,f[k]:=c2,a:=1
}
} 
}
loop % 2*n+1
{
v:=f[A_index]
if v
z:=1
r.=z?(!v?".":v):v
}
return Rtrim(r,".")
}


The code can be more shortened by renaming all vars to 1 character .. It should then be about 610 characters.

Test Cases

v := "
(7,A,B,G,Q,U
B,Q,4
A,B,10
G,U,13
Q,U,10
A,G,9
G,Q,3
A,Q,6 
)"

msgbox % f(v)
msgbox % f("3,P,H,I`nP,H,3`nH,I,1`nP,I,4")