Swap Two Values in a List

Introduction:

Although we have a lot of challenges where swapping two items in a list is a subtask, like Single swaps of an array; Swap to Sort an Array; $$\n\$$ swaps into a nop; etc., we don't have the simple challenge of just swapping two items given a list and two indices.

Input:
A list with some positive integers $$\L\$$, and two indices $$\a\$$ and $$\b\$$.

Output:
The same list, with the two items at the given indices swapped.

Challenge rules:

• The input-list is guaranteed to contain at least two items.
• The input-list is guaranteed to only contain positive integers.
• The input-indices can be either 0-based or 1-based (please specify in your answer which of the two you've used).
• The input-indices are guaranteed to be valid indices based on the length of the input-list.
• The input-indices are distinct, so will never be the same index. (The values in the input-list won't necessarily be distinct.)
• You can assume $$\a (and you're allowed to take the inputs in reversed order if it helps).
• I/O is flexible. You're allowed to take the input as a list/array/stream, from STDIN, as a delimited string, etc. You're allowed to modify the input-list directly, or return a new one with the two items swapped.

General rules:

• This is , so the shortest answer in bytes wins.
Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
• Standard rules apply for your answer with default I/O rules, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters and return-type, full programs. Your call.
• Default Loopholes are forbidden.

Test cases

All test cases use 0-based indices.

Inputs: L=[1,2,3,4,5,6,7,8,9,10], a=3, b=7
Output:   [1,2,3,8,5,6,7,4,9,10]

Inputs: L=[ 3, 8, 1, 4,10,10,10,10], a=0, b=5
Output:   [10, 8, 1, 4,10, 3,10,10]

Inputs: L=[5,1,4,2,3], a=0, b=4
Output:   [3,1,4,2,5]

Inputs: L=[5,6], a=0, b=1
Output:   [6,5]

Inputs: L=[2,2,2], a=0, b=1
Output:   [2,2,2]
• For un-number-input-friendly languages can we take in chars? (Assumed no)
– null
Oct 15 '21 at 16:04
• @null What are you using for the indices if your language of choice doesn't include numbers? Oct 15 '21 at 16:24
• They probably meant that parsing a number from input is difficult, so they wanted to take input as the byte value of a character code. I think it is pretty common to allow this, but it technically restricts the values (not all of them will restrict to bytes, but there is usually some cap). Oct 16 '21 at 16:50
• Duplicate? Jan 13 at 7:11
• @alephalpha Oh.. Apparently it is. Jan 13 at 7:16

Java, 27 bytes

java.util.Collections::swap

Try it online!

• Huh, something actually has a builtin for this. A little on the long side, but I guess a lambda would be longer still.
– Neil
Oct 16 '21 at 19:50
• @Neil A lambda without using the builtin would be 31 bytes: (a,i,j)->a[i]^=a[j]^(a[j]=a[i]) Oct 17 '21 at 13:19
• Hmm, in JShell java.util.* is imported by default. I wonder if you can leverage that by calling your language Java+JShell? Oct 18 '21 at 22:24

Python 2, 32 bytes

def f(a,b,l):l[a],l[b]=l[b],l[a]

Attempt This Online!

Mutates the input in-place.

26 bytes with a NumPy array:

def f(l,a):l[a[::-1]]=l[a]

Try it online!

• Blazingly fast 2!
– null
Oct 15 '21 at 15:13
• You're allowed to modify the input-list, so 32 bytes is possible with this approach. Oct 15 '21 at 15:14
• @KevinCruijssen thanks! Oct 15 '21 at 15:17
• The solution isn't specific to python 2 btw — it works just as well in python 3 Oct 15 '21 at 18:26
• @AlexWaygood It's in Python 2 here because originally it had ;print l, which was shorter in 2 than 3 Oct 15 '21 at 19:37

Brain-Flak, 122 bytes

(([{}]{()<({}[()]<({}<>)<>>)>}{})<(({}({}))([{}]{})<{({}()<<>({}<>)>)}{}>)>())<>({}<<>{({}[()]<({}<>)<>>)}{}>){<>({}<>)}{}

Try it online!

Works with all integers, 138 bytes

(([{}]{()<({}[()]<({}<>)<>>)>}{})<(({}({}))([{}]{})<{({}()<<>({}<>)>)}{}>)>())<>({}<<>{({}[()]<({}<>)<>>)}{}>)<>([]){({}[()]<({}<>)<>>)}<>

Try it online!

The difference here is that while the first uses

{<>({}<>)}{}

To pull all the items from the off stack onto the on stack this one has to use

<>({}){({}[()]<({}<>)<>>)}<>

The first one pulls until it hits a zero and then stops, so this will fail to produce the correct result when there is a zero before the first swapped value. The second checks the height and pulls that many times, thus it will work for any list.

R, 31 bytes

Or R>=4.1, 24 bytes by replacing the word function with \.

function(L,A){L[A]=L[rev(A)];L}

Try it online!

Takes input as a vector and a vector of two 1-based indices.

Rust, 11 bytes

<[_]>::swap

Modify the input in-place.

Try it online!

• shortest non-golfing language so far, isn't it?
– Tom
Oct 18 '21 at 18:35

Factor, 21 bytes

[ [ exchange ] keep ]

Try it online!

It's almost a built-in, but exchange has stack effect ( m n seq -- ) so we need keep to actually keep the sequence around on the data stack. 0-indexed.

Jelly, 7 5 bytes

œPżịF

Try it online!

Takes indexes as 1 indexed and reversed (so [b, a]), the Footer on TIO does this for you.

How it works

œPżịF - Main link. Takes indices I on the left, array A on the right
œP    - Partition A at the indices in I, not keeping the borders
ị  - Retrieve the elements of A at the indices in I; [A[b], A[a]]
ż   - Zip together
F - Flatten

Lean, 211 205 bytes

Helper:

notation L:=list ℕ
structure R:=m::(A:L)(B:ℕ)(C:L)
def r:L->L->ℕ->R
|p(h::t)0:=R.m p h t
|p(h::t)(n+1):=r(p++[h])t n
|_[]_:=R.m[]0[]

Actual function:

λl a b,let f:=r[]l a,z:=r[]f.C(b-a-1)in f.A++z.B::z.A++f.B::z.C

Try it online!

There's got to be a way to make product types and define type aliases easily, but I couldn't find it.

Jelly, 7 bytes

,U$yJ}ị Try It Online! A totally different Jelly 7-byter, so I figured I'd post this too. This is 1-indexed. ,U$yJ}ị    Main link; take indices on the left
,U$Pair the indices with the reverse of itself ([[a, b], [b, a]]) y Apply this as a translation to J} The indices of the right list (J takes a list of length L and returns [1, 2, ..., L]) ị Index back into the original list APL (Dyalog Unicode), 5 bytes 1-indexed. Reverse the sublist at the indices given by the second input of the first input. ⌽@⎕⊢⎕ Try it online! Haskell, 56 bytes (?)=splitAt (x!y)z|(q,d:e)<-y?z,(a,b:c)<-x?q=a++d:c++b:e Try it online! splitAt breaks the list into two parts at the particular index. This is useful because unlike (!!) we can get all the parts first. To start we split at the second element, then the first. Splitting at the second first means we don't have to do extra arithmetic do calculate the offset which is required if we split at the first. We use a pattern match to then get the first element of various pieces. • Blazingly fast! – null Oct 15 '21 at 15:12 Julia 1.0, 20 bytes L*i=L[i]=L[i[[2,1]]] Try it online! 1-indexed expects L*[a,b] and mutates L JavaScript, 31 bytes l=>a=>b=>l[a]^=l[b]^(l[b]=l[a]) Only works for integers. Try it online! Thanks to Arnauld. JavaScript, 32 bytes l=>a=>b=>[l[a],l[b]]=[l[b],l[a]] Try it online! stacked, 5 bytes$exch

Try it online!

<<<$@ Attempt This Online! Takes the array on the command line, with the two indices in files called i and j. A bit of quote trickery to avoid escapes. Pip-xp, 8 bytes aRAba@Rb Takes input as two command-line arguments: the list, and a list containing the two indices (0-based). Like this: [1;2;3;4] [1;3]. Replit! Or, here's a 9-byte equivalent (simulating the -x flag) in Pip Classic: Try it online! Explanation The -x flag is for taking the arguments as lists rather than strings; the -p flag is for displaying the result as a list rather than concatenated together. a ; In the first argument RA ; replace the items at indices given by b ; the second argument a ; with the values in the first argument @ ; at indices Rb ; reverse(second argument) The straightforward version, which takes the indices as separate arguments, comes in at 9 bytes: a@b::a@ca :: ; Swap a@b ; the item in a at index b a@c ; with the item in a at index c a ; Output the new value of a C (clang), 34 bytes f(*a,i,j){a[i]^=a[j]^(a[j]=a[i]);} Try it online! Port of Unmitigated's C++ answer TI-Basic, 39 33 bytes Prompt L,A,B ʟL(A→X ʟL(B→ʟL(A X→ʟL(B ʟL -6 bytes thanks to MarcMush. Input indices are 1-based. Output is stored in Ans and is displayed. ErrLess, 6 bytes 0m:r.M A macro. Explanation 0 { Push a 0 to the stack to identify the macro } m { Start macro definition } : { (L a b) -> (L (a b)) } r { Rotate } . { Halt (Return) } M { End macro definition } You can test it with the following program: 0m :r. M { Test cases: } 1,2x3x4x5x6x7x8x9xax 3 7 0" # a? { Outputs "(1 2 3 8 5 6 7 4 9 10)" and a newline } 3,8x1x4xaxaxaxax 0 5 0" # a? { Outputs "(10 8 1 4 10 3 10 10)" and a newline } 5,1x4x2x3x 0 4 0" # a? { Outputs "(3 1 4 2 5)" and a newline } 5,6x 0 1 0" # a? { Outputs "(6 5)" and a newline } 2,2x2x 0 1 0" # a? { Outputs "(2 2 2)" and a newline } . Try it online! Python 2, 49 bytes lambda a,b,c:a[:b]+[a[c]]+a[b+1:c]+[a[b]]+a[c+1:] Try it online! PHP, 46 bytes fn(&$a,$i,$j)=>[$a[$i],$a[$j]]=[$a[$j],$a[$i]]

Try it online!

changes the array in place, 0 indexing

My first shot was with list, but PHP has array destructuring since 7.1, so it ends up like the JS answer with lots of dollars (money money money!)

Vyxal, 7 bytes

İṘZ(n÷Ȧ

Try it Online!

This could almost certainly be a bit smaller, but I got smol brain and can't think of a good way to swap values.

Explanation:

İ        # Get the values at the indexes
Ṙ       # Reverse the values
Z      # Zip the values with the new indexes
(n    # For each value/index pair:
÷   #  Split the value/index
Ȧ  #  Put the value at that index

Retina 0.8.2, 99 bytes

2\d+
$* 1*(,1*);$1,$& (?<=(?=.*;(?<-2>\d+,)*(\d+))(1)*,(?(4)$)(?<-4>1)*(,1*)?;(\d+,)*)\d+
$1 .*; Try it online! Link includes test cases. Takes input in the form a,b;L. Explanation: 2\d+$*

Convert the indices to unary.

1*(,1*);
$1,$&

Make a second copy of b so that we now have b,a,b;L.

(?<=(?=.*;(?<-2>\d+,)*(\d+))(1)*,(?(4)$)(?<-4>1)*(,1*)?;(\d+,)*)\d+$1

Match an integer in L, with index $#4 equalling either a or b (using a .NET balancing group), then match the other index in$#2, and match the integer at that index as the replacement for this integer (also using a .NET balancing group).

.*;

Delete a and b.

Red, 33 bytes

func[l a b][swap at l a at l b l]

Try it online!

1-indexed

Wolfram Language (Mathematica), 24 21 bytes

1-based indices, input is a list and a tuple of indices to reverse

Reverse~SubsetMap~##&

Try it online!

-3 bytes thanks to att.

• 21 bytes
– att
Oct 16 '21 at 4:03

Core Maude, 158 bytes

mod S is pr ARRAY{Nat,Nat0}*(sort Array{Nat,Nat0}to A). var I J X Y : Nat . op
s : A Nat Nat -> A . eq s(A:A,I,J)= insert(I,A:A[J],insert(J,A:A[I],A:A)). endm

Example Session

\||||||||||||||||||/
--- Welcome to Maude ---
/||||||||||||||||||\
Maude 3.1 built: Oct 12 2020 20:12:31
Sat Oct 16 22:01:13 2021
Maude> mod S is pr ARRAY{Nat,Nat0}*(sort Array{Nat,Nat0}to A). var I J X Y : Nat . op
> s : A Nat Nat -> A . eq s(A:A,I,J)= insert(I,A:A[J],insert(J,A:A[I],A:A)). endm
Maude> red s(0 |-> 1 ; 1 |-> 2 ; 2 |-> 3 ; 3 |-> 4 ; 4 |-> 5 ; 5 |-> 6 ; 6 |-> 7 ;
>       7 |-> 8 ; 8 |-> 9 ; 9 |-> 10, 3, 7) .
result A: 0 |-> 1 ; 1 |-> 2 ; 2 |-> 3 ; 3 |-> 8 ; 4 |-> 5 ; 5 |-> 6 ; 6 |-> 7 ;
7 |-> 4 ; 8 |-> 9 ; 9 |-> 10
Maude> red s(0 |-> 3 ; 1 |-> 8 ; 2 |-> 1 ; 3 |-> 4 ; 4 |-> 10 ; 5 |-> 10 ; 6 |-> 10 ;
>       7 |-> 10, 0, 5) .
result A: 0 |-> 10 ; 1 |-> 8 ; 2 |-> 1 ; 3 |-> 4 ; 4 |-> 10 ; 5 |-> 3 ; 6 |->
10 ; 7 |-> 10
Maude> red s(0 |-> 5 ; 1 |-> 1 ; 2 |-> 4 ; 3 |-> 2 ; 4 |-> 3, 0, 4) .
result A: 0 |-> 3 ; 1 |-> 1 ; 2 |-> 4 ; 3 |-> 2 ; 4 |-> 5
Maude> red s(0 |-> 5 ; 1 |-> 6, 0, 1) .
result A: 0 |-> 6 ; 1 |-> 5
Maude> red s(0 |-> 2 ; 1 |-> 2 ; 2 |-> 2, 0, 1) .
result A: 0 |-> 2 ; 1 |-> 2 ; 2 |-> 2

Ungolfed

mod S is
pr ARRAY{Nat,Nat0} * (sort Array{Nat,Nat0} to A).
var I J X Y : Nat .
op s : A Nat Nat -> A .
eq s(A:A, I, J) = insert(I, A:A[J], insert(J, A:A[I], A:A)) .
endm

The answer is obtained by reducing the function s with the list, given as a Maude array (e.g., 0 |-> 1 ; 1 |-> 2 for [1, 2]), and the two indices, zero-indexed.

Maude does have lists (e.g., 0 1 for the same list [1, 2]), but this is one case where it's actually shorter to use arrays (which are generally very verbose) because we don't need to use an array literal syntax in the code, and because we need indexing. The FAQ says it's allowed to accept input as either an array or a list.

Javascript 38 bytes

(l,a,b)=>(l[a]=[l[b],l[b]=l[a]])&&l

05AB1E, 4 bytes

è¹Rǝ

Since no one posted an 05AB1E answer yet and it's been a couple of days, I'm gonna post my prepared 4-byter.

First input is a pair of indices $$\[a,b]\$$, second input is the list $$\L\$$.

Explanation:

è    # Index the first (implicit) input into the second (implicit) input-list
¹   # Push the first input-indices again
R  # Reverse them
ǝ # Insert the values at those reversed indices into the (implicit) second input-list
# (after which the result is output implicitly)