-3

Consider sorted lists of length 7 where each entry x is a number 2 <= x <= 14 and the duplicate count of any entry can't exceed 4. The assumption here is that a high-performance algorithm has already determined that we have a non-straight / non-flush hand.

Online poker sites would be interested in high-performance algorithms taking care of the next step of getting the 5 best cards in this context.

Writing a program in Python that doesn't import modules is a great way to prototype such algorithms.

Most likely the 'monster size' online poker sites don't need any help from us, but it would be interesting to see algorithms designed for speed. In the question

7 Card Poker Hand Evaluator

from 2010 this was examined, but many links are broken. It would be nice to know the status of the fastest known algorithms used today.

Question: Is the algorithm discussed below known? Has some algorithm been determined to be a standout for performance?

My work

I noticed that a list of length 7 has a midpoint and that there is 'combinatorial symmetry' and structure that an algorithm can incorporate. We implement this logic in the following code. One can think of a lightening fast program written in assembler that calculates a GOTO number offset with the solution.

Note: I also have a one-pass sort routine that takes any 7 cards and determines whether straight or flushes can be made. But I've been advised to keep my questions more focused, so that is not discussed here.

Python Program:

hand=[2,2,7,7,8,11,12]
hand=[2,3,4,7,7,7,11]


start_spot = 3
end_spot = 3

if hand[3] == hand[4]:
    if hand[4] == hand[5]:
        if hand[5] == hand[6]:
            end_spot = 6
        else:
            end_spot = 5
    else:
        end_spot = 4

if hand[3] == hand[2]:
    if hand[2] == hand[1]:
        if hand[1] == hand[0]:
            start_spot = 0
        else:
            start_spot = 1
    else:
        start_spot = 2

if end_spot - start_spot == 3:
    if end_spot == 6:
        Kick = hand[start_spot-1]
    else:
        Kick = hand[6]
    best5 = [Kick,hand[start_spot],hand[start_spot+1],hand[start_spot+2],hand[start_spot+3]]
    print(hand, best5, 'four of a kind')
    raise SystemExit
else:
    pass


def multCount(c1,c2,c3):
    pc = 0
    if c1 == c2: pc = pc + 1
    if c2 == c3: pc = pc + 10
    return pc

pc_r = multCount(hand[4],hand[5],hand[6])
pc_l = multCount(hand[2],hand[1],hand[0])

