Old Russian measure of length

From Rosetta Code
Revision as of 00:40, 23 July 2014 by rosettacode>Lambertdw (J entry)
Old Russian measure of length is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

The program should make the conversion of the old Russian measures of length in the metric and vice versa.

Is an example of the transformation of several variables that are linearly. The program accepts a single value in the selected unit, and return it in the rest: vershoks, arshins, sazhens, versts, meters, centimeters and kilometers.

МК-61/52

<lang>П7 1 0 0 * П8 1 ВП 5 / П9 ИП7 1 0 6 7 / П0 5 0 0 * ПC 3 * ПA 1 6 * ПB С/П ПB 1 6 / ПA 3 / ПC 5 0 0 / П0 1 0 6 7 / БП 00</lang>

Instruction: l, meters = РX В/О С/П; l, vershoks = БП 3 1 С/П; l, arshins = РX БП 3 5 С/П; l, sazhens = РX БП 3 8 С/П; l, versts = РX БП 4 3 С/П; РX = РB = l, vershoks; РA = l, arshins; РB = l, versts; РC = l, sazhens; Р7 = l, meters; Р8 = l, centimeters; Р9 = l, kilometers.

Example: 100 m = 2249,2971 vershoks = 140,58107 arshins = 46,860366 sazhens = 0,093790712 versts; 3 vershoks = 13,3375 cm; 2 sazhens = 96 vershoks = 6 arshins = 4,268 m; 1 verst = 1,067 km.

C++

<lang cpp>

  1. include <iostream>
  2. include <iomanip>

//------------------------------------------------------------------------------------------- using namespace std;

//------------------------------------------------------------------------------------------- class ormConverter { public:

   ormConverter() :  AR( 0.7112f ), CE( 0.01f ), DI( 0.0254f ), FU( 0.3048f ), KI( 1000.0f ), LI( 0.00254f ), ME( 1.0f ),

MI( 7467.6f ), PI( 0.1778f ), SA( 2.1336f ), TO( 0.000254f ), VE( 0.04445f ), VR( 1066.8f ) {}

   void convert( char c, float l )
   {

system( "cls" ); cout << endl << l; switch( c ) { case 'A': cout << " Arshin to:"; l *= AR; break; case 'C': cout << " Centimeter to:"; l *= CE; break; case 'D': cout << " Diuym to:"; l *= DI; break; case 'F': cout << " Fut to:"; l *= FU; break; case 'K': cout << " Kilometer to:"; l *= KI; break; case 'L': cout << " Liniya to:"; l *= LI; break; case 'M': cout << " Meter to:"; l *= ME; break; case 'I': cout << " Milia to:"; l *= MI; break; case 'P': cout << " Piad to:"; l *= PI; break; case 'S': cout << " Sazhen to:"; l *= SA; break; case 'T': cout << " Tochka to:"; l *= TO; break; case 'V': cout << " Vershok to:"; l *= VE; break; case 'E': cout << " Versta to:"; l *= VR; }

float ar = l / AR, ce = l / CE, di = l / DI, fu = l / FU, ki = l / KI, li = l / LI, me = l / ME, mi = l / MI, pi = l / PI, sa = l / SA, to = l / TO, ve = l / VE, vr = l / VR; cout << left << endl << "=================" << endl << setw( 12 ) << "Arshin:" << ar << endl << setw( 12 ) << "Centimeter:" << ce << endl << setw( 12 ) << "Diuym:" << di << endl << setw( 12 ) << "Fut:" << fu << endl << setw( 12 ) << "Kilometer:" << ki << endl << setw( 12 ) << "Liniya:" << li << endl << setw( 12 ) << "Meter:" << me << endl << setw( 12 ) << "Milia:" << mi << endl << setw( 12 ) << "Piad:" << pi << endl << setw( 12 ) << "Sazhen:" << sa << endl << setw( 12 ) << "Tochka:" << to << endl << setw( 12 ) << "Vershok:" << ve << endl << setw( 12 ) << "Versta:" << vr << endl << endl << endl;

   }

