Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
reading
Jul 27, 2013

onionradish posted:

Unrelated to your issue, but something to be aware of because things like this can really bite you in the butt later:

If you use "map" as a variable name, you are overwriting the built-in Python function "map" with your data. You variable will work, but the function won't, and it won't be obvious why code that uses that function looks like it should be working but isn't.

You're probably not using the "map" function in your script and may not need to, but it's a good habit to avoid using Python reserved words as variables. Otherwise, it's really easy to accidentally write things like "list = [1,2,3]" or "type = 'mountains'" or "range = 10".

You *can* use reserved words as class attribute names like "self.map[x][y]" in the example from SurgicalOntologist below, because they're attached to the object.

PyCharm was invaluable when I was learning because it flagged that kind of stuff.

I agree, I was only using the word "map" here because the tutorial I initially based things off of used it. A pretty terrible practice which I'm glad to get away from.

I've been implementing a GameMap class, but something odd happens with the indexing when I play around with it in the interpreter. Here's the class:

Python code:
class GameMap(object):

    def __init__(self, id_number, level, location='surface'):
        self.id_number = id_number
        self.level = level  #this is the actual map.
        self.location = location

    def __getitem__(self, index):
        return self.level[index]
then I create a map and add it to a list_of_maps with:

Python code:
newmap = make_surface_map()
list_of_maps.append(GameMap(map_number, newmap, 'surface'))
which works ok in my code, but when I make some maps in the interpreter and explore the list_of_maps, I notice that I need 4 indexes to get a specific (x, y) coordinate of a map.
list_of_maps[0][1][x][y].foo works to give me the info on a specific x, y coordinate. The first index is the GameMap object in the list_of_maps, that's clear, but I don't know what the second value is. That second index, if I put 0, just returns 0, and if I put 1, it returns the entire 2D array of map tiles so I think it's the map array. If I put 2 it is out of bounds. What the heck is that second value indexing? Writing:
list_of_maps[0][1][0][0]
and
list_of_maps[0].level[1][0][0]
both refer to the exact same map square at (0, 0) but I don't get why the self.level thing needs the [1].

Edit: Is it the self.level variable in the GameMap object? I didn't know those could be indexed.

vvvvv I think you're right, make_surface_map was returning the map index as well as the new map.

reading fucked around with this message at 19:22 on Jan 3, 2015

Adbot
ADBOT LOVES YOU

SurgicalOntologist
Jun 17, 2004

I'm going to guess the problem is wherever you construct the map. For some reason make_surface_map is returning [0, actual_map].

You may also consider using numpy for your maps, if you're doing any math with them you'll find it invaluable. If you're not it's probably overkill, the only advantage being that it will allow you to do indexing like game_map[0, 0] or even game_map[:, 0] (first column) which is a bit trickier with just a list of lists.

Tacos Al Pastor
Jun 20, 2003

Trying to solve one of the problems on Google Foobar and its failing all the tests. Heres the problem:

quote:

Origins and order
=================

What do we know about Professor Boolean's past? It's mostly rumor and conjecture, but a few things are known to be true.

Mad Professor Boolean wasn't always a super villain. Early in his career, he was an average paper pusher, working in an office with some very backwards technology. One of his primary jobs was to carry date cards between departments. One morning, he tripped over a unicycle and dropped his date cards on the floor. He hit his head - and hit upon the idea of breeding an army of zombie rabbits to do his bidding and manage simple tasks. But that comes later. Before he could quit with an explosive YouTube video, the professor had to get his cards back in order.

Aha! It seems he recorded the details of this life-changing event in his diary. Let's try to reproduce his methods:

The goal is to get the date cards back in order. Each set of date cards consists of 3 cards, each with a number written on it. When arranged in some order, the numbers make up the representation of a date, in the form month/day/year. However, sometimes multiple representations will be possible. For example, if the date cards read 1, 1, 99 it could only mean 01/01/99, but if the date cards read 2, 30, 3, it could mean any one of 02/03/30, 03/02/30, or 03/30/02.

Write a function called answer(x, y, z) that takes as input the 3 numbers on the date cards. You may assume that at least one valid representation of a date can be constructed from the cards.

If there is only one valid representation, the function should return it as a string, in the form MM/DD/YY. If there are multiple valid representations, the function should return the string "Ambiguous." Each of x, y, z will be between 1 to 99 inclusive. You may also assume that there are no leap years.

Languages
=========

To provide a Python solution, edit solution.py
To provide a Java solution, edit solution.java

Test cases
==========

Inputs:
(int) x = 19
(int) y = 19
(int) z = 3
Output:
(string) "03/19/19"

