8
\$\begingroup\$

Introduction

So John finally has his holidays! And what better could he do than watching some movies. He indeed has a lot of movies to watch, but he is unable to decide which one to watch first. He has a list of movies, each in the format: <Movie name> (<Year>). So he makes a simple set of rules to decide his order of watching movies.

1) The first preference is given to the release year. If a movie released a year or earlier than others, then he would watch them first.

2) If two or more movies released in the same year, and one of them begins with a number, then he would prefer to watch that movie first.

3) If two or more movies released in the same year begin with a number as well, then the movie which comes first on the original list would be watched first.

4) If two or more movies released in the same year begin with a letter, then the movie beginning with a letter which comes earlier in the English alphabet will be chosen first. If two movies begin with the same letter, then the one containing a lesser number of characters in the movie name(including spaces) will be chosen first.

5) If the number of characters is also same, then the movie which comes later in the original list would be watched first.

Well, what a great set of rules indeed. Now the challenge.

Challenge

The input will be a list of movies, i.e, strings - all following the specified format, and you need to output the sorted list, following the above stated rules. Be case insensitive , i.e, treat both uppercase and lower case characters equally and assume all inputs to be valid, and the list will contain no duplicate elements. Also, every character in the movie name is either a letter, or a number and there are blank spaces only in between. You can assume the release year is 4 digits long.

Examples

Input
Output

['The Town (2010)', 'The Prestige (2006)', 'The Departed (2006)'] 
['The Departed (2006)', 'The Prestige (2006)', 'The Town (2010)']

['Hello (2001)', '15 minutes (2001)', '25 Minutes (2002)']
['15 minutes (2001)', 'Hello (2001)', '25 Minutes (2002)']

['15 (1960)', '25 days (1960)']
['15 (1960)', '25 days (1960)']

['Jjjj (2004)', 'Hello (2004)']
['Hello (2004)', 'Jjjj (2004)']

['all gone (2018)', 'Be careful (2018)']
['all gone (2018)', 'Be careful (2018)']

['Be careful (2018)', 'all gone (2018)']
['all gone (2018)', 'Be careful (2018)']

Scoring

This is , so the shortest code wins!

\$\endgroup\$
16
  • 1
    \$\begingroup\$ "i.e. be case in-sensitive" - does this mean "treat upper and lowercase characters from the input as equal" or does it mean "you may assume input will always be in a single case" or does it mean "it does not matter how you compare different cases" or does it mean something else? (none of the examples help decipher it) \$\endgroup\$ Mar 10, 2018 at 16:02
  • 1
    \$\begingroup\$ @JonathanAllan I think "case insensitive" says it all. In addition to that, <Movie name> and all the examples are mixed case. \$\endgroup\$
    – Titus
    Mar 10, 2018 at 17:08
  • 1
    \$\begingroup\$ It was autocorrect. I just realised it when editing finished. Fixed now \$\endgroup\$ Mar 10, 2018 at 17:40
  • 1
    \$\begingroup\$ @Titus depends. Like what stuff. \$\endgroup\$ Mar 10, 2018 at 18:08
  • 1
    \$\begingroup\$ @Titus yes, that's acceptable. \$\endgroup\$ Mar 10, 2018 at 18:36

7 Answers 7

3
\$\begingroup\$

Python 3, 115 bytes

lambda a:sorted(a[::-1],key=lambda s:(s.split()[-1],-("/"<s[0]<":"),a.index(s)*("/"<s[0]<":"),s[0].lower(),len(s)))

Try it online!

-11 bytes thanks to spec change (thanks Jonathan Allan for pointing it out)
-6 bytes thanks to Lynn

\$\endgroup\$
7
  • \$\begingroup\$ I believe that since it has been confirmed that the year is guaranteed to be four digits that you could replace int(s.split()[-1][1:-1]) with s.split()[-1] \$\endgroup\$ Mar 10, 2018 at 15:44
  • \$\begingroup\$ @JonathanAllan cool, thanks! \$\endgroup\$
    – hyper-neutrino
    Mar 10, 2018 at 15:54
  • \$\begingroup\$ A new rule clarification has made this solution invalid (it should be case-insensitive). \$\endgroup\$ Mar 10, 2018 at 16:47
  • \$\begingroup\$ Unfortunately (due to clarification of the intended meaning of "be case in-sensitive") this fails for ['all low (2018)','B movie (2018)'] \$\endgroup\$ Mar 10, 2018 at 17:28
  • \$\begingroup\$ @EriktheOutgolfer thanks fixed \$\endgroup\$
    – hyper-neutrino
    Mar 10, 2018 at 18:09
