Problem with learning

I am having a general problem with learning python. I got through the first three lessons (syntax, functions, and control flow) just fine, and I feel like I have a very solid understanding of those. But then I hit lists, and the struggle has been real. I labored through it, and moved on to loops, hoping that some things that just didn’t click would click later. Loops apparently are tightly related to lists - at least the way codeacademy teaches it. I understood loops much better than lists, but I still find myself mashing that “show solution” button way too frequently. See, with lists, I understand all the concepts on an individual basis, so when I reworked my way through the lessons it was a cakewalk. But when the coding challenges begin is when I hit trouble. And looking at the solutions hasn’t helped either- often the solution involves something that makes me wonder how the heck I was expected to know how to do that in the first place. For example, take the middle element challenge for lists. Here is the solution:

def middle_element(lst):
if len(lst) % 2 == 0:
sum = lst[int(len(lst)/2)] + lst[int(len(lst)/2) - 1]
return sum / 2
else:
return lst[int(len(lst)/2)]

This is some serious index stacking going on. I’m not sure how I was supposed to logically solve this problem coming from zero coding background. I mean, I can look at the solution and have a sense for what is going on with the code, but I never would have been able to come up with this solution on my own. I don’t think we were ever taught about converting lengths of lists to integers, for example. Surprisingly, the loops challenge code went a lot smoother for me, probably because the syntax of loops are more logical like booleans, and read in a logical thought pattern. Is it just unfamiliarity with what you can do with lists? These solutions seem to take some level of connecting dots with concepts that seem to be evading me. I even created a cheat sheet and rewrote individual concepts in my own words and even referring to that I fail to make certain connections that it feels like codeacademy expects me to make. As best I can figure out, my weak spots are list slicing and indexing, even though both concepts make perfect sense to me on a fundamental level, when it comes time to use them mixed with other code, I can’t seem to make a logical progression of thought using them. Anyhow, I’ve droned on enough, just was hoping someone could suggest anything or identify with the problems I am having. Tired of spinning my wheels and going over the lessons and studying code over and over again to no avail. Sorry for the complaining, I’m just frustrated!

That itself returns an integer(len). So if the length (len) of a list is 3 elements, it returns 3 as an integer.

Not exactly what your asking, or the answer to this post. What I suggest is to muscle through it, take the quizzes, and then revisit the areas you have trouble with, which will be shown by the results in the quiz results. But, do something else first, and let this all sink in over time, THEN come back and revisit the problem areas. I find that my second, definitely my third time around on a course, things finally sink in.

1 Like

That’s the problem though, I have aced the quizzes because they are just asking about individual concepts. I don’t have a problem with the concepts, I have a problem pulling combinations of concepts into solutions for coding challenges; which then gets even more muddied by having a few arrangements that as someone with no prior experience in coding would never have thought to do. I suppose I should walk through an example with my thought process.

" Create a function called middle_element that has one parameter named lst .

If there are an odd number of elements in lst , the function should return the middle element. If there are an even number of elements, the function should return the average of the middle two elements."

So here I am with a blank python terminal in front of me. I can instantly figure a few things. First, I need to (obviously) write a function with a single parameter called “lst”.

def middle_element(lst):

Now I need to identify whether the lst (which is user defined) has an odd number of indices or even. There are a couple ways to do this that I know, but the first one that comes to mind is:

if len(lst) % 2 == 0:
return #some equation that will return the average of the middle two indices

except that in the solution, I should wrap this equation up in a variable and then return that variable. Fair enough. Except that the way they find this average is extremely confusing. They say,

sum = lst[int(len(lst)/2)] +
lst[int(len(lst)/2) - 1]

Now this might be the right way to express this, but to me, I’m still not quite certain which operators go into which parenthesis, and unfortunately the python error messages just tell me that the syntax is invalid because the operator type is invalid which doesn’t exactly help me.

Bottom line, I need something to bridge the gap between the core concepts that codeacademy does a wonderful job of explaining, and the code challenges that seem to expect you to connect a lot more dots than I think someone with zero coding experience would do very well.

(As a side note I find roughly 50% of the coding challenges to not be a problem, I just don’t understand how to get to the other half with what has been taught without having those connections pointed out)

In cases like this I personally have learned how to solve those problems using code challenge sites. In that case, where a collection, array, list, stack, container, etc. is of odd length, and the object itself is 0 index (languages like Lua not zero index, they start at 1), you just get the length and divide that by 2 and return that int as the middle element.

So if the list is lst = {0, 1, 2}, then if you divide the length, you get 1.5. Well, an integer is a whole number, so if no rounding/flooring/ceiling is needed, then it will truncate to 1. As you can see, 1 is the middle element, the one you want. The tricky part is when the list has an even number of elements. So, an additional line of code for most people is needed to determine if its odd or even, and if even I believe its the same formula + 1 is the answer.

Anyhow, all that is stuff you learn on your way. It takes application of skills and knowledge you learned. Lot of that stuff has formulas you can find online, to do it all in one line. I personally don’t know that stuff or was never good in math, so often I will walk out my thought process to solve the answer and then go back and refactor it to a more readable, concise line/s of code.

Things like you mention with operators go into which parenthesis is easier to understand if you know how they work in math. Same rules here.

