From deeppunster at gmail.com Thu Mar 7 11:57:20 2019 From: deeppunster at gmail.com (Travis Risner) Date: Thu, 07 Mar 2019 11:57:20 -0500 Subject: [CentralOH] [COhPy] DoJo Rumblings: Tonight's Python Challenge Message-ID: Here is a small problem for us to consider. At tonight?s DoJo meeting we will work together to solve this as individuals or small groups. We will also discuss the advantages of each approach. Given a array of numbers representing the stock prices of a company in chronological order, write a function that calculates the maximum profit you could have made from buying and selling that stock once. You must buy before you can sell it. For example, given [9, 11, 8, 5, 7, 10], you should return 5, since you could buy the stock at 5 dollars and sell it at 10 dollars. DoJo is at Smokehouse Brewing, 1130 Dublin Road, Columbus, Ohio. Join us at 6:00 or any time after that! Travis From neil.ludban at gmail.com Thu Mar 7 12:15:20 2019 From: neil.ludban at gmail.com (neil ludban) Date: Thu, 7 Mar 2019 19:15:20 +0200 Subject: [CentralOH] [COhPy] DoJo Rumblings: Tonight's Python Challenge In-Reply-To: References: Message-ID: With a minor pre-processing of the inputs, there's a O(n) solution with code (in python) on Wikipedia. :) On Thu, Mar 7, 2019, 18:57 Travis Risner wrote: > Here is a small problem for us to consider. At tonight?s DoJo meeting > we will work together to solve this as individuals or small groups. We > will also discuss the advantages of each approach. > > Given a array of numbers representing the stock prices of a > company in > chronological order, write a function that calculates the maximum > profit you > could have made from buying and selling that stock once. You must > buy > before > you can sell it. > > For example, given [9, 11, 8, 5, 7, 10], you should return 5, > since you > could buy the stock at 5 dollars and sell it at 10 dollars. > > DoJo is at Smokehouse Brewing, 1130 Dublin Road, Columbus, Ohio. Join > us at 6:00 or any time after that! > > Travis > _______________________________________________ > CentralOH mailing list > CentralOH at python.org > https://mail.python.org/mailman/listinfo/centraloh > -------------- next part -------------- An HTML attachment was scrubbed... URL: From deeppunster at gmail.com Thu Mar 7 20:05:22 2019 From: deeppunster at gmail.com (Travis Risner) Date: Thu, 07 Mar 2019 20:05:22 -0500 Subject: [CentralOH] Anonymous Solution Message-ID: <89EBFD45-E7C9-49BD-8325-17CECEC82F6B@gmail.com> #!/usr/bin/env python3 """ Anonymous solution to the following problem: Given a array of numbers representing the stock prices of a company in chronological order, write a function that calculates the maximum profit you could have made from buying and selling that stock once. You must buy before you can sell it. For example, given [9, 11, 8, 5, 7, 10], you should return 5, since you could buy the stock at 5 dollars and sell it at 10 dollars. This solution accepts the array on th command line. """ import sys def get_prices_from_arguments(args): return list(map(int, args[1:])) def calculate_maximum_profit(prices): maximum_profit = 0 maximum_price = None for price in reversed(prices): if maximum_price is None or price > maximum_price: maximum_price = price profit = maximum_price - price if profit > maximum_profit: maximum_profit = profit return maximum_profit def main(args): prices = get_prices_from_arguments(args) maximum_profit = calculate_maximum_profit(prices) print(maximum_profit) if __name__ == '__main__': main(sys.argv) -------------- next part -------------- An HTML attachment was scrubbed... URL: From kennethpatierno at gmail.com Thu Mar 7 20:04:09 2019 From: kennethpatierno at gmail.com (Kenneth Patierno) Date: Thu, 7 Mar 2019 20:04:09 -0500 Subject: [CentralOH] Solution for Max Stock Profit Message-ID: Cheers! KENNY PATIERNO *p : *614 <614-902-7379>-902-7379 *e : *kennethpatierno at gmail.com [image: Facebook] [image: Instagram] [image: Twitter] ? -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- stock_prices = [40,13,70,3,8,43,54,12,7,90,8] max_profit = -99 for stock_price in stock_prices: buy_price = stock_price for sell_price in stock_prices: net_profit = sell_price - buy_price if net_profit > max_profit: max_profit = net_profit stock_prices.pop(stock_prices.index(stock_price)) print("\nTotal Max Profit Available = $" + str(max_profit)) From jim.prior at accenture.com Fri Mar 8 14:22:10 2019 From: jim.prior at accenture.com (Prior, Jim) Date: Fri, 8 Mar 2019 19:22:10 +0000 Subject: [CentralOH] 2019-03-25 Python Meeting Message-ID: The March Monthly Python Meeting _will_ be at the (old) Columbus Forge on the ground floor of the Smith Brothers Hardware Company Building. https://www.meetup.com/Central-Ohio-Python-Users-Group/events/259333335/ Although Pillar will be moving in the next month or two, the March Python meeting will be at the regular place. ________________________________ This message is for the designated recipient only and may contain privileged, proprietary, or otherwise confidential information. If you have received it in error, please notify the sender immediately and delete the original. Any other use of the e-mail by you is prohibited. Where allowed by local law, electronic communications with Accenture and its affiliates, including e-mail and instant messaging (including content), may be scanned by our systems for the purposes of information security and assessment of internal compliance with Accenture policy. Your privacy is important to us. Accenture uses your personal data only in compliance with data protection laws. For further information on how Accenture processes your personal data, please see our privacy statement at https://www.accenture.com/us-en/privacy-policy. ______________________________________________________________________________________ www.accenture.com From deeptinker at gmail.com Sat Mar 9 00:06:40 2019 From: deeptinker at gmail.com (Travis Risner) Date: Sat, 09 Mar 2019 00:06:40 -0500 Subject: [CentralOH] Solution for Max Stock Profit In-Reply-To: References: Message-ID: Hi Ken, Thanks for posting this solution to the list! Travis On 7 Mar 2019, at 20:04, Kenneth Patierno wrote: > Cheers! > > KENNY PATIERNO > > *p : *614 <614-902-7379>-902-7379 > *e : *kennethpatierno at gmail.com > [image: Facebook] [image: > Instagram] [image: Twitter] > > > ? > _______________________________________________ > CentralOH mailing list > CentralOH at python.org > https://mail.python.org/mailman/listinfo/centraloh -------------- next part -------------- An HTML attachment was scrubbed... URL: From jim.prior at accenture.com Mon Mar 11 12:22:47 2019 From: jim.prior at accenture.com (Prior, Jim) Date: Mon, 11 Mar 2019 16:22:47 +0000 Subject: [CentralOH] Kenny's Solution for Max Stock Profit In-Reply-To: References: Message-ID: On Thursday, March 7, 2019 8:04:09 PM, Kenny wrote a solution to the challenge. If an extra value of 140 is appended to the initial stock_prices, what output does one expect? Does the code output that? ________________________________ This message is for the designated recipient only and may contain privileged, proprietary, or otherwise confidential information. If you have received it in error, please notify the sender immediately and delete the original. Any other use of the e-mail by you is prohibited. Where allowed by local law, electronic communications with Accenture and its affiliates, including e-mail and instant messaging (including content), may be scanned by our systems for the purposes of information security and assessment of internal compliance with Accenture policy. Your privacy is important to us. Accenture uses your personal data only in compliance with data protection laws. For further information on how Accenture processes your personal data, please see our privacy statement at https://www.accenture.com/us-en/privacy-policy. ______________________________________________________________________________________ www.accenture.com From neil.ludban at gmail.com Tue Mar 12 18:41:54 2019 From: neil.ludban at gmail.com (neil ludban) Date: Tue, 12 Mar 2019 18:41:54 -0400 Subject: [CentralOH] [COhPy] DoJo Rumblings: Tonight's Python Challenge In-Reply-To: References: Message-ID: #!/usr/bin/env python3.7 def delta(x): a = next(x) for b in x: yield b - a a = b def positive_sums(x): s = 0 for c in x: s += c if s > 0: yield s else: s = 0 prices = [ 9, 11, 8, 5, 7, 10 ] print(max(positive_sums(delta(iter(prices))))) On Thu, Mar 7, 2019 at 11:57 AM Travis Risner wrote: > Here is a small problem for us to consider. At tonight?s DoJo meeting > we will work together to solve this as individuals or small groups. We > will also discuss the advantages of each approach. > > Given a array of numbers representing the stock prices of a > company in > chronological order, write a function that calculates the maximum > profit you > could have made from buying and selling that stock once. You must > buy > before > you can sell it. > > For example, given [9, 11, 8, 5, 7, 10], you should return 5, > since you > could buy the stock at 5 dollars and sell it at 10 dollars. > > DoJo is at Smokehouse Brewing, 1130 Dublin Road, Columbus, Ohio. Join > us at 6:00 or any time after that! > > Travis > _______________________________________________ > CentralOH mailing list > CentralOH at python.org > https://mail.python.org/mailman/listinfo/centraloh > -------------- next part -------------- An HTML attachment was scrubbed... URL: From pybokeh at gmail.com Wed Mar 13 00:46:32 2019 From: pybokeh at gmail.com (pybokeh) Date: Wed, 13 Mar 2019 00:46:32 -0400 Subject: [CentralOH] Anyone uses nteract papermill? Call for opinions on using jupyter notebooks in production Message-ID: Hello, At my new role, I started to use papermill (admittedly with reservation and skepticism) to orchestrate the execution of parameterized jupyter notebooks used to automate my group's data processing needs. The result? I am now totally blown away and thrilled with papermill ( https://github.com/nteract/papermill). At my previous role, I had used jupyter notebook to prototype a data process to automatically create invoices. But to productionalize (sadly, didn't know papermill existed at the time), I had to port my jupyter notebook code to using a data pipelining framework called Luigi (https://github.com/spotify/luigi). Now with papermill, I see no need for me to port my jupyter notebooks to something completely different and thus incur more technical debt from having to learn yet another framework. With papermill, I define which jupyter notebooks run and what they depend on (dependency management). Furthermore, when a failure occurs, I can fix the bug, then run only the notebooks that didn't run (failure recovery) instead of re-running everything. So with these features afforded to me in papermill, the beauty is I can keep developing in jupyter notebooks as data pipeline scripts and use them for production. Also, with papermill, those that don't come from a software engineering or computer science background, can perform practical "data engineering" without having to learn sophisticated data engineer tools like Apache Airflow or Spotify Luigi, since papermill is far easier to learn, use, and get started than those heavyweight frameworks. Furthermore, a well annotated jupyter notebook is so much easier to debug and explain what it is doing to a team member. If you've avoided jupyter notebooks because of the tediousness of version controlling them or not being able to work with them using your favorite text editor or IDE, there is now jupytext (https://github.com/mwouts/jupytext) which allows you to edit notebooks as plain text. I think with all of these things in place, there is little to not like about using papermill to execute notebooks as workflows. However, since I am just a data analyst or "citizen developer", I would like to hear opinions/thoughts from seasoned IT professionals or data engineers who have worked with jupyter notebooks. I know of a couple limitations with papermill, it does not come with a means for scheduling tasks and it doesn't come with a fancy GUI or visualization tool. But would like to see what others come up with. I was inspired to give papermill a spin from Netflix's blog article: https://medium.com/netflix-techblog/notebook-innovation-591ee3221233 I figured if papermill/jupyter notebooks were a good fit for Netflix, I explored if they could be a good fit for my uses at work. So far, I am pleased with the initial results. - Daniel -------------- next part -------------- An HTML attachment was scrubbed... URL: From deeppunster at gmail.com Thu Mar 14 15:22:19 2019 From: deeppunster at gmail.com (Travis Risner) Date: Thu, 14 Mar 2019 15:22:19 -0400 Subject: [CentralOH] Python Problem for DoJo Tonight Message-ID: <85828E70-4515-499C-B036-8F061AA4E7F0@gmail.com> Hi folks, Here is today?s problem for people who show up at the DoJo tonight. Implement a URL shortener with the following methods: shorten(URL), which shortens the URL into a six-character alphanumeric string, such as zLg6wl. restore(short), which expands the shortened string into the original URL. If no such shortened string exists, return null. Hint: What if we enter the same URL twice? See you at the DoJo: Smokehouse Brewing 1130 Dublin Road Columbus, OH 43215 (614) 485-0227 Travis -------------- next part -------------- An HTML attachment was scrubbed... URL: From mrehner at e-wrench.net Fri Mar 15 15:01:08 2019 From: mrehner at e-wrench.net (mrehner) Date: Fri, 15 Mar 2019 19:01:08 +0000 Subject: [CentralOH] Python Problem for DoJo Tonight In-Reply-To: <85828E70-4515-499C-B036-8F061AA4E7F0@gmail.com> References: <85828E70-4515-499C-B036-8F061AA4E7F0@gmail.com> Message-ID: <0F9E1D0DC01BC4489DC8D649BF9F27F501CB3EF026@EXMBX01.prov.ad.hostmanagement.net> Hi Since no one posted a solution here's one with a list of python tutorial links. import random import string # a list of urls for testing url_list = ["https://astro-pi.org/", "https://wiki.python.org/moin/BeginnersGuide", "http://gvr.sourceforge.net/", "https://docs.python-guide.org/", "https://docs.python.org/3/tutorial/", "https://developers.google.com/edu/python/", "https://docs.python.org/3/tutorial/"] # the data store- a key,value pair url_dict = {} # if url is not in the url dictionary # creates a random 6 character key # updates url dictionary with key and url def shorten(url): if not search_for_url(url): key = make_key() # Add new key value pair url_dict.update({key: url}) # returns a url value if key is in dictionary, if not returns None (null) def restore(short): return url_dict.get(short, None) # Create 6 char key using upper case, lower case and numerical digits def make_key(): # seed function automatically called with system current time value as the seed value. random.seed() return ''.join(random.choice(string.ascii_letters + string.digits) for _i in range(6)) # returns true if a url is a value in the dictionary def search_for_url(url): return url in url_dict.values() if __name__ == '__main__': # fill the dictionary for item in url_list: shorten(item) # Verify results for k in url_dict: print(k, ": ", url_dict[k]) print("url for key: ", k, " is ", restore(k), "\n") print("Should return None: ", restore("1a2b3c")) I'm sure it can be improved and some may worry about a collision with a 62^6 random character generator, but that's it for me. Cheers, Mike ______________________________________ From: CentralOH [centraloh-bounces+mrehner=e-wrench.net at python.org] on behalf of Travis Risner [deeppunster at gmail.com] Sent: Thursday, March 14, 2019 3:22 PM To: COhPy Mailing List Subject: [CentralOH] Python Problem for DoJo Tonight Hi folks, Here is today?s problem for people who show up at the DoJo tonight. Implement a URL shortener with the following methods: shorten(URL), which shortens the URL into a six-character alphanumeric string, such as zLg6wl. restore(short), which expands the shortened string into the original URL. If no such shortened string exists, return null. Hint: What if we enter the same URL twice? See you at the DoJo: Smokehouse Brewing 1130 Dublin Road Columbus, OH 43215 (614) 485-0227 Travis From deeppunster at gmail.com Fri Mar 15 16:25:28 2019 From: deeppunster at gmail.com (Travis Risner) Date: Fri, 15 Mar 2019 16:25:28 -0400 Subject: [CentralOH] Python Problem for DoJo Tonight In-Reply-To: <85828E70-4515-499C-B036-8F061AA4E7F0@gmail.com> References: <85828E70-4515-499C-B036-8F061AA4E7F0@gmail.com> Message-ID: <4707E9E2-8E9D-46B3-8E0B-026E7C3C6777@gmail.com> Hi folks, Mike Rehner has published a solution (see his email in this thread). I have created a (perhaps overly complicated) solution and posted it on GitHub at https://github.com/deeppunster/ShortLongURL. If you have a solution you are willing to share, please post it here (or a link to it). Travis On 14 Mar 2019, at 15:22, Travis Risner wrote: > Hi folks, > > Here is today?s problem for people who show up at the DoJo tonight. > > Implement a URL shortener with the following methods: > > shorten(URL), which shortens the URL into a six-character > alphanumeric > string, such as zLg6wl. > > restore(short), which expands the shortened string into the > original URL. If no such shortened string exists, return null. > > Hint: What if we enter the same URL twice? > > See you at the DoJo: > > Smokehouse Brewing > 1130 Dublin Road > Columbus, OH 43215 > (614) 485-0227 > > Travis -------------- next part -------------- An HTML attachment was scrubbed... URL: From deeppunster at gmail.com Thu Mar 21 15:38:49 2019 From: deeppunster at gmail.com (Travis Risner) Date: Thu, 21 Mar 2019 15:38:49 -0400 Subject: [CentralOH] DoJo Problem for Tonight Message-ID: Hi folks, If you are interested, here is a problem to consider for tonight?s meeting. ???????? Given a 2D matrix of characters and a target word, write a function that returns whether the word can be found in the matrix by going left-to-right, or up-to-down. For example, given the following matrix: [['F', 'A', 'C', 'I'], ['O', 'B', 'Q', 'P'], ['A', 'N', 'O', 'B'], ['M', 'A', 'S', 'S']] and the target word 'FOAM', you should return true, since it's the leftmost column. Similarly, given the target word 'MASS', you should return true, since it's the last row. ???????? See you tonight! Travis From winningham at gmail.com Thu Mar 21 16:12:53 2019 From: winningham at gmail.com (Thomas Winningham) Date: Thu, 21 Mar 2019 16:12:53 -0400 Subject: [CentralOH] DoJo Problem for Tonight In-Reply-To: References: Message-ID: I tried to make a one-liner for this. I can imagine a possibly simpler NumPy based idea though maybe? Essentially joins the strings by column and then simply by row, appends both of those, and then tests for membership. This would not find partial matches. the_matrix=[['F', 'A', 'C', 'I'], ['O', 'B', 'Q', 'P'], ['A', 'N', 'O', 'B'], ['M', 'A', 'S', 'S']] test_function = lambda t : t in [ ''.join([y[z] for y in the_matrix]) for z in range(len(the_matrix[0]))] + [ ''.join(y) for y in the_matrix] >>> test_function('FOAM') True >>> test_function('FOA') False >>> test_function('FOAMS') False >>> test_function('MASS') True >>> test_function('MAS') False On Thu, Mar 21, 2019 at 3:39 PM Travis Risner wrote: > Hi folks, > > If you are interested, here is a problem to consider for tonight?s > meeting. > > ???????? > > Given a 2D matrix of characters and a target word, write a function that > returns whether the word can be found in the matrix by going > left-to-right, or up-to-down. > > For example, given the following matrix: > > [['F', 'A', 'C', 'I'], > ['O', 'B', 'Q', 'P'], > ['A', 'N', 'O', 'B'], > ['M', 'A', 'S', 'S']] > and the target word 'FOAM', you should return true, since it's the > leftmost column. Similarly, given the target word 'MASS', you should > return true, since it's the last row. > > ???????? > > See you tonight! > > Travis > _______________________________________________ > CentralOH mailing list > CentralOH at python.org > https://mail.python.org/mailman/listinfo/centraloh > -------------- next part -------------- An HTML attachment was scrubbed... URL: From neil.ludban at gmail.com Thu Mar 21 21:27:26 2019 From: neil.ludban at gmail.com (neil ludban) Date: Thu, 21 Mar 2019 21:27:26 -0400 Subject: [CentralOH] DoJo Problem for Tonight In-Reply-To: References: Message-ID: #!/usr/bin/env python3.7 def row_generator(p): for row in p: yield ''.join(row) def col_generator(p): for col in zip(*p): yield ''.join(col) def word_in_puzzle(w, p): for x in row_generator(p): if w in x: return True for x in col_generator(p): if w in x: return True return False puzzle = [ [ 'F', 'A', 'C', 'I' ], [ 'O', 'B', 'Q', 'P' ], [ 'A', 'N', 'O', 'B' ], [ 'M', 'A', 'S', 'S' ], ] print(word_in_puzzle('FOAM', puzzle)) print(word_in_puzzle('MASS', puzzle)) On Thu, Mar 21, 2019 at 3:39 PM Travis Risner wrote: > Hi folks, > > If you are interested, here is a problem to consider for tonight?s > meeting. > > ???????? > > Given a 2D matrix of characters and a target word, write a function that > returns whether the word can be found in the matrix by going > left-to-right, or up-to-down. > > For example, given the following matrix: > > [['F', 'A', 'C', 'I'], > ['O', 'B', 'Q', 'P'], > ['A', 'N', 'O', 'B'], > ['M', 'A', 'S', 'S']] > and the target word 'FOAM', you should return true, since it's the > leftmost column. Similarly, given the target word 'MASS', you should > return true, since it's the last row. > > ???????? > > See you tonight! > > Travis > _______________________________________________ > CentralOH mailing list > CentralOH at python.org > https://mail.python.org/mailman/listinfo/centraloh > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ducharmemp at gmail.com Thu Mar 21 23:35:32 2019 From: ducharmemp at gmail.com (Matthew DuCharme) Date: Thu, 21 Mar 2019 23:35:32 -0400 Subject: [CentralOH] DoJo Problem for Tonight In-Reply-To: References: Message-ID: Since everyone has gone for the readable solutions so far, here's mine. I wish I could figure out some way to avoid allocating the extra strings from the slices overall. from itertools import chain, product def is_word_in_puzzle(word, puzzle): rows = len(puzzle) columns = len(puzzle[0]) puzzle = "".join(chain.from_iterable(puzzle)) return any( word in ( puzzle[i * columns: i * columns + columns], puzzle[j::columns] ) for i, j in product(range(rows), range(columns)) ) puzzle = [ [ 'F', 'A', 'C', 'I' ], [ 'O', 'B', 'Q', 'P' ], [ 'A', 'N', 'O', 'B' ], [ 'M', 'A', 'S', 'S' ], ] assert is_word_in_puzzle('FOAM', puzzle) == True assert is_word_in_puzzle('ABNA', puzzle) == True assert is_word_in_puzzle('CQOS', puzzle) == True assert is_word_in_puzzle('ANOBFFF', puzzle) == False assert is_word_in_puzzle('MASS', puzzle) == True On Thu, Mar 21, 2019 at 9:27 PM neil ludban wrote: > #!/usr/bin/env python3.7 > > def row_generator(p): > for row in p: > yield ''.join(row) > > def col_generator(p): > for col in zip(*p): > yield ''.join(col) > > def word_in_puzzle(w, p): > for x in row_generator(p): > if w in x: > return True > for x in col_generator(p): > if w in x: > return True > return False > > puzzle = [ > [ 'F', 'A', 'C', 'I' ], > [ 'O', 'B', 'Q', 'P' ], > [ 'A', 'N', 'O', 'B' ], > [ 'M', 'A', 'S', 'S' ], > ] > > print(word_in_puzzle('FOAM', puzzle)) > print(word_in_puzzle('MASS', puzzle)) > > > On Thu, Mar 21, 2019 at 3:39 PM Travis Risner > wrote: > >> Hi folks, >> >> If you are interested, here is a problem to consider for tonight?s >> meeting. >> >> ???????? >> >> Given a 2D matrix of characters and a target word, write a function that >> returns whether the word can be found in the matrix by going >> left-to-right, or up-to-down. >> >> For example, given the following matrix: >> >> [['F', 'A', 'C', 'I'], >> ['O', 'B', 'Q', 'P'], >> ['A', 'N', 'O', 'B'], >> ['M', 'A', 'S', 'S']] >> and the target word 'FOAM', you should return true, since it's the >> leftmost column. Similarly, given the target word 'MASS', you should >> return true, since it's the last row. >> >> ???????? >> >> See you tonight! >> >> Travis >> _______________________________________________ >> CentralOH mailing list >> CentralOH at python.org >> https://mail.python.org/mailman/listinfo/centraloh >> > _______________________________________________ > CentralOH mailing list > CentralOH at python.org > https://mail.python.org/mailman/listinfo/centraloh > -------------- next part -------------- An HTML attachment was scrubbed... URL: From deeppunster at gmail.com Thu Mar 28 15:28:00 2019 From: deeppunster at gmail.com (Travis Risner) Date: Thu, 28 Mar 2019 15:28:00 -0400 Subject: [CentralOH] DoJo Mumbilings for March 28, 2019 Message-ID: <1DCBAA90-1492-48C9-A1A9-E5AEDD52384B@gmail.com> Hi folks, Here is a problem proposed by one of our own members. (The problem is in the attached PDF.) Travis -------------- next part -------------- A non-text attachment was scrubbed... Name: Joe's Problem.pdf Type: application/pdf Size: 129444 bytes Desc: not available URL: From winningham at gmail.com Thu Mar 28 17:41:36 2019 From: winningham at gmail.com (Thomas Winningham) Date: Thu, 28 Mar 2019 17:41:36 -0400 Subject: [CentralOH] DoJo Mumbilings for March 28, 2019 In-Reply-To: <1DCBAA90-1492-48C9-A1A9-E5AEDD52384B@gmail.com> References: <1DCBAA90-1492-48C9-A1A9-E5AEDD52384B@gmail.com> Message-ID: 1. Fixes row 9 to have category 2 2. Creates an EAV "facts" table, sort of like a graph 3. Assumes only one matching value, no aggregate sums, etc 4. Extendable to other similar problems, although report generation is rather hard coded for this dataset import uuid fields = ['id','category','type','value'] data = [ [1,1,"A",2], [2,3,"D",5], [3,4,"B",7], [4,2,"C",8], [5,4,"D",9], [6,4,"C",1], [7,1,"D",3], [8,3,"C",9], [9,2,"A",5], [10,3,"A",4], [11,1,"B",6], [12,4,"A",2], [13,2,"D",6], [14,3,"B",3], [15,2,"B",8], [16,1,"C",0] ] # Create fact table facts = [] for x in data: this_fact=str(uuid.uuid1()) for f in range(len(fields)): facts.append((this_fact, fields[f], x[f])) # Create some query functions for EAV structure E,A,V = 0,1,2 q_e4av = lambda a,v : [x[E] for x in facts if x[A]==a and x[V]==v] q_v4a = lambda a : [x[V] for x in facts if x[A]==a] q_v4ea = lambda e,a : [x[V] for x in facts if x[E]==e and x[A]==a] # Generate report uniq_cats = sorted(list(set(q_v4a('category')))) uniq_typs = sorted(list(set(q_v4a('type')))) result=[] for c in uniq_cats: row=[] for t in uniq_typs: cat_ids = set(q_e4av('category',c)) typ_ids = set(q_e4av('type',t)) result_entity = list(cat_ids & typ_ids) if len(result_entity) > 0: row.append(q_v4ea(result_entity[0],'value')[0]) else: row.append(None) result.append(row) print('\t'+'\t'.join(uniq_typs)) for c in range(len(uniq_cats)): print('\t'.join([str(uniq_cats[c])]+[repr(x) for x in result[c]])) #----------------------- $ python3 test1.py A B C D 1 2 6 0 3 2 5 8 8 6 3 4 3 9 5 4 2 7 1 9 On Thu, Mar 28, 2019 at 3:53 PM Travis Risner wrote: > Hi folks, > > Here is a problem proposed by one of our own members. (The problem is > in the attached PDF.) > > Travis > > _______________________________________________ > CentralOH mailing list > CentralOH at python.org > https://mail.python.org/mailman/listinfo/centraloh > -------------- next part -------------- An HTML attachment was scrubbed... URL: From neil.ludban at gmail.com Thu Mar 28 22:09:20 2019 From: neil.ludban at gmail.com (neil ludban) Date: Thu, 28 Mar 2019 22:09:20 -0400 Subject: [CentralOH] DoJo Mumbilings for March 28, 2019 In-Reply-To: <1DCBAA90-1492-48C9-A1A9-E5AEDD52384B@gmail.com> References: <1DCBAA90-1492-48C9-A1A9-E5AEDD52384B@gmail.com> Message-ID: #!/usr/bin/env python3.7 import re from itertools import chain def load_table(text): for row in text.splitlines(): m = re.match(r'[0-9]+\s+([1-4])\s+([A-D])\s+([0-9])', row) if not m: continue yield m.groups() return def make_report(data): sep = '+----------+-----+-----+-----+-----+' yield sep headers = [ 'A', 'B', 'C', 'D' ] it = chain(headers, data) sep = sep.replace('-', '=') for Category in ( 'Category', '1', '2', '3', '4' ): A, B, C, D = next(it), next(it), next(it), next(it) yield F'| {Category:>8} | {A} | {B} | {C} | {D} |' yield sep sep = sep.replace('=', '-') return sample_table_1 = ''' === ========= ===== ===== ID Category Type Value === ========= ===== ===== 1 1 A 2 2 3 D 5 3 4 B 7 4 2 C 8 5 4 D 9 6 4 C 1 7 1 D 3 8 3 C 9 9 2 A 5 XXX 10 3 A 4 11 1 B 6 12 4 A 2 13 2 D 6 14 3 B 3 15 2 B 8 16 1 C 0 === ========= ===== ===== ''' sample_report_1 = ''' +----------+-----+-----+-----+-----+ | Category | A | B | C | D | +==========+=====+=====+=====+=====+ | 1 | 2 | 6 | 0 | 3 | +----------+-----+-----+-----+-----+ | 2 | 5 | 8 | 8 | 6 | +----------+-----+-----+-----+-----+ | 3 | 4 | 3 | 9 | 5 | +----------+-----+-----+-----+-----+ | 4 | 2 | 7 | 1 | 9 | +----------+-----+-----+-----+-----+ ''' rows = [ row[2] for row in sorted(load_table(sample_table_1)) ] report = '\n'.join(make_report(rows)) print(report) assert report.strip() == sample_report_1.strip() #--# On Thu, Mar 28, 2019 at 3:53 PM Travis Risner wrote: > Hi folks, > > Here is a problem proposed by one of our own members. (The problem is > in the attached PDF.) > > Travis > > _______________________________________________ > CentralOH mailing list > CentralOH at python.org > https://mail.python.org/mailman/listinfo/centraloh > -------------- next part -------------- An HTML attachment was scrubbed... URL: