This commit is contained in:
Ingy döt Net 2013-04-10 21:29:02 -07:00
parent 764da6cbbb
commit db842d013d
19005 changed files with 197040 additions and 7 deletions

View file

@ -0,0 +1,6 @@
Given two [[wp:Interval (mathematics)|ranges]], <math>[a_1,a_2]</math> and <math>[b_1,b_2]</math>; then a value <math>s</math> in range <math>[a_1,a_2]</math> is linearly mapped to a value <math>t</math> in range <math>[b_1,b_2]</math> when:
:<math>t = b_1 + {(s - a_1)(b_2 - b_1) \over (a_2 - a_1)}</math>
The task is to write a function/subroutine/... that takes two ranges and a real number, and returns the mapping of the real number from the first to the second range. Use this function to map values from the range <code>[0, 10]</code> to the range <code>[-1, 0]</code>.
'''Extra credit:''' Show additional idiomatic ways of performing the mapping, using tools available to the language.

View file

@ -0,0 +1,4 @@
(defun mapping (a1 a2 b1 b2 s)
(+ b1 (/ (* (- s a1)
(- b2 b1))
(- a2 a1))))

View file

@ -0,0 +1,33 @@
with Ada.Text_IO;
procedure Map is
type First_Range is new Float range 0.0 .. 10.0;
type Second_Range is new Float range -1.0 .. 0.0;
function Translate (Value : First_Range) return Second_Range is
B1 : Float := Float (Second_Range'First);
B2 : Float := Float (Second_Range'Last);
A1 : Float := Float (First_Range'First);
A2 : Float := Float (First_Range'Last);
Result : Float;
begin
Result := B1 + (Float (Value) - A1) * (B2 - B1) / (A2 - A1);
return Second_Range (Result);
end;
function Translate (Value : Second_Range) return First_Range is
B1 : Float := Float (First_Range'First);
B2 : Float := Float (First_Range'Last);
A1 : Float := Float (Second_Range'First);
A2 : Float := Float (Second_Range'Last);
Result : Float;
begin
Result := B1 + (Float (Value) - A1) * (B2 - B1) / (A2 - A1);
return First_Range (Result);
end;
Test_Value : First_Range := First_Range'First;
begin
loop
Ada.Text_IO.Put_Line (First_Range'Image (Test_Value) & " maps to: "
& Second_Range'Image (Translate (Test_Value)));
exit when Test_Value = First_Range'Last;
Test_Value := Test_Value + 1.0;
end loop;
end Map;

View file

@ -0,0 +1,10 @@
mapRange(a1, a2, b1, b2, s)
{
return b1 + (s-a1)*(b2-b1)/(a2-a1)
}
out := "Mapping [0,10] to [-1,0] at intervals of 1:`n"
Loop 11
out .= "f(" A_Index-1 ") = " mapRange(0,10,-1,0,A_Index-1) "`n"
MsgBox % out

View file

@ -0,0 +1,7 @@
)abbrev package TESTP TestPackage
TestPackage(R:Field) : with
mapRange: (Segment(R), Segment(R)) -> (R->R)
== add
mapRange(fromRange, toRange) ==
(a1,a2,b1,b2) := (lo fromRange,hi fromRange,lo toRange,hi toRange)
(x:R):R +-> b1+(x-a1)*(b2-b1)/(a2-a1)

View file

@ -0,0 +1,2 @@
f := mapRange(1..10,a..b)
[(xi,f xi) for xi in 1..10]

View file

@ -0,0 +1,7 @@
b + 8a 2b + 7a b + 2a 4b + 5a 5b + 4a
[(1,a), (2,------), (3,-------), (4,------), (5,-------), (6,-------),
9 9 3 9 9
2b + a 7b + 2a 8b + a
(7,------), (8,-------), (9,------), (10,b)]
3 9 9
Type: List(Tuple(Fraction(Polynomial(Integer))))

View file

@ -0,0 +1,12 @@
@% = 5 : REM Column width
DIM range{l, h}
DIM A{} = range{}, B{} = range{}
A.l = 0 : A.h = 10
B.l = -1 : B.h = 0
FOR n = 0 TO 10
PRINT n " maps to " FNmaprange(A{}, B{}, n)
NEXT
END
DEF FNmaprange(a{}, b{}, s)
= b.l + (s - a.l) * (b.h - b.l) / (a.h - a.l)

View file

@ -0,0 +1,13 @@
( ( mapRange
= a1,a2,b1,b2,s
. !arg:(?a1,?a2.?b1,?b2.?s)
& !b1+(!s+-1*!a1)*(!b2+-1*!b1)*(!a2+-1*!a1)^-1
)
& out$"Mapping [0,10] to [-1,0] at intervals of 1:"
& 0:?n
& whl
' ( !n:~>10
& out$("f(" !n ") = " flt$(mapRange$(0,10.-1,0.!n),2))
& 1+!n:?n
)
);

View file

@ -0,0 +1,26 @@
#include <iostream>
#include <utility>
template<typename tVal>
tVal map_value(std::pair<tVal,tVal> a, std::pair<tVal, tVal> b, tVal inVal)
{
tVal inValNorm = inVal - a.first;
tVal aUpperNorm = a.second - a.first;
tVal normPosition = inValNorm / aUpperNorm;
tVal bUpperNorm = b.second - b.first;
tVal bValNorm = normPosition * bUpperNorm;
tVal outVal = b.first + bValNorm;
return outVal;
}
int main()
{
std::pair<float,float> a(0,10), b(-1,0);
for(float value = 0.0; 10.0 >= value; ++value)
std::cout << "map_value(" << value << ") = " << map_value(a, b, value) << std::endl;
return 0;
}

View file

@ -0,0 +1,19 @@
#include <stdio.h>
double mapRange(double a1,double a2,double b1,double b2,double s)
{
return b1 + (s-a1)*(b2-b1)/(a2-a1);
}
int main()
{
int i;
puts("Mapping [0,10] to [-1,0] at intervals of 1:");
for(i=0;i<=10;i++)
{
printf("f(%d) = %g\n",i,mapRange(0,10,-1,0,i));
}
return 0;
}

View file

@ -0,0 +1,12 @@
Mapping [0,10] to [-1,0] at intervals of 1:
f(0) = -1
f(1) = -0.9
f(2) = -0.8
f(3) = -0.7
f(4) = -0.6
f(5) = -0.5
f(6) = -0.4
f(7) = -0.3
f(8) = -0.2
f(9) = -0.1
f(10) = 0

View file

@ -0,0 +1,17 @@
(defn maprange [[a1 a2] [b1 b2] s]
(+ b1 (/ (* (- s a1) (- b2 b1)) (- a2 a1))))
> (doseq [s (range 11)]
(printf "%2s maps to %s\n" s (maprange [0 10] [-1 0] s)))
0 maps to -1
1 maps to -9/10
2 maps to -4/5
3 maps to -7/10
4 maps to -3/5
5 maps to -1/2
6 maps to -2/5
7 maps to -3/10
8 maps to -1/5
9 maps to -1/10
10 maps to 0

View file

@ -0,0 +1,11 @@
(defun map-range (a1 a2 b1 b2 s)
(+ b1
(/ (* (- s a1)
(- b2 b1))
(- a2 a1))))
(loop
for i from 0 to 10
do (format t "~F maps to ~F~C" i
(map-range 0 10 -1 0 i)
#\Newline))

View file

@ -0,0 +1,13 @@
import std.stdio;
double mapRange(in double[] a, in double[] b, in double s)
pure nothrow {
return b[0] + ((s - a[0]) * (b[1] - b[0]) / (a[1] - a[0]));
}
void main() {
const r1 = [0.0, 10.0];
const r2 = [-1.0, 0.0];
foreach (s; 0 .. 11)
writefln("%2d maps to %5.2f", s, mapRange(r1, r2, s));
}

View file

@ -0,0 +1,6 @@
(defun maprange (a1 a2 b1 b2 s)
(+ b1 (/ (* (- s a1) (- b2 b1)) (- a2 a1))))
(dotimes (i 10)
(princ (maprange 0.0 10.0 -1.0 0.0 i))
(terpri))

View file

@ -0,0 +1,5 @@
-module(map_range).
-export([map_value/3]).
map_value({A1,A2},{B1,B2},S) ->
B1 + (S - A1) * (B2 - B1) / (A2 - A1).

View file

@ -0,0 +1,7 @@
function map_range(sequence a, sequence b, atom s)
return b[1]+(s-a[1])*(b[2]-b[1])/(a[2]-a[1])
end function
for i = 0 to 10 do
printf(1, "%2g maps to %4g\n", {i, map_range({0,10},{-1,0},i)})
end for

View file

@ -0,0 +1,3 @@
USE: locals
:: map-range ( a1 a2 b1 b2 x -- y )
x a1 - b2 b1 - * a2 a1 - / b1 + ;

View file

@ -0,0 +1,5 @@
USING: locals infix ;
:: map-range ( a1 a2 b1 b2 x -- y )
[infix
b1 + (x - a1) * (b2 - b1) / (a2 - a1)
infix] ;

View file

@ -0,0 +1 @@
10 iota [| x | 0 10 -1 0 x map-range ] map . ! { -1 -9/10 -4/5 -7/10 -3/5 -1/2 -2/5 -3/10 -1/5 -1/10 }

View file

@ -0,0 +1,34 @@
class FRange
{
const Float low
const Float high
// in constructing a range, ensure the low value is smaller than high
new make (Float low, Float high)
{
this.low = ( low <= high ? low : high )
this.high = ( low <= high ? high : low )
}
// return range as a string
override Str toStr () { "[$low,$high]" }
// return a point in given range interpolated into this range
Float remap (Float point, FRange given)
{
this.low + (point - given.low) * (this.high - this.low) / (given.high - given.low)
}
}
class Main
{
public static Void main ()
{
range1 := FRange (0f, 10f)
range2 := FRange (-1f, 0f)
11.times |Int n|
{
m := range2.remap (n.toFloat, range1)
echo ("Value $n in ${range1} maps to $m in ${range2}")
}
}
}

View file

@ -0,0 +1,9 @@
\ linear interpolation
: lerp ( b2 b1 a2 a1 s -- t )
fover f-
frot frot f- f/
frot frot fswap fover f- frot f*
f+ ;
: test 11 0 do 0e -1e 10e 0e i s>f lerp f. loop ;

View file

@ -0,0 +1,3 @@
: lerp ( o2 r2 r1 o1 s -- t ) fswap f- fswap f/ f* f+ ;
: test 11 0 do -1e 1e 10e 0e i s>f lerp f. loop ;

View file

@ -0,0 +1,21 @@
program Map
implicit none
real :: t
integer :: i
do i = 0, 10
t = Maprange((/0.0, 10.0/), (/-1.0, 0.0/), real(i))
write(*,*) i, " maps to ", t
end do
contains
function Maprange(a, b, s)
real :: Maprange
real, intent(in) :: a(2), b(2), s
Maprange = (s-a(1)) * (b(2)-b(1)) / (a(2)-a(1)) + b(1)
end function Maprange
end program Map

View file

@ -0,0 +1,19 @@
package main
import "fmt"
type rangeBounds struct {
b1, b2 float64
}
func mapRange(x, y rangeBounds, n float64) float64 {
return y.b1 + (n - x.b1) * (y.b2 - y.b1) / (x.b2 - x.b1)
}
func main() {
r1 := rangeBounds{0, 10}
r2 := rangeBounds{-1, 0}
for n := float64(0); n <= 10; n += 2 {
fmt.Println(n, "maps to", mapRange(r1, r2, n))
}
}

View file

@ -0,0 +1,37 @@
package main
import "fmt"
type rangeBounds struct {
b1, b2 float64
}
func newRangeMap(xr, yr rangeBounds) func(float64) (float64, bool) {
// normalize direction of ranges so that out-of-range test works
if xr.b1 > xr.b2 {
xr.b1, xr.b2 = xr.b2, xr.b1
yr.b1, yr.b2 = yr.b2, yr.b1
}
// compute slope, intercept
m := (yr.b2 - yr.b1) / (xr.b2 - xr.b1)
b := yr.b1 - m*xr.b1
// return function literal
return func(x float64) (y float64, ok bool) {
if x < xr.b1 || x > xr.b2 {
return 0, false // out of range
}
return m*x + b, true
}
}
func main() {
rm := newRangeMap(rangeBounds{0, 10}, rangeBounds{-1, 0})
for s := float64(-2); s <= 12; s += 2 {
t, ok := rm(s)
if ok {
fmt.Printf("s: %5.2f t: %5.2f\n", s, t)
} else {
fmt.Printf("s: %5.2f out of range\n", s)
}
}
}

View file

@ -0,0 +1,7 @@
def mapRange(a1, a2, b1, b2, s) {
b1 + ((s - a1) * (b2 - b1)) / (a2 - a1)
}
(0..10).each { s ->
println(s + " in [0, 10] maps to " + mapRange(0, 10, -1, 0, s) + " in [-1, 0].")
}

View file

@ -0,0 +1,21 @@
import Data.Ratio
import Text.Printf
-- Map a value from the range [a1,a2] to the range [b1,b2]. We don't check
-- for empty ranges.
mapRange :: (Fractional a) => (a, a) -> (a, a) -> a -> a
mapRange (a1,a2) (b1,b2) s = b1+(s-a1)*(b2-b1)/(a2-a1)
main = do
-- Perform the mapping over floating point numbers.
putStrLn "---------- Floating point ----------"
mapM_ (\n -> prtD n . mapRange (0,10) (-1,0) $ fromIntegral n) [0..10]
-- Perform the same mapping over exact rationals.
putStrLn "---------- Rationals ----------"
mapM_ (\n -> prtR n . mapRange (0,10) (-1,0) $ n%1) [0..10]
where prtD :: PrintfType r => Integer -> Double -> r
prtD n x = printf "%2d -> %6.3f\n" n x
prtR :: PrintfType r => Integer -> Rational -> r
prtR n x = printf "%2d -> %s\n" n (show x)

View file

@ -0,0 +1,23 @@
record Range(a, b)
# note, we force 'n' to be real, which means recalculation will
# be using real numbers, not integers
procedure remap (range1, range2, n : real)
if n < range2.a | n > range2.b then fail # n out of given range
return range1.a + (n - range2.a) * (range1.b - range1.a) / (range2.b - range2.a)
end
procedure range_string (range)
return "[" || range.a || ", " || range.b || "]"
end
procedure main ()
range1 := Range (0, 10)
range2 := Range (-1, 0)
# if i is out of range1, then 'remap' fails, so only valid changes are written
every i := -2 to 12 do {
if m := remap (range2, range1, i)
then write ("Value " || i || " in " || range_string (range1) ||
" maps to " || m || " in " || range_string (range2))
}
end

View file

@ -0,0 +1,5 @@
procedure remap (range1, range2, n)
n *:= 1.0
if n < range2.a | n > range2.b then fail # n out of given range
return range1.a + (n - range2.a) * (range1.b - range1.a) / (range2.b - range2.a)
end

View file

@ -0,0 +1,6 @@
maprange=:2 :0
'a1 a2'=.m
'b1 b2'=.n
b1+((y-a1)*b2-b1)%a2-a1
)
NB. this version defers all calculations to runtime, but mirrors exactly the task formulation

View file

@ -0,0 +1,6 @@
maprange=:2 :0
'a1 a2'=.m
'b1 b2'=.n
b1 + ((b2-b1)%a2-a1) * -&a1
)
NB. this version precomputes the scaling ratio

View file

@ -0,0 +1,2 @@
2 4 maprange 5 11 (2.718282 3 3.141592)
7.15485 8 8.42478

View file

@ -0,0 +1,3 @@
adjust=:2 4 maprange 5 11 NB. save the derived function as a named entity
adjust 2.718282 3 3.141592
7.15485 8 8.42478

View file

@ -0,0 +1,2 @@
0 10 maprange _1 0 i.11
_1 _0.9 _0.8 _0.7 _0.6 _0.5 _0.4 _0.3 _0.2 _0.1 0

View file

@ -0,0 +1,12 @@
public class Range {
public static void main(String[] args){
for(float s = 0;s <= 10; s++){
System.out.println(s + " in [0, 10] maps to "+
mapRange(0, 10, -1, 0, s)+" in [-1, 0].");
}
}
public static double mapRange(double a1, double a2, double b1, double b2, double s){
return b1 + ((s - a1)*(b2 - b1))/(a2 - a1);
}
}

View file

@ -0,0 +1,12 @@
// Javascript doesn't have built-in support for ranges
// Insted we use arrays of two elements to represent ranges
var mapRange = function(from, to, s) {
return to[0] + (s - from[0]) * (to[1] - to[0]) / (from[1] - from[0]);
};
var range = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
for (var i = 0; i < range.length; i++) {
range[i] = mapRange([0, 10], [-1, 0], range[i]);
}
console.log(range);

View file

@ -0,0 +1,19 @@
var mapRange = function(from, to, s) {
// mapRange expects ranges generated by _.range
var a1 = from[0];
var a2 = from[from.length - 1];
var b1 = to[0];
var b2 = to[to.length - 1];
return b1 + (s - a1) * (b2 - b1) / (a2 - a1);
};
// The range function is exclusive
var fromRange = _.range(0, 11);
var toRange = _.range(-1, 1);
// .map constructs a new array
fromRange = fromRange.map(function(s) {
return mapRange(fromRange, toRange, s);
});
console.log(fromRange);

View file

@ -0,0 +1,14 @@
f:{[a1;a2;b1;b2;s] b1+(s-a1)*(b2-b1)%(a2-a1)}
+(a; f[0;10;-1;0]'a:!11)
((0;-1.0)
(1;-0.9)
(2;-0.8)
(3;-0.7)
(4;-0.6)
(5;-0.5)
(6;-0.4)
(7;-0.3)
(8;-0.2)
(9;-0.1)
(10;0.0))

View file

@ -0,0 +1,5 @@
to interpolate :s :a1 :a2 :b1 :b2
output (:s-:a1) / (:a2-:a1) * (:b2-:b1) + :b1
end
for [i 0 10] [print interpolate :i 0 10 -1 0]

View file

@ -0,0 +1,7 @@
function map_range( a1, a2, b1, b2, s )
return b1 + (s-a1)*(b2-b1)/(a2-a1)
end
for i = 0, 10 do
print( string.format( "f(%d) = %f", i, map_range( 0, 10, -1, 0, i ) ) )
end

View file

@ -0,0 +1 @@
Rescale[#,{0,10},{-1,0}]&/@Range[0,10]

View file

@ -0,0 +1,4 @@
maprange(a, b, c, d) := buildq([e: ratsimp(('x - a)*(d - c)/(b - a) + c)],
lambda([x], e))$
f: maprange(0, 10, -1, 0);

View file

@ -0,0 +1,12 @@
#!/usr/bin/perl -w
use strict ;
sub mapValue {
my ( $range1 , $range2 , $number ) = @_ ;
return ( $range2->[ 0 ] +
(( $number - $range1->[ 0 ] ) * ( $range2->[ 1 ] - $range2->[ 0 ] ) ) / ( $range1->[ -1 ]
- $range1->[ 0 ] ) ) ;
}
my @numbers = 0..10 ;
my @interval = ( -1 , 0 ) ;
print "The mapped value for $_ is " . mapValue( \@numbers , \@interval , $_ ) . " !\n" foreach @numbers ;

View file

@ -0,0 +1,9 @@
(scl 1)
(de mapRange (Val A1 A2 B1 B2)
(+ B1 (*/ (- Val A1) (- B2 B1) (- A2 A1))) )
(for Val (range 0 10.0 1.0)
(prinl
(format (mapRange Val 0 10.0 -1.0 0) *Scl) ) )

View file

@ -0,0 +1,19 @@
>>> def maprange( a, b, s):
(a1, a2), (b1, b2) = a, b
return b1 + ((s - a1) * (b2 - b1) / (a2 - a1))
>>> for s in range(11):
print("%2g maps to %g" % (s, maprange( (0, 10), (-1, 0), s)))
0 maps to -1
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.3
8 maps to -0.2
9 maps to -0.1
10 maps to 0

View file

@ -0,0 +1,17 @@
>>> from fractions import Fraction
>>> for s in range(11):
print("%2g maps to %s" % (s, maprange( (0, 10), (-1, 0), Fraction(s))))
0 maps to -1
1 maps to -9/10
2 maps to -4/5
3 maps to -7/10
4 maps to -3/5
5 maps to -1/2
6 maps to -2/5
7 maps to -3/10
8 maps to -1/5
9 maps to -1/10
10 maps to 0
>>>

View file

@ -0,0 +1,12 @@
/*REXX program maps a number from one range to another range. */
rangeA = '0 10'
rangeB = '-1 0'
do j=0 to 10
say right(j,3) ' maps to ' mapRange(rangeA, rangeB, j)
end /*j*/
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────MAPRANGE subroutine─────────────────*/
mapRange: procedure; arg a1 a2,b1 b2,x; return b1+(x-a1)*(b2-b1)/(a2-a1)

View file

@ -0,0 +1,9 @@
/*REXX program maps a number from one range to another range. */
do j=0 to 10
say right(j,3) ' maps to ' mapRange(0 10, -1 0, j)
end /*j*/
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────MAPRANGE subroutine─────────────────*/
mapRange: procedure; arg a1 a2,b1 b2,x; return b1+(x-a1)*(b2-b1)/(a2-a1)

View file

@ -0,0 +1,9 @@
/*REXX program maps a number from one range to another range. */
rangeA = '0 10'; parse var rangeA a1 a2
rangeB = '-1 0'; parse var rangeB b1 b2
do j=0 to 10
say right(j,3) ' maps to ' b1+(x-a1)*(b2-b1)/(a2-a1)
end /*j*/
/*stick a fork in it, we're done.*/

View file

@ -0,0 +1,9 @@
def map_range(a, b, s)
af, al, bf, bl = a.first, a.last, b.first, b.last
bf + (s - af).*(bl - bf).quo(al - af)
end
11.times do |s|
s *= 1.0 # force floating point
print s, " maps to ", map_range((0..10), (-1..0), s), "\n"
end

View file

@ -0,0 +1,4 @@
def mapRange(a1:Double, a2:Double, b1:Double, b2:Double, x:Double):Double=b1+(x-a1)*(b2-b1)/(a2-a1)
for(i <- 0 to 10)
println("%2d in [0, 10] maps to %5.2f in [-1, 0]".format(i, mapRange(0,10, -1,0, i)))

View file

@ -0,0 +1,6 @@
package require Tcl 8.5
proc rangemap {rangeA rangeB value} {
lassign $rangeA a1 a2
lassign $rangeB b1 b2
expr {$b1 + ($value - $a1)*double($b2 - $b1)/($a2 - $a1)}
}

View file

@ -0,0 +1,4 @@
interp alias {} demomap {} rangemap {0 10} {-1 0}
for {set i 0} {$i <= 10} {incr i} {
puts [format "%2d -> %5.2f" $i [demomap $i]]
}