I finally got a working solution for PS2 P3. http://codepad.org/brXhb25U I had been using brute-force methods since my mind and coding is more math-centered than logic-centered. Also, I had a lot of trouble getting "stuck" in loops which caused lots of incorrect values. Basically, I set up a function, and a counter. Whenever a combination of 6, 9 and 20 proved to be a solution for n, the counter would be increased. Thus, a value for n that had no solutions would have a counter of zero. Any constructive criticism regarding my 20 lines of code? Other than condensing setting variables to 0?
Overall, at least for me, your code looks clean and good. Cheers for getting a solution :-). Only two things that come to my mind, one is not really a critic, just something to keep in mind: int values in Python have boolean values linked to them, in the sense that, if an int is != 0, it is considered True, and the opposite also holds, if int == 0, then it is False. I am saying this because, if though it makes a lot more sense in your code to write checkval == 0 (it's more readable that way), sometimes writing only if not checkval is considered a bit better, because it almost looks like English. Second thing is something that maybe someone disagrees with me here, but you shouldn't compare int floats. I mean, in lines 11, 12 and 13, that range function implicitly converted the float to int, but it is usually the case that it's better to just truncate the float. Thing is, you are actually assuming the language does good comparisons between different data types, something which might not hold true. Better safe than sorry, at least for me. As a side note, xrange is usually better than range, range creates a list, which consumes more memory and more time, I believe, than xrange does.
Typo: "Even though it makes..."
Hmmm. I can see how I can substitute some "if not" statements, but I have not really had any experience with that area of Boolean logic. Or for that matter, any implicit int->bool workings. I recently switched from using while-loops to using for-loops since they seem more economical. Looking up xrange, I find the utility interesting. Finally, I am not quite sure how truncating my floating values would be of any use, since I am only using positive integers here. If I require some precision for something like finding roots of not-perfect squares, I could perhaps use a floating step-size that approaches zero. Although I would only be able to get so far without massive memory consumption... Any further input gladly accepted! After months of unreasonable messing about with looping issues, I re-approached it with the intent of using logic and/or Return tools.
Yeah, I don't really care that much for that point also, I pretty much only write if not if the value is already a boolean, like a function returning a True or False value. Indeed, for loops in Python are somewhat better than while, or at least I had less rage moments due to strange bugs using for, ^^. Generally, xrange is better if you don't loop many times a fixed list, or if you don't want to slice the list implicitly created by range. Especially important stuff, since xrange is the default in Python 3.x (? unsure about this, remember seeing Guido talking about this once). And, yes, in your program, it won't really be that much of useful, but my point being that you shouldn't trust the language much. It really does some strange stuff sometimes. Or, as a better example, suppose you are actually writing in another language and are used to compare ints and floats in Python. This may cause a runtime error in another language, or, even worse, returning a wrong result. I don't know, I generally consider it good defensive programming, but, really, it all sums up to the style you develop and what the costs are of implementing a safer code (and how redundant it will be, also something important). Just as an advice for future reference (I know that I had a lot of trouble, not with this, but with lazy programming habits from Python, when I wrote some code in C/C++, :-) )
I like the idea of setting a list with the package sizes. I hadn't thought of that.
This is pretty good code. I don't think we know about functions for this problem set, so it would be a little more correct to remove the function and put the test directly in the inner loop. The function doesn't do much, anyway, so it's not too hard. bmp says you're comparing ints and floats, but you're not. Those expressions in the range function are all integer math. Also he recommends treating integers as booleans in conditions, which I strongly recommend NOT doing. Java doesn't allow this, for good reasons. xrange is a good idea, but it won't make much of a difference. I've started using it in my for loops, probably more for principle than performance. If you're going to use the tuple of package sizes, use it throughout. The range() arguments should use the tuple, not literal 6/9/20. Use of booleans. First, don't compare a boolean to True/False. The boolean is already True or False, so just use it as the condition (with "not" if you want to detect False). In your factor() function you could just return the condition, instead of returning True if it's True and False if it's False. checkval is not a good variable name. numSolutions would be better. Even better would be to make it a boolean a call it hasSolution or something like that. Set it to True where you're currently incrementing checkval. Your n loop is a for loop that goes to 150, which works because we know the answer is 43. If you didn't know that beforehand you would want it to loop indefinitely. So it should be a while loop. It doesn't use the concept of finding 6 consecutive buyable numbers to end the loop. You're really only detecting the largest buyable number under 150. The final print statement looks like it came from some Python 3 code, with the parens. Python 2 thinks you're printing a tuple, so that's why you get the parens, comma, and quotes in the output. The code WORKS, which is the important bit. But there are almost always things that can be improved. If you want to make any of these suggested changes, make a backup of your working code before breaking it. Then make one change at a time, and test the code after each change, even the small ones.
how can you not know something if you know it.? I cannot imagine that reading ahead or doing xtra research to augment a lecture then using that knowledge could ever be penalized.
@dmancine, I didn't recommend using the numerical True/False values on Python. I said that, sometimes, people might prefer because it looks more readable, but, personally, I never use it as it makes the code less intuitive. About the range, I know the division for 2.x returns the floor, but it's deprecated since 3.x releases, just check this code using from __future__ import division to see my point. Check this PEP: http://www.python.org/dev/peps/pep-0238/ My point is that, in order to range(x/y) work, you have to assume one of two things: 1) The division operator is ambiguous, which, in my mind, shouldn't happen in a formal language. (this is also prone to change, due to being a strange design choice, as it did happened) 2)You have to assume that range() implicitly floors a float given as an argument, which does not happen and shouldn't happen, because, if that was the case, you would be severely overloading the range function. Anyway, at least for me, the cost of preemptively truncating is minimal, and it makes your code more portable for 3.x, but really, it was more of a broad advice in creating your programming discipline. After all this rambling, I would say to take what I said with a pinch of salt, as I am learning here also, and many times corrected by others, which is always great :-)
@bmp, I think it's more readable to people coming from C/C++ because they don't have booleans, or they use ints to fake booleans, so they're totally used to viewing 0 as false and everything else as true. I'm coming from Java and C#, and I have a haughty self-righteous religious aversion to treating non-booleans as booleans. But in python, which has so few clues as to what type a variable is supposed to be, I'm very in favor of explicitly using as many clues as possible. If you write "if x" then as someone reading that code I have to infer from context what type x is supposed to be. And in python there might not be enough clues in the local function context to infer the type, so you have to go to where the function is used. And in those places the context might imply different things about the type of x. In my code, if I write "if x" then I know x is a boolean. If x isn't a boolean then I'd always have a specific check, like "if x != 0" or "if x != None". I don't have Python 3, so the little knowledge I have of it is anecdotal. I'm aware of the "//" operator in python 2, and I think it's a good idea. But that still doesn't change the behavior of "/" when given two integers. I'm glad they changed it to be unambiguous in python 3. But this is another example of python's lax typing rearing its ugly head. As for treating python 2 code as written for python 3, I'm not sure that's valid. This is an introductory course, and the concept of writing one version of code for multiple platforms is a complicated topic that's probably beyond its scope. The course says to use python 2, and the caveat is for people who choose to use python 3, that their code won't be compatible with python 2. So trying to apply python 3 concepts to python 2 code can only cause confusion. Indeed, the OP was confused by the suggestion to use floor() for his range limits, because he, rightly, thought he was working with integers. In fact, if I saw python 2 code calling floor() on an integer I'd say the author is confused about what types they think they're using. But maybe changing the divisions to use "//" would be more clear. Types. Types types types. The one most important thing I've learned from this class is that I never ever ever want to professionally maintain any python code. It really makes me feel like I'm coding with my pants down. It has removed lots of important basic checks that keep me out of trouble. This lack of automatic checking must necessarily be replaced with programmers' discipline, and no one can possibly be that disciplined. I mean, that's why we have strongly typed languages with compile-time type checking. Python is a neat toy language, useful for teaching programming. It's a nice place to visit, but I wouldn't want to live there.
@dmancine, I see your point now, and I retract myself. You are right, all I did was confusing more than helping OP, I am quite nit-picky when it comes down to portability (tells how much I hate fflush in C/C++ and stuff like that). But yeah, I agree with you. As for the last point, do you think so? Personally, I think that, even though Python does not have the potential to become an industrial language, at least not on pair with C-family/Java, I still think that it is a pretty useful language for small stuff. Better than shell scripting (as it has a bigger scope), clean and elegant language, even if it has its bad designs options. (but yeah, more industrial languages have a lot more scope for usage & implementation) As a last question, have you ever heard about Go, the programming language? If yes, do you think it will have the same problems that Python does? I mean, it treats the types somewhat strangely, but it seems better than Python.
@bmp, I don't think anything you said was actually wrong, just maybe not the kind of feedback the OP was looking for. And I learned more about division in the different versions of Python, which is good to be aware of. But I think we've found some common ground and moved past our disagreements, and now we can get back to the task of continuing to completely destroy whatever remains of the original topic of this post. (What was it again? Oh yeah, Preston wrote some code.) Don't get me wrong, I am enjoying python. Development is fast and simple. (Of course, I haven't done any large-scale development in python yet; it's all pretty much been limited to a single file per program.) Code tends to be pretty minimal, because there aren't any curly braces floating around to indicate blocks, there are no types to get in the way, lists and dictionaries are built-in types with powerful syntactical support, etc. In short, code is brief and to the point, which makes it easy to write and read. But, like I said, I feel very exposed when writing python. The absence of types is a huge deal. Also, moving lots of basic errors from compile time to run time makes testing extremely important. And it's not just unit testing; it's necessarily complete coverage. It means that if I assign to the wrong variable, or misspell a function name, or make a typo, I won't know until I run my code. Java still lets me pass -1 to Math.sqrt(), but I have never passed a String to it. The compiler tells me when I do that right away, before I deploy my code. There are plenty of opportunities to make semantic mistakes when programming. Why add in all the syntactical errors, too? (I know Math.sqrt("abc") is not strictly a syntactical error, but it's so fundamentally wrong that I have trouble saying it's semantics.) I have heard of Go, but I know nothing about it. Looking briefly at their webpage it looks interesting. But I really don't have time right now to go tooling around learning other languages. I'll put it in my queue.
Join our real-time social learning platform and learn together with your friends!