Get the indices of an array after sorting

14

1

Your challenge today is to write a program or function which takes a list l and gives the positions in l at which each successive element of l sorted appears.

In other words, output the index of the smallest value, followed by the index of the second smallest value, etc.

You can assume that the input array will contain only positive integers, and will contain at least one element.

Test cases:

Input                  | Output (1-indexed)
[7, 4, 5]              | [2, 3, 1]
[1, 2, 3]              | [1, 2, 3]
[2, 6, 1, 9, 1, 2, 3]  | [3, 5, 1, 6, 7, 2, 4]
[4]                    | [1]

When two or more elements with the same value appear, their indices should appear next to each other from smallest to largest.

This is , fewest bytes wins!

Pavel

Posted 2017-07-30T04:49:11.143

Reputation: 8 585

16-1 for a trivial challenge that can be solved with built-ins in common golfing languages, and for accepting an answer in less than 24 hours. This was neither a fair challenge, nor an interesting one. – Cody Gray – 2017-07-30T11:44:06.353

3Well, I get why he accepted an answer within 24 hours, it's impossible to beat. – Zacharý – 2017-07-30T14:28:40.253

3@CodyGray I thought downvoting when I saw the 1-2 bytes answer, but actually, I don't think it's a bad challenge for more standard programming languages. Of course, it's not a hard challenge, but still, there is definitely some golfing possibilities. Of course, it's unpleasant to see 1-byte built-ins, but I don't think that it's fair to blame the challenge for that. – Dada – 2017-07-30T16:07:59.550

I'll just leave this here. Lots of good suggestions in there; this one is especially relevant.

– Cody Gray – 2017-07-30T16:12:30.790

1Using a 1 character builtin is hardly practice. Easy doesn't necessarily mean solvable using only builtins. – JAD – 2017-07-31T07:36:26.867

I mean, let's just suppose for the sake of argument that a 1-character answer using a built-in is a good, competitive answer and should be accepted. It is still not true that the answer is "unbeatable". It could certainly be tied, and then what would you do? Oh, look—and it already has been tied with an APL answer. Which goes back to it's just generally unsporting to accept an answer to a code-golf question the same day that you post the question. – Cody Gray – 2017-07-31T08:46:01.767

2The best solution in such cases is to forget about te accept feature, which isn't really relevant anyway here. – Mr. Xcoder – 2017-07-31T09:01:48.083

The test cases only have 1 digit numbers; my solution only works well on 1 digit numbers. Is there any problem? – sergiol – 2017-10-21T17:28:48.823

Answers

9

Jelly, 1 byte

Try it online!

Dennis

Posted 2017-07-30T04:49:11.143

Reputation: 196 637

Heh that was too obvious... – Erik the Outgolfer – 2017-07-30T08:25:29.750

2APL deserved this one, +1 though for your speed. – Zacharý – 2017-07-30T14:25:34.913

@Zacharý I'm sure Jelly picked this one up from J, which in turn inherited it from APL. – Adám – 2017-08-17T12:51:45.473

11

Dyalog APL, 1 byte

Dyalog APL has a built in operator function (thank you Zacharý for clearing this up) to do this.

Example

⍋11 2 4 15
    2 3 1 4  
{⍵[⍋⍵]}11 4 2 15
    2 4 11 15

Here I'm indexing into the list by the sorted indices to return the list in ascending order.

James Heslip

Posted 2017-07-30T04:49:11.143

Reputation: 139

Oh, just to alert you to some confusing terminology, in APL, builtins like are considered functions, while things like ¨⍨⍣.∘/\⌿⍀⌸⍤ are operators. – Zacharý – 2017-07-30T15:45:12.523

9

Haskell, 43 42 bytes

1-indexed:

import Data.List
map snd.sort.(`zip`[1..])

Try it online!

-1 byte thanks to @ØrjanJohansen!

ბიმო

Posted 2017-07-30T04:49:11.143

Reputation: 15 345

2Pointfree version saves one byte: map snd.sort.(`zip`[1..]). – Ørjan Johansen – 2017-07-30T05:56:41.497

9

Python 2, 56 bytes

This solution is 0-indexed. This abuses the fact that sorted() creates a copy of the original list.

l=input()
for k in sorted(l):a=l.index(k);print a;l[a]=0

Try it online!

Mr. Xcoder

Posted 2017-07-30T04:49:11.143

Reputation: 39 774

Why did you ungolf this? – Erik the Outgolfer – 2017-07-30T09:11:03.523

@EriktheOutgolfer Fixed, Rollback. – Mr. Xcoder – 2017-07-30T09:13:10.337

9

Javascript (ES6), 39 bytes

-2 bytes thanks to @powelles

This only works in browsers where Array.prototype.sort is stable.

a=>[...a.keys()].sort((b,c)=>a[b]-a[c])

