Cascading Style Sheets (CSS) is a style sheet language used for describing the look and formatting of a document written in a markup language. A style sheet consists of a list of rules. Each rule or rule-set consists of one or more selectors, and a declaration block. Selector describes which element it matches.

Sometimes element is matched to multiple selectors. In this case, element inherits multiple styles, from each rule it matches. Rules can override each other. To solve this problem, each selector has it's own 'specificity' - e.g. weight. The selector with greater specificity overrides the other selector.

Your task is to calculate the weights of two selectors and determine which of them will beat the other one.

```python
compare("body p", "div") # returns "body p"
compare(".class", "#id") # returns "#id"
compare("div.big", ".small") # returns "div.big"
compare(".big", ".small") # returns ".small" (because it appears later)
```

For simplicity, all selectors in test cases are CSS1-compatible, test cases don't include pseudoclasses, pseudoelements, attribute selectors, etc. Below is an explanation on how to weight two selectors. You can read more about specificity here.

The simplest selector type is ``tagname`` selector. It writes as a simple  alphanumeric identifier: eg ``body``, ``div``, ``h1``, etc. It has the least weight. If selectors have multiple elements - the selector with more elements win. For example, ``body p`` beats ``div``, because it refers to 2 (nested) elements rather than 1.

Another simple selector is ``.class`` selector. It begins with dot and refer to element with specific ``class`` attribute. Class selectors can also be applied to tagname selectors, so ``div.red`` refer to ```` element. They can be grouped, for example, ``.red.striped``. Class selector beats tagname selector.

The most weighted selector type in stylesheet is ``#id`` selector. It begins with hash sign and refer to element with specific ``id`` attribute. It can also be standalone, or applied to an element. Id selector beats both selector types.

And the least weighted selector is ``*``, which has no specificity and can be beat by any other selector.

Selectors can be combined, for example, ``body #menu ul li.active`` refers to ``li`` element with ``class="active"``, placed inside ``ul`` element, placed inside element width ``id="menu"``, placed inside ``body``.

Specificity calculation is simple. 

Selector with more #id selectors wins
If both are same, the winner is selector with more .class selectors
If both are same, selector with more elements wins
If all of above values are same, the winner is selector that appear last


For example, let's represent the number of ``#id`` , ``.class``, ``tagname`` selectors as array (in order from worst to best):

SelectorSpecificity (#id,.class,tagname)
*0, 0, 0
span0, 0, 1
body p0, 0, 2
.green0, 1, 0
apple.yellow0, 1, 1
div.menu li0, 1, 2
.red .orange0, 2, 0
div.big .first0, 2, 1
#john1, 0, 0
div#john1, 0, 1
body #john span1, 0, 2
menu .item #checkout.active1, 2, 1
#foo div#bar.red .none2, 2, 1

Difficulty: introductory

Starter code:

def compare(a, b):
	

Solutions:
import re

def compare(a, b):
    return a if specificity(a) > specificity(b) else b
  
def specificity(s):
    return [len(re.findall(r, s)) for r in (r'#\w+', r'\.\w+', r'(^| )\w+')]

import re
def compare(a, b):

  def scoreCSS(s):
    d = {'#':0, '.':0, ' ':0}
    for c in re.findall("[#\. ](?=[\w-])", " {}".format(s)):
        d[c] = d[c] + 1
    return (d['#'], d['.'], d[' '])
  
  return a if (scoreCSS(a) > scoreCSS(b)) else b


from functools import reduce
import re


SIMPLE_SELECTOR_PATTERN = re.compile(r'[\s+~>]+|(\[[^[]+\]|[#\.:]?[^[\s#\.:+~>]+)')
SPECIFICITY_PATTERN = re.compile(r'(^#)|(^[\.\[:][^:]?)|(^::|^[^#\.:[])')


def compare(a, b):
    return max((b,a), key=get_specificity)


def get_specificity(selector):
    return reduce(sum_specificities, list(map(simple_selector_to_specificity, get_simple_selectors(selector))))


def sum_specificities(*specificities):
    return list(map(sum, list(zip(*specificities))))


def simple_selector_to_specificity(simple_selector):
    if simple_selector == '*':
        return [0,0,0]
    return [1 if x else 0 for x in SPECIFICITY_PATTERN.match(simple_selector).groups()]


def get_simple_selectors(selector):
    return [
        match.group(1)
        for match in SIMPLE_SELECTOR_PATTERN.finditer(selector)
        if match.group(1)
    ]


tagname = __import__("re").compile(r"(^|(?<=\s))[^#\.*]").findall

def compare(a, b):
    return max(b, a, key=lambda x: (x.count('#'), x.count('.'), len(tagname(x))))

def tokenise(s, split='*#. '):
    """
    Takes a string and splits it on any of the characters in the split string, 
    yields each split with the character used to split as it's prefix, with 
    the exception of spaces followed by another split character, when spaces 
    are removed
    
    Example:
        split('.abc #123 .def.ghi *')
    will yield the following strings:
        '.abc', '#123', '.def', '.ghi', '*'
    """
    buffer = ''
    for c in s:
        if c in split:
            if buffer.strip():
                yield buffer.strip()
                buffer = ''
        buffer += c
    if buffer.strip():
        yield buffer.strip()

def score_selector(selector):
    """
    Given a CSS selector build a score for the selector that can be used for 
    sorting precendence.
    
    Returns a tuple with counts of the following:
        (stars, ids, classes, tagnames)
    Stars are numbered positively, the others are numbered negatively 
    so that natural ordering can be used without having to specify a key
    for the sort call.
    """
    low, ids, classes, tags = 0, 0, 0, 0
    for part in tokenise(selector):
        if part.startswith('.'):
            classes -= 1
        elif part.startswith('#'):
            ids -= 1
        elif part.startswith('*'):
            low += 1
        else:
            tags -= 1
        
    return low, ids, classes, tags 


def compare(a, b):
    """Compares two CSS selectors and returns the one with highest precedence"""
    return sorted([(score_selector(s), -i, s) for i, s in enumerate([a, b])])[0][-1]


import re

def compare(a, b):
  [pa, pb] = [(x.count('#'), x.count('.'), len(re.findall(r"[\w']+", x)) - x.count('#') - x.count('.')) for x in [a, b]]
  return a if pa > pb else b

import re

def key(t):
    i,s = t
    return (s.count('#'), s.count('.'), len(re.split(r'(?!<^)[ .#]+', s)), s!='*', i)

def compare(*args):
    return max(enumerate(args), key=key)[1]

def compare(a, b):
    return max((b, a), key=lambda sel:
        (sel.count('#'), sel.count('.'),
            sum(not t.startswith(('.', '#', '*')) for t in sel.split())))