-2
\$\begingroup\$

Introduction

In a list of strings, there is a certain length you can shorten strings to before they become indistinguishable. This is a pretty bad explanation, so here is an example.

  1. ['hello', 'help', 'helmet']
  2. ['hell', 'help', 'helme']
  3. ['hell', 'help', 'helm']
  4. ['hel', 'hel', 'hel'] <- At this point the strings are indistinguishable

Challenge

Given a list of strings, you program must shorten them until just before any of them become indistinguishable. Shorting is defined as removing one character from the end of a string. To shorten a list of strings by one remove the last character from all of the longest strings in the list, or, if all strings are the same length, every string in the list. For example, given the above input, your program would output ['hell', 'help', 'helm']. If the strings cannot be shortened, or are already indistinguishable, your program should just output the list unchanged. If, at any point, shortening the strings in the list would make some, but not all, of the strings indistinguishable, you program should still output the list as is, instead of shortening it more.

Note for those who are wondering: If multiple strings can be shortened in the list, they should all be shortened.

  • Your program may take input in any format you like, as long as it is one of the default I/O methods. Input can be of any encoding, but must be a valid UTF-8 string, or your language's equivalent, as can the list of strings. The strings will never be empty, but they might be of different lengths. They will always have at least one common character or be all the same length. There are no restrictions on string content, other than this. The list can also be of any length.
  • The same goes for output: you may use any of the default I/O methods. Output can be of any encoding and type, just like the input. All strings in the output should be the same length.

Example I/O

  • ['hello', 'help', 'helmet']
    ['hell', 'help', 'helm']

  • ['like', 'likable', 'lick']
    ['like', 'lika', 'lick']

  • ['hello', 'hello', 'hello']
    ['hello', 'hello', 'hello']

  • ['a1', 'a2', 'bb']
    ['a1', 'a2', 'bb']

  • ['farm', 'farms', 'farmer']
    ['farm', 'farms', 'farmer']

  • ['ape', 'bison', 'caterpillar']
    ['a', 'b', 'c']

  • ['😀😁😂', '😀🤨😐😑', '😀😛😜😝']
    ['😀', '😀', '😀']

Scoring

This is , so the shortest answer in bytes wins!

\$\endgroup\$
  • \$\begingroup\$ Comments are not for extended discussion; this conversation has been moved to chat. \$\endgroup\$ – DJMcMayhem Dec 31 '19 at 22:20
1
\$\begingroup\$

Charcoal, 54 bytes

≔⌊EθLιζ≔⌈EθLιδ≔EδEθ…λ⎇‹ιζι⌈⟦ζ⁻⁺ιLλδ⟧η≔Φη⬤ι⁼№ιλ¹η⎇η§η⁰θ

Try it online! Link is to verbose version of code. Explanation:

≔⌊EθLιζ≔⌈EθLιδ≔Eδ

Get the length of the shortest and longest strings, and loop over the latter.

Eθ…λ⎇‹ιζι⌈⟦ζ⁻⁺ιLλδ⟧η

Trim each string appropriately; the longest string simply trims a character each time but shorter strings stop when they reach the length of the shortest string, until finally the longest string joins them and all the strings can be trimmed again.

≔Φη⬤ι⁼№ιλ¹η

Filter out the results with indistinguishable prefixes.

⎇η§η⁰θ

Print the shortest distinguishable prefixes, or failing that, the original strings.

\$\endgroup\$
  • 1
    \$\begingroup\$ @JonathanAllan Thanks, I think I have that behaviour now. \$\endgroup\$ – Neil Dec 30 '19 at 22:53
0
\$\begingroup\$

Jelly, (11?) 18 bytes

This follows the example given in the question rather than "To shorten a list of strings by one remove the last character from all of the longest strings in the list, or, if all strings are the same length, every string in the list."

Ṗ€µẈnṂ$TȯJµ¦ƬQƑƇṪȯ

Try it online! Or see the test-suite.
(Both use the footer to format the resulting list of strings).

How?

Ṗ€µẈnṂ$TȯJµ¦ƬQƑƇṪȯ - Link: list, S
            Ƭ      - collect up until a fixed point applying:
           ¦       -   sparse application...
  µ       µ        -   ...to indices: this monadic chain:
   Ẉ               -       length of each
      $            -       last two links as a monad:
     Ṃ             -         minimum
    n              -         not equal (vectorises)
       T           -       truthy indices
         J         -       range of length (of current list) - i.e. all indices
        ȯ          -       logical OR 
Ṗ€                 -   ...action: pop each 
               Ƈ   - filter keep those for which:
              Ƒ    -   is invariant under:
             Q     -     deduplicate
                Ṫ  - tail (0 if none remain)
                 ȯ - logical OR with S (for the 0 case)

If the text is correct rather than the example then this works for 11 bytes:

ḣ€ⱮẈṀ$QƑƇḢȯ

A monadic Link accepting a list which yields a list.

Try it online! Or see the test-suite.
(Both use the footer to format the resulting list of strings).

How?

ḣ€ⱮẈṀ$QƑƇḢȯ - Link: list, S
     $      - last two links as a monad - f(S):
   Ẉ        -   length of each
    Ṁ       -   maximum
  Ɱ         - map across (implicit range [1..m]) applying:
ḣ€          -   head each to index
        Ƈ   - filter keep those for which:
       Ƒ    -   is invariant under:
      Q     -     deduplicate
         Ḣ  - head (0 if none remain)
          ȯ - logical OR with S (for the 0 case)
\$\endgroup\$

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