1-indexed version (47 bytes):

a=>a.map((_,i)=>i+1).sort((b,c)=>a[b-1]-a[c-1])

Example code snippet:

f=
a=>[...a.keys()].sort((b,c)=>a[b]-a[c])
console.log("7,4,5 => "+f([7,4,5]))
console.log("1,2,3 => "+f([1,2,3]))
console.log("2,6,1,9,1,2,3 => "+f([2,6,1,9,1,2,3]))
console.log("4 -> "+f([4]))

Herman L

Posted 2017-07-30T04:49:11.143

Reputation: 3 611

[...a.keys()] instead of a.map((_,i)=>i) will save you a couple of bytes. – powelles – 2017-07-30T18:32:01.853

7

Python 2, 48 bytes

lambda x:sorted(range(len(x)),key=x.__getitem__)

Try it online!

Erik the Outgolfer

Posted 2017-07-30T04:49:11.143

Reputation: 38 134

Nice, I got outgolfed >_<. I switched my answer to Python 3 such that I don't feel that bad – Mr. Xcoder – 2017-07-30T09:06:37.370

4@Mr.Xcoder Well, that's his job... – Neil – 2017-07-30T09:14:03.233

@Mr.Xcoder Come on, you shouldn't feel bad for that! You made a full program, I made a function, and my approach is a bit different. – Erik the Outgolfer – 2017-07-30T09:14:19.223

I don't feel bad, I knew this will appear (I personally hate the __<blahblah>__ syntax). I will do some Jelly, I don't want to lose my training :) – Mr. Xcoder – 2017-07-30T09:16:09.120

1@Mr.Xcoder Codegolf doesn't mean pretty syntax and formatting. ;) – Erik the Outgolfer – 2017-07-30T09:17:02.760

@EriktheOutgolfer Those aren't news for me :) (I've been around for a while, I learnt that long ago) – Mr. Xcoder – 2017-07-30T09:17:34.480

5

Perl 6,  27  21 bytes

*.pairs.sort(*.value)».key

Test it

->\x{sort {x[$_]},^x}

Test it

Inspired by a Python answer

Expanded:

->    # pointy block lambda
  \x  # declare sigilless parameter
{
  sort
    { x[$_] },  # sort by the value in 「x」 at the given position
    ^x          # Range up-to the number of elements in 「x」
}

Brad Gilbert b2gills

Posted 2017-07-30T04:49:11.143

Reputation: 12 713

5

Bash + coreutils, 20

nl|sort -nk2|cut -f1

Try it online.

Digital Trauma

Posted 2017-07-30T04:49:11.143

Reputation: 64 644

4

R, 5 bytes

There is a builtin function for this.

order

djhurio

Posted 2017-07-30T04:49:11.143

Reputation: 1 113

3Standard rules is to provide a program of function. order is already a function, so you don't have to handle input using scan(). This would be 5 bytes. – JAD – 2017-07-31T07:34:08.207

rank() would save a byte – gstats – 2017-08-01T15:10:12.753

1I am sure there was a rank answer by @JarkoDubbeldam, but I do not see it anymore. – djhurio – 2017-08-01T16:58:07.560

1Correct, it does not follow the spec so I deleted it. – JAD – 2017-08-01T17:02:53.850

4

Swift 4, 82 bytes

func f(l:[Int]){var l=l;for k in l.sorted(){let a=l.index(of:k)!;print(a);l[a]=0}}

Test Suite.

Explanation

In Swift, l.sorted() creates a sorted copy of the original Array. We loop through the sorted elements in the list and after printing each item's index in the original Array with let a=l.index(of:k)!;print(a), and then, in order to keep the correct indexes in the Array, we assign l[a] to 0, because it does not affect our normal output.


Take note that this is 0-indexed, since it is a port of my Python solution. If you want it to be 1-indexed, replace print(a) with print(a+1) or Try it online!.

Mr. Xcoder

Posted 2017-07-30T04:49:11.143

Reputation: 39 774

4

Ruby, 40 bytes

->a{a.zip([*1..a.size]).sort.map &:last}

Try it online!

G B

Posted 2017-07-30T04:49:11.143

Reputation: 11 099

3

MATL, 2 bytes

&S

Try it online!

Input and output are implicit.

Sanchises

Posted 2017-07-30T04:49:11.143

Reputation: 8 530

3

Octave, 17 bytes

@(i)[~,y]=sort(i)

Try it online!

Octave is like MATLAB but with inline assignment, making things possible that gives the folks at Mathworks HQ headaches. It doesn't matter what you call y, but you can't do without that dummy variable, as far as I know.

Sanchises

Posted 2017-07-30T04:49:11.143

Reputation: 8 530

3

MY, 3 bytes

MY also has a builtin for this!

⎕⍋↵

Try it online!

How?

Evaluated input, grade up, then output with a newline.

Indexed however you set the index, with /0x48. (Can even be some weird integer like -1 or 2, the default is 1).

Zacharý

Posted 2017-07-30T04:49:11.143

Reputation: 5 710

3

J, 2 bytes

/:

Try it online!

Zero-based indexing.

Tikkanz

Posted 2017-07-30T04:49:11.143

Reputation: 191

Was going to post this... – Cyoce – 2017-08-01T04:19:52.537

3

Java 8, 128 + 19 = 147 bytes

Based on Mr. Xcoder's solution. 0-based. Lambda takes input as an Integer[] and returns Integer[]. Byte count includes lambda expression and required import.

import java.util.*;

l->{Integer o[]=l.clone(),s[]=l.clone(),i=0;for(Arrays.sort(s);i<l.length;)l[o[i]=Arrays.asList(l).indexOf(s[i++])]=0;return o;}

Try It Online

Ungolfed lambda

l -> {
    Integer
        o[] = l.clone(),
        s[] = l.clone(),
        i = 0
    ;
    for (Arrays.sort(s); i < l.length; )
        l[o[i] = Arrays.asList(l).indexOf(s[i++])] = 0;
    return o;
}

Notes

I use Integer[] instead of int[] to allow use of Arrays.asList, which has no primitive versions. Integer is preferred to Long because values are used as array indices and would require casting.

This ended up being shorter than my best procedural-style List solution because of the cost of class and method names.

This also beat a solution I tried that streamed the inputs, mapped to (value, index) pairs, sorted on values, and mapped to indices, mostly because of the baggage needed to collect the stream.

Acknowledgments

  • -5 bytes thanks to Nevay

Jakob

Posted 2017-07-30T04:49:11.143

Reputation: 2 428

1You don't need j: l->{Integer o[]=l.clone(),s[]=l.clone(),i=0;for(Arrays.sort(s);i<l.length;l[o[i]=Arrays.asList(l).indexOf(s[i++])]=0);return o;} (19+128 bytes). – Nevay – 2017-08-16T18:23:33.943

2

Common Lisp, 82 bytes

