﻿ Python | Test if number is valid Excel column, Python | Check if string is a valid identifier, Python - Test if list is Palindrome, Python | Test if String is Monotonous, Python | Test if string is subset of another, Python | Test if tuple is distinct,

1. Python | Test if number is valid Excel column
2. Python | Check if string is a valid identifier
3. Python - Test if list is Palindrome
4. Python | Test if String is Monotonous
5. Python | Test if string is subset of another
6. Python | Test if tuple is distinct

## Python | Test if number is valid Excel column

In Microsoft Excel, columns are denoted with letters. The first 26 columns use the letters A to Z. After Z, columns are represented with two letters: AA, AB, AC,..., AZ, BA, and so forth. It's a base-26 system, but with the notable twist that there's no zero representation (i.e., unlike our decimal system which goes 0-9, Excel's columns go from A-Z without any representation for zero).

Here's how you can determine if a given string represents a valid Excel column:

### 1. Basic Validity Check:

First, we want to ensure the string only contains uppercase English alphabets. A regular expression can be a quick way to do this.

```import re

def is_valid_excel_column(s):
return bool(re.match('^[A-Z]+\$', s))

print(is_valid_excel_column("A"))     # True
print(is_valid_excel_column("AB"))    # True
print(is_valid_excel_column("AAA"))   # True
print(is_valid_excel_column("1A"))    # False
```

In the Excel system, the string "A" is valid, "Z" is valid, but the string "AA" follows "Z". This means "A" is equivalent to "01" in our base 10 system. Similarly, "AA" is like "10", "AB" is like "11", etc.

Therefore, sequences like "BA" are valid (it follows "AZ") but "ZA" would be invalid (because it should be "AA").

Here's how you can validate an Excel column with this consideration:

```def is_valid_excel_column(s):
if not bool(re.match('^[A-Z]+\$', s)):
return False

# Check sequence validity
for i in range(1, len(s)):
if s[i] == 'A':
continue
if s[i-1] != 'Z':
return False

return True

print(is_valid_excel_column("A"))     # True
print(is_valid_excel_column("Z"))     # True
print(is_valid_excel_column("AA"))    # True
print(is_valid_excel_column("ZA"))    # False
print(is_valid_excel_column("AB"))    # True
print(is_valid_excel_column("BA"))    # True
```

The function first checks if the string consists solely of uppercase alphabets. After that, it ensures the sequence is valid.

This approach ensures that only valid Excel column sequences pass the validation.

## Python | Check if string is a valid identifier

In Python, a string is considered a valid identifier if:

1. It starts with a letter (a-z, A-Z) or an underscore (_).
2. The rest of the string can contain letters, numbers, and underscores.
3. It does not match any of Python's keyword names.

You can use the `str.isidentifier()` method to check if a given string is a valid identifier. Additionally, to ensure that the string isn't a reserved keyword, you can use the `keyword` module.

Here's how you can do it:

```import keyword

def is_valid_identifier(s):
return s.isidentifier() and not keyword.iskeyword(s)

# Test
test_strings = ["_hello", "123abc", "for", "hello_world", "import"]
for s in test_strings:
print(f"'{s}' is a valid identifier: {is_valid_identifier(s)}")
```

This will print:

```'_hello' is a valid identifier: True
'123abc' is a valid identifier: False
'for' is a valid identifier: False
'hello_world' is a valid identifier: True
'import' is a valid identifier: False
```

As you can see, `_hello` and `hello_world` are valid identifiers, while `123abc` (starts with a number), `for`, and `import` (both are keywords) are not.

## Python - Test if list is Palindrome

A palindrome is a sequence that reads the same backward as forward. Lists can also be palindromic in nature if they read the same from the start and the end.

Let's go through a step-by-step tutorial on how to check if a given list is a palindrome in Python:

### 1. Basic Approach:

The most straightforward approach is to reverse the list and check if it is equal to the original list.

```def is_palindrome(lst):
return lst == lst[::-1]

lst = [1, 2, 3, 2, 1]
print(is_palindrome(lst))  # True
```

### 2. Iterative Approach:

You can check the first item with the last item, the second item with the second last item, and so on until the middle of the list.

```def is_palindrome(lst):
for i in range(len(lst) // 2):
if lst[i] != lst[-i - 1]:
return False
return True

lst = [1, 2, 3, 2, 1]
print(is_palindrome(lst))  # True
```

### 3. Using deque from collections:

Python's `collections` module has a `deque` class that provides a method `popleft()`, which pops from the left end of the list. Using this, you can efficiently check for palindromes by comparing and popping elements from both ends.

```from collections import deque

def is_palindrome(lst):
d = deque(lst)
while len(d) > 1:
if d.popleft() != d.pop():
return False
return True

lst = [1, 2, 3, 2, 1]
print(is_palindrome(lst))  # True
```

### 4. Recursive Approach:

A recursive approach can be utilized by checking the first and last element and then recursively checking the inner list.

```def is_palindrome(lst):
if len(lst) <= 1:
return True
if lst != lst[-1]:
return False
return is_palindrome(lst[1:-1])

lst = [1, 2, 3, 2, 1]
print(is_palindrome(lst))  # True
```

### Conclusion:

All of these methods work, and you can choose the one that best fits your needs. For most cases, the basic or iterative approach would be sufficient. However, if you're working on a problem that requires efficiency, especially with larger lists, you might want to consider using the `deque` approach or check other optimization techniques.

## Python | Test if String is Monotonous

To determine if a string is monotonous, we need to check if its characters are either in entirely non-decreasing or non-increasing order. Let's go through how we can achieve this in Python.

### 1. Using Loops:

The idea here is to traverse the string and compare adjacent characters. We can detect if the string is increasing, decreasing, or neither.

```def is_monotonous(s):
increasing = decreasing = True

for i in range(1, len(s)):
# Check if the string is not in non-decreasing order
if s[i] < s[i-1]:
increasing = False

# Check if the string is not in non-increasing order
if s[i] > s[i-1]:
decreasing = False

return increasing or decreasing

# Test cases:
print(is_monotonous("abcde"))    # True (non-decreasing)
print(is_monotonous("edcba"))    # True (non-increasing)
print(is_monotonous("aabbcc"))   # True (non-decreasing)
print(is_monotonous("abcda"))    # False
```

### 2. Using Python's `all()` function:

Python's built-in `all()` function checks if all the elements in an iterable are `True`. This can be combined with a generator expression for a more concise solution.

```def is_monotonous(s):
return all(s[i] <= s[i+1] for i in range(len(s)-1)) or all(s[i] >= s[i+1] for i in range(len(s)-1))

# Test cases:
print(is_monotonous("abcde"))    # True (non-decreasing)
print(is_monotonous("edcba"))    # True (non-increasing)
print(is_monotonous("aabbcc"))   # True (non-decreasing)
print(is_monotonous("abcda"))    # False
```

### Conclusion:

A monotonous string will either be entirely in non-decreasing or non-increasing order. Depending on your preference for readability or brevity, you can choose either the loop method or the `all()` function method to test for monotonous strings in Python.

## Python | Test if string is subset of another

To determine if one string (let's call it `s1`) is a subset of another string (let's call it `s2`), we need to ensure that every character in `s1` appears in `s2` with the same or greater frequency.

There are several ways to check this. Below, we'll go through a couple of methods:

### 1. Using Counter from `collections`:

The `Counter` class in Python's `collections` module provides an easy way to count occurrences of each character in a string. We can compare these counts to determine if one string is a subset of another.

```from collections import Counter

def is_subset(s1, s2):
counter1 = Counter(s1)
counter2 = Counter(s2)

# Check if every character in s1 has a count less than or equal to its count in s2
for char, count in counter1.items():
if counter2[char] < count:
return False
return True

# Test cases:
print(is_subset("abc", "aabbcc"))     # True
print(is_subset("aabc", "aabbcc"))    # True
print(is_subset("aaabc", "aabbcc"))   # False
print(is_subset("def", "aabbcc"))     # False
```

### 2. Using set and count:

We can also achieve this by using Python's built-in set and string count function. This method is less efficient than using `Counter` but is still a valid approach.

```def is_subset(s1, s2):
for char in set(s1):
if s1.count(char) > s2.count(char):
return False
return True

# Test cases:
print(is_subset("abc", "aabbcc"))     # True
print(is_subset("aabc", "aabbcc"))    # True
print(is_subset("aaabc", "aabbcc"))   # False
print(is_subset("def", "aabbcc"))     # False
```

### Conclusion:

The `Counter` approach is more efficient, especially for longer strings, as it avoids multiple calls to `str.count()`, which can be expensive. However, for smaller strings or one-off checks, either method will suffice.

## Python | Test if tuple is distinct

To check if a tuple contains only distinct (unique) elements, you can make use of Python's data structures and built-in functions. This tutorial will guide you through different methods to determine if a tuple contains distinct elements.

### 1. Using the `set` data structure:

The `set` data structure in Python does not allow duplicate values. You can convert the tuple to a set, and if the length of the set is equal to the length of the tuple, then the tuple contains all distinct elements.

```def is_distinct(t):
return len(t) == len(set(t))

# Test cases:
tuple1 = (1, 2, 3, 4, 5)
tuple2 = (1, 2, 3, 3, 4)

print(is_distinct(tuple1))  # True
print(is_distinct(tuple2))  # False
```

### 2. Using the `Counter` from `collections`:

The `Counter` class can count occurrences of each element. If the most common element's count is 1, then all elements are distinct.

```from collections import Counter

def is_distinct(t):
return Counter(t).most_common(1) == 1

# Test cases:
tuple1 = (1, 2, 3, 4, 5)
tuple2 = (1, 2, 3, 3, 4)

print(is_distinct(tuple1))  # True
print(is_distinct(tuple2))  # False
```

### 3. Using a loop:

You can iterate through the tuple and use a set to keep track of seen elements. If an element is already in the set, then the tuple has duplicates.

```def is_distinct(t):
seen = set()
for item in t:
if item in seen:
return False
return True

# Test cases:
tuple1 = (1, 2, 3, 4, 5)
tuple2 = (1, 2, 3, 3, 4)

print(is_distinct(tuple1))  # True
print(is_distinct(tuple2))  # False
```

### Conclusion:

All the above methods achieve the goal of determining if a tuple has distinct elements. The first method using the `set` data structure is the most straightforward and Pythonic. The second and third methods provide alternative approaches. Depending on the specific use case and the desired level of readability, you can choose the method that's best suited for you.