Thursday, March 21, 2024

Strings and Loops

 

Strings and Loops
Now that we know that strings are basically lists in disguise, we can start to harness the power of loops with them.

Let's look a bit further into string slicing.

Using a for loop
This for loop creates a variable called letter. It is used to store each character in the string as the loop goes through it, starting at the first character.

The print statement uses the letter variable and will output the string one character at a time (like a list).

myString = "Day 21"
for letter in myString:
print(letter)

output 
D
a
y
 
2
1

This means that we can do certain things to certain characters inside the loop.

if statement inside the loop

This code will examine the lower-case version of each character. If it's an 'a', the computer will change the font colour to yellow before printing.

Outside of the loop, the last line sets the font colour back to default for the next character in the loop.

myString = "Day 38"
for letter in myString:
if letter.lower() == "a":
print('\033[33m', end='') #yellow
print(letter)
print('\033[0m', end='')

Using a list to specify search items:-
If the letters are in my list called vowels, they will print out in yellow.
I changed the print statement on the last line back to the default color with the ending system.

vowels = ["a","e","i","o","u"]
myString = "Will my vowels now be yellow?"
for letter in myString:  
  if letter.lower() in vowels:
    print('\033[33m', end='') #yellow    
  print(letter, end="")
  print('\033[0m', end='') #back to default

Coding challenge :
Ask the user to input any sentence (string).
Now we'll rainbow-ize (nope, me neither) it.
As soon as the string contains an 'r', every letter from that point on should be red.
When the computer encounters a 'b', 'g', 'p' or 'y', from there the output should be blue for 'b', green for 'g'...you get the idea.
Loop through the string and output it (so the color continues through the loop).
The output should change color every time it encounters a new r,g,b,p or y.

Extra points for resetting the output color back to default every time there's a space.

It would be like this........

#import os, time
def colorChange(color):
  if color=="r":
    return ("\033[31m")
  elif color=="w":
    return ("\033[0m")
  elif color=="b":
    return ("\033[34m")
  elif color=="":
    return ("\033[33m")
  elif color == "g":
    return ("\033[32m")
  elif color == "p":
    return ("\033[35m")

while True:
  #os.system("clear")
  listofWords= input("Tell me what do want: ").split()
  print(listofWords)
  i=0
  for i in listofWords:
    if i[0]=="r":
      print(colorChange('r'),i,end="" )
    elif i[0] == "w":
      print(colorChange('w'),i,end="")
    elif i[0] == "b":
      print(colorChange('b'),i,end="")
    elif i[0] == "g":
      print(colorChange('g'),i,end="")
  print()
  print(colorChange('w'))


More better way :- 

import os

def colorChange(color):
    colors = {
        'r': '\033[91m',  # Red
        'w': '\033[0m',   # White (reset)
        'b': '\033[94m',  # Blue
        'g': '\033[92m'   # Green
    }
    return colors.get(color, '\033[0m')  # Default to white if color not found

while True:
    os.system("clear")  # Clear the console (uncomment this line if you want to clear the console before each input)
    listofWords = input("Tell me what you want: ").split()
    print(listofWords)
    
    for word in listofWords:
        if word[0] == "r":
            print(colorChange('r') + word, end=" ")
        elif word[0] == "w":
            print(colorChange('w') + word, end=" ")
        elif word[0] == "b":
            print(colorChange('b') + word, end=" ")
        elif word[0] == "g":
            print(colorChange('g') + word, end=" ")
        else:
            print(word, end=" ")  # Print the word without color change if it doesn't start with a recognized letter

    print()
    print(colorChange('w'))  # Reset color to white after printing the words

Picking from a list randomly

Random.choice() picks a random item from a list.

listOfWords = ["british", "suave", "integrity", "accent", "evil", "genius", "Downton"]
wordChosen = random.choice(listOfWords)

Coding Challenges
Prompt the user to type in a letter.
Check if the letter is in the word.
If it does, output the word with all blanks apart from the letter(s) they've already guessed.
Keep a running list of the letters they've used.
Count how many times they've picked a letter that isn't in the word - more than 6 and they lose.
Output a 'win' message if they reveal all the letters.