2
\$\begingroup\$

Red, 108 bytes

func[b][s: copy[]foreach m b[append/only s reverse split m"("]foreach m sort/all s[print rejoin[m/2"("m/1]]]

Try it online!

Explanation:

f: func[b] [                                 the argument is a block of strings
    s: copy []                               prepare an empty block
    foreach m b [                            for each string in the input block
       append/only s reverse split m "("     split it on "(" and append in reversed order
    ]  
    foreach m sort/all s [                   sort the new block
       print rejoin[m/2 "(" m/1]             and print it in the right order
    ]
]

Red's sort/all (sort function with refinement all) performs a stable sort, comparing all the fields of a compound argument:

sort/all [[1 2 3 1] [1 1 6] [2 1 3] [1 2 3 4]]
== [[1 1 6] [1 2 3 1] [1 2 3 4] [2 1 3]]
\$\endgroup\$
2
\$\begingroup\$

PHP, 231 115 113 bytes

PHP sort stabilized by using keys including the position

while($s=$argv[++$i])$a[substr($s,-6).($s<A?:$s&_).str_pad($s<A?$i:$argc-$i,$argc,0,0)]=$s;ksort($a);print_r($a);

Run with php -nr '<code>' 'movie1 (year1)' 'movie2 (year2)' ... or try it online.

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

R, 95 87 85 bytes

-2 thanks to Wheat Wizard

function(v)v[order(unlist(regmatches(v,gregexpr("[0-9]{4}",v))),tolower(v),nchar(v))]

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ Hello and welcome to the site! I don't know R so I might be wrong here but I don't think you need the f=. It looks like you are making an anonymous function and assigning it to a variable. If this is an anonymous function that can be called in line you can get rid of the assignment. \$\endgroup\$
    – Wheat Wizard
    Mar 13, 2018 at 16:02
  • \$\begingroup\$ you're right, it worked thanks! \$\endgroup\$
    – DS_UNI
    Mar 13, 2018 at 16:16
  • \$\begingroup\$ What is the purpose of tolower ? \$\endgroup\$
    – JayCe
    Jun 13, 2018 at 17:32
2
\$\begingroup\$

Perl 6, 58 bytes