private:

   const float AR, CE, DI, FU, KI, LI, ME, MI, PI, SA, TO, VE, VR;

}; //------------------------------------------------------------------------------------------- int _tmain(int argc, _TCHAR* argv[]) {

   ormConverter c;
   char s; float l;
   while( true )
   {

cout << "What unit:\n(A)rshin, (C)entimeter, (D)iuym, (F)ut\n(K)ilometer, (L)iniya, (M)eter, m(I)lia, (P)iad\n(S)azhen, (T)ochka, (V)ershok, v(E)rsta, (Q)uit\n"; cin >> s; if( s & 32 ) s ^= 32; if( s == 'Q' ) return 0; cout << "Length (0 to Quit): "; cin >> l; if( l == 0 ) return 0; c.convert( s, l ); system( "pause" ); system( "cls" );

   }
   return 0;

} //------------------------------------------------------------------------------------------- </lang> Output:

1 Milia to:
=================
Arshin:     10500
Centimeter: 746760
Diuym:      294000
Fut:        24500
Kilometer:  7.4676
Liniya:     2.94e+006
Meter:      7467.6
Milia:      1
Piad:       42000
Sazhen:     3500
Tochka:     2.94e+007
Vershok:    168000
Versta:     7

1 Meter to:
=================
Arshin:     1.40607
Centimeter: 100
Diuym:      39.3701
Fut:        3.28084
Kilometer:  0.001
Liniya:     393.701
Meter:      1
Milia:      0.000133912
Piad:       5.6243
Sazhen:     0.468691
Tochka:     3937.01
Vershok:    22.4972
Versta:     0.000937383

D

Translation of: Perl6

<lang d>import std.stdio, std.string, std.algorithm, std.conv;

void main(in string[] args) {

   auto factor = ["arshin":         0.7112,
                  "centimeter":     0.01,
                  "diuym":          0.0254,
                  "fut":            0.3048,
                  "kilometer":  1_000.0,
                  "liniya":         0.00254,
                  "meter":          1.0,
                  "milia":      7_467.6,
                  "piad":           0.1778,
                  "sazhen":         2.1336,
                  "tochka":         0.000254,
                  "vershok":        0.04445,
                  "versta":     1_066.8];
   if (args.length != 3 || !isNumeric(args[1]) || args[2] !in factor)
       return writeln("Please provide args Value and Unit.");
   immutable magnitude = args[1].to!double;
   immutable meters = magnitude * factor[args[2]];
   writefln("%s %s to:\n", args[1], args[2]);
   foreach (immutable key; factor.keys.schwartzSort!(k => factor[k]))
      writefln("%10s: %s", key, meters / factor[key]);

}</lang>

Output:
1 meter to:

    tochka: 3937.01
    liniya: 393.701
centimeter: 100
     diuym: 39.3701
   vershok: 22.4972
      piad: 5.6243
       fut: 3.28084
    arshin: 1.40607
     meter: 1
    sazhen: 0.468691
 kilometer: 0.001
    versta: 0.000937382
     milia: 0.000133911

1 milia to:

    tochka: 2.94e+07
    liniya: 2.94e+06
centimeter: 746760
     diuym: 294000
   vershok: 168000
      piad: 42000
       fut: 24500
    arshin: 10500
     meter: 7467.6
    sazhen: 3500
 kilometer: 7.4676
    versta: 7
     milia: 1