import random, os, time
listOfWords = ["apple", "orange", "grapes", "pear"]
letterPicked = []
lives = 6
word = random.choice(listOfWords)
while True:
time.sleep(5)
os.system("clear")
letter = input("Choose a letter: ").lower()
if letter in letterPicked:
print("You've tried that before")
continue
letterPicked.append(letter)
if letter in word:
print("You found a letter")
else:
print("Nope, not in there")
lives -= 1
allLetters = True
print()
for i in word:
if i in letterPicked:
print(i, end="")
else:
print("_", end="")
allLetters = False
print()
if allLetters:
print(f"You won with {lives} left!")
break


if lives<=0:
print(f"You ran out of lives! The answer was {word}")
break
else:
print(f"Only {lives} left")

String Manipulation

 

String Manipulation
Let's do some string manipulation to make if statements even easier.

name = input("What's your name? ")
if name == "David" or name == "david":
  print("Hello Baldy!")
else: 
  print("What a beautiful head of hair!")

Right now, if the user writes "DAVID" or "david", the if statement works correctly. However, "DaVID" does not give the correct output.
To the computer, " david", "dAviD", and "david" are completely different.
To simplify what the user typed in, we can add these functions to the end of the name of the variable:


  • .lower = all letters are lower case
    .upper = all letters are upper case
    .title = capital letter for the first letter of every word
    .capitalize = capital letter for the first letter of only the first word

lower

The computer is converting everything to lowercase before it compares my if statements.
You need to type your if statement in lower case when you use .lower. The if statement needs to be written in upper case when you use .upper, etc.

name = input("What's your name? ")
if name.lower() == "david": 
  print("Hello Baldy!")
else: 
  print("What a beautiful head of hair!")

What if we put a space first?
Adding .strip() removes any spaces on either side of the word.

name = input("What's your name? ")
if name.lower().strip() == "david": 
  print("Hello Baldy!")
else: 
  print("What a beautiful head of hair!")

No Duplicates
This is a simple program that creates a list with a simple subroutine. In the while True loop, the user is adding something to the list. (This is nowhere near as complicated as what you have done).

myList = []

def printList():
  print()
  for i in myList:
    print(i)
  print()

while True:
  addItem = input("Item > ").strip().capitalize()
  if addItem not in myList:
    myList.append(addItem)
  printList()

Note: Whatever you do after the . will happen to the string. If you use .lower, then the string will print in lower case.

Coding Challenge :- 
Create a list of people's names. Ask for first and last name (surname) separately.
Strip any extra spaces.
Store names in a capitalized version.
Create a new string using an fString that combines the tidied up version of the first name and tidied up version of the last name.
Add those new versions to a list.
Do not allow duplicates.
Each time you add a new name, you should print out the full list.

import os,time
yourName=[]

def prettyPrint():
  os.system('clear')
  print("Chart of All People")
  print()
  for i in yourName:
    print(i)
    time.sleep(1)

while True:
  os.system('clear')
  firstName=input("First Name please:").strip().capitalize()
  lastName=input("Last Name please:").strip().capitalize()
  name =f"{firstName} {lastName}"
  if name in yourName:
    print("already in the list")
  elif name not in yourName:
    yourName.append(name)
  prettyPrint()

String Slicing

However, sometimes we might want to take part of a string to use it somewhere else. Sometimes, we might want to look at just the first letter of a string or chop it into chunks.

To do this, we use string slicing.

A string isn't just one big lump of text. In fact it's a list of individual characters. 

By giving our program an index, we can specify which part of the string to chop out. 

Slicing

To slice a single character from a string, you use the index of that character in square brackets [] just like you'd use with a list!

myString = "Hello there my friend."
print(myString[0])

# This code outputs the 'H' from 'Hello'


To slice more than one character, you use two indices (yes that is the plural form of 'index'): the start character and one after your desired end character.

myString = "Hello there my friend."
print(myString[6:11])
# This code outputs 'there'.

