10
\$\begingroup\$

The input is an array of (at least 3, maximum 20) different integers. Each integer is greater than -1000 and smaller than 1000.

Your task is to shrink the numbers by "linearly mapping" them from 0.0 to 1.0. This means the smallest number in the array will be mapped to 0.0, the largest to 1.0.

You get the array as a parameter (inside a function) or stdin/program arguments (you can choose). Print out the result in the format double1;double2;double3;.... The output has to have the same order as the input.

If you want, you can round the output to 2 digits after the decimal point. There must be atleast 1 digit after the decimal point.

The usage of built-in functions (functions which scale down the numbers for you, such as mathematicas Rescale) is disallowed.

Examples:

Input              Output
[5,-20,30]         0.5;0.0;1.0
[1,2,3,4,5]        0.0;0.25;0.5;0.75;1.0
[0,5,100,400]      0.0;0.01;0.25;1.0

(The last output is rounded, otherwise it would be 0.0;0.0125;0.25;1.0)

\$\endgroup\$
  • 2
    \$\begingroup\$ So even we write a function the result has to be printed? (As opposed to returning a corresponding array of doubles.) \$\endgroup\$ – Martin Ender Oct 1 '14 at 12:24
  • \$\begingroup\$ @MartinBüttner Yes, they have to be printed. Built-in functions are disallowed. \$\endgroup\$ – CommonGuy Oct 1 '14 at 12:27
  • \$\begingroup\$ " usage of built-in functions (such as mathematicas Rescale) is disallowed." - that's too vague. What functions are disallowed? Only those that solve the full problem (which would be a standard loophole) are? \$\endgroup\$ – John Dvorak Oct 1 '14 at 12:53
  • \$\begingroup\$ Wait, so, the input may be a function argument, but the output must be to the screen??? \$\endgroup\$ – John Dvorak Oct 1 '14 at 12:58
  • 1
    \$\begingroup\$ @Dennis The format has to match the one shown in the question. This means the numbers are seperated by semicolons. \$\endgroup\$ – CommonGuy Oct 2 '14 at 13:30

18 Answers 18

5
\$\begingroup\$

CJam, 18 bytes

q~_$0=f-_$W=df/';*

Note that the online interpreter wrongfully represents 0d as 0 instead of 0.0.

Example run

$ cjam shrink.cjam <<< '[5 -20 30]'; echo
0.5;0.0;1.0
$ cjam shrink.cjam <<< '[1 2 3 4 5]'; echo
0.0;0.25;0.5;0.75;1.0
$ cjam shrink.cjam <<< '[0 5 100 400]'; echo
0.0;0.0125;0.25;1.0

How it works

q~                    " P := eval(input())         ";
  _$0=                " S := sorted(P)[0]          ";
      f-              " Q := { X - S : X ∊ P }     ";
        _$W=d         " D := double(sorted(Q)[-1]) ";
             f/       " R := { X / D : X ∊ Q }     ";
               ';*    " print(join(R, ';'))        ";
\$\endgroup\$
  • \$\begingroup\$ My reaction to this, as a CJam source: Wtf? explanation needed... \$\endgroup\$ – edc65 Oct 1 '14 at 14:57
  • 2
    \$\begingroup\$ Nice way of getting min and max using array index instead of popping and then swapping things around \$\endgroup\$ – Optimizer Oct 1 '14 at 14:59
  • \$\begingroup\$ It's probably my cold speaking, but why do you sort twice? Shouldn't a sorted array stay sorted if a constant is subtracted from each element? \$\endgroup\$ – Ingo Bürk Oct 1 '14 at 17:23
  • \$\begingroup\$ @IngoBürk The sorted array doesn't survive the array access, I think. Which makes sense, because the final result must not be sorted. \$\endgroup\$ – Martin Ender Oct 1 '14 at 17:24
  • \$\begingroup\$ @MartinBüttner D'oh. Of course. We need to retain order for the result. Thanks! \$\endgroup\$ – Ingo Bürk Oct 1 '14 at 17:25
4
\$\begingroup\$

JavaScript, ES6, 81 bytes

Thanks to @edc65 for the toFixed trick

F=a=>a.map(v=>((v-n)/d).toFixed(2),n=Math.min(...a),d=Math.max(...a)-n).join(';')

Run it in latest Firefox Console.

This creates a function f which you can invoke like