{{header|J}

Java

<lang java>public class OldRussianMeasures {

   final static String[] keys = {"tochka", "liniya", "centimeter", "diuym",
       "vershok", "piad", "fut", "arshin", "meter", "sazhen", "kilometer",
       "versta", "milia"};
   final static double[] values = {0.000254, 0.00254, 0.01,0.0254,
       0.04445, 0.1778, 0.3048, 0.7112, 1.0, 2.1336, 1000.0,
       1066.8, 7467.6};
   public static void main(String[] a) {
       if (a.length == 2 && a[0].matches("[+-]?\\d*(\\.\\d+)?")) {
           double inputVal = lookup(a[1]);
           if (!Double.isNaN(inputVal)) {
               double magnitude = Double.parseDouble(a[0]);
               double meters = magnitude * inputVal;
               System.out.printf("%s %s to: %n%n", a[0], a[1]);
               for (String k: keys)
                   System.out.printf("%10s: %g%n", k, meters / lookup(k));
               return;
           }
       }
       System.out.println("Please provide a number and unit");
   }
   public static double lookup(String key) {
       for (int i = 0; i < keys.length; i++)
           if (keys[i].equals(key))
               return values[i];
       return Double.NaN;
   }

}</lang>

1 meter to: 

    tochka: 3937,01
    liniya: 393,701
centimeter: 100,000
     diuym: 39,3701
   vershok: 22,4972
      piad: 5,62430
       fut: 3,28084
    arshin: 1,40607
     meter: 1,00000
    sazhen: 0,468691
 kilometer: 0,00100000
    versta: 0,000937383
     milia: 0,000133912

1 milia to: 

    tochka: 2,94000e+07
    liniya: 2,94000e+06
centimeter: 746760
     diuym: 294000
   vershok: 168000
      piad: 42000,0
       fut: 24500,0
    arshin: 10500,0
     meter: 7467,60
    sazhen: 3500,00
 kilometer: 7,46760
    versta: 7,00000
     milia: 1,00000

Perl 6

Fairly straightfoward. Define a hash of conversion factors then apply them. Does some basic error trapping. Makes no attempt to do correct pluralization because I have no idea what the correct plurals are and little interest in researching them. Conversion factors from Wikipedia: Obsolete Russian units of measurement.

<lang perl6>convert(1, 'meter');

say '*' x 40, "\n";

convert(1, 'milia');

sub convert (Real $magnitude, $unit) {

    my %factor = ( 
       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,
       centimeter => 0.01,
       meter      => 1.0,
       kilometer  => 1000.0,
   );
   die "Unknown unit $unit\n" unless %factor.exists($unit.lc);
   my $meters = $magnitude * %factor.delete($unit.lc);
   say "$magnitude $unit to:\n", '_' x 40;
   printf "%10s: %s\n", $_,  $meters / %factor{$_}
     for %factor.keys.sort:{ +%factor{$^_} }

} </lang>

1 meter to:
________________________________________
    tochka: 3937.007874
    liniya: 393.700787
centimeter: 100
     diuym: 39.370079
   vershok: 22.497188
      piad: 5.624297
       fut: 3.280840
    arshin: 1.406074
    sazhen: 0.468691
 kilometer: 0.001
    versta: 0.000937
     milia: 0.000134
****************************************

1 milia to:
________________________________________
    tochka: 29400000
    liniya: 2940000
centimeter: 746760
     diuym: 294000
   vershok: 168000
      piad: 42000
       fut: 24500
    arshin: 10500
     meter: 7467.6
    sazhen: 3500
 kilometer: 7.4676
    versta: 7

Python

Run as:

commandname <value> <unit>

<lang python>from sys import argv

unit2mult = {"arshin": 0.7112, "centimeter": 0.01, "diuym": 0.0254,

            "fut":    0.3048, "kilometer":  1000.0,   "liniya":  0.00254,
            "meter":  1.0,    "milia":      7467.6,   "piad":    0.1778,
            "sazhen": 2.1336, "tochka":     0.000254, "vershok": 0.04445,
            "versta": 1066.8}

if __name__ == '__main__':

   assert len(argv) == 3, 'ERROR. Need two arguments - number then units'
   try:
       value = float(argv[1])
   except:
       print('ERROR. First argument must be a (float) number')
       raise
   unit = argv[2]
   assert unit in unit2mult, ( 'ERROR. Only know the following units: ' 
                               + ' '.join(unit2mult.keys()) )
   print("%g %s to:" % (value, unit))
   for unt, mlt in sorted(unit2mult.items()):
       print('  %10s: %g' % (unt, value * unit2mult[unit] / mlt))</lang>
Output:
1 meter to:
      arshin: 1.40607
  centimeter: 100
       diuym: 39.3701
         fut: 3.28084
   kilometer: 0.001
      liniya: 393.701
       meter: 1
       milia: 0.000133912
        piad: 5.6243
      sazhen: 0.468691
      tochka: 3937.01
     vershok: 22.4972
      versta: 0.000937383
Output:
1 milia to:
      arshin: 10500
  centimeter: 746760
       diuym: 294000
         fut: 24500
   kilometer: 7.4676
      liniya: 2.94e+06
       meter: 7467.6
       milia: 1
        piad: 42000
      sazhen: 3500
      tochka: 2.94e+07
     vershok: 168000
      versta: 7
Output:

When given a wrong number

ERROR. First argument must be a (float) number
Traceback (most recent call last):
  File "C:\Users\Paddy\Google Drive\Code\old_russian_lengths.py", line 18, in <module>
    value = float(argv[1])
ValueError: could not convert string to float: '1xx'
Output:

When given a wrong unit

Traceback (most recent call last):
  File "C:\Users\Paddy\Google Drive\Code\old_russian_lengths.py", line 24, in <module>
    + ' '.join(unit2mult.keys()) )
