9

If I have like

{a,b}

and I want to get

 {{a+1,b},{a-1,b},{a,b+1},{a,b-1}}    

We don't care about the ordering of the list.Such as the {{a-1,b},{a+1,b},{a,b+1},{a,b-1}} also is a valid list.

This is current method

MapAt[Reverse, 
 Transpose[{Distribute[Unevaluated@Plus[{1, -1}, {a, b}], List], 
   Riffle[{b, b}, {a, a}]}], {{2}, {4}}]

{{1+a,b},{a,1+b},{-1+a,b},{a,-1+b}}

Or this

Catenate@({Tuples[{Plus[#, {1, -1}], {#2}}], 
     Tuples[{{#}, Plus[#2, {1, -1}]}]} & @@ {a, b})

{{1+a,b},{-1+a,b},{a,1+b},{a,-1+b}}

Very ugly code.Are there more beautiful solution can do this?

yode
  • 26,686
  • 4
  • 62
  • 167

5 Answers5

14

The following approach will be very fast for large lists since it utilizes vectorization:

Table[{a, b}, 4] + Join[#, -#] &[IdentityMatrix[2]]
RunnyKine
  • 33,088
  • 3
  • 109
  • 176
6

Just for fun:

Join @@ (# + {a, b} & /@ {#, -#} & /@ {{1, 0}, {0, 1}})
ubpdqn
  • 60,617
  • 3
  • 59
  • 148
4

A double Transpose might be considered "beautiful", and it certainly can be very fast too.

Transpose[Transpose[{{-1, 0}, {1, 0}, {0, -1}, {0, 1}}] + {a, b}]
KennyColnago
  • 15,209
  • 26
  • 62
3

Not as fast as some of the other methods, but a TranslationTransform approach is also possible:

TranslationTransform[{a,b}][{{-1, 0}, {1, 0}, {0, -1}, {0, 1}}]

{{-1 + a, b}, {1 + a, b}, {a, -1 + b}, {a, 1 + b}}

Carl Woll
  • 130,679
  • 6
  • 243
  • 355
2
  list = {a, b};     
  Partition[Flatten@Table[ReplacePart[
          list, i -> list[[i]] + #] & /@ {1, -1}, {i, 1, 2}], 2]

  (*{{1 + a, b}, {-1 + a, b}, {a, 1 + b}, {a, -1 + b}}*)
Hubble07
  • 3,614
  • 13
  • 23