# Your list. Any element. Any range.
# indexing and slicing — reaching into a list

squad = ["Raven", "Wolf", "Ghost", "Viper", "Bull"]

# ─────────────────────────────────────────────
# Indexing — one element at a time
# ─────────────────────────────────────────────

print(squad[0])     # Raven  — first element
print(squad[1])     # Wolf
print(squad[2])     # Ghost
print(squad[3])     # Viper
print(squad[4])     # Bull   — last element

#   ["Raven", "Wolf", "Ghost", "Viper", "Bull"]
#       0        1       2        3        4

# ─────────────────────────────────────────────
# Negative indexes — counting from the end
# ─────────────────────────────────────────────

print(squad[-1])    # Bull   — last element
print(squad[-2])    # Viper
print(squad[-3])    # Ghost
print(squad[-4])    # Wolf
print(squad[-5])    # Raven  — first element

#   ["Raven", "Wolf", "Ghost", "Viper", "Bull"]
#      -5       -4      -3       -2       -1

# ─────────────────────────────────────────────
# Slicing — a range of elements
# ─────────────────────────────────────────────

# list[start:stop] — start included, stop excluded
print(squad[1:4])   # ['Wolf', 'Ghost', 'Viper']
print(squad[0:2])   # ['Raven', 'Wolf']

# leave start empty — begins from index 0
print(squad[:3])    # ['Raven', 'Wolf', 'Ghost']

# leave stop empty — goes to the end
print(squad[2:])    # ['Ghost', 'Viper', 'Bull']

# leave both empty — full copy of the list
print(squad[:])     # ['Raven', 'Wolf', 'Ghost', 'Viper', 'Bull']

# ─────────────────────────────────────────────
# Slicing with a step
# ─────────────────────────────────────────────

# list[start:stop:step]
print(squad[::2])   # ['Raven', 'Ghost', 'Bull']  — every second element
print(squad[1::2])  # ['Wolf', 'Viper']            — every second, from index 1

# step -1 reverses the list
print(squad[::-1])  # ['Bull', 'Viper', 'Ghost', 'Wolf', 'Raven']

# ─────────────────────────────────────────────
# Indexing vs slicing — the difference
# ─────────────────────────────────────────────

one   = squad[2]     # 'Ghost'         — a string
chunk = squad[1:4]   # ['Wolf', 'Ghost', 'Viper'] — a list

print(type(one))     # <class 'str'>
print(type(chunk))   # <class 'list'>

# original list is never changed
print(squad)         # ['Raven', 'Wolf', 'Ghost', 'Viper', 'Bull']

# ─────────────────────────────────────────────
# IndexError — what to avoid
# ─────────────────────────────────────────────

# squad[5]   → IndexError: list index out of range
# squad[-6]  → IndexError: list index out of range

# slicing never raises IndexError — returns what it can
print(squad[2:100])  # ['Ghost', 'Viper', 'Bull']

# ─────────────────────────────────────────────
# Quick reference
# ─────────────────────────────────────────────

# list[i]          — element at index i
# list[-1]         — last element
# list[a:b]        — elements from a up to (not including) b
# list[:b]         — from start up to b
# list[a:]         — from a to the end
# list[:]          — full copy
# list[a:b:s]      — every s-th element from a to b
# list[::-1]       — reversed copy
#
# indexing → returns the element (string, int, etc.)
# slicing  → returns a new list
# original list is never modified by either