Inputs:
(int) x = 2
(int) y = 30
(int) z = 3
Output:
(string) "Ambiguous"

Use verify [file] to test your solution and see how it does. When you are finished editing your code, use submit [file] to submit your answer. If your solution passes the test cases, it will be removed from your home folder.

And here is my code:
Python code:
def answer(x, y, z):   
    month = 12
    day = 31
    year = 99
    
    
    if x == y == z and x <= month and y <= day and z <= year:
        return('\"%d\%d\%d\"'%(x, y , z))
    elif x == y or y == z or x == z:
            if y < z and x < z:
                return('\"%02d\%02d\%02d\"'%(x, y ,z))
            elif y < x and z < x:
                return('\"%02d\%02d\%02d\"'%(z , y, x))
            elif x < y and z < y:
                return('\"%02d\%02d\%02d\"'%(x ,y, z))
            elif x ==y and y > z:
                return('\"%02d\%02d\%02d\"'%(z ,y, x))
            elif x == z and y < z:
                return('\"%02d\%02d\%02d\"'%(y ,z, x))
            elif y == z and x < y:
                return('\"%02d\%02d\%02d\"'%(x ,y, z))
    elif x <= month and y <= day or y <= month and z<= day or x<= month and y <= day:
        return("\"Ambigous\"")

