Fork me on GitHub

Brittany's CodingBat Exercises - Level 2

by Brittany Hayes

12 Feb 2014

Screenshots

Warmup-2

Warmup-2

List-2

List-2

String-2

String-2

Logic-2

Logic-2

Three Interesting/Challenging Exercises

List-2: centered_average(nums)

Return the "centered" average of an array of ints, which we'll say is the mean average of the values, except ignoring the largest and smallest values in the array. If there are multiple copies of the smallest value, ignore just one copy, and likewise for the largest value. Use int division to produce the final average. You may assume that the array is length 3 or more.

There were a couple of exercises in the List-2 section that were a bit tricky for me, including this one. The big thing here was that I had trouble figuring out how to deal with cases where all of the values are the same. My code looked for the index of the max() and min() in order to not include those values in the avg; however, in cases where the max and min are the same, the index returned would always be the lowest index (i.e., the values stored in variables smallest and largest were the same). I ended up adding an if-statement to find the highest index of the value to use in the largest variable. I'm sure there is a more efficient way to do this, but this option worked.

def centered_average(nums):
    sum = 0
    total = len(nums)-2
    largest = nums.index(max(nums))     #index of largest value
    smallest = nums.index(min(nums))    #index of smallest value
    if largest == smallest:             #cases where min and max value are same
        for i in range(len(nums)):      #find the largest index position
            if nums[i] == nums[smallest]:
                largest = i             
    for i in range(len(nums)):
        if i != largest and i != smallest:      #add up values that aren't min or max
            sum = sum + nums[i] 
    if total > 0:
        return sum / total          #calculate avg
    else:
        return sum      

Logic-2: make_bricks(small, big, goal)

We want to make a row of bricks that is goal inches long. We have a number of small bricks (1 inch each) and big bricks (5 inches each). Return True if it is possible to make the goal by choosing from the given bricks. This is a little harder than it looks and can be done without any loops.

This problem, along with make_chocolate(), were probably the most challenging exercises I've encountered so far. With make_bricks(), I initially was going to try to use some for loops, but I read in the description that loops were unneccessary. As such, I set out to think about how it could be solved otherwise. I started to think that the modulo operation would probably be of use in this case, in order to find the remainder (after big bricks) that you would need (made up of small bricks) to add up to the goal amount. I also realized that you could easily tell if it was impossible to make the goal length if the total of both small and big was less than the goal. I added that as a condition to my code. Along the same lines, if the sum of small and big brick lengths equaled the goal, that would automatically mean that the goal length was possible. I combined all of these observations to write this function. It required a few modifications (changing the order of statements, fixing some of the calculations, etc), but ultimately the code below worked. I later saw that there was a sample solution video, which was so much more concise than my code (but focused on the same things I did).

def make_bricks(small, big, goal):
    total = small + (5*big)         
    if total < goal:                #total length is shorter than goal, so False
        return False
    if big != 0 and small != 0:         #cases where there are both types of bricks
        remainding = goal % 5           #remainder of goal divided by 5
        if remainding - small <= 0:     #if remainder is less than or equal to small length
            return True                 #length is possible
        else:
            return False     
    elif big == 0 and small != 0:       #cases where there are only small bricks
        if goal - small > 0:            #if goal is bigger than small length, task is impossible
            return False
        else:
            return True
    elif big !=0 and small == 0:        #cases where there are only big bricks
        remainding = goal % 5
        if remainding == 0:             #no remainder, task is possible
            return True
        else:
            return False
    elif big == 0 and small == 0:       #cases where there are no bricks
        return False

Logic-2: make_chocolate(small, big, goal)

We want make a package of goal kilos of chocolate. We have small bars (1 kilo each) and big bars (5 kilos each). Return the number of small bars to use, assuming we always use big bars before small bars. Return -1 if it can't be done.

make_chocolate() was even harder than make_bricks() for me. I started out with the observations I had gleaned from completing make_bricks(), and modifying the code so that it would return the appropriate number rather than True/False. I kept running it and modifying little things, which would give me more correct tests, but there were a number of incorrect instances. I examined them and tried to figure out what they had in common, making little tweaks to my code in an attempt to account for those cases. At one point, I got all the actual test cases correct, but the bottom "other cases" element showed that there was still some underlying problem with my code. I decided to just step back and rewrite the code. I felt that the case I was not capturing correctly were those where you had multiple big bars, and you needed them all [for example, the last case I was getting wrong -- make_chocolate(1000, 1000000, 5000006) --> 6]. I tried to use the middle case (right before the final else) to capture those kinds of instances. Ultimately, the rewritten code was much shorter and was successful for all cases.

def make_chocolate(small, big, goal):
    total = small + (5*big)         #sum weight of all chocolate
    if total < goal:                #sum weight is less than the goal, so goal is impossible
        return -1
    if total == goal:               #sum weight is exactly goal, so all small bars are needed
        return small
    if big*5 < goal and (goal - big*5) <= small:    #when you use all the big bars 
        return goal - (big*5)                       #and the remainder is <= remaining small bars
    else:
        remainding = goal % 5       
        if remainding == small:     #if remainder is same as small, all small bars are needed
            return small 
        if remainding > small:      #if remainder is greater than amt of small bars
            return -1               #request is impossible
        else:
            return remainding       #remainder is less than small, so return remainder
Brittany is a second year MSIS student. She is interested in information retrieval, data mining, and natural language processing. Find Brittany Hayes on Twitter, Github, and on the web.
comments powered by Disqus