Leaving the first index blank defaults to 'start from index 0'.
myString = "Hello there my friend."
print(myString[:11])
# This code outputs 'Hello there'.

Leaving the last index blank defaults to 'go to the end'.
myString = "Hello there my friend."
print(myString[12:])
# This code outputs 'my friend.'.

The Secret Third Argument

Adding a third argument to the square brackets [] specifies the gap left between characters.



Try to print every other character in the word 'hello':
myString = "Hello there my friend."
print(myString[0:6:2])

# This code outputs 'Hlo' (every second character from 'Hello').

Can you print every third character in the whole string?

myString = "Hello there my friend."
print(myString[::3])

# This code outputs 'Hltrmfe!' (every third character from the whole string).

Using a negative number in the third argument can be super useful. It starts the slice from the end of the string instead of the beginning.

myString = "Hello there my friend."
print(myString[::-1])

#This code reverses the string, outputting '.dneirf ym ereht olleH'

Split

split lets us split a string into a list of individual words by separating it at the space characters.

myString = "Hello there my friend."
print(myString.split())

#This code outputs ['Hello', 'there', 'my', 'friend.']

It stops printing too early

Why is it printing 'Hell' instead of 'Hello'?

myString = "Hello there my friend."
print(myString[0:4])

The second argument should always be one more than the index of the final character.

myString = "Hello there my friend."
print(myString[0:5])

It won't stop printing the same character

myString = "Hello there my friend."
print(myString[0:4:0])---- wrong code

The 0 in the third argument means 'move on 0 characters in the string each time'. You've told it to print the same character again and again and again....

The third argument should be at least 1.

CODING CHALLENGE
Ask the user to input their first & last names.
Slice the first 3 letters of the first name.
Slice the first 3 letters of the last name (surname).
Join them together. Ideally change the case so that it looks good - think fStrings or .upper()/.lower(). This is the user's Star Wars first name.
Now ask the user for their mother's maiden name and the city where they were born. (Maiden name is the last name they had before they got married. If you are not sure, make up a last name.)
Combine the first two letters of the maiden name with the last 3 letters of the city to make the user's Star Wars last name. Remember, fStrings and .upper()/.lower().
Finally, print them both as part of a sentence.

 Extra points for getting all the inputs with just one input command and the split function.

import os,time
starWars=[]


while True:
  os.system('clear')
  print("🌟Star Wars Name Generator🌟")
  print()
  print()
  input_all= input("Input your first name., Input your last name,Input your Mother's name,Input your city name with a space in each word:").slipt().upper()
  input1= input("Input your first name:").strip().upper()
  input2= input("Input your last name:").strip().upper()
  #output1= f"star wars first name is {input1[0:3]} {input2[0:3]}"   
  #print(output1)
  input3= input("Input your Mother's name:").strip().upper()
  input4= input("Input your city name:").strip().upper()
  #output2= f"star wars second name is {input3[0:2]}{input4[0:3:-1]}"
  #data = f"{input1[0:3]}{input2[0:3]}  {input3[0:2]}{input4[-3:]}"
  #print(f"{input1[0:3]}{input2[0:3]}  {input3[0:2]}{input4[-3:]}")
  
  #starWars.append(f"{input_all[0][0:3]}{input_all[1][0:3]}  {input_all[2][0:2]}{input_all[3][-3:]}")
  starWars.append(f"{input1[0:3]}{input2[0:3]}  {input3[0:2]}{input4[-3:]}")
  print(input_all)
  print(starWars)
  time.sleep(2)


More better version :-  


print("STAR WARS NAME GENERATOR")

all = input("Enter your first name, last name, Mum's maiden name and the city you were born in").split()

first = all[0].strip()
last = all[1].strip()
maiden = all[2].strip()
city = all[3].strip()

name = f"{first[:3].title()}{last[:3].lower()} {maiden[:2].title()}{city[-3:].lower()}"

print(f"Your Star Wars name is {name}")

  2D Dictionaries Remember that dictionaries are very similar to lists, except that they store data as key:value pairs. The value is what it...