When I run it locally everything works ok. I am not sure why its failing all the tests :( I know it looks dirty, Im working on this on the side for fun, havent put too much effort into it to really reduce smell.

Any insight?? Am I missing something?? Has anyone done these before?

edit: One thing that I might be missing is that for certain months, the days are not going to be 31, like for Feb and April for instance. So there is no 02/31/20. That might actually be a test case that I am failing.

Tacos Al Pastor fucked around with this message at 06:26 on Jan 4, 2015

BabyFur Denny
Mar 18, 2003
I think a function that checks if a date is a valid date might be very helpful here.

code:
import datetime
correctDate = None
try:
    newDate = datetime.datetime(x,y,z)
    correctDate = True
except ValueError:
    correctDate = False

baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

Yeah your logic doesn't look right - try taking your first test case (19, 19, 3) and reading through the code to see where that set of inputs takes you. Then change it to (12, 12, 3) - which is completely ambiguous - and see where that leads you in the code path.

It's a good idea to write more tests! Think of a few examples of all the awkward situations you'd need to test for (you've already been doing that in writing your code) and add them as tests, so you can be sure everything's working the way you think it is. And that way, when something fails you can debug it and find out exactly why it's tripping up

Also you spelled 'ambiguous' wrong in your return statement, so it's technically not producing the required output for those cases

Begall
Jul 28, 2008
Is there a solution much cleaner than this? Is there any decent publicly available page with teasers like these?

Python code:
import datetime

def answer(x, y, z):

    num = 0  
    possibilitymap = [(x, y, z), (y, x, z), (y, z, x), (x, z, y), (z, y, x), (z, x, y)]
    
    for values in possibilitymap:
        try:
            d = datetime.datetime(int('20' + str(values[0])), values[1], values[2])
            num += 1
            a = d
        except:
            pass

    if num > 1: 
        return "\"Ambiguous\""
    else:
        return "\"" + a.strftime("%m/%d/%y") + "\""

Begall fucked around with this message at 17:49 on Jan 4, 2015

supercrooky
Sep 12, 2006

Begall posted:

Is there a solution much cleaner than this? Is there any decent publicly available page with teasers like these?

Well, the problem statement says you can ignore leap years. I would hope this is because there are no test cases where it matters, but if there were a datetime based solution would be "wrong" for getting leap years correct. You also don't correctly handle the case (19, 19, 3), which is unambiguous.

You could cut down on checks by sorting the input values before checking for valid dates, since we know that for an unambiguous date, month <= 12, 12 < day <= daysinmonth, year > daysinmonth. So the date is ambiguous if our middle value (day) is a valid month and not equal to the smallest value, or our highest value (year) is a valid day and not equal to the middle value.

A solution taking advantage of the no leap years clause:

Python code:
def answer(x, y, z):
    month_length = {1: 31, 2: 28, 3: 31, 4: 30, 5: 31, 6:30, 7: 31, 8: 31, 9: 30, 10: 31, 11: 30, 12: 31}
    date = tuple(sorted((x, y, z)))
    if (date[1] <= 12 and date[0] != date[1]) or (date[2] <= month_length[date[0]] and date[1] != date[2]):
        return "Ambiguous"
    else:
        return "%02d/%02d/%02d" % date

Dominoes
Sep 20, 2007

Any things that can cause sorted() not to work as expected?

Python code:
 x = [{'std_low': 1.0,
  'conv_thresh': -0.1,
  'profit': 0.0079000000000000008,
  'sell_days': 6,
  'std_high': 2.5},
 {'std_low': 1.0,
  'conv_thresh': -0.1,
  'profit': nan,
  'sell_days': 6,
  'std_high': 3.0},
 {'std_low': 1.5,
  'conv_thresh': -0.1,
  'profit': 0.0038999999999999998,
  'sell_days': 6,
  'std_high': 2.5},
 {'std_low': 1.5,
  'conv_thresh': -0.1,
  'profit': nan,
  'sell_days': 6,
  'std_high': 3.0},
 {'std_low': 1.0,
  'conv_thresh': -0.09,
  'profit': 0.0079000000000000008,
  'sell_days': 6,
  'std_high': 2.5}]

[{'std_low': 1.0,
  'conv_thresh': -0.1,
  'profit': 0.0079000000000000008,
  'sell_days': 6,
  'std_high': 2.5},
 {'std_low': 1.0,
  'conv_thresh': -0.1,
  'profit': nan,
  'sell_days': 6,
  'std_high': 3.0},
 {'std_low': 1.5,
  'conv_thresh': -0.1,
  'profit': 0.0038999999999999998,
  'sell_days': 6,
  'std_high': 2.5},
 {'std_low': 1.5,
  'conv_thresh': -0.1,
  'profit': nan,
  'sell_days': 6,
  'std_high': 3.0},
 {'std_low': 1.0,
  'conv_thresh': -0.09,
  'profit': 0.0079000000000000008,
  'sell_days': 6,
  'std_high': 2.5}]
Same if I use operator.itemgetter() for the key. What's up? I suspect it has something to do with floats being weird sometimes. I don't think it's the numpy.nan thing, since it still doesn't work with those entries removed.

This works as expected:
Python code:
In [38]: x  = [{'v': 4}, {'v': 2}, {'v': 99}, {'v': np.nan}]

In [39]: sorted(x, key=lambda i: i['v'])
Out[39]: [{'v': 2}, {'v': 4}, {'v': 99}, {'v': nan}]
Looks like if I replace the profit values manually with ones that didn't get hosed by round(), it works. So, chalking this up to floats being weird.

Dominoes fucked around with this message at 21:34 on Jan 4, 2015

Tacos Al Pastor
Jun 20, 2003

supercrooky posted:


Python code:
def answer(x, y, z):
    month_length = {1: 31, 2: 28, 3: 31, 4: 30, 5: 31, 6:30, 7: 31, 8: 31, 9: 30, 10: 31, 11: 30, 12: 31}
    date = tuple(sorted((x, y, z)))
    if (date[1] <= 12 and date[0] != date[1]) or (date[2] <= month_length[date[0]] and date[1] != date[2]):
        return "Ambiguous"
    else:
        return "%02d/%02d/%02d" % date

This looks great. Sorting it actually simplifies it a lot now that I looked at your solution and sorting it doesn't really affect the result of the date or whether its ambiguous.

QuarkJets
Sep 8, 2008

Dominoes posted:

Any things that can cause sorted() not to work as expected?

Python code:
 x = [{'std_low': 1.0,
  'conv_thresh': -0.1,
  'profit': 0.0079000000000000008,
  'sell_days': 6,
  'std_high': 2.5},
 {'std_low': 1.0,
  'conv_thresh': -0.1,
  'profit': nan,
  'sell_days': 6,
  'std_high': 3.0},
 {'std_low': 1.5,
  'conv_thresh': -0.1,
  'profit': 0.0038999999999999998,
  'sell_days': 6,
  'std_high': 2.5},
 {'std_low': 1.5,
  'conv_thresh': -0.1,
  'profit': nan,
  'sell_days': 6,
  'std_high': 3.0},
 {'std_low': 1.0,
  'conv_thresh': -0.09,
  'profit': 0.0079000000000000008,
  'sell_days': 6,
  'std_high': 2.5}]

[{'std_low': 1.0,
  'conv_thresh': -0.1,
  'profit': 0.0079000000000000008,
  'sell_days': 6,
  'std_high': 2.5},
 {'std_low': 1.0,
  'conv_thresh': -0.1,
  'profit': nan,
  'sell_days': 6,
  'std_high': 3.0},
 {'std_low': 1.5,
  'conv_thresh': -0.1,
  'profit': 0.0038999999999999998,
  'sell_days': 6,
  'std_high': 2.5},
 {'std_low': 1.5,
  'conv_thresh': -0.1,
  'profit': nan,
  'sell_days': 6,
  'std_high': 3.0},
 {'std_low': 1.0,
  'conv_thresh': -0.09,
  'profit': 0.0079000000000000008,
  'sell_days': 6,
  'std_high': 2.5}]
Same if I use operator.itemgetter() for the key. What's up? I suspect it has something to do with floats being weird sometimes. I don't think it's the numpy.nan thing, since it still doesn't work with those entries removed.

This works as expected:
Python code:
In [38]: x  = [{'v': 4}, {'v': 2}, {'v': 99}, {'v': np.nan}]

In [39]: sorted(x, key=lambda i: i['v'])
Out[39]: [{'v': 2}, {'v': 4}, {'v': 99}, {'v': nan}]
Looks like if I replace the profit values manually with ones that didn't get hosed by round(), it works. So, chalking this up to floats being weird.

Can you describe your problem a little more clearly? That first chunk of code is just a list of dictionaries with no output shown

Dominoes
Sep 20, 2007

Oops, this: sorted(x, key=lambda i: i['profit']) was meant to be inserted between the two lists. The second list is the output. The second code block demonstrates a simplified example of what should be the same logic, working.

Sorted()'s not doing anything, and my only explanation is 'floats are weird'. I thought it might be because I tried to round the 'profit' values early, hence the weird 0-trailing decimals, but it turns out that's not it.

Dominoes fucked around with this message at 07:55 on Jan 5, 2015

brosmike
Jun 26, 2009
Your issue is probably that your input includes NaNs, which are explictly defined as being unordered with respect to other floats. Try it:

code:
>>> float('nan') < 1.0
False
>>> float('nan') >= 1.0
False
The sorted function cannot do anything sane with input which is defined to be unsortable, and essentially returns garbage. See this Stack Overflow post for a more in depth explanation.

QuarkJets
Sep 8, 2008

Yeah, floats aren't really weird, but NaN is weird.

Dominoes
Sep 20, 2007

Hey, looks like y'all are right about nan, and Mike's explanation makes sense. Using sum() and len() instead of np.mean() to generate 'profit' fixed it.

Dominoes fucked around with this message at 20:43 on Jan 5, 2015

neosloth
Sep 5, 2013

Professional Procrastinator
What would be the easiest way to run a periodic (once every 24 hours) task within a flask app. It's literally 3 lines of code so I wouldn't want to use something advanced like celery

EAT THE EGGS RICOLA
May 29, 2008

superstepa posted:

What would be the easiest way to run a periodic (once every 24 hours) task within a flask app. It's literally 3 lines of code so I wouldn't want to use something advanced like celery

What are you trying to do? If it's something super simple I'd probably just set up a cron job.

neosloth
Sep 5, 2013

Professional Procrastinator

EAT THE EGGS RICOLA posted:

What are you trying to do? If it's something super simple I'd probably just set up a cron job.

I just want to use beautfulsoup to scrape data from a table once every 24 hours. I want it to work on windows and I'd like to have all the code in python within the app but at the moment cron does seem like the best option

SurgicalOntologist
Jun 17, 2004

There's a Windows cron equivalent. Google "windows 7/8 schedule task." There will probably be a way to schedule it programmatically if that's what you're looking for.

namaste friends
Sep 18, 2004

by Smythe
What's this thread think about threading vs multiprocessing vs pathos?

I'm trying to count a large number of AWS S3 objects (in the order of millions) as quickly as possible. I started out with threading and then discovered that each thread wasn't run concurrently due to the Global Interpreter Lock and the implementation of threads. I'm playing around with multiprocessing now and through some debugging and problems pickling, I discovered pathos.

I thought I'd find out what you guys thought before I went and (possibly) wasted more time.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

I just wanted to stop in and say that I've been using mypy for the last week (I've just played with it previously) and it's pretty super if you've thought that Python could use option static type checking.

I won't use it all the time, but for larger programs its pretty nice (well it's still experimental so I won't use it for larger programs either yet).

Dominoes
Sep 20, 2007

Thermopyle posted:

I just wanted to stop in and say that I've been using mypy for the last week (I've just played with it previously) and it's pretty super if you've thought that Python could use option static type checking.