F([5,-20,30])
\$\endgroup\$
  • \$\begingroup\$ 1) why eval(prompt) when a function is allowed? 2)There must be at least 1 digit after the decimal point. 3)no need to store M, just d=M-m \$\endgroup\$ – edc65 Oct 1 '14 at 13:27
  • \$\begingroup\$ Updated. Although, getting at least 1 digit after decimal is tough \$\endgroup\$ – Optimizer Oct 1 '14 at 13:31
  • \$\begingroup\$ If you want, you can round the output to 2 digits after the decimal point that's the simpler way I think \$\endgroup\$ – edc65 Oct 1 '14 at 13:44
  • \$\begingroup\$ @edc65 But there is no way to convert 1 to 1.0 except for what I did. \$\endgroup\$ – Optimizer Oct 1 '14 at 13:55
  • \$\begingroup\$ Nope. May I hint? \$\endgroup\$ – edc65 Oct 1 '14 at 13:57
4
\$\begingroup\$

Python 2, 72 68 63 56 55

Obviously not as concise as other answers, but anyway:

x=input()
m=min(x)
print[(i*1.-m)/(max(x)-m)for i in x]

Sample run:

[1,100,25,8,0]                  #input
[0.01, 1.0, 0.25, 0.08, 0.0]    #output

Old (68 characters, written in Python 3):

x=eval(input())
y=sorted(x)
print([(i-y[0])/(y[-1]-y[0])for i in x])
\$\endgroup\$
  • \$\begingroup\$ You can save one more char by defining m=min(x). \$\endgroup\$ – FryAmTheEggman Oct 1 '14 at 14:58
4
\$\begingroup\$

CJam, 24 23 bytes

