9
\$\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\$
14
  • 2
    \$\begingroup\$ So even we write a function the result has to be printed? (As opposed to returning a corresponding array of doubles.) \$\endgroup\$ Commented Oct 1, 2014 at 12:24
  • \$\begingroup\$ @MartinBüttner Yes, they have to be printed. Built-in functions are disallowed. \$\endgroup\$ Commented Oct 1, 2014 at 12:27
  • 1
    \$\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\$ Commented Oct 1, 2014 at 12:53
  • 1
    \$\begingroup\$ @Dennis The format has to match the one shown in the question. This means the numbers are seperated by semicolons. \$\endgroup\$ Commented Oct 2, 2014 at 13:30
  • 2
    \$\begingroup\$ The atleast one digit after the decimal point rule needlessly complicates things, as well as the forced string output. In RProgN, the solution could just be ] max /, however, these formatting demands make it ] max / ';' . '1$' '1.0' R '^0' '0.0;' R \$\endgroup\$
    – ATaco
    Commented Nov 10, 2016 at 23:04

20 Answers 20

6
\$\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\$
5
  • \$\begingroup\$ My reaction to this, as a CJam source: Wtf? explanation needed... \$\endgroup\$
    – edc65
    Commented Oct 1, 2014 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
    Commented Oct 1, 2014 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
    Commented Oct 1, 2014 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\$ Commented Oct 1, 2014 at 17:24
  • \$\begingroup\$ @MartinBüttner D'oh. Of course. We need to retain order for the result. Thanks! \$\endgroup\$
    – Ingo Bürk
    Commented Oct 1, 2014 at 17:25
5
\$\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\$
8
  • \$\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
    Commented Oct 1, 2014 at 13:27
  • \$\begingroup\$ Updated. Although, getting at least 1 digit after decimal is tough \$\endgroup\$
    – Optimizer
    Commented Oct 1, 2014 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
    Commented Oct 1, 2014 at 13:44
  • \$\begingroup\$ @edc65 But there is no way to convert 1 to 1.0 except for what I did. \$\endgroup\$
    – Optimizer
    Commented Oct 1, 2014 at 13:55
  • \$\begingroup\$ Nope. May I hint? \$\endgroup\$
    – edc65
    Commented Oct 1, 2014 at 13:57
5
\$\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\$
1
  • \$\begingroup\$ You can save one more char by defining m=min(x). \$\endgroup\$ Commented Oct 1, 2014 at 14:58
5
\$\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\$
4
  • 1
    \$\begingroup\$ Ah, that's a much better idea to get minimum and maximum. \$\endgroup\$ Commented Oct 1, 2014 at 13:18
  • \$\begingroup\$ This prints 0;0.5;1 instead of 0.0;0.5;1.0. \$\endgroup\$ Commented Oct 1, 2014 at 13:34
  • \$\begingroup\$ @Manu - Yes, trying to fix that. And almost all answers do this only. \$\endgroup\$
    – Optimizer
    Commented Oct 1, 2014 at 13:36
  • 2
    \$\begingroup\$ You don't need the fix. The Java interpreter represents the Double 0 as 0.0. \$\endgroup\$
    – Dennis
    Commented Oct 1, 2014 at 14:11
4
\$\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\$
4
\$\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\$
7
  • \$\begingroup\$ Should add the byte count... \$\endgroup\$
    – Optimizer
    Commented Oct 1, 2014 at 14:01
  • \$\begingroup\$ Which is 24 bytes only. \$\endgroup\$
    – Optimizer
    Commented Oct 1, 2014 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
    Commented Oct 1, 2014 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
    Commented Oct 1, 2014 at 14:29
  • 1
    \$\begingroup\$ Output has to be seperated by semicolons, not spaces. \$\endgroup\$ Commented Oct 2, 2014 at 13:31
4
\$\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\$
4
  • \$\begingroup\$ The output is not formatted correctly. \$\endgroup\$ Commented Oct 2, 2014 at 13:31
  • \$\begingroup\$ @Manu Sorry about that, I've fixed it. \$\endgroup\$
    – isaacg
    Commented Oct 2, 2014 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\$ Commented Oct 2, 2014 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
    Commented Oct 3, 2014 at 0:01
3
\$\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
  • 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\$ Commented Oct 1, 2014 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
    Commented Oct 3, 2014 at 12:59
3
\$\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\$
3
\$\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\$
2
  • \$\begingroup\$ This prints 0;0.5;1 instead of 0.0;0.5;1.0. \$\endgroup\$ Commented Oct 1, 2014 at 13:35
  • \$\begingroup\$ @Manu See Dennis's comment on Optimizer's answer. It works fine in the Java interpreter. \$\endgroup\$ Commented Oct 1, 2014 at 14:30
3
\$\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\$
3
\$\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\$
2
\$\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\$
2
\$\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\$
2
\$\begingroup\$

05AB1E, 13 bytes (Non-competing)

ZsWD1.S*+s/Z/

Try it online!

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

Q (31) IMPROPER OUTPUT FORMAT

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

input

1 2 3

output

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

Perl - 60

my@a=sort@ARGV;print map{($_-$a[0])/($a[-1]-$a[0])." "}@ARGV
\$\endgroup\$
1
\$\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\$
1
\$\begingroup\$

Vyxal, 5 bytes

g-:G/

Try it Online!

Outputs as arbitrary-precision rationals. Look Ma, no Unicode!

g-    # Subtract the minimum
  :G  # Make a copy and get the maximum of that
    / # Divide (list - min) by the maximum
\$\endgroup\$
2
  • \$\begingroup\$ Output has to be ;-separated :-( \$\endgroup\$
    – Adám
    Commented Jan 28, 2022 at 8:55
  • \$\begingroup\$ @Adám There’s a meta consensus somewhere, will find once back on computer \$\endgroup\$
    – emanresu A
    Commented Jan 28, 2022 at 9:47
1
\$\begingroup\$

Ly, 33 bytes

&n&sr>las<l/uy[';ofl/0L[!f!]pu,];

Try it online!

This is pretty direct translation of the requirements, but there are two things which add code I wanted to avoid... First, since 0 is a valid number in the list, the code has to explicitly add (and manipulate) a loop iterator on the stack. And second, since the rules imply that negative numbers should produce a 0 output, there's some extra code for that. If -0.0 is an acceptable output, the code could be a few bytes shorter. :)

&n&sr                             (1) read input and prep for processing
&n     - read STDIN onto the stack
  &s   - save a copy of the stack 
    r  - reverse the stack

     >las<                        (2) find/stash the largest input number
>       - switch to an empty stack
 l      - restore a copy of the input list
  a     - sort the stack
   s    - save the top of stack (largest number) to backup cell
    <   - switch back to the stack with the original input

          l/uy                    (3) print first entry, prep for loop
 l     - load the largest number from the backup cell     
  /    - divide to get the 0-1 scaled number
   u   - print as a number
    y  - push the stack size onto the stack  

              [';ofl/0L[!f!]pu,]; (4) process 2-N list entries
 [                ]   - loop through all the list entries
  ';o                 - print the ";" field separator
     f                - flip the iterator and next list entry on stack
      l               - load the largest number on the input
       /              - divide to get the 0-1 ratio
        0L            - compare result against 0, looking for "<0"
          [   ]p      - if/then structure, true if result <0
           !f!        - true: make top two stack entries "0"
                u     - print ratio (or "0" if result was <0)
                 ,    - decrement iterator
                   ;  - exit program to avoid print extraneous "0"

If -0.0 is an acceptable output, this 4 bytes shorter version could be used.

 &n&sr>las<l/uy[';ofl/0L!*u,];
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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