The Boredless Tourist

Hi everyone

I’m hoping you guys can help me figure this code out. I watched the help video and went through my code line by line. As far as I can tell, my code matches the video.

I’m supposed to be returning:

“Hi Dereck Smill, we think you’ll like these places around Paris, France: the Arc de Triomphe”

Instead, I’m returning:

“Hi Dereck Smill, we think you’ll like these places around Paris, France:” I have no idea why I can’t get the final part to show up. I’ve spent hours trying to figure this out:

Here’s the code:

destinations = ["Paris, France", "Shanghai, China", "Los Angeles, USA", "So Paulo, Brazil", "Cairo, Egypt"]

test_traveler = ['Erin Wilkes', 'Shanghai, China', ['historical site', 'art']]

def get_destination_index(destination):
  destination_index = destinations.index(destination)
  return destination_index

def get_traveler_location(traveler):
  traveler_destination = traveler[1]
  traveler_destination_index = get_destination_index(traveler_destination)
  return traveler_destination_index

attractions = []
for destination in destinations:
  attractions.append([])
  
def add_attraction(destination, attraction):
  try:
    destination_index = get_destination_index(destination)
    attractions_for_destination = attractions[destination_index].append(attraction)
  except SyntaxError:
    return

add_attraction("Paris, France", ["the Louvre", ["art", "museum"]])
add_attraction("Paris, France", ["Arc de Triomphe", ["historical site", "monument"]])
add_attraction("Shanghai, China", ["Yu Garden", ["garden", "historcical site"]])
add_attraction("Shanghai, China", ["Yuz Museum", ["art", "museum"]])
add_attraction("Shanghai, China", ["Oriental Pearl Tower", ["skyscraper", "viewing deck"]])
add_attraction("Los Angeles, USA", ["LACMA", ["art", "museum"]])
add_attraction("So Paulo, Brazil", ["So Paulo Zoo", ["zoo"]])
add_attraction("So Paulo, Brazil", ["Ptio do Colgio", ["historical site"]])
add_attraction("Cairo, Egypt", ["Pyramids of Giza", ["monument", "historical site"]])
add_attraction("Cairo, Egypt", ["Egyptian Museum", ["museum"]])

def find_attractions(destination, interests):
  destination_index = get_destination_index(destination)
  attractions_in_city = attractions[destination_index]
  attractions_with_interest = []
  
  for attraction in attractions_in_city:
    possible_attraction = attraction
    attraction_tags = attraction[1]
    
    for interest in interests:
      if interest in attraction_tags:
        attractions_with_interest.append(possible_attraction[0])
    return attractions_with_interest
  
def get_attractions_for_traveler(traveler):
  traveler_destination = traveler[1]
  traveler_interests = traveler[2]
  traveler_attractions = find_attractions(traveler_destination, traveler_interests)
  
  interests_string = "Hi " + traveler[0] + ". We think you'll like these places around " + traveler_destination + ":"
  
  for i in range(len(traveler_attractions)):
    if traveler_attractions[-1] == traveler_attractions[i]:
      interests_string += " the " + traveler_attractions[i] + "."
    else:
      interests_string += " the " + traveler_attractions[i] + ", "
  return interests_string

smills_france = get_attractions_for_traveler(['Dereck Smill', "Paris, France", 'monument'])

print(smills_france)

It’s for this project:

https://www.codecademy.com/paths/computer-science/tracks/cspath-cumulative-tourism/modules/cspath-boredless-tourist/projects/the-boredless-tourist

Thank you all for your help!!!

Hey @tjohnson139

Firstly, never underestimate the power of a print call for debugging purposes. I went through your code, and added in several print calls so I could see what your code is working on at various points through its execution. Here’s what I ended up with:

destinations = ["Paris, France", "Shanghai, China", "Los Angeles, USA", "So Paulo, Brazil", "Cairo, Egypt"]

test_traveler = ['Erin Wilkes', 'Shanghai, China', ['historical site', 'art']]

def get_destination_index(destination):
  destination_index = destinations.index(destination)
  return destination_index

def get_traveler_location(traveler):
  traveler_destination = traveler[1]
  traveler_destination_index = get_destination_index(traveler_destination)
  return traveler_destination_index

attractions = []
for destination in destinations:
  attractions.append([])
  
def add_attraction(destination, attraction):
  try:
    destination_index = get_destination_index(destination)
    attractions_for_destination = attractions[destination_index].append(attraction)
  except SyntaxError:
    return