I won't use it all the time, but for larger programs its pretty nice (well it's still experimental so I won't use it for larger programs either yet).
I like how the type signatures provide a quick insight of what the function's doing. It's especially useful when inputting or outputting complex/nested data structures.

Dominoes fucked around with this message at 19:40 on Jan 8, 2015

KernelSlanders
May 27, 2013

Rogue operating systems on occasion spread lies and rumors about me.

Thermopyle posted:

I just wanted to stop in and say that I've been using mypy for the last week (I've just played with it previously) and it's pretty super if you've thought that Python could use option static type checking.

I won't use it all the time, but for larger programs its pretty nice (well it's still experimental so I won't use it for larger programs either yet).

It's an interesting idea, but seems to go against a lot of pythonic practices, especially the centrality of the dict or list with non-uniform types.

Dominoes posted:

I like how the type signatures provide a quick insight of what the function's doing. It's especially useful when inputting or outputting complex/nested data structures.

While that can be a plus when things are not otherwise well documented, but it doesn't replace proper documentation. I've been doing a fair bit of scala programming lately and it's amazing how many library authors think "type safe" means "don't have to write documentation."

reading
Jul 27, 2013
I'm having an issue with importing modules.

classes.py:
Python code:
from maincode import *

class MyThing(object):
    def __init__(self, params):
        self.params = params
        #some stuff