If you are looking for a site with code challenges that has some form of mentoring like here, then exercism.io is a good site for that.

1 Like

They’re converting to int to compensate for an earlier mistake, doing floating point division. Neither of those things should be done.

Anyway grab the two middle values (using integer math, so 3 / 2 is 1 with a remainder of 1) and get the average of them, and I’m guessing you have no issue with that… add them, divide by two (this time you might want to do floating point division, unlike when figuring out the index)

Hello, @data4031771770. Since you’re new to programming, figuring out how to put the pieces together can be a challenge. As you gain experience, you’ll start to recognize which ‘tools’ work best for which task. Even seasoned programmers learn new things all the time, and refactor old code to be more efficient. There’s no shame in not immediately understanding complex solutions. It may be easier at first to break your code into tiny pieces. Do one thing at a time, and put the pieces together to accomplish the task. Then you can review your code, and start thinking about ways to reduce the number of steps. Here is an example of the challenge you referred to broken into little pieces with extra print() statements to help visualize what is happening. Using print() to see the values assigned to variables and the results of evaluating expressions is a good habit to develop. Once everything is working properly, they can be commented out or deleted. Please excuse all of the comments if you find them unnecessary.

lst1 = [1,2,3,4,5,6]
lst2 = [1,2,3,4,5]

def middle_element(lst):
    list_length = len(lst) #assign length of list to a variable rather than call the function repeatedly
    if list_length  % 2 == 0:
        #using floor division // (returns an integer instead of float i.e. 5 // 2 returns 2)
        mid1 = list_length // 2 - 1 #mid1 is the index of the first of the two middle elements
        mid2 = list_length // 2 #mid2 is the index of the second
        mid_sum = lst[mid1] + lst[mid2] #mid_sum is the sum of the two middle elements
        #We can print the values assigned to the variable to see what is happening
        print(f'lst: {lst}\nlist_length: {list_length}\nmid1: {mid1}\nmid2: {mid2}\nlst[mid1]: {lst[mid1]}\nlst[mid2]: {lst[mid2]}\nmid_sum: {mid_sum}')
        return mid_sum / 2 #return the average of the two middle elements
        
    else:
        mid = list_length // 2
        print(f'lst: {lst}\nmid: {mid}')
        return lst[mid]
        
print(middle_element(lst1), "\n") # 3.5
print(middle_element(lst2)) # 3

Output:

lst: [1, 2, 3, 4, 5, 6]
list_length: 6
mid1: 2
mid2: 3
lst[mid1]: 3
lst[mid2]: 4
mid_sum: 7
3.5

lst: [1, 2, 3, 4, 5]
mid: 2
3

Then after seeing that the code works as desired, I might try thinking about how to implement other tools that I’ve learned to use:

def get_mid(lst):
    lst_len = len(lst)
    return lst[lst_len // 2] if lst_len % 2 else (lst[lst_len // 2] + lst[lst_len // 2 - 1]) / 2

print(get_mid(lst1)) # 3.5
print(get_mid(lst2)) # 3

Output:

3.5
3

Hang in there, and don’t hesitate to ask for help when needed. :grinning:

Edit:

After reviewing this, I see that I’ve repeated the same operation using the same values 3 different times. Need to fix that. Since the value I’m using is going to be the index for the list, I’ll call it i.

def get_mid(lst):
    lst_len = len(lst)
    i = lst_len // 2
    return lst[i] if lst_len % 2 else (lst[i] + lst[i - 1]) / 2

print(get_mid(lst1)) # 3.5
print(get_mid(lst2)) # 3

That’s better.

1 Like

Exploration

def middle(s):
    n = len(s)
    m = n // 2
    return [(s[m] + s[m - 1]) / 2, s[m]][n % 2]

No logic involved. This is the sort of intuitive approach that isn’t being taught in the courses, although it ought to be hinted at once in awhile so learners see other possibilities, not just a single path.


Even this will work…

def middle(s):
    n = len(s)
    m = n // 2
    return [sum(s[m - 1 : m + 1]) / 2, s[m]][n % 2]
>>> middle([4,6,8,6,3,2,9,8,9,1,2,3])
5.5
>>> middle([4,6,8,6,3,2,9,8,9,1,2,3,7])
9
>>> 

It would be cool if some of the lessons, had learners go back, and try to refactor their code using a different approach.

1 Like

Thought I fixed that. Must go back and do it now. Thanks for the heads up.

1 Like

Arguably that thing with the list is the same as an if-expression, except it eagerly evaluates both paths. (can’t really write any computer code without logic, since they’re made of logic gates)

There’s also something that can be done that works for both.

For an odd-length list, dropping half from the start or from the end makes the middle value the next one.

For an even-length list, dropping half from the left side makes the next value the right-middle value, dropping from the right side makes the next value the left-middle value (whereas for odd it produces the middle both times)

If one took both of those and averaged them … that’d be it.

Using views into the original one could use slicing for this, but rather than slice one can also work out what the indices would be.
So one would make halflength steps towards the middle, and that would be the value to look at:

def middle(xs):
    half = len(xs) // 2
    return (xs[half] + xs[-1 - half]) / 2
2 Likes