add_attraction("Paris, France", ["the Louvre", ["art", "museum"]])
add_attraction("Paris, France", ["Arc de Triomphe", ["historical site", "monument"]])
add_attraction("Shanghai, China", ["Yu Garden", ["garden", "historcical site"]])
add_attraction("Shanghai, China", ["Yuz Museum", ["art", "museum"]])
add_attraction("Shanghai, China", ["Oriental Pearl Tower", ["skyscraper", "viewing deck"]])
add_attraction("Los Angeles, USA", ["LACMA", ["art", "museum"]])
add_attraction("So Paulo, Brazil", ["So Paulo Zoo", ["zoo"]])
add_attraction("So Paulo, Brazil", ["Ptio do Colgio", ["historical site"]])
add_attraction("Cairo, Egypt", ["Pyramids of Giza", ["monument", "historical site"]])
add_attraction("Cairo, Egypt", ["Egyptian Museum", ["museum"]])

def find_attractions(destination, interests):
  destination_index = get_destination_index(destination)
  print("Destination index: %r" % destination_index)
  attractions_in_city = attractions[destination_index]
  print("Attractions in city: %r" % attractions_in_city)
  attractions_with_interest = []
  
  for attraction in attractions_in_city:
    possible_attraction = attraction
    print("Possible attraction: %r" % possible_attraction)
    attraction_tags = attraction[1]
    print("Attraction tags: %r" % attraction_tags)
    
    for interest in interests:
      print("Checking interest '%r'" % interest)
      if interest in attraction_tags:
        attractions_with_interest.append(possible_attraction[0])
        print("Matched attraction %r with interest %r" % (possible_attraction[0], interest))
      else:
        print("Discarding attraction %r as no match!" % possible_attraction[0])
    return attractions_with_interest
  
def get_attractions_for_traveler(traveler):
  traveler_destination = traveler[1]
  traveler_interests = traveler[2]
  traveler_attractions = find_attractions(traveler_destination, traveler_interests)
  
  interests_string = "Hi " + traveler[0] + ". We think you'll like these places around " + traveler_destination + ":"

  print("Traveler attractions: %r " % traveler_attractions)
  
  for i in range(len(traveler_attractions)):
    if traveler_attractions[-1] == traveler_attractions[i]:
      interests_string += " the " + traveler_attractions[i] + "."
    else:
      interests_string += " the " + traveler_attractions[i] + ", "
  return interests_string

smills_france = get_attractions_for_traveler(['Dereck Smill', "Paris, France", 'monument'])

print(smills_france)

The first thing that I noticed, whilst reading through your code and adding my prints is that you have an indentation issue in find_attractions:

def find_attractions(destination, interests):
  destination_index = get_destination_index(destination)
  attractions_in_city = attractions[destination_index]
  attractions_with_interest = []
  
  for attraction in attractions_in_city:
    possible_attraction = attraction
    attraction_tags = attraction[1]
    
    for interest in interests:
      if interest in attraction_tags:
        attractions_with_interest.append(possible_attraction[0])
    return attractions_with_interest ### this is indented incorrectly!!

The indentation for your return statement places it within the for structure of for attraction in attractions_in_city, so this loop will only ever execute once. I fixed that, then I ran your code. Here’s the output:

Destination index: 0
Attractions in city: [['the Louvre', ['art', 'museum']], ['Arc de Triomphe', ['historical site', 'monument']]]
Possible attraction: ['the Louvre', ['art', 'museum']]
Attraction tags: ['art', 'museum']
Checking interest ''m''
Discarding attraction 'the Louvre' as no match!
Checking interest ''o''
Discarding attraction 'the Louvre' as no match!
Checking interest ''n''
Discarding attraction 'the Louvre' as no match!
Checking interest ''u''
Discarding attraction 'the Louvre' as no match!
Checking interest ''m''
Discarding attraction 'the Louvre' as no match!
Checking interest ''e''
Discarding attraction 'the Louvre' as no match!
Checking interest ''n''
Discarding attraction 'the Louvre' as no match!
Checking interest ''t''
Discarding attraction 'the Louvre' as no match!
Possible attraction: ['Arc de Triomphe', ['historical site', 'monument']]
Attraction tags: ['historical site', 'monument']
Checking interest ''m''
Discarding attraction 'Arc de Triomphe' as no match!
Checking interest ''o''
Discarding attraction 'Arc de Triomphe' as no match!
Checking interest ''n''
Discarding attraction 'Arc de Triomphe' as no match!
Checking interest ''u''
Discarding attraction 'Arc de Triomphe' as no match!
Checking interest ''m''
Discarding attraction 'Arc de Triomphe' as no match!
Checking interest ''e''
Discarding attraction 'Arc de Triomphe' as no match!
Checking interest ''n''
Discarding attraction 'Arc de Triomphe' as no match!
Checking interest ''t''
Discarding attraction 'Arc de Triomphe' as no match!
Traveler attractions: [] 
Hi Dereck Smill. We think you'll like these places around Paris, France:

Can you see where your issue is coming from?

I'd invite you to try and fix it yourself before reading my solution here...

So, what’s happening is you’re passing a string to get_attractions_for_traveler in traveler[2]: that value is ‘monument’.

As strings are iterable, instead of checking each discrete interest ('monument' or 'historical site' for example) your code is checking each character of the interest ('m', 'o', 'n' etc…) against the interests of the site.

If you pass the interests of the traveller as a list when you call get_attractions_for_traveler or otherwise verify (and convert if necessary) the contents of traveler[2] are a list before iterating over it, you’ll get the output you’re expecting:

Destination index: 0
Attractions in city: [['the Louvre', ['art', 'museum']], ['Arc de Triomphe', ['historical site', 'monument']]]
Possible attraction: ['the Louvre', ['art', 'museum']]
Attraction tags: ['art', 'museum']
Checking interest ''monument''
Discarding attraction 'the Louvre' as no match!
Possible attraction: ['Arc de Triomphe', ['historical site', 'monument']]
Attraction tags: ['historical site', 'monument']
Checking interest ''monument''
Matched attraction 'Arc de Triomphe' with interest 'monument'
Traveler attractions: ['Arc de Triomphe'] 
Hi Dereck Smill. We think you'll like these places around Paris, France: the Arc de Triomphe.

Hope that helps. :slight_smile:

4 Likes

Thank you so much for spending so much time on this. You helped a ton! I’m new to coding but it’s frustrating one indent or one set of brackets can throw off your whole code :slight_smile:

Thank you again! I really appreciate it!!!

1 Like

I just want to second this statement, bring it to a vote and pass it unanimously!!!

2 Likes

lol. I still don’t understand all the code he used in the print statements but that helped so much that’s one of my next things to learn :slight_smile:

2 Likes

No problem at all, glad I could help. :slight_smile:

What in particular didn’t you understand in the print calls I added to your code? :slight_smile:

This part - %r" % - but that’s OK. I’m sure I’ll learn it. I’m working on another project now and putting random print statements in and it’s helping a lot. And I’m sure I’ll figure it out eventually. It’s a confusing language and it’s taking a lot of brain power and even more frustration. :slight_smile:

Thank you again for all your help. I can’t thank you enough for your time and help!

1 Like

Ah, I thought it might be that.

So, you know how you can pass variables into strings by using placeholders? For example:

the_math = 3 * 5
print("The answer is %d!" % the_math)

where %d tells Python to expect a variable, of type int.

%r tells Python to use the representation of the object, which is returned by the repr() function. So, if you have the following code:

print("The object looks like %r" % the_thing)

and the_thing = ['a','b','c','d'], then your output would be The object looks like ['a','b','c','d'].

If the_thing = 123, you’d get The object looks like 123.

%r basically gives you the friendly representation of the object you’re passing into the string.

If this still seems weird to you, there’s more info in the Python docs.

https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting

It explains what the % operator is for, and how you can use it, in the context of formatting strings. :slight_smile:

1 Like

Awesome. Thank you. That may actually help on the project I’m working on now.

Thanks again!!

1 Like

Hi everyone, this is driving me crazy, I understand what the error I am getting is, but I do not understand why I am getting it. I

The error: la_arts = find_attractions(“Los Angeles, U
SA”, [“art”])
File “script.py”, line 48, in find_attractio
ns
attractions_in_city = attractions[destinat
ion_index]
UnboundLocalError: local variable 'attractions
’ referenced before assignment

My code;