maincode.py:
Python code:
from classes import *

newthing = MyThing(params)
The error when I run "python maincode.py" is: NameError: global name 'MyThing' is not defined. I'm pretty sure I want to use the "from X import *" syntax because I want everything directly brought in to the namespace, and I don't want to have to prefix all the names with classes.MyThing(...).

KernelSlanders
May 27, 2013

Rogue operating systems on occasion spread lies and rumors about me.
You seem to have a circular dependency.

KICK BAMA KICK
Mar 2, 2009

That looks like the problem is a circular import, though in Python 3 those raise an ImportError rather than NameError but I assume that's a Python 2 thing.

maincode relies on classes which relies on maincode etc. and the interpreter can't resolve that for you. There are cheap fixes (lazily import one of the modules inside a function where it's first needed) and there's the right way to do it, which is almost always to structure your code in a different way. A module called maincode should probably not be imported by anything else; it should probably only contain the script glue that sets all your other components in motion. If there's something that classes needs inside maincode, that something should probably go in a third module. This can get tricky, feel free to elaborate.

e:f;b, and also don't get into the import * habit. It's much easier to type out classes. a few times than to inadvertently pollute your namespace or come back to your code later and wonder where the gently caress Foo comes from.

KICK BAMA KICK fucked around with this message at 04:29 on Jan 9, 2015

SurgicalOntologist
Jun 17, 2004

...or do from classes import SomeClass, SomeOtherClass and then every time you realize you need a new one stick it on the end of that import statement.

(an alternative to from classes import *, not circular dependencies). I would say a reasonable circularity dependency solution is to take whatever piece of maincode that you're importing into classes and just stick it in classes. In general, "classes" vs. "not classes" is probably not a good way to split your code.

SurgicalOntologist fucked around with this message at 04:41 on Jan 9, 2015

reading
Jul 27, 2013
Thanks, those are great ideas.

Tacos Al Pastor
Jun 20, 2003

In this case since MyClass is the only class you have to import, specifically say that, but even if you have multiple ones inside classes.py its just good practice to point out which one you want to use.

supermikhail
Nov 17, 2012


"It's video games, Scully."
Video games?"
"He enlists the help of strangers to make his perfect video game. When he gets bored of an idea, he murders them and moves on to the next, learning nothing in the process."
"Hmm... interesting."
I've tried to post this question multiple times, but it seemed like I came up with a new possible solution every time. I guess now I've diluted it to the essentials.

Do I have to do this?
code:
    @staticmethod
    def check(problem, answer):
        OneOperandProblem.check(problem, answer)
        answer = Decimal(str(answer))
        dec_places = -answer.as_tuple().exponent
        print("Decimal places: " + str(dec_places))
        correct = Decimal(str(round(sqrt(problem), dec_places)))
        print("Correct solution: " + str(correct))
        print("Submitted answer: " + str(answer))
        if answer == correct:
            return True
        else:
            return False
