How to swap elements in a vector using an anonymous function in Octave?

15

Swapping two elements in a vector/matrix is very simple in Octave:

x='abcde';
x([4,1])=x([1,4])
x = 
   dbcae

Unfortunately, I have yet to find a way to do this inside an anonymous function. While the function below is syntactically correct, it only gives back the two elements that are swapped, not the entire x vector:

f=@(x)(x([4,1])=x([1,4]))
f(x)
ans = 
     ad

Is there a way to achieve the desired behavior using anonymous functions in a golfy way? Can several elements be swapped this way using an anonymous function?

I could create an indexing vector: f=@(x)x([4,2,3,1,5]), but creating such a vector dynamically will likely take a lot of bytes too.

Stewie Griffin

Posted 2018-04-23T08:29:29.200

Reputation: 43 471

Relevant meta post. – Stewie Griffin – 2018-04-23T08:31:54.617

Answers

21

Argument List

f=@(x,y=x([4 1])=x([1 4]))x;

Try it online!

rahnema1

Posted 2018-04-23T08:29:29.200

Reputation: 5 435

5Wait what? I never knew this was possible in Octave. This opens up so many new techniques.... – Sanchises – 2018-04-23T11:41:53.830

4What in the...? – Stewie Griffin – 2018-04-23T11:43:49.307

1Please post this in the Tips for Octave question! With this technique, you can basically do everything in the argument list, so you never need to choose between a 'full' and anonymous function again. I'm shocked. – Sanchises – 2018-04-23T11:47:20.943

3Amazing. BTW, you can remove the final ; for the purposes of byte count – Luis Mendo – 2018-04-23T11:56:30.543

Thanks to all .@Sanchises It seems that Octave is a shocking language. Be careful! It is added to tips. – rahnema1 – 2018-04-23T12:16:54.100

@LuisMendo, you can't actually. Not sure why though... Try it.

– Stewie Griffin – 2018-04-24T08:35:11.023

@StewieGriffin Just move the ; to the footer; see here

– Luis Mendo – 2018-04-24T08:36:33.640

That feels like cheating... I know it's pretty much the same as moving the f=... to the header. The difference is that the function would still work with ans('abc') if we remove f=..., but it's a syntax error without the ;. – Stewie Griffin – 2018-04-24T08:39:44.840

@StewieGriffin and LuisMendo I think it is a bug. It can be used in arrayfun,cellfun... – rahnema1 – 2018-04-24T18:35:14.180

11

Be eval

f=@(x)eval"x([4 1])=x([1 4])"

Try it online!


In Matlab the parentheses cannot be omitted:

f=@(x)eval('x([4 1])=x([1 4])')

Luis Mendo

Posted 2018-04-23T08:29:29.200

Reputation: 87 464

9Only on PPCG is eval the answer :-) – Stewie Griffin – 2018-04-23T09:27:49.733

Do you want to add this to the Octave tips question? for loop inside an anonymous function using eval saved a lot of bytes there, and can probably do it on many other challenges too,,,

– Stewie Griffin – 2018-04-23T12:52:17.477

Not sure if it is ever golfier, but I suppose you can do it even without anonymous function: s='x([1 4])=x([4 1])';eval(s) -- I suppose this is mostly interesting if you already made a function to do eval with minimal chars. – Dennis Jaheruddin – 2018-04-23T13:07:41.527

@StewieGriffin I think you should add it. Thanks for asking! – Luis Mendo – 2018-04-23T13:13:50.407

1Added :) – Stewie Griffin – 2018-04-23T13:26:06.793

2I think this answer is the only one thusfar that is both valid Octave and Matlab. – Batman – 2018-04-23T23:34:39.107

@StewieGriffin Thanks! Now it's even eviller – Luis Mendo – 2018-05-20T11:58:27.957

Are you sure about the parentheses in Matlab? I thought a single space and apostrophes was enough. I might be wrong though... – Stewie Griffin – 2018-05-21T06:31:50.660

I think it should work if you use commas as the delimiter at least..? – Stewie Griffin – 2018-05-21T09:11:29.727

8

Cell array

One option is to use a cell array, like this:

f=@(x){x([1,4])=x([4,1]);x}{2}

Try it online!

Stewie Griffin

Posted 2018-04-23T08:29:29.200

Reputation: 43 471

Nice one! Reminds me of this trick

– Luis Mendo – 2018-04-23T09:15:53.963