def find_attractions(destination, interests):
  destination_intex = get_destination_index(destination)
  attractions_in_city = attractions[destination_index]
  attractions_with_interest = []

  for attractions in attractions_in_city:
    possible_attraction = attraction
    attraction_tags = attraction[1]
    for interest in interests:
      if interest in attraction_tags: 
        attractions_with_interest.append(possible_attaction)
 
  return attractions_with_interest

la_arts = find_attractions("Los Angeles, USA", ["art"])
print(la_arts)

Hi! I’m sure you figured this out a while ago.
There is an itty bitty typo in the code you left here in Dec.

destination_intex …instead of desination_index

could be throwing off the rest of your code.

hope it all worked out!

1 Like

This was very helpful! Thank you.

2 Likes

I almost finishing data structures :smiley:, but thanks for the reply rokchel, I really appreciate it!

1 Like

How the same code can be written for attractions using list comprehensions?

Thank you in advance.

Which bit in particular, and have you already attempted it that way? :slight_smile:

I tried but not successful

attractions = [attraction for attraction in destinations]

but in Codecademy solution :

attractions =[]
  for attraction in  destinations:
    attractions.append([])

Please can you explain how can I append the same by using list comprehensions. I was feeling bit difficulty here.

Thank you in advance.

In the “solution” code, we’re appending an empty list object to attractions with every iteration of the loop.

Your approach doesn’t append an empty list, it instead adds the current attraction to the list. Can you see the difference, and how you need to change your list comprehension to match the longer for loop approach? :slight_smile:

yeah, I have noticed the difference and now I tried adding the attraction.append() which is not working because a string cannot be appended. So, can this be achieved via list comprehension ? and How?

Than you again in advance!:slight_smile:

Yes, because .append() is a list method not a string method. Also, where in the following code are we appending to attraction?

attractions =[]
  for attraction in  destinations:
    attractions.append([])

Answer: We aren’t…

Yes, you can do the same thing with a list comprehension…

I’m not going to give you the solution, because a) it’s surprisingly easy and b) you’ll learn more if you figure it out for yourself.

So, here’s an example. Please explain to me, in bullet points, what the following code snippet is doing every step along the way from start to finish.

example_variable = []
for a in range(5):
    example_variable.append(a*2)

Hopefully, since you’re attempting to solve this by using them, you understand what a list comprehension does. Let’s repeat what we’ve just done, but this time with some different code. Again, in bullet points, what is this code doing?

example_variable2 = [a*2 for a in range(5)]
1 Like

Hey there, I have a question about this problem too, and thought I’d add to an existing thread rather than start a new one. Plus, although I’m not using list comprehensions, I think the quote above might be relevant to my question. In my code I ended up appending lists to lists and losing track of which shell I was in.

I pasted my solution below and it works, but it isn’t as simple and concise as the solution from the video. I’m trying to figure out if there’s a better way to search for an element within a list of lists, and when there is a match, to be able to figure out the indices of both the outer and inner lists in which the match occurred…

def find_attractions(destination, interests):
  destination_index = get_destination_index(destination)
  attractions_in_city = attractions[destination_index]
  attractions_with_interest = []
  possible_attraction = []
  attraction_tags = []
  for attraction in attractions_in_city:
    possible_attraction.append(attraction)
    attraction_tags.append(attraction[1])
    for interest in interests:
      for i in attraction_tags:
        if interest in i:
          indexmatch = attraction_tags.index(i)
          matchname = possible_attraction[indexmatch]
          attractions_with_interest.append(matchname[0])
          continue
  return attractions_with_interest

I think I got off track at task #42, compared to the solution in the video. I thought I needed to iterate over attractions_in_city, adding each attraction to the list possible_attraction (i.e. creating a new list of all of the attractions of a given city, identical to the list you’d get if you called the city’s index in attractions). This led me to define both possible_attraction and attraction_tags outside of the for loop.

From there I had to append each attraction to the possible_attraction list as I iterated through attractions_in_city. Same thing with attraction_tags. So attraction_tags was a list whose elements were lists of strings. I started having issues when I tried to use:

for interest in interests:
      if interest in attraction_tags:

It would return False, even if I knew that interest was an element in a list within attraction_tags. (e.g. 'art' in ['beach', ['art', 'museum'] evaluated to False.) I couldn’t get the in function to search through elements in a list of lists, so I had to make yet another for loop to iterate through the items. It ended up getting really messy in the innermost if shell, because I had to define all sorts of new variables in order to call on in specific elements within those lists. Is there a better way to do search for an element in a list of lists?