AssertionError: ERROR. Only know the following units: kilometer tochka versta fut diuym liniya vershok meter arshin piad centimeter sazhen milia

Racket

Follows the Perl solution, produces similar output. <lang racket>

  1. lang racket

(define units

 '([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]
   [centimeter    0.01]
   [meter         1.0]
   [kilometer  1000.0]))

(define (show u)

 (printf "1 ~s to:\n" u)
 (define n (cadr (assq u units)))
 (for ([u2 units] #:unless (eq? u (car u2)))
   (displayln (~a (~a (car u2) #:width 10 #:align 'right) ": "
                  (~r (/ n (cadr u2)) #:precision 4))))
 (newline))

(show 'meter) (show 'milia) </lang>

REXX

Program features:

  • shows all other units of measurements when any unit is specified.
  • accepts abbreviations of the length units
  • does rounding for so results are more meaningful and recognizable
  • does error checking on the user input
  • added other old Russian units of measurements
  • uses the correct length unit names when not plural
  • columnarized the output   (instead of a horizontal stream).

<lang rexx>/*REXX program to read a config file and assign VARs as found within. */

                             numeric digits 200
 /*──translation──*/
 /*tip, top*/                vershok  = 22.492971          /*1.75 inch.*/
 /*palm, quarter*/           piad     = vershok    / 4     /*≡chetvert.*/
 /*yard*/                    arshin   = vershok    / 16
 /*fathom*/                  sazhen   = arshin     / 3
 /*turn (of a plow)*/        verst    = sazhen     / 500   /*≡versta.  */
 /*mile*/                    milia    = verst      / 1.5
 /*inch*/                    diuym    = arshin     * 28
 /*foot*/                    fut      = diuym      / 12
 /*line*/                    liniya   = diuym      * 10
 /*point*/                   tochka   = diuym      * 100

KM=1000; CM=100 /*define a couple of multipliers.*/ parse arg N what _ . /*obtain the user's input from CL*/ if N == then call err 'no arguments specified.' if \datatype(N,'N') then call err 'units not numeric: ' N if _\== then call err 'too many arguments specified.' n=n/1 /*normalize it (004──►4 7.──►7)*/ if what== then what='meters' /*None specified? Assume meters.*/ whatU=what; upper whatU /*an uppercase version for ABBREV*/

                  select              /*convert the length ───► meters.*/
                  when abbrev('METRES'     ,whatU   ) |,
                       abbrev('METERS'     ,whatU   )    then m=N
                  when abbrev('KILOMETRES' ,whatU,2 ) |,
                       abbrev('KILOMETERS' ,whatU,2 ) |,
                       abbrev('KMS'        ,whatU,  )    then m=N*KM
                  when abbrev('CENTIMETRES',whatU,2 ) |,
                       abbrev('CENTIMETERS',whatU,2 ) |,
                       abbrev('CMS'        ,whatU,2 )    then m=N/CM
                  when abbrev('ARSHINS'    ,whatU   )    then m=N/arshin
                  when abbrev('DIUYM'      ,whatU   )    then m=N/diuym
                  when abbrev('FUT'        ,whatU   )    then m=N/fut
                  when abbrev('LINIYA'     ,whatU   )    then m=N/liniya
                  when abbrev('PIADS'      ,whatU   ) |,
                       abbrev('CHETVERTS'  ,whatU,2 )    then m=N/piad
                  when abbrev('SAZHENS'    ,whatU   )    then m=N/sazhen
                  when abbrev('TOCHKA'     ,whatU   )    then m=N/tochka
                  when abbrev('VERSHOKS'   ,whatU,5 )    then m=N/vershok
                  when abbrev('VERSTAS'    ,whatU,5 ) |,
                       abbrev('VERSTS'     ,whatU,2 )    then m=N/verst
                  when abbrev('MILIA'      ,whatU,2 )    then m=N/milia
                  otherwise    call err 'invalid measure name: ' what
                  end   /*select*/
                                         say centre('metric',79,"─")

call saym m/KM , 'kilometer' call saym m , 'meter' call saym m*CM , 'centimeter'

                                         say centre('old Russian',79,"─")

call saym m*milia , 'milia' call saym m*verst , 'verst' call saym m*sazhen , 'sazhen' call saym m*arshin , 'arshin' call saym m*fut , 'fut' call saym m*piad , 'piad' call saym m*vershok , 'vershok' call saym m*diuym , 'diuym' call saym m*liniya , 'liniya' call saym m*tochka , 'tochka' exit /*stick a fork in it, we're done.*/ /*───────────────────────────────ERR subroutine─────────────────────────*/ err: say; say; say center(' error! ', max(40, linesize()%2), "*"); say

               do j=1  for arg();  say arg(j);  say;  end;  say;  exit 13

/*───────────────────────────────S subroutine───────────────────────────*/ s: if arg(1)=1 then return arg(3); return word(arg(2) 's',1) /*plural*/ /*───────────────────────────────SAYM subroutine────────────────────────*/ saym: parse arg _; numeric digits digits()%25; _=_/1

      say right(_,40) arg(2)s(_);         return</lang>

This REXX program makes use of   LINESIZE   REXX program (or BIF) which is used to determine the screen width (or linesize) of the terminal (console).
The   LINESIZE.REX   REXX program is included here ──► LINESIZE.REX.

output when using the input of: 100 metres

────────────────────────────────────metric─────────────────────────────────────
                                     0.1 kilometers
                                     100 meters
                                   10000 centimeters
──────────────────────────────────old Russian──────────────────────────────────
                             0.062480475 milias
                             0.093720713 versts
                               46.860356 sazhens
                               140.58107 arshins
                               328.02249 futs
                               562.32428 piads
                               2249.2971 vershoks
                               3936.2699 diuyms
                               39362.699 liniyas
                               393626.99 tochkas

output when using the input of: 1.4058107 arshins

────────────────────────────────────metric─────────────────────────────────────
                                   0.001 kilometers
                                       1 meter
                                     100 centimeters
──────────────────────────────────old Russian──────────────────────────────────
                           0.00062480476 milias
                           0.00093720713 versts
                              0.46860357 sazhens
                               1.4058107 arshins
                                3.280225 futs
                               5.6232428 piads
                               22.492971 vershoks
                                 39.3627 diuyms
                                 393.627 liniyas
                                 3936.27 tochkas

output when using the input of: -46.860366 sazhens

────────────────────────────────────metric─────────────────────────────────────
                             -0.10000002 kilometers
                              -100.00002 meters
                              -10000.002 centimeters
──────────────────────────────────old Russian──────────────────────────────────
                            -0.062480488 milias
                            -0.093720732 versts
                              -46.860366 sazhens
                               -140.5811 arshins
                              -328.02256 futs
                              -562.32439 piads
                              -2249.2976 vershoks
                              -3936.2707 diuyms
                              -39362.707 liniyas
                              -393627.07 tochkas