From 4acfe89f92fef5531c5ece510618525f3fb6a74e Mon Sep 17 00:00:00 2001 From: Felix Martin Date: Mon, 24 Dec 2018 16:13:21 -0500 Subject: [PATCH] Drafted solution for 53 and 54. I will have to validate. --- ipython/EulerProblem053.ipynb | 52 +++++++++ ipython/EulerProblem054.ipynb | 201 ++++++++++++++++++++++++++++++++++ 2 files changed, 253 insertions(+) diff --git a/ipython/EulerProblem053.ipynb b/ipython/EulerProblem053.ipynb index 70d3466..b370f57 100644 --- a/ipython/EulerProblem053.ipynb +++ b/ipython/EulerProblem053.ipynb @@ -30,6 +30,58 @@ "How many, not necessarily distinct, values of nCr, for 1 ≤ n ≤ 100, are greater than one-million?" ] }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import math\n", + "\n", + "def combinations_naiv(n, r):\n", + " return math.factorial(n) // (math.factorial(r) * math.factorial(n - r))\n", + "\n", + "assert(combinations_naiv(5, 3) == 10)\n", + "assert(combinations_naiv(23, 10) == 1144066)\n", + "assert(combinations_naiv(20, 20) == 1)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "count = 0\n", + "\n", + "for n in range (1, 101):\n", + " for r in range(1, n + 1):\n", + " if combinations_naiv(n, r) > 10**6:\n", + " count += 1\n", + "\n", + "s = count" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4075\n" + ] + } + ], + "source": [ + "print(s)\n", + "assert(s == 4075)" + ] + }, { "cell_type": "code", "execution_count": null, diff --git a/ipython/EulerProblem054.ipynb b/ipython/EulerProblem054.ipynb index 5f56868..012bf64 100644 --- a/ipython/EulerProblem054.ipynb +++ b/ipython/EulerProblem054.ipynb @@ -50,6 +50,207 @@ "How many hands does Player 1 win?\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's start with some helper functions." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "def suit_to_value(suit):\n", + " return {\n", + " \"2\": 2,\n", + " \"3\": 3,\n", + " \"4\": 4,\n", + " \"5\": 5,\n", + " \"6\": 6,\n", + " \"7\": 7,\n", + " \"8\": 8,\n", + " \"9\": 9,\n", + " \"T\": 10,\n", + " \"J\": 11,\n", + " \"Q\": 12,\n", + " \"K\": 13,\n", + " \"A\": 14,\n", + " }[suit]\n", + "\n", + "assert(suit_to_value('K') == 13)\n", + "\n", + "\n", + "def is_flush(colors):\n", + " first_color = colors[0]\n", + " for color in colors:\n", + " if color != first_color:\n", + " return False\n", + " return True\n", + "\n", + "\n", + "assert(is_flush([\"H\", \"H\", \"H\", \"H\", \"H\"]))\n", + "assert(is_flush([\"H\", \"H\", \"D\", \"H\", \"H\"]) == False)\n", + "\n", + "def is_straight(suits):\n", + " suits = sorted(suits)\n", + " first_suit = suits[0]\n", + " for suit in suits[1:]:\n", + " if first_suit + 1 != suit:\n", + " return False\n", + " first_suit = suit\n", + " return True\n", + "\n", + "assert(is_straight([6,3,4,5,7]))\n", + "assert(is_straight([6,3,4,5,8]) == False)" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [], + "source": [ + "def get_numbered_groups(ns):\n", + " \"\"\" Takes [0, 3, 0, 3, 1] and returns\n", + " [(2, 3), (2, 0), (1, 1)]\n", + " \"\"\"\n", + " rs = []\n", + " current_group = []\n", + " for n in sorted(ns, reverse=True):\n", + " if not current_group or n in current_group:\n", + " current_group.append(n)\n", + " else:\n", + " rs.append(current_group)\n", + " current_group = [n]\n", + " rs.append(current_group)\n", + " rs = sorted([(len(r), r[0]) for r in rs], reverse=True)\n", + " return rs\n", + "\n", + "assert(get_numbered_groups([0, 3, 0, 3, 1]) == [(2, 3), (2, 0), (1, 1)])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's put that stuff together." + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": {}, + "outputs": [], + "source": [ + "def rank(hand):\n", + " \"\"\" A hand must be provided as a list of two letter strings.\n", + " The first letter is the suit and the second the suit of a card.\n", + " \n", + " The function returns a tuple. The first value represents the hand as an integer\n", + " where 0 means high card and 9 means Straight Flush. The second value is a list of integers\n", + " ranking the value of the respective rank. For example, a Royal Flush would be (9, [14, 13, 12, 11, 10]),\n", + " while 22aqj would be (1, [2, 2, 14, 12, 11]). By doing this we can simply compare to hands\n", + " by first comparing the rank itself and then the list of integers.\n", + " \n", + " We get something like [\"5H\", \"6S\", \"7S\", \"5C\", \"KD\"].\n", + " \"\"\"\n", + " \n", + " suits, colors = zip(*(map(lambda s: (s[0], s[1]), hand)))\n", + " suits = sorted(map(suit_to_value, suits))\n", + "\n", + " flush = is_flush(colors)\n", + " straight = is_straight(suits)\n", + " numbered_suits = get_numbered_groups(suits)\n", + " if flush and straight:\n", + " return [8, numbered_suits]\n", + " if flush:\n", + " return [5, numbered_suits]\n", + " if straight:\n", + " return [4, numbered_suits]\n", + " if numbered_suits[0][0] == 4:\n", + " return [7, numbered_suits]\n", + " if numbered_suits[0][0] == 3 and numbered_suits[1][0] == 2:\n", + " return [6, numbered_suits]\n", + " if numbered_suits[0][0] == 3:\n", + " return [3, numbered_suits]\n", + " if numbered_suits[0][0] == 2 and numbered_suits[1][0] == 2:\n", + " return [2, numbered_suits]\n", + " if numbered_suits[0][0] == 2:\n", + " return [1, numbered_suits]\n", + " return [0, numbered_suits]\n", + " \n" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": {}, + "outputs": [], + "source": [ + "assert(rank([\"5H\", \"5C\", \"6S\", \"7S\", \"KD\"]) == [1, [(2, 5), (1, 13), (1, 7), (1, 6)]]) # Pair of Fives\n", + "assert(rank([\"5D\", \"8C\", \"9S\", \"JS\", \"AC\"]) == [0, [(1, 14), (1, 11), (1, 9), (1, 8), (1, 5)]]) # Highest card Ace\n", + "assert(rank([\"2D\", \"9C\", \"AS\", \"AH\", \"AC\"]) == [3, [(3, 14), (1, 9), (1, 2)]]) # Three Aces\n", + "assert(rank([\"4D\", \"6S\", \"9H\", \"QH\", \"QC\"]) == [1, [(2, 12), (1, 9), (1, 6), (1, 4)]]) # Pair of Queens Highest card Nine\n", + "assert(rank([\"2H\", \"2D\", \"4C\", \"4D\", \"4S\"]) == [6, [(3, 4), (2, 2)]]) # Full House With Three Fours\n", + "assert(rank([\"2C\", \"3S\", \"8S\", \"8D\", \"TD\"]) == [1, [(2, 8), (1, 10), (1, 3), (1, 2)]]) # Pair of Eights \n", + "assert(rank([\"2C\", \"5C\", \"7D\", \"8S\", \"QH\"]) == [0, [(1, 12), (1, 8), (1, 7), (1, 5), (1, 2)]]) # Highest card Queen \n", + "assert(rank([\"3D\", \"6D\", \"7D\", \"TD\", \"QD\"]) == [5, [(1, 12), (1, 10), (1, 7), (1, 6), (1, 3)]]) # Flush with Diamonds \n", + "assert(rank([\"3D\", \"6D\", \"7H\", \"QD\", \"QS\"]) == [1, [(2, 12), (1, 7), (1, 6), (1, 3)]]) # Pair of Queens Highest card Seven \n", + "assert(rank([\"3C\", \"3D\", \"3S\", \"9S\", \"9D\"]) == [6, [(3, 3), (2, 9)]]) # Full House with Three Threes \n" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "metadata": {}, + "outputs": [], + "source": [ + "def read_hands():\n", + " \"\"\" Reads a list of tuples where each field\n", + " in the tuple represents a hand.\n", + " \"\"\"\n", + " hands = []\n", + " with open(\"EulerProblem054.txt\", \"r\") as f:\n", + " for line in f.readlines():\n", + " cards = line.strip().split(\" \")\n", + " hands.append((cards[:5], cards[5:]))\n", + " return hands\n", + "\n", + "p1_wins = 0\n", + "\n", + "for p1_hand, p2_hand in read_hands():\n", + " if rank(p1_hand) > rank(p2_hand):\n", + " p1_wins += 1\n", + " msg = \"P1 hand {} wins over P2 hand {}.\"\n", + " #print(msg.format(p1_hand, p2_hand))\n", + " else:\n", + " msg = \"P1 hand {} loses versus P2 hand {}.\"\n", + " #print(msg.format(p1_hand, p2_hand))\n", + " \n", + "s = p1_wins " + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "376\n" + ] + } + ], + "source": [ + "print(s)\n", + "assert(s == 376)" + ] + }, { "cell_type": "code", "execution_count": null,