l~_$)\(:M\;-\Mf-\df/';*

Input be like:

[5 -20 30]

Try it online here Note that online compiler prints Double 0 as 0 only. Run in the java interpreter which prints correctly.

How it works:

l~                      "Evaluate input and convert each element to double";
  _$                    "Copy the array and sort the copied array";
    )                   "Pop the last element out of the array. This is Max";
     \                  "Swap last two stack elements, bring sorted array on top";
      (:M               "Pop the first element of array and store it in M. This is Min";
         \;             "Bring the remaining of sorted array on top and remove it from stack";
           -\           "Subtract Max and Min and bring the original array to top of stack"
             Mf-        "Push min to stack and subtract it from each array element";
                \df/    "Bring (Double)(Max-Min) to top and divide each array element by it";
                   ';*  "Push the character ; to stack and join the array with it";
\$\endgroup\$
  • 1
    \$\begingroup\$ Ah, that's a much better idea to get minimum and maximum. \$\endgroup\$ – Martin Ender Oct 1 '14 at 13:18
  • \$\begingroup\$ This prints 0;0.5;1 instead of 0.0;0.5;1.0. \$\endgroup\$ – CommonGuy Oct 1 '14 at 13:34
  • \$\begingroup\$ @Manu - Yes, trying to fix that. And almost all answers do this only. \$\endgroup\$ – Optimizer Oct 1 '14 at 13:36
  • 2
    \$\begingroup\$ You don't need the fix. The Java interpreter represents the Double 0 as 0.0. \$\endgroup\$ – Dennis Oct 1 '14 at 14:11
3
\$\begingroup\$

C# 92

Running inside LinqPad

void F(int[]a)
{
   double n=a.Min(),d=a.Max()-n;
   a.Select(x=>((x-n)/d).ToString("0.00")).Dump();
}

Test in LinqPad

void Main()
{
    F(new int[]{5,-20,30});
}
void F(int[]a){double n=a.Min(),d=a.Max()-n;a.Select(x=> ((x-n)/d).ToString("0.00")).Dump();}

Output

IEnumerable<String> (3 items)
0,50 
0,00 
1,00 
\$\endgroup\$
3
\$\begingroup\$

APL (15)

(2⍕+÷⌈/)(+-⌊/)⎕

(or, without trains, also 15 characters:)

2⍕V÷⌈/V←V-⌊/V←⎕

This reads the argument from the keyboard and prints the result to the screen.

Explanation:

  • : read a line from the keyboard and evaluate it
  • +-⌊/: subtract the lowest item in the array from all items in the array
  • +÷⌈/: divide each item in the array by the array's highest item
  • 2⍕: format with two decimal places

Test:

      (2⍕+÷⌈/)(+-⌊/)⎕
⎕:
     5 ¯20 30
 0.50 0.00 1.00
      (2⍕+÷⌈/)(+-⌊/)⎕
⎕:
      1 2 3 4 5
 0.00 0.25 0.50 0.75 1.00
      (2⍕+÷⌈/)(+-⌊/)⎕
⎕:
      0 5 100 400
 0.00 0.01 0.25 1.00
\$\endgroup\$
  • \$\begingroup\$ Should add the byte count... \$\endgroup\$ – Optimizer Oct 1 '14 at 14:01
  • \$\begingroup\$ Which is 24 bytes only. \$\endgroup\$ – Optimizer Oct 1 '14 at 14:22
  • 2
    \$\begingroup\$ @Optimizer: Unless the question states otherwise, every answer is scored using the encoding that yields the smallest byte count. There's an APL codepage that represents every APL character by one byte. \$\endgroup\$ – Dennis Oct 1 '14 at 14:27
  • \$\begingroup\$ Correct me if I am doing something wrong here, but by default, code-golf are counted in bytes and mothereff.in/byte-counter#%282%E2%8D%95+%C3%B7%E2%8C%88/… page says its 24 bytes. Did I miss something ? \$\endgroup\$ – Optimizer Oct 1 '14 at 14:29
  • 1
    \$\begingroup\$ Output has to be seperated by semicolons, not spaces. \$\endgroup\$ – CommonGuy Oct 2 '14 at 13:31
3
\$\begingroup\$

Pyth, 18

Now with correct formatting!

j\;mc-dhSQ-eSQhSQQ

Test:

$ pyth -c 'j\;mc-dhSQ-eSQhSQQ' <<< '[0,5,100,400]'
0.0;0.0125;0.25;1.0

Explanation:

(implicit)              Q = eval(input())
j\;                     ';'.join(
   m                             map(lambda d:
    c                                         float_div(
     -dhSQ                                              d-sorted(Q)[0],
     -eSQhSQ                                            sorted(Q)[-1]-sorted(Q)[0]),
    Q                                         Q))
\$\endgroup\$
  • \$\begingroup\$ The output is not formatted correctly. \$\endgroup\$ – CommonGuy Oct 2 '14 at 13:31
  • \$\begingroup\$ @Manu Sorry about that, I've fixed it. \$\endgroup\$ – isaacg Oct 2 '14 at 14:38
  • \$\begingroup\$ Doesn't creating your own language, which you change over time, slightly stretching the rules? You can obviously just add a new feature to make the program shorter? \$\endgroup\$ – Chris Jefferson Oct 2 '14 at 23:36
  • 3
    \$\begingroup\$ @ChrisJefferson I always use the newest version of the language that came out before the problem was asked. Since it's all pushed to Github, it can be verified that I'm not adding anything after the problem is posted. That's the standard CG.SE rule - the language must be older than the question, and I abide by it. \$\endgroup\$ – isaacg Oct 3 '14 at 0:01
2
\$\begingroup\$

Octave 25

b=min(l);(l-b)/(max(l)-b)

Assumes input is in l and since it's an interactive shell the result is printed automatically (is this allowed?)

\$\endgroup\$
  • 2
    \$\begingroup\$ Octave/Matlab does have input though to get user input and mimick STDIN. You can also write a function. Also, does this print the result in the correct format? \$\endgroup\$ – Martin Ender Oct 1 '14 at 13:03
  • \$\begingroup\$ And no, just returning and having the shell print it generally doesn't count. Golfscript and the like are different because the language specifiesthat the stack is printed in the end. But this isn't the case for, e.g., Javascript. And I don't think for Matlab/Octave either. \$\endgroup\$ – Ingo Bürk Oct 3 '14 at 12:59
2
\$\begingroup\$

APL, 31 characters / 55 bytes

{b←⌊/⍵⋄c←(⌈/⍵)-b⋄{2⍕(⍵-b)÷c}¨⍵}

Old code without digits after decimal point:

{b←⌊/⍵⋄c←(⌈/⍵)-b⋄{(⍵-b)÷c}¨⍵}

Take minimum of vector, take difference between maximum and minimum of vector, subtract the minimum from each element and divide by the difference between min and max.

Edited Code to print two digits after the decimal point:

\$\endgroup\$
2
\$\begingroup\$

CJam, 30 29 bytes

l~:d_{e>}*\_{e<}*:Mf-\M-f/';*

Expects the input on STDIN like [5 -20 30].

Test it here. (This will print integer 0 and 1 without decimal point, but the Java interpreter does print 0.0 and 1.0.)

Due to a bug I can't shorten {e>}* to :e> although that should be possible as per the spec (which would save 4 bytes when applied to both min and max).

Slightly outdated explanation: (will amend later)

l~:d_{e<}*_@_{e>}*@-\@f-\f/';* "Read and eval the input leaving an array of strings on the stack";
l~                             "Read and eval the input leaving an array of strings on the stack";
  :d                           "Convert all elements to double";
    _                          "Duplicate the array";
     {e<}*                     "Wrap the MIN function in a black and fold it onto the array";
          _                    "Duplicate the minimum";
           @                   "Rotate the stack, pulling the array to the top";
            _                  "Duplicate the array";
             {e>}*             "Same as before, now with MAX";
                  @            "Rotate the stack, pulling the minimum to the top";
                   -           "Subtract to give the total range";
                    \          "Swap range and array";
                     @         "Rotate the stack, pulling the other minimum to the top";
                      f-       "Subtract the minimum from each element in the array";
                        \      "Swap range and array";
                         f/    "Divide each element in the array by the range";
                           ';  "Push a semicolon character";
                             * "Riffle the semicolon into the array";

At the end of the program, the stack contents are printed by default.

I'm sure there is a way to save half of the stack reshuffling, but I'm not that comfortable with CJam yet.

\$\endgroup\$
  • \$\begingroup\$ This prints 0;0.5;1 instead of 0.0;0.5;1.0. \$\endgroup\$ – CommonGuy Oct 1 '14 at 13:35
  • \$\begingroup\$ @Manu See Dennis's comment on Optimizer's answer. It works fine in the Java interpreter. \$\endgroup\$ – Martin Ender Oct 1 '14 at 14:30
2
\$\begingroup\$

Xojo, 179 bytes

dim x,n as double,k,z as int16,s() as string
n=1e3
x=-n
for each k in a
x=max(x,k)
n=min(n,k)
next
for k=0 to ubound(a)
s.append str((a(k)-n)/(x-n),"0.0#")
next
msgbox join(s,";")
\$\endgroup\$
2
\$\begingroup\$

R, 60 bytes

m=min(x<-scan());cat(sprintf("%f",(x-m)/(max(x)-m)),sep=";")    

Formatting eats up a lot of bytes due to 0 and 1 by default are trimmed to display nothing past the integer part.

\$\endgroup\$
1
\$\begingroup\$

Clojure 63

(fn[v](let[l(apply min v)](map #(/(- % l)(-(apply max v)l))v))) 

Doesn't quite follow the rules, since it returns fractions instead of doubles. If that's not acceptable, add 7 bytes

Ungolfed:

(fn [values]
    (let [low (apply min values)]
         (map #(/ (- % low)
                  (- (apply max values) low))
              values)))

Callable like this:

((fn[v](let[l(apply min v)](map #(/(- % l)(-(apply max v)l))v))) [5 -20 30])

Output: (1/2 0 1)

\$\endgroup\$
1
\$\begingroup\$

Ruby, 49

f=->a{$><<a.map{|x|(x-l=a.min).fdiv(a.max-l)}*?;}

Explanation:

f=->a{}     # Define a lambda that takes one argument a
$><<        # Print the following to STDOUT
a.map{|x|}  # For each element x
(x-l=a.min) # Find the lowest element of a, assign it to l, and subtract it from x
.fdiv       # Float division (/ truncates)
(a.max - l) # Divide by the maximum minus the minimum
*?;         # Convert the resulting array into a string joined by the ';' character
\$\endgroup\$
1
\$\begingroup\$

05AB1E, 13 bytes (Non-competing)

ZsWD1.S*+s/Z/

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Q (31) IMPROPER OUTPUT FORMAT

{(%/)(x;max x)-min x}(.:)(0::)0

input

1 2 3

output

0 .5 1
\$\endgroup\$
0
\$\begingroup\$

Perl - 60

my@a=sort@ARGV;print map{($_-$a[0])/($a[-1]-$a[0])." "}@ARGV
\$\endgroup\$
0
\$\begingroup\$

Java 7, 149 bytes

float[]c(int[]x){int b=1<<31,a=b-1,j=0,l=x.length;for(int i:x){a=i<a?i:a;b=i>b?i:b;}float[]r=new float[l];for(;j<l;r[j]=x[j++]-a)*1f/(b-a);return r;}

Ungolfed & test code:

Try it here.

import java.util.Arrays;
class M{
  static float[] c(int[] x){
    int b = Integer.MIN_VALUE,
        a = b-1, // In Java, Integer.MIN_VALUE - 1 = Integer.MAX_VALUE (and vice-versa)
        j = 0,
        l = x.length;
    for(int i : x){
      a = i < a ? i : a; // Determine min value of array
      b = i > b ? i : b; // Determine max value of array
    }
    float[] r = new float[l];
    for(; j < l; r[j] = (x[j++] - a) * 1f / (b-a));
    return r;
  }

  public static void main(String[] a){
    System.out.println(Arrays.toString(c(new int[]{ 5, -20, 30 })));
    System.out.println(Arrays.toString(c(new int[]{ 1, 2, 3, 4, 5 })));
    System.out.println(Arrays.toString(c(new int[]{ 0, 5, 100, 400 })));
  }
}

Output:

[0.5, 0.0, 1.0]
[0.0, 0.25, 0.5, 0.75, 1.0]
[0.0, 0.0125, 0.25, 1.0]
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.