3
\$\begingroup\$

Given a list of strings in any convenient format display the amount of comparisons between individual characters that a merge sort algorithm would perform.

The merge-sort algorithm is a divide & conquer method for sorting lists. It divides the unsorted list into n sublists, each containing one element (a list of one element is considered sorted). We repeatedly merge sublists to produce new sorted sublists until there is only one sublist remaining. This will be the sorted list.

The merging process compares elements from the array on the left to elements from the array on the right in order, filling in the resulting array.

In particular, we will use it with a comparator that naively scans the strings for the first difference and returns a value in range [-1, 0, 1].

The reference implementation to validate yours against: Try it online!

Some test cases:

['banana','anana','nana','ana','na','a'] => 18
['aaaa','aaab','aaac','aaad'] => 16
['aaad','aaab','aaac','aaaa'] => 20
['mor','tor','rot','tor','rotor'] => 13

Shortest code wins.

\$\endgroup\$
7
  • 5
    \$\begingroup\$ "We repeatedly merge sublists to produce new sorted sublists until there is only one sublist remaining." Please provide merging order \$\endgroup\$ Commented Jul 23, 2024 at 20:39
  • 4
    \$\begingroup\$ Proof that it matters \$\endgroup\$ Commented Jul 23, 2024 at 20:41
  • \$\begingroup\$ may we assume lowercase alphabetic chars? \$\endgroup\$ Commented Jul 24, 2024 at 6:53
  • 2
    \$\begingroup\$ "We repeatedly merge sublists to produce new sorted sublists until there is only one sublist remaining. " - in what order? Does it merge smaller lists together or perform a reduction (fold)? Maybe a worked example is called for here... (I don't read JS but it looks like it splits the list into two, not into singletons.) \$\endgroup\$ Commented Jul 24, 2024 at 18:27
  • 2
    \$\begingroup\$ I agree the reference implementation makes this clear imo. \$\endgroup\$ Commented Jul 26, 2024 at 5:35

1 Answer 1

2
\$\begingroup\$

APL(Dyalog Unicode), 91 bytes SBCS

{1≥n←≢⍵:0⋄+/(⍵{(×l)++/∧\⊃=/⍺⍵↑⍨¨l←⍺⌊⍥≢⍵}¨(⍵,⊂⍬)[r⍳{⍵+m=(m,2)[r⍳⍵]}⍣≡r←⍋⍋⍵]),∇¨⍵⊂⍨≠m←n<2×⍳n}

Try it on APLgolf!

A recursive function computing the total number of comparisons. Rough breakdown:

1≥n←≢⍵:0. If there is only a single string in the list, no comparisons are needed.

∇¨⍵⊂⍨≠m←n<2×⍳n. Split the list into two halves, call the function recursively.

⍵ ... (⍵,⊂⍬)[r⍳{⍵+m=(m,2)[r⍳⍵]}⍣≡r←⍋⍋⍵]. Match up each string with the next larger string in the other half.

{(×l)++/∧\⊃=/⍺⍵↑⍨¨l←⍺⌊⍥≢⍵}¨ For each pairing, count the necessary character comparisons to sort.


APL(Dyalog Unicode), 95 bytes SBCS

There is probably some better way to implement the grouping function, would be 24 bytes shorter if the input length was a power of 2.

{+/1+{+/∧\⊃=/⍺⍵↑⍨¨⍺⌊⍥≢⍵}/⍵[⍋⍵][↑⍸(××≠⍤1)k×⍉∧\×k←⊃⍤⍸¨∘.≠⍨↓↑({1=⍵:0⋄⊃,/1 2,¨¨∇¨(⌊,⌈)⍵÷2}≢⍵)[⍋⍵]]}

Try it on APLgolf!

\$\endgroup\$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.