21
\$\begingroup\$

Given a ragged list, e.g.

[[4, 7], [5, 3, [], [6, [2]]]]

Your challenge is to sort only the numbers in it. For example, with the above, the result would be

[[2, 3], [4, 5, [], [6, [7]]]]

The shape of the output should remain the same, only the numeric contents should change.

This is , shortest code wins!

All numbers will be unique positive integers. You may do input / output with strings.

Testcases

[2, [3, [1, []]]] -> [1, [2, [3, []]]]
[6, 5, [[9]], 7] -> [5, 6, [[7]], 9]
[12, [43, 51], [[23, 4], 9, [22, []]]] -> [4, [9, 12], [[22, 23], 43, [51, []]]]
[9, 4, 2] -> [2, 4, 9]
\$\endgroup\$
2
  • \$\begingroup\$ May we take input and leave output as a string or should it be a native list type? \$\endgroup\$
    – chunes
    Mar 14, 2022 at 8:45
  • \$\begingroup\$ @chunes Allowing I/O as a string seems reasonable. \$\endgroup\$
    – emanresu A
    Mar 14, 2022 at 8:46

14 Answers 14

13
\$\begingroup\$

Jelly, 3 bytes

FṢṁ

Try it online!

How it works

FṢṁ - Main link. Takes a ragged list R on the left
F   - Flatten R
 Ṣ  - Sort the flattened R
  ṁ - Mold the sorted flattened R into the same shape as R
\$\endgroup\$
4
  • \$\begingroup\$ 10 upvotes for this…? \$\endgroup\$
    – Lynn
    Mar 15, 2022 at 12:37
  • \$\begingroup\$ @Lynn FGITW effect, I'm guessing. Plus the answer was posted just before the question hit HNQ :/ \$\endgroup\$ Mar 15, 2022 at 17:15
  • \$\begingroup\$ @Lynn Different people value different aspects of answers. Sure Jelly makes it easy for this particular task (due to its built-in mold), but it's still a 3-bytes answer to a Code Golf question, so I personally think it deserves recognition -- if only to put Jelly in a prominent place. \$\endgroup\$ Mar 16, 2022 at 15:03
  • \$\begingroup\$ Any language with a "reshape" function (including R) makes the challenge kind of trivial \$\endgroup\$
    – qwr
    Mar 17, 2022 at 3:46
10
\$\begingroup\$

Ruby, 51 47 bytes

->l{eval"#{l}".gsub(/\d+/,'%d')%l.flatten.sort}

Try it online!

-4 bytes thanks to Sisyphus

\$\endgroup\$
2
  • 1
    \$\begingroup\$ This is really clever. \$\endgroup\$
    – Jonah
    Mar 14, 2022 at 16:48
  • \$\begingroup\$ 47 bytes: Try it online! \$\endgroup\$
    – Sisyphus
    Mar 15, 2022 at 22:17
8
\$\begingroup\$

R, 29 bytes

\(l)relist(sort(unlist(l)),l)

Attempt This Online!

\$\endgroup\$
4
  • \$\begingroup\$ I think you can go even shorter using rapply! \$\endgroup\$
    – JDL
    Mar 16, 2022 at 9:38
  • \$\begingroup\$ @JDL I'm curious what do you have in mind, as I'm not very experienced with rapply? \$\endgroup\$
    – pajonk
    Mar 16, 2022 at 14:38
  • \$\begingroup\$ \(L)rapply(L,sort,,,"l") --- actuallly rereading the question, I misunderstood it the first time so this doesn't quite do what is asked. I got so excited thinking finally rapply would have a use in code golf, "when you have a hammer, everything looks like a nail" \$\endgroup\$
    – JDL
    Mar 16, 2022 at 16:42
  • \$\begingroup\$ @JDL Right, not exactly what OP was looking for. Seems like we need to keep searching for a use of this function in code golf... \$\endgroup\$
    – pajonk
    Mar 16, 2022 at 17:35
6
\$\begingroup\$

Wolfram Language (Mathematica), 34 bytes

0#/.(i=0):>Sort[Flatten@#][[++i]]&

Try it online!

Also works if input numbers are not unique.