if start_spot == 3 and end_spot == 3:
    if   pc_l ==  0 and pc_r == 0:        
        best5 = [hand[2],hand[3],hand[4],hand[5],hand[6]]
        print(hand, best5, 'no pair')
        raise SystemExit
    elif pc_l ==  0 and pc_r == 1:   
        best5 = [hand[2],hand[3],hand[6],hand[4],hand[5]]
        print(hand, best5, 'one pair')
        raise SystemExit
    elif pc_l ==  0 and pc_r == 10:       
        best5 = [hand[2],hand[3],hand[4],hand[5],hand[6]]
        print(hand, best5, 'one pair')
        raise SystemExit
    elif pc_l ==  0 and pc_r == 11:       
        best5 = [hand[2],hand[3],hand[4],hand[5],hand[6]]
        print(hand, best5, 'trips')
        raise SystemExit

    elif pc_l == 1  and pc_r == 0:        
        best5 = [hand[4],hand[5],hand[6],hand[1],hand[2]]
        print(hand, best5, 'one pair')
        raise SystemExit
    elif pc_l == 1  and pc_r == 1:       
        best5 = [hand[6],hand[1],hand[2],hand[4],hand[5]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l == 1  and pc_r == 10:       
        best5 = [hand[4],hand[1],hand[2],hand[5],hand[6]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l == 1  and pc_r == 11:       
        best5 = [hand[1],hand[2],hand[4],hand[5],hand[6]]
        print(hand, best5, 'full house')
        raise SystemExit

    elif pc_l == 10 and pc_r == 0:        
        best5 = [hand[4],hand[5],hand[6],hand[0],hand[1]]
        print(hand, best5, 'one pair')
        raise SystemExit
    elif pc_l == 10 and pc_r == 1:       
        best5 = [hand[6],hand[0],hand[1],hand[4],hand[5]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l == 10 and pc_r == 10:       
        best5 = [hand[4],hand[0],hand[1],hand[5],hand[6]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l == 10 and pc_r == 11:       
        best5 = [hand[0],hand[1],hand[4],hand[5],hand[6]]
        print(hand, best5, 'full house')
        raise SystemExit

    elif pc_l == 11 and pc_r == 0:        
        best5 = [hand[5],hand[6],hand[0],hand[1],hand[2]]
        print(hand, best5, 'trips')
        raise SystemExit
    elif pc_l == 11 and pc_r == 1:       
        best5 = [hand[4],hand[5],hand[0],hand[1],hand[2]]
        print(hand, best5, 'full house')
        raise SystemExit
    elif pc_l == 11 and pc_r == 10:       
        best5 = [hand[5],hand[6],hand[0],hand[1],hand[2]]
        print(hand, best5, 'full house')
        raise SystemExit
    elif pc_l == 11 and pc_r == 11:       
        best5 = [hand[1],hand[2],hand[4],hand[5],hand[6]]
        print(hand, best5, 'full house')
        raise SystemExit

    else:
        pass



if start_spot == 3 and end_spot == 4:
    if   pc_l ==  0 and pc_r == 0:        
        best5 = [hand[2],hand[5],hand[6],hand[3],hand[4]]
        print(hand, best5, 'one pair')
        raise SystemExit
    elif pc_l ==  0 and pc_r == 1:
        print("ERROR 1")
        pass # can't happen
        raise SystemExit    
    elif pc_l ==  0 and pc_r == 10:       
        best5 = [hand[2],hand[3],hand[4],hand[5],hand[6]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l ==  0 and pc_r == 11:       
        print("ERROR 2")
        pass # can't happen
        raise SystemExit

    elif pc_l == 1  and pc_r == 0:        
        best5 = [hand[6],hand[1],hand[2],hand[3],hand[4]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l == 1  and pc_r == 1:       
        print("ERROR 3")
        pass # can't happen
        raise SystemExit    
    elif pc_l == 1  and pc_r == 10:       
        best5 = [hand[2],hand[3],hand[4],hand[5],hand[6]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l == 1  and pc_r == 11:       
        print("ERROR 4")
        pass # can't happen
        raise SystemExit

    elif pc_l == 10 and pc_r == 0:        
        best5 = [hand[6],hand[0],hand[1],hand[3],hand[4]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l == 10 and pc_r == 1:       
        print("ERROR 5")
        pass # can't happen
        raise SystemExit
    elif pc_l == 10 and pc_r == 10:       
        best5 = [hand[4],hand[0],hand[1],hand[5],hand[6]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l == 10 and pc_r == 11:       
        print("ERROR 6")
        pass # can't happen
        raise SystemExit

    elif pc_l == 11 and pc_r == 0:        
        best5 = [hand[3],hand[4],hand[0],hand[1],hand[2]]
        print(hand, best5, 'full house')
        raise SystemExit
    elif pc_l == 11 and pc_r == 1:       
        print("ERROR 7")
        pass # can't happen
        raise SystemExit
    elif pc_l == 11 and pc_r == 10:       
        best5 = [hand[5],hand[6],hand[0],hand[1],hand[2]]
        print(hand, best5, 'full house')
        raise SystemExit
    elif pc_l == 11 and pc_r == 11:       
        print("ERROR 8")
        pass # can't happen
        raise SystemExit

    else:
        pass


if start_spot == 2 and end_spot == 3:
    if   pc_l ==  0 and pc_r == 0:        
        best5 = [hand[4],hand[5],hand[6],hand[2],hand[3]]
        print(hand, best5, 'one pair')
        raise SystemExit
    elif pc_l ==  0 and pc_r == 1:
        best5 = [hand[6],hand[2],hand[3],hand[4],hand[5]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l ==  0 and pc_r == 10:       
        best5 = [hand[4],hand[2],hand[3],hand[5],hand[6]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l ==  0 and pc_r == 11:       
        print("ERROR 9")
        pass # can't happen
        raise SystemExit

    elif pc_l == 1  and pc_r == 0:        
        print("ERROR 10")
        pass # can't happen
        raise SystemExit
    elif pc_l == 1  and pc_r == 1:       
        print("ERROR 11")
        pass # can't happen
        raise SystemExit    
    elif pc_l == 1  and pc_r == 10:       
        print("ERROR 12")
        pass # can't happen
        raise SystemExit
    elif pc_l == 1  and pc_r == 11:       
        print("ERROR 13")
        pass # can't happen
        raise SystemExit

    elif pc_l == 10 and pc_r == 0:        
        best5 = [hand[6],hand[0],hand[1],hand[2],hand[3]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l == 10 and pc_r == 1:       
        best5 = [hand[6],hand[2],hand[3],hand[4],hand[5]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l == 10 and pc_r == 10:       
        best5 = [hand[4],hand[2],hand[3],hand[5],hand[6]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l == 10 and pc_r == 11:       
        print("ERROR 14")
        pass # can't happen
        raise SystemExit

    elif pc_l == 11 and pc_r == 0:        
        print("ERROR 15")
        pass # can't happen
        raise SystemExit
    elif pc_l == 11 and pc_r == 1:       
        print("ERROR 16")
        pass # can't happen
        raise SystemExit
    elif pc_l == 11 and pc_r == 10:       
        print("ERROR 17")
        pass # can't happen
        raise SystemExit
    elif pc_l == 11 and pc_r == 11:       
        print("ERROR 18")
        pass # can't happen
        raise SystemExit

    else:
        pass


if start_spot == 2 and end_spot == 4:
    if   pc_l ==  0 and pc_r == 0:        
        best5 = [hand[5],hand[6],hand[2],hand[3],hand[4]]
        print(hand, best5, 'trips')
        raise SystemExit
    elif pc_l ==  0 and pc_r == 1:
        print("ERROR 19")
        pass # can't happen
        raise SystemExit    
    elif pc_l ==  0 and pc_r == 10:       
        best5 = [hand[5],hand[6],hand[2],hand[3],hand[4]]
        print(hand, best5, 'full house')
        raise SystemExit
    elif pc_l ==  0 and pc_r == 11:       
        print("ERROR 20")
        pass # can't happen
        raise SystemExit

    elif pc_l == 1  and pc_r == 0:        
        print("ERROR 21")
        pass # can't happen
        raise SystemExit
    elif pc_l == 1  and pc_r == 1:       
        print("ERROR 22")
        pass # can't happen
        raise SystemExit    
    elif pc_l == 1  and pc_r == 10:       
        print("ERROR 23")
        pass # can't happen
        raise SystemExit
    elif pc_l == 1  and pc_r == 11:       
        print("ERROR 24")
        pass # can't happen
        raise SystemExit

    elif pc_l == 10 and pc_r == 0:        
        best5 = [hand[0],hand[1],hand[2],hand[3],hand[4]]
        print(hand, best5, 'full house')
        raise SystemExit
    elif pc_l == 10 and pc_r == 1:       
        print("ERROR 25")
        pass # can't happen
        raise SystemExit
    elif pc_l == 10 and pc_r == 10:       
        best5 = [hand[5],hand[6],hand[2],hand[3],hand[4]]
        print(hand, best5, 'full house')
        raise SystemExit
    elif pc_l == 10 and pc_r == 11:       
        print("ERROR 26")
        pass # can't happen
        raise SystemExit

    elif pc_l == 11 and pc_r == 0:        
        print("ERROR 27")
        pass # can't happen
        raise SystemExit
    elif pc_l == 11 and pc_r == 1:       
        print("ERROR 28")
        pass # can't happen
        raise SystemExit
    elif pc_l == 11 and pc_r == 10:       
        print("ERROR 29")
        pass # can't happen
        raise SystemExit
    elif pc_l == 11 and pc_r == 11:       
        print("ERROR 30")
        pass # can't happen
        raise SystemExit

    else:
        pass


if start_spot == 1 and end_spot == 3:
    if   pc_r ==  0:
        best5 = [hand[5],hand[6],hand[1],hand[2],hand[3]]
        print(hand, best5, 'trips')
        raise SystemExit
    elif pc_r ==  1:
        best5 = [hand[4],hand[5],hand[1],hand[2],hand[3]]
        print(hand, best5, 'full house')
        raise SystemExit
    elif pc_r ==  10:   
        best5 = [hand[5],hand[6],hand[1],hand[2],hand[3]]
        print(hand, best5, 'full house')
        raise SystemExit
    elif pc_r ==  11:
        best5 = [hand[2],hand[3],hand[4],hand[5],hand[6]]
        print(hand, best5, 'full house')
        raise SystemExit

    else:
        pass


if start_spot == 3 and end_spot == 5:
    if   pc_l ==  0:
        best5 = [hand[2],hand[6],hand[3],hand[4],hand[5]]
        print(hand, best5, 'trips')
        raise SystemExit
    elif pc_l ==  1:
        best5 = [hand[1],hand[2],hand[3],hand[4],hand[5]]
        print(hand, best5, 'full house')
        raise SystemExit
    elif pc_l ==  10:   
        best5 = [hand[0],hand[1],hand[3],hand[4],hand[5]]
        print(hand, best5, 'full house')
        raise SystemExit
    elif pc_l ==  11:
        best5 = [hand[1],hand[2],hand[4],hand[5],hand[6]]
        print(hand, best5, 'full house')
        raise SystemExit

    else:
        pass


print("ERROR 99")
pass # can't happen
raise SystemExit
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
CopyPasteIt
  • 532
  • 1
  • 8
  • 22
  • I'd suggest having a bunch of individual checks for straight, full house, triplet, etc., and then seeing which of those yields the best result. Most of those checks should be rather trivial after sorting the cards by value and/or grouping them by suit. – tobias_k Feb 06 '19 at 17:42
  • @tobias_k It certainly helps if you know poker so you can cut down the decision tree. – CopyPasteIt Feb 06 '19 at 17:44
  • 1
    Please read and follow the posting guidelines in the help documentation, as suggested when you created this account. [On topic](http://stackoverflow.com/help/on-topic), [how to ask](http://stackoverflow.com/help/how-to-ask), and [... the perfect question](https://codeblog.jonskeet.uk/2010/08/29/writing-the-perfect-question/) apply here. StackOverflow is not a design, coding, research, or tutorial resource. However, if you follow whatever resources you find on line, make an honest coding attempt, and run into a problem, you'd have a good example to post. – Prune Feb 06 '19 at 17:47
  • with 2 downvotes it would be nice if someone could tell me what is wrong with the question. Gee whiz, there is evan a poker tag! – CopyPasteIt Feb 06 '19 at 17:48
  • In fact, you only need two basic algorithms for "same card, different suit" which can be used for pairs, triplets, four-of-a-kind and full house, and streets for straight and straight flush. – tobias_k Feb 06 '19 at 17:48
  • 1
    The problem with the question is: While the problem is indeed somewhat interesting, there seems to be very limited effort from your side, and the question is also very broad, requiring to implement e.g. all of those above checks. Also, if this indeed is meant as some kind of code-golf challenge, those are in fact not on-topic here. – tobias_k Feb 06 '19 at 17:50
  • @Prune This was a challenge! But I guess I will be only redeemed when I post my solution, now that the question is being trashed and put into the gutter. – CopyPasteIt Feb 06 '19 at 17:50
  • @tobias_k I have a working partial algorithm and only with that did I 'go out on a limb'. – CopyPasteIt Feb 06 '19 at 17:51
  • @tobias_k Well, I also posted it with the thought that some answers might help me learn some things about Python... – CopyPasteIt Feb 06 '19 at 17:57
  • 3
    I didn't think it deserved a down-vote, but the question is really broad. Like did you want me to write the entire program for you? The algorithm seems like you have an idea and just gave us rather arbitrary pieces of it? It's like you tried to write a homework question to post on here. – I Funball Feb 06 '19 at 17:59
  • @IFunball If you 'got in it your head' like I did (thinking about it for hours) you might be motivated to put out an answer. Certainly you have to be in the 'Python hobbyist ' camp and also interested in poker. I posted it thinking (especially with the poker tag) that it might be a **fun** 'homework problem'. – CopyPasteIt Feb 06 '19 at 18:13
  • Do not remove the question and replace it with an answer. That's not what edits are for. – Cody Gray - on strike Feb 13 '19 at 22:26

2 Answers2

1

I believe I've implemented the algorithm you specify, but its very easy to make a mistake so let me know if there's any issues. I pretty much just do four core evaluations on the hand

  • Is it a straight?
  • Is it a flush?
  • How many k-pairs does it contain?
  • What's the size of the largest k-pair?

From these I determine the best hand a particular combination of 5 cards can make in a series of if-statements, and sort the cards accordingly. I then create a list of all 5-card combinations from a set of 7, determine the max / best hand using this logic (I rearrange the score and hand order to accomplish this), and return that hand.

from collections import Counter
from itertools import combinations

def num_of_kind(cards):
    return Counter(c[0] for c in cards)

def count_pairs(cards):
    return sum(i > 1 for i in num_of_kind(cards).values())

def largest_pair(cards):
    return max(num_of_kind(cards).values())

def is_straight(cards):
    values = [c[0] for c in cards]
    index = "A23456789TJQKA"["K" in values:].index
    indices = sorted(index(v) for v in values)
    return all(x == y for x, y in enumerate(indices, indices[0]))

def is_flush(cards):
    suit_pop = Counter(c[1] for c in cards)
    return any(s > 4 for s in suit_pop.values())

def straight_sort(cards):
    values = [c[0] for c in cards]
    index = "A23456789TJQKA"["K" in values:].index
    return sorted(cards, key=lambda x:index(x[0]), reverse=True)

def flush_sort(cards):
    suit_pop = Counter(c[1] for c in cards)
    return sorted(cards, key=lambda x: suit_pop[x[1]], reverse=True)

def pair_sort(cards):
    num = num_of_kind(cards)
    return sorted(cards, key=lambda x: num[x[0]], reverse=True)

def card_vals(cards):
    return [c[0] for c in cards]

def score_hand(cards):
    pairs = count_pairs(cards)
    largest = largest_pair(cards)
    straight = is_straight(cards)
    flush = is_flush(cards)

    cards = straight_sort(cards)
    hand_score = 0
    if flush and straight:
        hand_score, cards = 8, flush_sort(cards)
    elif largest == 4:
        hand_score, cards = 7, pair_sort(cards)
    elif pairs == 2 and largest == 3:
        hand_score, cards = 6, pair_sort(cards)
    elif flush:
        hand_score, cards = 5, flush_sort(cards)
    elif straight:
        hand_score = 4
    elif largest == 3:
        hand_score, cards = 3, pair_sort(cards)
    else:
        hand_score, cards = pairs, pair_sort(cards)
    return hand_score, card_vals(cards), cards

def best_hand(cards):
    cards = max(list(combinations(cards, 5)), key=score_hand)
    score, _, hand = score_hand(cards)
    return hand[::-1], score

def main():
    hand = ['2c','Ah','3d', '5s','4h','5d', '3h']
    print(*best_hand(hand))

if __name__ == "__main__":
    main()

I could bore you with the details of every method, but I feel like its all fairly self-explanatory. The only tricky bit is in is_straight(), and that's just some indexing trickery to determine if the card values can be ordered in sequential order.

Dillon Davis
  • 6,679
  • 2
  • 15
  • 37
  • My question was marked as 'too broad' yet in no time at all you came up with an answer that is not only 'adequate' (and brief), but is exactly what I was looking for. I feel bad that I can't award you the bounty now - I am certainly open to giving you the 50 points if you know who to contact. – CopyPasteIt Feb 10 '19 at 02:14
  • The code does need some work. With `hand=['2h','9h','3h','5s','4h','5h','3c']` the statement `print(hand, *best_hand(hand))` outputs `['2h', '9h', '3h', '5s', '4h', '5h', '3c'] ['5s', '3h', '4h', '5h', '9h'] 5`. But thanks again for the effort! – CopyPasteIt Feb 10 '19 at 02:26
  • @CopyPasteIt I think that was just a misunderstanding of what was meant by "natural sort", because the hand should be a flush I believe, with those cards in particular, I've since corrected it to sort by most important cards first. I also discovered a small bug where suite can cause the algorithm to pick a suboptimal variant of a hand under very specific circumstances. – Dillon Davis Feb 10 '19 at 02:55
  • Also, if you do decide to award the bounty, you can always award a bounty on a random answer from someone else's question (you don't have to be the asker)- the PCCG exchange does this frequently on competitions. Otherwise, I understand; you did not choose to close the question after all. – Dillon Davis Feb 10 '19 at 02:59
  • 1
    The natural sort makes it possible to easily calculate which of two hands is better by reading from last (highest) to start (lowest) when the HC classifier is equal. So `['Ac', 'Th', 'Tc', 'Ks', 'Kc'] < ['Qc', 'Jd', 'Js', 'Ks', 'Kc']` since `Tc < Js`. – CopyPasteIt Feb 10 '19 at 03:04
  • @CopyPasteIt can I ask what the expected output for `['2h','9h','3h','5s','4h','5h','3c']` was then? It seems that `['5s', '3h', '4h', '5h', '9h']` follows the pattern you just described, unless I am misunderstanding – Dillon Davis Feb 10 '19 at 03:09
  • It is a flush and you take the best 5 cards representing a flush, so ['2h','3h','4h','5h','9h'], 5 - a 9 high flush. This flush is a loser to every other 9 high flush except it is tied to the ones with the same rank cards below 9. – CopyPasteIt Feb 10 '19 at 03:14
  • @CopyPasteIt oh, duh- I didn't notice the suit on the `5s`. Looking at my code, I have `any(s > 3 ...` which is a typo- it should read `> 4`. I'll fix that real quick and everything should run right. – Dillon Davis Feb 10 '19 at 03:18
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/188164/discussion-between-dillon-davis-and-copypasteit). – Dillon Davis Feb 10 '19 at 03:20
0

Here are some thoughts you may consider when designing your algorithm for finding the best hand:

  • The comparisons all deal with comparing the card value (number) and/or suit. So you may want to consider making a list of the card numbers and a list of the card suits. Or look at the tricks that the itertools module has.
  • Flush and straight flush are the only hands where the suit matters. Otherwise, you're only looking at the card numbers.
  • Straight and straight flush are the only hands where you have to look for 5 consecutive numbers. Keep in mind that this can include aces and face cards. Also, if an ace is included then it must be at the start or the end (e.g., "Q K A 2 3" doesn't count as a straight). You may also want to look into the module more_itertools.consecutive_groups.
  • The other hands (one pair, two pair, three of a kind, full house, four of a kind) are all based on how often same numbers appear. If a value appears 4 times, then there's no need to check for the other hands in this list. If one appears 3 times, then check if you can make a full house, otherwise it's a three of a kind. You can keep checking down this list like this from highest hand to lowest hand, stopping when you get a match.
  • You may even consider making a class called Card, and feeding your cards in as objects of type "Card". Then you can have functions in the class to return the card's suit or numeric value.
Bill M.
  • 1,388
  • 1
  • 8
  • 16
  • There is no need to be fancy. Use strings for cards. Throwing it into a dictionary by card value and testing that is great for 4 of a kind, full house, 2 pair, trips, and a pair. Throwing it in a dictionary another way is great for a flush. Sorting and scanning is great for finding a straight, either out of the original 7 or out of a flush. And if no better type matches, just sort and take the top cards. – btilly Feb 06 '19 at 19:57
  • Never, ever, use strings to represent cards. Strings are for humans. Computers use numbers: they can be efficiently stored, easily compared, combined, etc. This is a common rookie programmer affliction leading to what we call "stringly typed" programming (a pun on "strongly typed"). Using numbers will make your program smaller, simpler, more reliable, and 100x faster. Just use strings for I/O. – Lee Daniel Crocker Feb 06 '19 at 20:06
  • 1
    Why are the two of you commenting on my reply, instead of posting your own reply? – Bill M. Feb 06 '19 at 22:41
  • @LeeDanielCrocker For high performance code, sure. Replacing short strings with numbers during I/O results in code that is 1-2 orders of magnitude faster. But I find it faster to write and debug a simple working program with strings. And in a scripting language, there is no significant performance difference. – btilly Feb 08 '19 at 23:31
  • @BillM. For me, it was because I didn't want to write a full fledged answer with code for someone who doesn't seem to want to put their own effort in. So I gave the practical tip to someone who did. And the other person was replying to me for his own reasons, and has linked high performance code related to this on his profile. – btilly Feb 08 '19 at 23:33
  • @btilly And I thought my question demonstrated that I had put considerable thought into the functionality and design of the algorithm. But you have to ask yourself what on earth is my motivation for asking such a question. If you cranked out the answer for me what would I do with it? Scenario 1: I am going to ask more questions on this site and put together a fully functional commercial tool that I can sell for big bucks! Scenario 2: I am going to claim that your ideas are mine and use it to fake my way into a big job as a Python programmer,. Scenario 3: #education #instruction – CopyPasteIt Feb 09 '19 at 03:50
  • "And I thought my question demonstrated that I had put considerable thought into the functionality and design of the algorithm" -- But not enough thought to make it a valid reply? – Bill M. Feb 11 '19 at 18:18
  • @CopyPasteIt You rewrote your question long after my comment was written. But my guess at the time was that this was homework. – btilly Feb 11 '19 at 19:13
  • @btilly Yea. I actually set a 50 point bounty and then the question was closed, so I did a complete rewrite. But it looks like it will remain closed. I just wanted to pull a bunch of disparate tangential questions into one place. And I certainly appreciate Dillon Davis' answer - so few lines of Python coding - a powerful open-source library backs up this language. I write Python code as a hobby and can get rusty if I stay away for awhile, especially when my neurons drifting (I'm retired). – CopyPasteIt Feb 11 '19 at 19:34