I'm referring to the numerous 'Decimal(str(' expressions. Otherwise it refuses to work. A possible input would be (80, 8.94), and as I've determined, the omission of any 'Decimal(str(' expression returns False, while it should be True. Also, I thought 'answer' came in from the calling method as a Decimal, because that's what it is there, but apparently no.

A similar method in a different place seems to work a little simpler:
code:
    @staticmethod
    def check(problem, answer):
        TwoOperandProblem.check(problem, answer)
        dec_places = -Decimal(str(answer)).as_tuple().exponent
        print("decimal places: " + str(dec_places))
        correct = round(Decimal(problem[0]) / problem[1], dec_places)
        print("correct answer: " + str(correct))
        if answer == correct:
            return True
        else:
            return False
But in the first method putting Decimal anywhere except around the whole expression doesn't seem to work. Sort of strange because I'd think it's the output of 'round' as a float which would be the problem. Although, I don't even have to convert 'answer' to Decimal for the comparison. Maybe I haven't tested it enough? drat. Okay, I'm going to post it now because it's late at night, and if you think I should do it, I'll retest the second method tomorrow.

QuarkJets
Sep 8, 2008

supermikhail posted:

I've tried to post this question multiple times, but it seemed like I came up with a new possible solution every time. I guess now I've diluted it to the essentials.

Do I have to do this?
code:
    @staticmethod
    def check(problem, answer):
        OneOperandProblem.check(problem, answer)
        answer = Decimal(str(answer))
        dec_places = -answer.as_tuple().exponent
        print("Decimal places: " + str(dec_places))
        correct = Decimal(str(round(sqrt(problem), dec_places)))
        print("Correct solution: " + str(correct))
        print("Submitted answer: " + str(answer))
        if answer == correct:
            return True
        else:
            return False
I'm referring to the numerous 'Decimal(str(' expressions. Otherwise it refuses to work. A possible input would be (80, 8.94), and as I've determined, the omission of any 'Decimal(str(' expression returns False, while it should be True. Also, I thought 'answer' came in from the calling method as a Decimal, because that's what it is there, but apparently no.

A similar method in a different place seems to work a little simpler:
code:
    @staticmethod
    def check(problem, answer):
        TwoOperandProblem.check(problem, answer)
        dec_places = -Decimal(str(answer)).as_tuple().exponent
        print("decimal places: " + str(dec_places))
        correct = round(Decimal(problem[0]) / problem[1], dec_places)
        print("correct answer: " + str(correct))
        if answer == correct:
            return True
        else:
            return False
But in the first method putting Decimal anywhere except around the whole expression doesn't seem to work. Sort of strange because I'd think it's the output of 'round' as a float which would be the problem. Although, I don't even have to convert 'answer' to Decimal for the comparison. Maybe I haven't tested it enough? drat. Okay, I'm going to post it now because it's late at night, and if you think I should do it, I'll retest the second method tomorrow.

It'd be useful if we knew what we were looking at here. Can you show us an entire class definition?

For instance:

quote:

Do I have to do this?
code:
    @staticmethod
    def check(problem, answer):
        OneOperandProblem.check(problem, answer)
        answer = Decimal(str(answer))
        dec_places = -answer.as_tuple().exponent
        print("Decimal places: " + str(dec_places))
        correct = Decimal(str(round(sqrt(problem), dec_places)))
        print("Correct solution: " + str(correct))
        print("Submitted answer: " + str(answer))
        if answer == correct:
            return True
        else:
            return False
I'm referring to the numerous 'Decimal(str(' expressions. Otherwise it refuses to work. A possible input would be (80, 8.94), and as I've determined, the omission of any 'Decimal(str(' expression returns False, while it should be True. Also, I thought 'answer' came in from the calling method as a Decimal, because that's what it is there, but apparently no.
It's going to depend on entirely how you're calling check(problem, answer). Did you define OneOperandProblem?

Try calling type(answer) and seeing what kind of answer is being passed in. You probably don't need to use Decimal(str(...)) but you might need Decimal(). You definitely don't need to invoke str() on this line:
code:
Decimal(str(round(sqrt(problem), dec_places)))
We can tell that "problem" is some sort of number, since it's apparently a valid argument for sqrt() without any type conversion. And then you round it. And then you could just call Decimal() on that value instead of Decimal(str())

In order to know for sure whether you need to convert the value returned by OneOperandProblem.check to a string before invoking Decimal(), we'd first have to know how OneOperandProblem.check is defined, or at least what kind of value it returns. It's likely that you don't need to use str() there.

QuarkJets
Sep 8, 2008

Also, if you pass 80, 8.94 to either of the methods shown here, then the lines that looks like this:
code:
OneOperandProblem.check(problem, answer)
don't actually accomplish anything because you're not catching any output. The "answer" variable within the scope of your check() method is not being modified by OneOperandProblem.check().

Rlazgoth
Oct 10, 2003
I attack people at random.
I am currently working on my first programming project ever, which is a tool for mining academic databases and automatically storing search matches in a local .txt file for later processing. I have no previous experience in programming whatsoever but after a LOT of reading and watching tutorials I managed to get an initial version of the script working. The script is very short and simple, but I will have to build a GUI for it since the potential users will very likely have no proficiency in programming.

I have made some attempts at creating a GUI with Tkinter, but I'm finding it much more difficult to program than the main script. Is there an easier and faster way to build GUIs? What I'm attempting to create is akin to search form, with several search bars (the number of which is defined by the user), with a dropdown menu for search type besides each of them (e.g, "Topic", "Author", etc.), and another for boolean operators.

Dominoes
Sep 20, 2007

Rlazgoth posted:

I am currently working on my first programming project ever, which is a tool for mining academic databases and automatically storing search matches in a local .txt file for later processing. I have no previous experience in programming whatsoever but after a LOT of reading and watching tutorials I managed to get an initial version of the script working. The script is very short and simple, but I will have to build a GUI for it since the potential users will very likely have no proficiency in programming.

I have made some attempts at creating a GUI with Tkinter, but I'm finding it much more difficult to program than the main script. Is there an easier and faster way to build GUIs? What I'm attempting to create is akin to search form, with several search bars (the number of which is defined by the user), with a dropdown menu for search type besides each of them (e.g, "Topic", "Author", etc.), and another for boolean operators.
I feel like PyQt is the most sophisticated and actively-developed GUI for python. That said, expect it to take longer to learn than the script you described. The QT docs are detailed, but are written for C++. There are no good tutorials. If you go this route, use the included examples as a reference, and ask questions here when you run into trouble.

There's a nice included WYSIWYG editor for it, but it's still a pain to learn.

Dominoes fucked around with this message at 22:55 on Jan 9, 2015

KICK BAMA KICK
Mar 2, 2009

Whatever GUI library you use (seconding Dominoes) the most important thing is structuring your code to separate the user interface from the logic. Not doing that will bite you in the rear end the second you realize you need to refactor something. There's a few different patterns like MVC and MVP that you can implement to satisfy this but don't get hung up on which, just pick something that makes sense to you.

Also, totally cool if you're just doing this to learn to code but just in case: is there something specific about your domain that makes writing a custom program a better solution to a problem that sounds like "search some databases" than just marshaling your data into a format usable by any of the myriad general-purpose database applications?

KICK BAMA KICK fucked around with this message at 23:00 on Jan 9, 2015

Rlazgoth
Oct 10, 2003
I attack people at random.

KICK BAMA KICK posted:

Whatever GUI library you use (seconding Dominoes) the most important thing is structuring your code to separate the user interface from the logic. Not doing that will bite you in the rear end the second you realize you need to refactor something. There's a few different patterns like MVC and MVP that you can implement to satisfy this but don't get hung up on which, just pick something that makes sense to you.

Also, totally cool if you're just doing this to learn to code but just in case: is there something specific about your domain that makes writing a custom program a better solution to a problem that sounds like "search some databases" than just marshaling your data into a format usable by any of the myriad general-purpose database applications?

In part this is a good opportunity for me to learn programming, which I've wanted to for a while now, but there was also some demand at the office for this kind of script. The site that we want to extract publication data from actually has an API for that, but it only allows retrieval of basic data - Author and Title. Even the search results page on the site only shows limited information. In order to get the full publication metadata - which we need - you have to click a series of buttons on the search page which lets you save the data in a .txt file. Unfortunately, this option only lets you save up to 500 records at a time - and the searches we run usually yield upwards of hundreds of thousands of results. We actually had a research assistant scrap together a dataset by manually exporting something like 200.000 records, in batches of 500 at a time. The idea of this script is to automate the process by having the user just run his search, and the script will download as many batches are necessary, merge them together, and save the output in a format which can then be used in a statistics package.

There might actually be an easier way to do this but I'm having a lot of fun programming so I don't mind. I completed the Python course on Codecademy before, but I think I'm learning much faster now that I'm actually working on something with a tangible result.

hooah
Feb 6, 2006
WTF?
I don't know if you're concerned about this, but it would be much more efficient to download the entire database (if that's possible) now, then download updates periodically.

supermikhail
Nov 17, 2012


"It's video games, Scully."
Video games?"
"He enlists the help of strangers to make his perfect video game. When he gets bored of an idea, he murders them and moves on to the next, learning nothing in the process."
"Hmm... interesting."

QuarkJets posted:

Also, if you pass 80, 8.94 to either of the methods shown here, then the lines that looks like this:
code:
OneOperandProblem.check(problem, answer)
don't actually accomplish anything because you're not catching any output. The "answer" variable within the scope of your check() method is not being modified by OneOperandProblem.check().

That could well be a newbie thing, but that checks that 'problem' and 'answer' are valid. OneOperandProblem is the superclass of several classes, each of which requires this operation (I think).

For clarity:
code:
class OneOperandProblem(Problem):
...
    @staticmethod
    def check(problem, answer):
        if type(problem) is not int or not issubclass(type(answer), Number):
            raise TypeError

QuarkJets posted:

It'd be useful if we knew what we were looking at here. Can you show us an entire class definition?
I don't think the entire class is going to be useful. It's a bunch of static methods which don't interact with each other. The one supremely confusing thing that I failed to clarify yesterday is above, and the class's name is RootProblem, so the idea of the method is to check that 'answer' is the correct root for the 'problem'. 'problem' is an int, by the way.

drat, I commented out the conversion of 'answer' into decimal and it works. (Type is 'Decimal'.) But I swear yesterday that broke the program... I don't even know what's going on anymore.

But omitting "str" from
code:
correct = Decimal(str(round(sqrt(problem), dec_places)))
still breaks it. 'correct' for root of 67 comes out as 8.199999999999999289457264239899814128875732421875.

QuarkJets
Sep 8, 2008

supermikhail posted:

That could well be a newbie thing, but that checks that 'problem' and 'answer' are valid. OneOperandProblem is the superclass of several classes, each of which requires this operation (I think).

For clarity:
code:
class OneOperandProblem(Problem):
...
    @staticmethod
    def check(problem, answer):
        if type(problem) is not int or not issubclass(type(answer), Number):
            raise TypeError

This is reasonable, I didn't expect you to be raising exceptions. However, a lot of Python programmers will frown at attempting to check the type of the input before doing something with it. Generally, the advice is to clearly document your function/method/whatever as expecting an integer (or something integer-like), and if a user provides something weird then it's on them. For instance, what if I wanted to be able to calculate the square root of a Decimal and check the answer? I'd pass Decimal(3.4) as the "problem" and your method would immediately raise an exception, because it's not an int, but otherwise I think that your code would work okay.

quote:

I don't think the entire class is going to be useful. It's a bunch of static methods which don't interact with each other. The one supremely confusing thing that I failed to clarify yesterday is above, and the class's name is RootProblem, so the idea of the method is to check that 'answer' is the correct root for the 'problem'. 'problem' is an int, by the way.

drat, I commented out the conversion of 'answer' into decimal and it works. (Type is 'Decimal'.) But I swear yesterday that broke the program... I don't even know what's going on anymore.

But omitting "str" from
code:
correct = Decimal(str(round(sqrt(problem), dec_places)))
still breaks it. 'correct' for root of 67 comes out as 8.199999999999999289457264239899814128875732421875.

That's because you're taking a float and then turning it into a Decimal. You need to work directly with Decimal objects instead. A lot of things in the math libraries will return a float. Have a look here:
https://docs.python.org/2/library/decimal.html

Here's an example of what you can do for this particular line:
code:
correct = Decimal(problem).sqrt().quantize(Decimal(10)**dec_places)
Take the Decimal first, then use the sqrt() method of Decimal, then round it using another method of Decimal

supermikhail
Nov 17, 2012


"It's video games, Scully."
Video games?"
"He enlists the help of strangers to make his perfect video game. When he gets bored of an idea, he murders them and moves on to the next, learning nothing in the process."
"Hmm... interesting."
Uh... I'm too much of a noob for this thread.

Okay, the input for the method comes from Django, and in fact the problem is randomly generated in the same model in a different method, so if the wrong types are submitted it's a bug I should fix... Aand I guess that's what tests are for. But for some reason it hasn't occurred to me previously... Or maybe not. Anyway, that's for the Django documentation.

Thanks for that decimal info, I didn't catch that when I first learned about the module. Though I'm not sure why the second method in my original post works as intended (except I should re-converting 'answer' to Decimal). Presumably it compares a Decimal to a float in the end.

supermikhail posted:

code:
    @staticmethod
    def check(problem, answer):
        TwoOperandProblem.check(problem, answer)
        dec_places = -Decimal(str(answer)).as_tuple().exponent
        print("decimal places: " + str(dec_places))
        correct = round(Decimal(problem[0]) / problem[1], dec_places)
        print("correct answer: " + str(correct))
        if answer == correct:
            return True
        else:
            return False
Oh. Here 'problem' is a tuple of two ints. Which is why I convert half of it to a Decimal. Although right now I'm not sure if I didn't do that in a fit of inspiration instead of based on actual concrete info.

Adbot
ADBOT LOVES YOU

Blinkz0rz
May 27, 2001

MY CONTEMPT FOR MY OWN EMPLOYEES IS ONLY MATCHED BY MY LOVE FOR TOM BRADY'S SWEATY MAGA BALLS

I'm still not clear what you're actually trying to do in general. Are you just writing a problem solver? How generic does it have to be? Do you want two operands? Three? n? What about operator types?

It seems as though you're calling TwoOperandProblem.check() so it seems like you've at least got a handle on the fact that you want to check a problem with two operands, but what if someone passes three operands into this check method?

You need to rethink your goal and then refactor the crap out of your code because it smells like you're trying to solve a problem that isn't actually the one you want to solve.

  • Locked thread