my @table = ( #### temperature [ c => f => sub { (\$_[0] * 9/5) + 32 }, sub { (\$_[0] - 32) * 5/9 }, ], [ c => k => sub { \$_[0] + 273.16 }, sub { \$_[0] - 273.16 }, ], #### mass/weight [ kg => g => 1000 ], [ floz => g => 30 ], [ lbs => kg => 0.4536 ], #### distance [ ft => m => 0.3048 ], [ ft => in => 12 ], [ in => cm => 2.54 ], [ m => cm => 100 ], [ yd => m => 0.9144 ], [ km => m => 1000 ], [ mile => km => 1.609347 ], ); my %table; for my \$conv ( @table ) { my( \$from, \$to, \$conv, \$rev )= @\$conv; if( exists \$table{\$from}{\$to} ) { warn "Duplicate conversions to \$to from \$from.\n"; } \$table{\$from}{\$to}= \$conv; if( \$rev ) { if( exists \$table{\$from}{\$to} ) { warn "Duplicate conversions to \$from from \$to.\n"; } \$table{\$to}{\$from}= \$rev; } } # Handle reverse conversions when a better one isn't provided: for my \$conv ( @table ) { my( \$from, \$to, \$conv )= @\$conv; if( ! ref(\$conv) && ! exists \$table{\$to}{\$from} ) { \$table{\$to}{\$from}= sub { \$_[0] / \$conv }; } } sub FindConversionPathTo { my( \$dest, \$source )= @_; my( @sol ); \$source= { \$source => "\$source " }; while( ! @sol ) { for my \$src ( keys %sources ) { if( exists \$table{\$src}{\$dest} ) { \$source{\$src} .= "\$dest "; push @sol, \$src; } else { for my \$dest ( keys %{\$table{\$src} ) { if( ! exists \$source{\$dest} ) { \$source{\$dest}= \$source{\$src} . "\$dest "; } } } } } # Pick one of the solutions at random: (: return split ' ', (@source{@sol})[rand @sol]; }