6
$\begingroup$

Given a list such as

{12,9,3,42,30,10,11,1,2}

I would like to place only the multiples of 3 in the natural order without changing the order of the other integers, so I would like to get as a result

{42,30,12,10,11,9,3,1,2}

What is a (simple) way to do this?

Thank you! This is my first post and I tried to read related questions before posting. I am just learning my way around in Mathematica. I am trying to write a little program. Here I will try to clarify the ordering I want to achieve:the integers to the right of 3n are smaller than 3n and those to the left of 3n are larger than 3n. Do not change the ordering of integers that are not multiple of 3. Thank you again. I am reading all your answers and testing them so I understand how they work.

$\endgroup$
7
  • 1
    $\begingroup$ Hi StefanoK, welcome to Mma.SE. Start by taking the tour now and learning about asking and what's on-topic. Always edit if improvable, show due diligence, give brief context, include minimal working example of code and data in formatted form. By doing all this you help us to help you and likely you will inspire great answers. The site depends on participation, as you receive give back: vote and answer questions, keep the site useful, be kind, correct mistakes and share what you have learned. $\endgroup$
    – rhermans
    Jul 5, 2019 at 16:17
  • $\begingroup$ Please notice that accepting is one of the things to do after your question is answered, but we recommend that users should test answers before voting and wait 24 hours before accepting the best one. That allows people in all timezones to answer your question and an opportunity for other users to point alternatives, caveats or limitations of the available answers. $\endgroup$
    – rhermans
    Jul 5, 2019 at 16:42
  • 2
    $\begingroup$ Why do none of the present answers have the desired order?? (But they've all been upvoted.) -- One reason is that the ordering is not clearly specified. To get the desired result, one has to move each multiple of three as far to the left as possible with the condition that nothing greater than the multiple appears to the right. StefanoK, is that the correct spec? $\endgroup$
    – Michael E2
    Jul 7, 2019 at 0:45
  • 1
    $\begingroup$ Michael, an exception to "none of the present answers": f,f1 and f2 do give the desired order :) $\endgroup$
    – kglr
    Jul 7, 2019 at 2:08
  • 2
    $\begingroup$ @kglr I concentrated the output lists in your answer and they didn't match the OP's. Inspecting what you did, I see that the output lists are not for the OP's problem, which is rather confusing -- even more so because the multiples of three stayed in front and were sorted, just as in the other answers. I didn't notice that the 2 moved. Anyway, I see now it works and I was wrong for not checking the code. $\endgroup$
    – Michael E2
    Jul 7, 2019 at 3:41

3 Answers 3

6
$\begingroup$

Answer

Depending what you mean one of these has your answer.

This matches your example, requiring any of the two numbers to be Divisible by 3 in order to sort them.

Sort[
 {12, 9, 3, 42, 30, 10, 11, 1, 2}
 , If[
   Divisible[#1, 3] || Divisible[#2, 3]
   , #2 < #1
   , 0
   ] &
 ]
(* {42, 30, 12, 10, 11, 9, 3, 1, 2} *)

This matches better your original text description, requires both numbers to be Divisible to sort them. Otherwise they remain in place.

Sort[
 {12, 9, 3, 42, 30, 10, 11, 1, 2}
 , If[
   Divisible[#1, 3] && Divisible[#2, 3]
   , #2 < #1
   , 0
   ] &
 ]
(* {42, 30, 12, 9, 3, 10, 11, 1, 2} *)

Explanation

Sort allows a second argument to define the ordering function.

Mathematica graphics

The ordering function takes two arguments #1 and #2 to be compared and normally should return either True or False. Sort also accepts it to return 0 when two elements should be treated as identical.

Mathematica graphics

So the strategy is to ask first If the numbers should be sorted using Divisible, and then return True or False if they should be sorted, or 0 otherwise. Number that are not sorted remain in their place.

$\endgroup$
3
  • $\begingroup$ Thank you. I apologize if my post was not clear. I added a few lines now. I hope it helps. Your answer, as it stands, does not give the ordering I wanted. $\endgroup$
    – StefanoK
    Jul 7, 2019 at 9:36
  • $\begingroup$ @StefanoK does the edited answer satisfy you need now? $\endgroup$
    – rhermans
    Jul 8, 2019 at 9:18
  • $\begingroup$ I am still testing and understanding it, but it seems to work. Thank you for adding the explanation as well. $\endgroup$
    – StefanoK
    Jul 8, 2019 at 9:25
5
$\begingroup$

Update: A more convenient function that takes a criterion and a sort-order as arguments:

ClearAll[f]
f[criterion_, sortorder_: Greater] := sortorder[##] Boole[AnyTrue[{##}, criterion]] &

Examples:

lst = {12, 9, 3, 42, 30, 10, 11, 1, 2};
sorted = {42, 30, 12, 10, 11, 9, 3, 1, 2}; (* desired output from OP *)   
Sort[lst, f[Divisible[#, 3] &]] == sorted

True

Sort in increasing order with the same criterion:

Sort[lst, f[Divisible[#, 3]&, Less]]

{3, 9, 10, 11, 1, 2, 12, 30, 42}

Use Divisible[#, 2]& as the criterion to specify the sublist that should be kept in its original order (those elements of lst that does not satisfy the criterion):

Sort[lst, f[Divisible[#, 2]&]]

{42, 30, 12, 9, 3, 11, 10, 2, 1}

Original answer:

lst = {12, 9, 3, 42, 30, 10, 11, 1, 2};
sorted = {42, 30, 12, 10, 11, 9, 3, 1, 2}; (* desired output from OP *)

ClearAll[f1]
f1[x_] := Boole[Or @@ Divisible[{##}, x]]Greater[##] &;

Sort[lst, f1 @ 3] == sorted

True

Sort[lst, f1 @ 2]

{42, 30, 12, 9, 3, 11, 10, 2, 1}

$\endgroup$
2
$\begingroup$

This would be how I would think of it

Extract multiples of 3

Sort into decreasing order

Extract non-multiples of 3

Join those two results together

and translate that into Mathematica

v={12,9,3,42,30,10,11,1,2};
mult3[x_]:=Mod[x,3]==0;
notmult3[x_]:=Mod[x,3]!=0;
Join[
  Sort[Select[v,mult3],Greater],
  Select[v,notmult3]
]

giving

{42, 30, 12, 9, 3, 10, 11, 1, 2}
$\endgroup$

Your Answer

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

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