*.sort({~m/\(\d+/,/^\d/??(0,$++)!!(1,.uc.ord,.chars,$--)})

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ You can use .uc instead of .uc.ord. Also you could use <( to ignore the \( as in / \( <( \d+/ would return 2010 instead of (2010. Since movies have only ever been produced in 4 digit years what you have is shorter and works. \$\endgroup\$ Mar 20, 2018 at 17:42
  • \$\begingroup\$ @BradGilbertb2gills .uc.ord is required to only sort on the first letter. An equally short alternative is m/./.uc. \$\endgroup\$
    – nwellnhof
    Mar 20, 2018 at 18:04
1
\$\begingroup\$

Jelly, 35 bytes

³i
ḲṪ$ḊṖV;1ịeØDƲ×Çṭ1Ɗ;Œlḷ/$;L;ÇN$µÞ

Try it online!

-4 bytes thanks to Mr. Xcoder

\$\endgroup\$
8
  • \$\begingroup\$ Perhaps 34 bytes? \$\endgroup\$
    – Mr. Xcoder
    Mar 10, 2018 at 7:27
  • \$\begingroup\$ And 33 bytes using a helper link (saves a byte from the 34-byte version, but if that’s not valid, then you can use these in your solution to get 35). Other than this, you can use ḷ\ instead of 1i$ to save another byte. \$\endgroup\$
    – Mr. Xcoder
    Mar 10, 2018 at 7:28
  • \$\begingroup\$ @Mr.Xcoder It's ḷ/, not ḷ\. ḷ\ is the same as ḷ/WẋLƲ. \$\endgroup\$ Mar 10, 2018 at 15:28
  • \$\begingroup\$ @EriktheOutgolfer I don’t think it matters here though. \$\endgroup\$
    – Mr. Xcoder
    Mar 10, 2018 at 15:33
  • \$\begingroup\$ @EriktheOutgolfer not sure it makes a difference, but thanks, I fixed it \$\endgroup\$
    – hyper-neutrino
    Mar 10, 2018 at 15:34
1
\$\begingroup\$

Jelly,  28 26 25  24 bytes

-1 thanks to Erik the Outgolfer (use a zip to replace pair then transpose)

µḲṚż>”<aŒlƲḢO;L;⁹iNƊȧ\ðÞ

A monadic link taking and returning lists of lists of characters.

Try it online! - footer reformats the result like the input (which is interpreted as a list of lists of characters)

...or see a test-suite

How?

µḲṚż>”<aŒlƲḢO;L;⁹iNƊȧ\ðÞ - Link: list of lists of characters, X
                                                     e.g. ["RV (2006)", "iChannel (2006)", "300 (2006)"]
                      ðÞ - sort by the following ðyadic key function (right is now X)
µ                        - ...start a monadic chain (left is now an item in X):
 Ḳ                       -   split at spaces              ["RV","(2006)"] / ["iChannel","(2006)"] / ["300","(2006)"]
  Ṛ                      -   reverse                      ["(2006)","RV"] / ["(2006)","iChannel"] / ["(2006)","300"]
          Ʋ              -   last four links as a monad:
     ”<                  -     literal '<' character (resides between digits*  and alphas ...* also the spaces and parentheses)
    >                    -     greater than? (vectorises) [1,1,0,0,0,0,0,0,0] / [1,1,1,1,1,1,1,1,0,0,0,0,0,0,0] / [0,0,0,0,0,0,0,0,0,0]
        Œl               -     lower-case                 ["rv (2006)"] / ["ichannel (2006)"] / ["300 (2006)"]
       a                 -     AND (vectorises)           ['r','v',0,0,0,0,0,0,0] / ['i','c','h','a','n','n','e','l',0,0,0,0,0,0,0] / [0,0,0,0,0,0,0,0,0,0]
   ż                     -   zip together                 [["(2006)",'r'],["RV",'v'],[0],[0],[0],[0],[0],[0],[0]] / [["(2006)",'i'],["iChannel",'c'],['h'],['a'],['n'],['n'],['e'],['l'],[0],[0],[0],[0],[0],[0],[0]] / [["(2006)",0],["300",0],[0],[0],[0],[0],[0],[0],[0],[0]]
           Ḣ             -   head                         ["(2006)",'r'] / ["(2006)",'i'] / ["(2006)",0]
            O            -   cast to ordinal (vectorises) [[40,50,48,48,54,41],114] / [[40,50,48,48,54,41],105] / [[40,50,48,48,54,41],0]
                         -   (Jelly cannot compare characters with integers)
              L          -   length                       9 / 15 / 10
             ;           -   concatenate                  [[40,50,48,48,54,41],114,9] / [[40,50,48,48,54,41],105,15] / [[40,50,48,48,54,41],0,10]
                   Ɗ     -   last three links as a monad:
                 i       -     1st index of item in...
                ⁹        -     chain's right argument, X    1 /  2 /  3
                  N      -     negated                     -1 / -2 / -3
               ;         -   concatenate                  [[40,50,48,48,54,41],114,9,-1] / [[40,50,48,48,54,41],105,15,-2] / [[40,50,48,48,54,41],0,10,-3]
                     \   -   cumulative reduce with:
                    ȧ    -     AND (does not vectorise)   [[40,50,48,48,54,41],114,9,-1] / [[40,50,48,48,54,41],105,15,-2] / [[40,50,48,48,54,41],0,0,0]
                         -                           i.e. max / middle / min
                         -                                so the sort, Þ, reverses this input:
                         -                                ["300 (2006)", "iChannel (2006)", "RV (2006)"]
\$\endgroup\$
7

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.