0#                                  numbers become 0
  /.   0 :>                         replace 0s (in order) with:
    (i= )  Sort[Flatten@#][[++i]]     the corresponding sorted value
\$\endgroup\$
6
\$\begingroup\$

Wolfram Language (Mathematica), 32 bytes

-2 bytes thanks to @att.

#/.Thread[#->Sort@#&@Flatten@#]&

Try it online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ 33 bytes \$\endgroup\$
    – att
    Mar 14, 2022 at 7:32
  • 1
    \$\begingroup\$ 32 bytes \$\endgroup\$
    – att
    Mar 17, 2022 at 17:10
5
\$\begingroup\$

Retina, 5 bytes

N`\d+

Try it online.

Explanation:

Sorts all numbers of 1 or more digits in the input in numerical order, and leaves every other character unchanged (including their positions).

\$\endgroup\$
4
\$\begingroup\$

JavaScript (Node.js), 62 bytes

n=>n.replace(r=/\d+/g,_=>n.match(r).sort((a,b)=>a-b)[i++],i=0)

Try it online!

Probably defeats the purpose of the challenge, but it is valid. Takes in a stringified list and outputs a stringified list. Replaces the i-th number (via string replacement) with the i-th element of the list of sorted numbers.

\$\endgroup\$
4
\$\begingroup\$

05AB1E, 19 bytes

"DdiI˜{¾è¼ë®δ.V"©.V

Unfortunately, a simple flatten and replace/transliterate doesn't work on nested lists apparently. So instead, the default recursive approach I've used in multiple other challenges have been used.

Try it online or verify all test cases.

Explanation:

"..."     # Create the recursive string explained below
     ©    # Store it in variable `®` (without popping)
      .V  # Evaluate and execute it as 05AB1E code
          # (after which the result is output implicitly)

D         # Duplicate the current item
          # (which will be the implicit input-list in the first iteration) 
 di       # If it's a (non-negative) integer:
   I      #  Push the input-list
    ˜     #  Flatten it
     {    #  Sort it
      ¾è  #  Get the `¾`'th value of this sorted list
        ¼ #  Then increase `¾` by 1
  ë       # Else (it's a list instead):
    δ     #  Map over each inner list:
   ® .V   #   Do a recursive call for each
\$\endgroup\$
4
\$\begingroup\$

Python 3.8 (pre-release), 89 bytes

def f(L):a=re.split('(\d+)',L);a[1::2]=sorted(a[1::2],key=int);return''.join(a)
import re

Try it online!

I/O are strings.

How

This simply ignores the nesting by picking out groups of digits sorting them and putting them back into the gaps.

\$\endgroup\$
3
\$\begingroup\$

Factor + sorting.human, 93 bytes

[ find-numbers [ string? ] partition natural-sort [ present ] map 2array round-robin ""join ]

Try it online!

Explanation

                       ! "[6,5,[[9]],7]"
find-numbers           ! { "[" 6 "," 5 ",[[" 9 "]]," 7 "]" }
[ string? ] partition  ! { "[" "," ",[[" "]]," "]" } { 6 5 9 7 }
natural-sort           ! { "[" "," ",[[" "]]," "]" } { 5 6 7 9 }
[ present ] map        ! { "[" "," ",[[" "]]," "]" } { "5" "6" "7" "9" }
2array                 ! { { "[" "," ",[[" "]]," "]" } { "5" "6" "7" "9" } }
round-robin            ! { "[" "5" "," "6" ",[[" "7" "]]," "9" "]" }
""join                 ! "[5,6,[[7]],9]"

Here's a slightly longer version that works on native sequences:

[ [ flatten natural-sort ] keep 0 -rot [ dup real? [ drop 2dup nth [ 1 + ] 2dip ] when ] deep-map ]
\$\endgroup\$
3
\$\begingroup\$

APL(Dyalog Unicode), 19 bytes SBCS

∊{a⊣(∊a)←⍺[⍋∊a←⍵]}⊢

Try it on APLgolf!

A tacit function which takes a ragged array.

Explanation

∊{a⊣(∊a)←⍺[⍋∊a←⍵]}⊢ Pass in:
                  ⊢ The input as is on the right
∊                   The flattened input on the left.
 {a⊣(∊a)←⍺[⍋∊a←⍵]}  and do the following:
            a←⍵     assign right arg to 'a'
         ⍺[⍋∊   ]   sort the flattened input
    (∊a)←           assign this result to 'a', preserving structure
  a⊣                return modified 'a'
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Very good 1! I think I quite understand what's going on but an explanation would be appreciated \$\endgroup\$
    – AZTECCO
    Mar 14, 2022 at 17:34
  • 1
    \$\begingroup\$ added an explanation \$\endgroup\$
    – Razetime
    Mar 15, 2022 at 11:02
2
\$\begingroup\$

Perl 5 -p, 37 bytes

@a=sort{$a-$b}/\d+/g;s/\d+/shift@a/ge

Try it online!

\$\endgroup\$
1
2
\$\begingroup\$

Vyxal, 38 bytes

1N→_a`\d+`?λ←_a1+→_a`\d+`?Ẏ⌊s←_a iS;øṙ

Try it Online!

Thanks @lyxal for helping me a lot in chat. I've never posted any Vyxal answers before.

This is a port of my JavaScript solution. Takes a stringified list (provided with backticks around a Python-like list syntax).

\$\endgroup\$
1
  • \$\begingroup\$ You can replace one variable with the register (£ to get and ¥ to set) and the other with the ghost variable, which has no name (Just and ) but is global. Also, 1N is u and 1+ is . \$\endgroup\$
    – emanresu A
    Mar 15, 2022 at 19:08
1
\$\begingroup\$

PARI/GP, 86 bytes

a->i=#l=[];t(b->l=setunion([b],l),a);t(b->l[i++],a)
t(g,a)=iferr([t(g,b)|b<-a],e,g(a))

Attempt This Online!

Explanation

Here is a helper function to traverse a ragged-list, since we need to traverse the input twice:

t(g,a)=iferr([t(g,b)|b<-a],e,g(a))

t(g,a) traverses the ragged-list a and replaces each number in it with g(a).

When a is a number, the list comprehension [t(g,b)|b<-a] will throws an error. iferr will catch this error and return g(a).

When a is a list, [t(g,b)|b<-a] doesn't have an error. It returns a list of t(g,b), where b runs through a.

Now look at the main function:

a->i=#l=[];t(b->l=setunion([b],l),a);t(b->l[i++],a)

This is an anonymous function with argument a.

First it initializes l to [], i to #l (the length of l, which is 0).

Now it can do the first traversal: t(b->l=setunion([b],l),a). For each number b in the list, it set l to the union of [b] and l. PARI/GP doesn't have a separated type for sets. A set is just a sorted list without duplicate elements.

Then it does the second traversal: t(b->l[i++],a). For each number b in the list, it increments i, and replaces b with the i'th element in l. This gives the final result.

\$\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.