Task

Write a program to perform a conversion of the old Russian measures of length to the metric system   (and vice versa).



It is an example of a linear transformation of several variables.



The program should accept a single value in a selected unit of measurement, and convert and return it to the other units:

vershoks, arshins, sazhens, versts, meters, centimeters and kilometers.



Also see

   Old Russian measure of length


with javascript_semantics 
constant units = {{"-- metric ---",0},
                  {"kilometer",1000},
                  {"km","kilometer"},
                  {"meter",1},
                  {"m","meter"},
                  {"centimeter",0.01},
                  {"cm","centimeter"},
                  {" old russian ",0},
                  {"tochka",0.000254},
                  {"liniya",0.00254},
                  {"diuym",0.0254},
                  {"vershok",0.04445},
                  {"piad",0.1778},
                  {"fut",0.3048},
                  {"arshin",0.7112},
                  {"sazhen",2.1336},
                  {"versta",1066.8},
                  {"milia",7467.6}},
        {names,facts} = columnize(units)
 
function strim(atom v)
    string res = sprintf("%,f",v)
    integer l = length(res)
    while l do
        integer c = res[l]
        if c!='0' then
            l -= 1+(c='.')
            exit
        end if
        l -= 1
    end while
    res = res[1..l+1]
    return res
end function
 
-- Obviously, uncomment these lines for a prompt (not under p2js)
--while true do
--  string input = prompt_string("\nEnter length & measure or CR to exit:")
--  if input="" then exit end if
--  input = lower(trim(input))
    string input = "7.4676 km"
    string fmt = iff(find(' ',input)?"%f %s":"%f%s")
    sequence r = scanf(input,fmt)
    if length(r)!=1 then
        printf(1,"enter eg 1km or 1 kilometer\n")
    else
        {atom v, string name} = r[1]
        integer k = find(name,names)
        if k=0 or facts[k]=0 then
            printf(1,"unrecognised unit: %s\n",{name})
        else
            if string(facts[k]) then
                -- abbreviation, eg cm->centimeter
                k = find(facts[k],names)
            end if
            for i=1 to length(names) do
                object f = facts[i]
                if f=0 then             -- header
                    printf(1,"--------------%s--------------\n",{names[i]})
                elsif atom(facts[i]) then -- not abbrev
                    printf(1,"%20s %s\n",{strim(v*facts[k]/facts[i]),names[i]})
                end if
            end for
        end if
    end if
--end while