(lambda(l)(loop as i in(sort(copy-seq l)'<)do(setf(elt l(print(position i l)))0)))

Try it online!

Renzo

Posted 2017-07-30T04:49:11.143

Reputation: 2 260

2

MATLAB / Octave, 29 bytes

[~,y]=sort(input(''));disp(y)

Try it online!

Luis Mendo

Posted 2017-07-30T04:49:11.143

Reputation: 87 464

While your answer is perfect MATLAB, you can actually do inline assignment in anonymous functions in Octave.

– Sanchises – 2017-07-30T14:18:53.753

Good one! I knew about in-line assignment, but I didn't know you could output directly like that – Luis Mendo – 2017-07-30T15:06:50.137

1To be honest, me neither. I started with something like @(X)([~,y]=sort(X)), and while I was looking of a way to get y from this, I realized y was actually the return value from the assignment, and closer inspection revealed that brackets weren't even needed. MATLAB likes everything explicit; Octave is happy when it's unambiguous. – Sanchises – 2017-07-30T15:40:02.310

2

Clojure, 39 bytes

#(map key(sort-by val(zipmap(range)%)))

NikoNyrh

Posted 2017-07-30T04:49:11.143

Reputation: 2 361

Translated to Perl 6 {map *.key,(sort *.value,(0..* Z=> @_))} – Brad Gilbert b2gills – 2017-07-30T13:51:57.263

2

CJam, 12 bytes

{ee{1=}$0f=}

Try it online!

Erik the Outgolfer

Posted 2017-07-30T04:49:11.143

Reputation: 38 134

2

JavaScript (ES6), 69 bytes

0-indexed. Works for lists containing up to 65,536 elements.

a=>[...a=a.map((n,i)=>n<<16|i)].sort((a,b)=>a-b).map(n=>a.indexOf(n))

Test cases

let f =

a=>[...a=a.map((n,i)=>n<<16|i)].sort((a,b)=>a-b).map(n=>a.indexOf(n))

console.log(JSON.stringify(f([7, 4, 5])))
console.log(JSON.stringify(f([1, 2, 3])))
console.log(JSON.stringify(f([2, 6, 1, 9, 1, 2, 3])))
console.log(JSON.stringify(f([4])))

Arnauld

Posted 2017-07-30T04:49:11.143

Reputation: 111 334

Can you change n=>a.indexOf(n) to just a.indexOf? – Zacharý – 2017-07-30T15:33:26.557

@Zacharý Unfortunately not. A method of an instanced object cannot be used as a callback. – Arnauld – 2017-07-30T15:36:03.910

@Zacharý Even worse is that Array#map passes 3 arguments to the callback function, and Array#indexOf expects 2, so it will give undesirable results. – kamoroso94 – 2017-07-31T04:56:48.923

2

Python 3 with Numpy, 38 26 bytes

12 bytes saved thanks to Jo King (no need to give the function a name)

import numpy
numpy.argsort

Output is 0-based.

Try it online!

Luis Mendo

Posted 2017-07-30T04:49:11.143

Reputation: 87 464

The function could just be numpy.argsort without the lambda part – Jo King – 2018-11-06T05:21:06.897

@JoKing Thanks for the suggestion. I wrote it that way because with just numpy.argsort;import numpy I get an error (numpy has not been imported yet), and with import numpy;numpy.argsort I need to move f= to the code part. Do you know that the standard procedure is in these cases? Move the f= and not count it? – Luis Mendo – 2018-11-06T10:36:03.707

Yeah, I guess. Maybe just redefine f=numpy.argsort in the footer – Jo King – 2018-11-06T10:42:57.023

@JoKing Good idea. Done. Thanks! – Luis Mendo – 2018-11-06T11:26:01.733

2

Python 3, 52 bytes

0-indexed. Based on Bruce Forte's Haskell answer here and G B's Ruby answer here.

lambda l:list(zip(*sorted(zip(l,range(len(l))))))[1]

Try it online!

Sherlock9

Posted 2017-07-30T04:49:11.143

Reputation: 11 664

2

Husk, 10 7 bytes

This is a direct port of my Haskell answer, also 1-indexed:

m→O`z,N

Try it online!

Ungolfed/Explained

Code        Description               Example
         -- implicit input            [2,6,1]
      N  -- natural numbers           [1,2,3,..]
   `z,   -- zip, but keep input left  [(2,1),(6,2),(1,3)]
  O      -- sort                      [(1,3),(2,1),(6,2)]
m→       -- keep only indices         [3,1,2]

ბიმო

Posted 2017-07-30T04:49:11.143

Reputation: 15 345

2

Java (OpenJDK 8), 72 bytes

l->l.stream().sorted().map(i->{int j=l.indexOf(i);l.set(j,0);return j;})

Try it online!

Takes a List<Integer>, returns a Stream<Integer> containing the results.

We get a Stream based off the initial list, sort it, then map each number to it's index in the list. In order to accommodate duplicate elements, we set the original element in the list to 0.

Xanderhall

Posted 2017-07-30T04:49:11.143

Reputation: 1 236

2

SmileBASIC, 67 bytes

DEF I(A)DIM B[0]FOR I=1TO LEN(A)PUSH B,I
NEXT
SORT A,B
RETURN B
END

Very simple, all it does is generate a list of numbers from 1 to (length of array) and sort this by the same order as the input.

12Me21

Posted 2017-07-30T04:49:11.143

Reputation: 6 110

1

05AB1E, 4 bytes

ā<Σè

Try it online!

Erik the Outgolfer

Posted 2017-07-30T04:49:11.143

Reputation: 38 134

1

Pari/GP, 16 bytes

a->vecsort(a,,1)

Try it online!

alephalpha

Posted 2017-07-30T04:49:11.143

Reputation: 23 988

1

PHP, 54 bytes

<?php function i($a){asort($a);return array_keys($a);}

Try it online!

This is zero-indexed. Simply sorts the array and returns the keys.

WebSmithery

Posted 2017-07-30T04:49:11.143

Reputation: 221

1The <?php tag is unnecessary for a function. 48 bytes. – Titus – 2017-08-21T17:33:38.553

1

Tcl, 21 bytes

(0-indexed)

puts [lsort -indi $L]

Try it online!

sergiol

Posted 2017-07-30T04:49:11.143

Reputation: 3 055

The test cases only have 1 digit numbers; my solution only works well on 1 digit numbers. – sergiol – 2017-10-21T17:29:01.843

1

Ruby, 34 bytes

->a{(0...a.size).sort_by{|i|a[i]}}

0-indexed, 1-indexing requires one more net byte:

->a{(1..a.size).sort_by{|i|a[i-1]}}

Also, a slightly golfed version of G B's answer is 37 bytes:

->a{a.each_with_index.sort.map &:pop}

histocrat

Posted 2017-07-30T04:49:11.143

Reputation: 20 600

1

Kotlin,  44  34 bytes

not today, crossed out 44

{l->(1..l.size).sortedBy{l[it-1]}}

Try it online!

1-indexed because that's what the examples give. A 0-indexed version looks like this for 30 bytes:

{l->l.indices.sortedBy{l[it]}}

snail_

Posted 2017-07-30T04:49:11.143

Reputation: 1 982

1

Japt, 6 5 bytes

0-indexed

ð ñ@v

Try it


Alternative, 6 bytes

í ñÎmÌ

Try it

Shaggy

Posted 2017-07-30T04:49:11.143

Reputation: 24 623