{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "
Peter Norvig
2012
updated 2019, 2023
\n", "\n", "# Weighing Twelve Balls on a Scale: ①②③④ ⚖ ⑤⑥⑦⑧ \n", "\n", "Here is [a classic](https://en.wikipedia.org/wiki/Balance_puzzle) brain-teaser puzzle from 1945: \n", "\n", "- *You are given twelve identical-looking balls and a two-sided balance scale. One of the balls is of a different weight, although you don't know whether it is lighter or heavier. How can you use just three weighings of the scale to determine not only what the different ball is, but also whether it is lighter or heavier?*\n", "\n", "\n", "However I want to solve not just this specific puzzle, but related puzzles where you can vary the number of balls; vary the number of weighings allowed; or vary the possibilities for the odd ball: maybe it can only be lighter, not heavier. Or maybe it is possible that all the balls actually weigh the same. (However, it will always be the case that at most one ball is different.) If I'm going to solve a puzzle with, say, 242 balls, I'd rather use a computer program, not pencil and paper (as was intended for the 1945 version of the puzzle). \n", "\n", "I originally wrote this program in Lisp around 1980, ported it to Python in 2012, and am republishing it here as a notebook after I saw the puzzle was mentioned yet again in the [538 Riddler](https://fivethirtyeight.com/features/which-billiard-ball-is-rigged/) for August 16, 2019. It also appeared in a [Numberplay](https://wordplay.blogs.nytimes.com/2014/07/21/12coin/) column in 2014 (with twelve coins instead of balls), in the Museum of Math's [Mind-Benders for the Quarantined!](https://momath.org/civicrm/?page=CiviCRM&q=civicrm/event/info&reset=1&id=1620) series in 2020, and in many other venues.\n", "\n", "\n", "# Defining the Vocabulary\n", " \n", "Here are the main concepts:\n", "\n", "- **Ball**: A positive integer from 1 to some *N*. \n", "- **Oddball**: The one ball that is different from the others, and the way it is different: heavier or lighter. I'll use, e.g., `+3` to mean that ball `3` is heavier than the rest, `-3` to mean that ball `3` is lighter than the rest, and `0` ito mean that all the balls actually weigh the same. \n", "- **Puzzle**: A description of the number of balls, number of allowable weighings, and the possible oddballs.\n", "- **Answer**: Given a specific puzzle with a specific oddball, a correct **answer** means identifying the specific oddball (in the allowable number of weighings).\n", "- **Solution**: A solution to a puzzle is a **strategy tree** that gives a correct answer for all possible oddballs (in the allowable number of weighings).\n", "- **Strategy tree**: A tree whose root is a **weighing** (of some balls on the left versus some balls on the right) and which specifies the three posssible outcomes of the weighing. Each of these outcomes leads to either another weighing, or a leaf nodes saying which oddball is the answer, under the contingency that the given outcomes occured. Every oddball in the puzzle must appear as a leaf somewhere in the tree. \n", "- **Outcome**: The **outcome** of a **weighing** will be that the weight of the left side is greater than, equal to, or less than the right side. \n", "- **Partition**: Each weighing partitions the possible oddballs into three subsets, corresponding to the three possible outcomes. \n", "- **Rule of 3**: The key insight is that one weighing partitions the set of possible oddballs into 3 subsets, two weighings into 3 x 3 = 9 subsets, three weighings into 3 x 3 x 3 = 27 subsets, and w weighings into 3w subsets. The 12 ball puzzle has 24 possible oddballs, and thus cannot possibly be solved in two weighings, but *might* be solved in three. In general, *w* weighings can never solve puzzles with more than 3w oddballs.\n", "\n", "\n", "# Implementation of Data Types and Constants" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from dataclasses import dataclass\n", "from typing import Union, Literal, Optional, Dict, Set, Tuple, List, Iterable\n", "import random\n", "random.seed(42) # For reproducability\n", "\n", "lt, eq, gt = 'lt', 'eq', 'gt' # The 3 possible outcomes of a weighing \n", "unreachable = () # A branch of a tree that is impossible to reach\n", "\n", "Ball = int # Balls are positive integers\n", "Oddball = int # Oddballs are positive (heavier), negative (lighter), or zero (same weight) integers\n", "Outcome = Literal[lt, eq, gt] # Possible outcomes of a weighing\n", "Leaf = Oddball # Leaves are oddballs\n", "# A tree can be an weighing, or a leaf oddball, or None to indicate failure, or `unreachable`\n", "Tree = Union['Weighing', Leaf, None, Literal[unreachable]] \n", "\n", "@dataclass\n", "class Weighing:\n", " \"\"\"An interior node of a strategy tree; represents a weighing and the three possible outcomes.\n", " Calling `partition` returns a `Weighing` where each gt/eq/lt branch holds a set of oddballs; \n", " then `solve` replaces each of those sets with a subtree.\"\"\"\n", " L: List[Ball]\n", " R: List[Ball]\n", " gt: Union[Set[Oddball], Tree]\n", " eq: Union[Set[Oddball], Tree]\n", " lt: Union[Set[Oddball], Tree]\n", "\n", "class Puzzle:\n", " \"\"\"A ball-weighing puzzle. \n", " `N`: the number of balls that can be weighed\n", " `weighings`: the number of weighings allowed\n", " `odd`: either a collection of oddball numbers, or a string with some of the characters '+-0',\n", " where '+' means any ball can be heavy, '-' means any ball can be light, \n", " and '0' means that it is possible that all the balls actually weigh the same.\"\"\"\n", " def __init__(self, N=12, weighings=3, odd='+-'):\n", " self.N = N\n", " self.weighings = weighings\n", " self.odd = odd\n", " self.balls = range(1, N + 1)\n", " self.oddballs = (oddballs(odd, N) if isinstance(odd, str) else odd)\n", " def __repr__(self): return f'Puzzle(N={self.N}, weighings={self.weighings}, odd={self.odd!r})'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Implementation of Basic Functions\n", "\n", "Here are some straightforward utility functions, before we get to the main `solve` function:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "def oddballs(odd: str, N: int) -> List[Oddball]:\n", " \"\"\"Parse a string containing \"+-0\" into a list of oddballs.\"\"\"\n", " oddballs = [0] if '0' in odd else []\n", " if '+' in odd: oddballs.extend(+b for b in range(1, N + 1))\n", " if '-' in odd: oddballs.extend(-b for b in range(1, N + 1))\n", " return oddballs\n", "\n", "def weigh(L, R, oddball) -> Outcome:\n", " \"\"\"Weighing the collection of balls `L` against the balls `R`, given the oddball; return gt, lt, or eq.\"\"\"\n", " def heavier(L, R) -> bool: return len(L) > len(R) or oddball in L or -oddball in R\n", " return (gt if heavier(L, R) else lt if heavier(R, L) else eq)\n", " \n", "def answer(tree, oddball) -> Oddball:\n", " \"\"\"What answer does the strategy tree produce for the given oddball?\"\"\"\n", " if isinstance(tree, Leaf):\n", " return tree\n", " else:\n", " outcome = weigh(tree.L, tree.R, oddball)\n", " return answer(getattr(tree, outcome), oddball)\n", " \n", "def is_solution(tree, puzzle) -> bool:\n", " \"\"\"Does the strategy tree solve the puzzle correctly for all possible oddballs?\"\"\"\n", " return (tree is not None and depth(tree) <= puzzle.weighings and \n", " all(answer(tree, oddball) == oddball \n", " for oddball in puzzle.oddballs))\n", "\n", "def depth(tree) -> int:\n", " \"\"\"Maximum depth (number of weighings) in tree.\"\"\"\n", " return (0 if isinstance(tree, Leaf) or not tree\n", " else 1 + max(depth(tree.gt), depth(tree.eq), depth(tree.lt)))\n", "\n", "def first(iterable): return next(iter(iterable))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's test out some of these functions:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def test1() -> bool:\n", " puzzle3 = Puzzle(3, 1, odd='+')\n", " solution3 = Weighing([1], [3], gt=1, eq=2, lt=3)\n", " assert is_solution(solution3, puzzle3)\n", " puzzle8 = Puzzle(8, 3) \n", " assert str(puzzle8) == \"Puzzle(N=8, weighings=3, odd='+-')\"\n", " assert puzzle8.balls == range(1, 9)\n", " assert puzzle8.oddballs == [1, 2, 3, 4, 5, 6, 7, 8, -1, -2, -3, -4, -5, -6, -7, -8]\n", " assert weigh([1, 2], [3, 4], -4) == 'gt'\n", " return True\n", "\n", "test1()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Partitions\n", "\n", "Now we've got all the pieces we need to find solutions. The first step is to **partition** a collection of oddballs into three subsets by weighing one set of balls against another. We store the three subsets in a `Weighing` tree node:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "def partition(L: List[Ball], R: List[Ball], oddballs) -> Weighing:\n", " \"A node that partitions the possible outcomes of weighing L versus R.\"\n", " weighing = Weighing(L, R, set(), set(), set())\n", " for oddball in oddballs:\n", " outcome = weigh(L, R, oddball)\n", " getattr(weighing, outcome).add(oddball)\n", " return weighing" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For example, with 12 balls, if we weigh balls [1, 2, 3] on the left versus [10, 11, 12] on the right, then there are 6 ways the left side can be greater than the right: either 10, 11 or 12 is lighter or 1, 2, or 3 is heavier. Similarly there are 6 ways of getting a `lt` outcome. The remaining 12 possibilities—balls 4 through 9 being either heavier or lighter—show up in the `eq` branch:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Weighing(L=[1, 2, 3], R=[10, 11, 12], gt={1, 2, 3, -12, -11, -10}, eq={4, 5, 6, 7, 8, 9, -9, -8, -7, -6, -5, -4}, lt={10, 11, 12, -2, -3, -1})" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "puzzle12 = Puzzle(12, 3)\n", "\n", "partition([1, 2, 3], [10, 11, 12], puzzle12.oddballs)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If this was the first weighing in our strategy tree, could we go on to solve the puzzle? \n", "\n", "**No!** After using one of our three weighings we can only solve the puzzle if every branch of the partition has no more than 32 = 9 oddballs, but here we have 12 oddballs in the `eq` branch. We call this a **bad partition**. A good partition is one where no branch has more than 3w oddballs when there are *w* remaining weighings. Being a good partition does not guarantee that the puzzle is solvable from there; but being a bad partition guarantees that it is not solvable.\n", " " ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "def good_partition(node, w) -> bool:\n", " \"Is this a partition which might lead to a solution in `w` more weighings?\"\n", " return all(len(oddballs) <= 3 ** w for oddballs in (node.lt, node.eq, node.gt))" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "good_partition(partition([1, 2, 3], [10, 11, 12], puzzle12.oddballs), 2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "With 12 balls, weighing 4 balls on each side is a good partition because each of the branches has 8 possibilities, and 8 is less than 32:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Weighing(L=[1, 2, 3, 4], R=[9, 10, 11, 12], gt={1, 2, 3, 4, -12, -11, -10, -9}, eq={5, 6, 7, 8, -8, -7, -6, -5}, lt={9, 10, 11, 12, -2, -4, -3, -1})" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "partition4 = partition([1, 2, 3, 4], [9, 10, 11, 12], puzzle12.oddballs)\n", "partition4" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "good_partition(partition4, 2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Solving Puzzles\n", "\n", "So now we have a viable approach to implementing `solve`: it partitions oddballs down to singletons (or gives up and returns `None` if that can't be done in the allowable number of weighings). For each subset of oddballs in a partition, recursively call `solve` on a new subproblem.\n", " \n", "Much of the work is done by `good_partitions`. It is a generator that yields good partitions (i.e. ones that might lead to a solution). Most of the time the first or one of the first few partitions will be accepted, but if a partition does not lead to a solution, it will keep generating new attempts up to `tries` times (default 300). It prefers shorter lists of balls on each side of the scale, but is not guaranteed to pick the shortest possible lists. After each try it randomly shuffles the balls, in order to get a different partition on the next try. (I note that for puzzles that specify `odd` as a `\"+-0\"` string, there's no sense making multiple tries on the first weighing–the only choice that matters is how many balls, `B`, to put on each side, because the balls are undifferentiated at this point. So I try each value of `B` only once.) If I wanted to solve puzzles with thousands of balls, not just dozens to hundreds, I would come back and make `good_partitions` more efficient." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "def solve(puzzle) -> Tree:\n", " \"Find a tree that covers all the oddballs in the given number of weighings.\"\n", " N, weighings, oddballs = puzzle.N, puzzle.weighings, puzzle.oddballs\n", " if len(oddballs) == 1:\n", " return first(oddballs) # One possibile oddball: an answer\n", " elif len(oddballs) == 0:\n", " return unreachable # This branch of the tree will never be reached\n", " elif weighings == 0:\n", " return None # No solution; failure\n", " else:\n", " for node in good_partitions(puzzle):\n", " node.lt = solve(Puzzle(N, weighings-1, node.lt))\n", " node.eq = solve(Puzzle(N, weighings-1, node.eq))\n", " node.gt = solve(Puzzle(N, weighings-1, node.gt))\n", " if None not in (node.lt, node.eq, node.gt):\n", " return node\n", " return None # No solution; failure\n", "\n", "def good_partitions(puzzle, tries=100) -> Iterable[Weighing]:\n", " \"Yield random good partitions.\"\n", " oddballs, weighings, balls = puzzle.oddballs, puzzle.weighings, list(puzzle.balls)\n", " if isinstance(puzzle.odd, str):\n", " tries = 1 # First weighing, undifferentiated balls: only need to try once.\n", " for _ in range(tries): \n", " for B in range(1, 1 + len(balls) // 2):\n", " L, R = balls[:B], balls[-B:]\n", " node = partition(L, R, oddballs)\n", " if good_partition(node, weighings - 1):\n", " yield node\n", " random.shuffle(balls)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here we see that `good_partitions` does its job:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Weighing(L=[1, 2, 3, 4], R=[9, 10, 11, 12], gt={1, 2, 3, 4, -12, -11, -10, -9}, eq={5, 6, 7, 8, -8, -7, -6, -5}, lt={9, 10, 11, 12, -2, -4, -3, -1})" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "first(good_partitions(puzzle12))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And so does `solve`:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Weighing(L=[1, 2, 3, 4], R=[9, 10, 11, 12], gt=Weighing(L=[7, 5, 2, 12], R=[1, 11, 9, 3], gt=Weighing(L=[1, 4, 6, 11], R=[12, 5, 3, 9], gt=-9, eq=2, lt=-11), eq=Weighing(L=[1, 2, 3], R=[10, 11, 12], gt=-10, eq=4, lt=()), lt=Weighing(L=[3], R=[1], gt=3, eq=-12, lt=1)), eq=Weighing(L=[7, 4, 5], R=[3, 6, 11], gt=Weighing(L=[10, 5], R=[7, 3], gt=5, eq=-6, lt=7), eq=Weighing(L=[1, 2, 3, 4, 5], R=[8, 9, 10, 11, 12], gt=-8, eq=(), lt=8), lt=Weighing(L=[1, 11, 12, 2, 5], R=[7, 8, 3, 4, 9], gt=-7, eq=6, lt=-5)), lt=Weighing(L=[8, 6, 3, 9], R=[5, 1, 2, 11], gt=Weighing(L=[5, 4], R=[1, 9], gt=-1, eq=-2, lt=9), eq=Weighing(L=[10, 11, 6], R=[12, 8, 3], gt=10, eq=-4, lt=12), lt=Weighing(L=[1, 2], R=[11, 12], gt=(), eq=-3, lt=11)))" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "solve(puzzle12)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "OK, that's really hard to read–my bad. Let's look at a much easier puzzle: 3 balls, 1 weighing allowed, and the oddball can only be heavier:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Weighing(L=[1], R=[3], gt=1, eq=2, lt=3)" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "solve(Puzzle(3, 1, odd='+'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This trivial tree says you weigh the first ball against the third (leaving the second unweighed), and the three possible weighing outcomes tell you which of the three balls is heavier. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Prettier Output\n", "\n", "Let's make the output easier to read. The function`do(puzzle)` will solve the puzzle, verify that the tree is valid (if it is not `None`), and print the tree in a pretty format using the function `pretty_str(tree)`:\n", "- Balls number 1 to 50 are represented as the Unicode characters `①` to `㊿`, and higher numbers by various other Unicode characters, mostly ball-like.\n", "- A string like `①②③④ ⚖ ⑨⑩⑪⑫ ➔` represents a weighing;\n", "- The three branches of a tree are represented by the prefixes \">:\" or \"=:\" or \"<:\" (on indented lines, unless they are all leaves).\n", "- The empty tree, representing the fact that all balls balance is represented as \"≡\"." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "def do(puzzle):\n", " \"Solve the puzzle; verify the solution; and print the solution in a pretty format.\"\n", " tree = solve(puzzle)\n", " assert (tree is None) or is_solution(tree, puzzle)\n", " print(pretty_str(tree))\n", " \n", "def pretty_str(tree, depth=0, prefix='') -> str:\n", " \"Pretty, indented string representing a strategy tree.\"\n", " if tree in (None, 0, unreachable):\n", " return f'{prefix}{tree}'\n", " elif isinstance(tree, Leaf):\n", " return f'{prefix}{\"+\" if tree > 0 else \"-\"}{ballstr([abs(tree)])}'\n", " else:\n", " subtrees = (pretty_str(tree.gt, depth + 1, '>:'), \n", " pretty_str(tree.eq, depth + 1, '=:'), \n", " pretty_str(tree.lt, depth + 1, '<:'))\n", " indent = ('' if depth == 0 else ('\\n' + ' ' * depth))\n", " return f'{indent}{prefix}{ballstr(tree.L)} ⚖ {ballstr(tree.R)} ➔ {\" \".join(subtrees)}'\n", " \n", "def ballstr(balls: List[Ball]) -> str:\n", " \"\"\"Unicode character string representing a list of balls. The first 50 balls are easy; then it gets a bit wacky.\"\"\"\n", " return ''.join(BALLS[i] if (1 <= i < len(BALLS)) else f'{i}' for i in balls)\n", "\n", "BALLS = (' ①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴㊵㊶㊷㊸㊹㊺㊻㊼㊽㊾㊿'\n", " 'ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏ'\n", " 'ⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ'\n", " '⦰⦱⦲⦳⦴⦵⦶⦷⦸⦹⦺⦻⦼⦽⦾⦿⧀⧁⧂⧃⨀⨁⨂⨴⨵⨶⨷⨸⓵⓶⓷⓸⓹⓺⓻⓼⓽⓾')" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "① ⚖ ③ ➔ >:+① =:+② <:+③\n" ] } ], "source": [ "# The easier puzzle from before: 3 balls, 1 weighing, only heavier balls possible\n", "do(Puzzle(3, 1, odd='+'))" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "① ⚖ ③ ➔ \n", " >:② ⚖ ① ➔ >:() =:-③ <:+① \n", " =:② ⚖ ① ➔ >:+② =:0 <:-② \n", " <:① ⚖ ② ➔ >:() =:+③ <:-①\n" ] } ], "source": [ "# 3 balls, 2 weighings, lighter, heavier or equal balls possible\n", "do(Puzzle(3, 2, '+-0'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that if both weighings have the outcome of weighing the same, then the string `=:0` above means that the answer is that no ball is different. \n", "\n", "Also, if the first weighing's outcome is that ① is heavier than ③ , and the second weighing's outcome is that ② is heavier than ①, then the string `>:()` above means that this pair of outcomes is impossible; there can be only one heavier ball, so it can't be that ② > ① > ③." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "①②③④ ⚖ ⑨⑩⑪⑫ ➔ \n", " >:④⑫① ⚖ ③⑧② ➔ \n", " >:① ⚖ ⑫ ➔ >:+① =:+④ <:() \n", " =:⑦⑩ ⚖ ②⑪ ➔ >:-⑪ =:-⑨ <:-⑩ \n", " <:⑤①⑩④⑨ ⚖ ⑫⑦⑪③⑥ ➔ >:-⑫ =:+② <:+③ \n", " =:⑩⑥⑤① ⚖ ⑦③④② ➔ \n", " >:③⑫① ⚖ ⑦⑤⑨ ➔ >:-⑦ =:+⑥ <:+⑤ \n", " =:①②③④⑤ ⚖ ⑧⑨⑩⑪⑫ ➔ >:-⑧ =:() <:+⑧ \n", " <:②③⑫ ⚖ ⑤⑦① ➔ >:-⑤ =:-⑥ <:+⑦ \n", " <:⑫⑧③⑦ ⚖ ⑨⑩①⑥ ➔ \n", " >:⑨⑩③⑥① ⚖ ⑪②④⑧⑤ ➔ >:() =:+⑫ <:-① \n", " =:⑧③⑦ ⚖ ②⑩⑪ ➔ >:-② =:-④ <:+⑪ \n", " <:③⑩ ⚖ ①④ ➔ >:+⑩ =:+⑨ <:-③\n" ] } ], "source": [ "# The original puzzle with 12 balls and 3 weighings\n", "do(puzzle12)" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "①②③④ ⚖ ⑨⑩⑪⑫ ➔ \n", " >:⑩①⑤ ⚖ ④③⑨ ➔ \n", " >:① ⚖ ⑫ ➔ >:+① =:-⑨ <:() \n", " =:④⑨⑦ ⚖ ②③⑫ ➔ >:-⑫ =:-⑪ <:+② \n", " <:①⑪③ ⚖ ④⑫⑤ ➔ >:+③ =:-⑩ <:+④ \n", " =:⑧⑪⑥ ⚖ ②③⑤ ➔ \n", " >:①④⑫⑪③ ⚖ ⑧②⑦⑤⑨ ➔ >:-⑤ =:+⑥ <:+⑧ \n", " =:①②③④⑤⑥ ⚖ ⑦⑧⑨⑩⑪⑫ ➔ >:-⑦ =:() <:+⑦ \n", " <:⑩⑨⑥ ⚖ ⑧①④ ➔ >:-⑧ =:+⑤ <:-⑥ \n", " <:⑥⑩⑧① ⚖ ⑨④⑦③ ➔ \n", " >:⑦⑥ ⚖ ③⑩ ➔ >:-③ =:-④ <:+⑩ \n", " =:⑫④① ⚖ ⑪⑧⑦ ➔ >:+⑫ =:-② <:+⑪ \n", " <:① ⚖ ⑫ ➔ >:() =:+⑨ <:-①\n" ] } ], "source": [ "# A different random solution to the same puzzle\n", "do(puzzle12)" ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "I note that the traditional answer to the 12-ball puzzle weighs 4 balls on each side of the first weighing, three balls on the second weighing, and 2 balls on the third weighing. But my program is not so orderly. It always weighs 4 balls on the first weighing (because that is the only good partition), but from there it can vary; it won't necessarily minimize the number of balls on each side of the scale, nor make one branch of the tree be symmetric with another branch.\n", "\n", "# Other Puzzles with 3 Weighings\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can do **12 balls in 3 weighings** even when we add in the possibility that there is no oddball–that all the balls weigh the same:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "①②③④ ⚖ ⑨⑩⑪⑫ ➔ \n", " >:①⑦⑧⑨ ⚖ ⑪⑫④③ ➔ \n", " >:②⑨④①⑫ ⚖ ⑩⑧③⑦⑥ ➔ >:+① =:-⑪ <:-⑫ \n", " =:①② ⚖ ⑪⑫ ➔ >:+② =:-⑩ <:() \n", " <:⑩②⑤③ ⚖ ④⑫⑦⑧ ➔ >:+③ =:-⑨ <:+④ \n", " =:⑤①⑧ ⚖ ③⑦④ ➔ \n", " >:①②③④⑤ ⚖ ⑧⑨⑩⑪⑫ ➔ >:+⑤ =:-⑦ <:+⑧ \n", " =:①②③④⑤⑥ ⚖ ⑦⑧⑨⑩⑪⑫ ➔ >:+⑥ =:0 <:-⑥ \n", " <:①②③④⑤ ⚖ ⑧⑨⑩⑪⑫ ➔ >:-⑧ =:+⑦ <:-⑤ \n", " <:⑪⑥③ ⚖ ④⑫① ➔ \n", " >:⑦⑨ ⚖ ①⑪ ➔ >:-① =:-④ <:+⑪ \n", " =:⑨⑤⑥② ⚖ ③④⑦⑧ ➔ >:+⑨ =:+⑩ <:-② \n", " <:① ⚖ ⑫ ➔ >:() =:-③ <:+⑫\n" ] } ], "source": [ "do(Puzzle(12, 3, odd='+-0'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Can we solve the **13-balls in 3 weighings** puzzle, which has 26 possibilities? After all, 26 is less than 33 = 27." ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "None\n" ] } ], "source": [ "puzzle13 = Puzzle(13, 3, odd='+-')\n", "do(puzzle13)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**No**, and the reason is that there is no first weighing that partitions the 26 possibilities into three branches, each of which has 9 or fewer possibilities (and thus can be handled in the two remaining weighings). No matter what we do, there will always be a branch with 10 or more possibilities:" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Weighing(L=[1, 2, 3, 4], R=[10, 11, 12, 13], gt={1, 2, 3, 4, -13, -12, -11, -10}, eq={5, 6, 7, 8, 9, -9, -8, -7, -6, -5}, lt={10, 11, 12, 13, -2, -4, -3, -1})" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "partition([1, 2, 3, 4], [10, 11, 12, 13], puzzle13.oddballs)" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Weighing(L=[1, 2, 3, 4, 5], R=[9, 10, 11, 12, 13], gt={1, 2, 3, 4, 5, -13, -12, -11, -10, -9}, eq={6, 7, 8, -8, -7, -6}, lt={9, 10, 11, 12, 13, -2, -5, -4, -3, -1})" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "partition([1, 2, 3, 4, 5], [9, 10, 11, 12, 13], puzzle13.oddballs)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "I'll define `partition_sizes` to make this more clear:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [], "source": [ "def partition_sizes(puzzle, B) -> List[int]:\n", " \"How big is each branch of a partition with B balls on both sides?\"\n", " node = partition(puzzle.balls[:B], puzzle.balls[-B:], puzzle.oddballs)\n", " return [len(oddballs) for oddballs in (node.gt, node.eq, node.lt)]" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{1: [2, 22, 2],\n", " 2: [4, 18, 4],\n", " 3: [6, 14, 6],\n", " 4: [8, 10, 8],\n", " 5: [10, 6, 10],\n", " 6: [12, 2, 12]}" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "{B: partition_sizes(puzzle13, B) for B in range(1, 7)}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can do **27 balls in 3 weighings** if we know that the oddball can only be lighter, not heavier (or vice-versa):" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "①②③④⑤⑥⑦⑧⑨ ⚖ ⑲⑳㉑㉒㉓㉔㉕㉖㉗ ➔ \n", " >:⑫⑭⑥④⑩⑱㉒⑦①⑤㉓⑳ ⚖ ③⑮⑲⑰⑬⑨㉔⑧⑯⑪②㉖ ➔ \n", " >:⑯㉓②㉑⑭⑮⑪⑦⑰⑬⑲ ⚖ ⑫⑳㉕①④⑥㉗⑱㉖⑤⑨ ➔ >:-㉖ =:-㉔ <:-⑲ \n", " =:⑯⑲⑤⑥㉒⑰⑳⑭⑫㉕ ⚖ ㉗①㉔③⑮④⑦⑨⑬② ➔ >:-㉗ =:-㉑ <:-㉕ \n", " <:㉖⑫⑤②⑮㉗㉔㉓ ⚖ ⑬㉕⑦③①⑯⑳㉑ ➔ >:-⑳ =:-㉒ <:-㉓ \n", " =:①②③④⑤⑥⑦⑧⑨⑩⑪⑫ ⚖ ⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗ ➔ \n", " >:⑥㉑⑧④②③⑲⑯ ⚖ ㉕㉓⑤⑨㉗⑰⑫⑦ ➔ >:-⑰ =:-⑱ <:-⑯ \n", " =:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬ ⚖ ⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗ ➔ >:-⑮ =:-⑭ <:-⑬ \n", " <:㉓㉗⑬⑥⑨⑧⑳⑲⑩ ⚖ ③⑭⑤⑮㉒㉕㉑②⑫ ➔ >:-⑫ =:-⑪ <:-⑩ \n", " <:③㉔⑬⑨②⑩⑱⑰㉖ ⚖ ⑧⑳①㉒⑪⑭④㉕⑮ ➔ \n", " >:㉓⑥⑦④㉗㉔⑫㉑⑰ ⚖ ①⑨㉕⑪⑭②⑳③⑮ ➔ >:-① =:-⑧ <:-④ \n", " =:㉓⑯⑬⑥⑪⑳ ⚖ ⑦㉒⑲㉑㉖⑨ ➔ >:-⑦ =:-⑤ <:-⑥ \n", " <:⑬㉓⑪㉕⑰⑮② ⚖ ⑨㉖㉑⑦④㉔⑳ ➔ >:-⑨ =:-③ <:-②\n" ] } ], "source": [ "do(Puzzle(27, 3, '-'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And we can do **26 balls** under the condition that either one ball is lighter or all the balls weigh the same:" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "①②③④⑤⑥⑦⑧⑨ ⚖ ⑱⑲⑳㉑㉒㉓㉔㉕㉖ ➔ \n", " >:㉖⑲⑫⑤⑱ ⚖ ㉔㉓⑨⑳⑥ ➔ \n", " >:⑰⑩②⑨⑦㉔⑧⑭⑲㉖⑬ ⚖ ㉓③⑤㉒⑯⑮⑥㉑⑪⑱⑫ ➔ >:-㉓ =:-⑳ <:-㉔ \n", " =:⑩⑧⑭㉖㉑ ⚖ ㉓㉕⑱⑰③ ➔ >:-㉕ =:-㉒ <:-㉑ \n", " <:⑩㉔⑫㉒⑦⑧⑱ ⚖ ⑮⑲④⑯⑭㉑㉓ ➔ >:-⑲ =:-㉖ <:-⑱ \n", " =:①②③④⑤⑥⑦⑧⑨⑩⑪⑫ ⚖ ⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖ ➔ \n", " >:⑦⑱⑫⑭⑨④⑰②⑥ ⚖ ⑮⑤㉓⑪⑳㉔㉑⑲㉒ ➔ >:-⑮ =:-⑯ <:-⑰ \n", " =:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬ ⚖ ⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖ ➔ >:-⑭ =:0 <:-⑬ \n", " <:①⑳⑨⑬⑱⑥⑯⑮⑪ ⚖ ⑲⑫⑦㉒㉕④㉑⑰③ ➔ >:-⑫ =:-⑩ <:-⑪ \n", " <:㉖⑦⑳⑤㉒③⑩⑲ ⚖ ①⑧⑬⑱㉔㉕④㉓ ➔ \n", " >:⑤⑳⑨⑧⑱ ⚖ ④⑩⑭㉑㉓ ➔ >:-④ =:-① <:-⑧ \n", " =:⑩⑲㉖⑬⑳⑤⑪⑥ ⚖ ⑯⑮㉒㉔⑦④⑨㉕ ➔ >:-⑨ =:-② <:-⑥ \n", " <:⑬⑯⑱㉓⑤⑮①⑲⑨⑥㉔ ⚖ ⑦④㉕㉑⑳⑩②㉖㉒⑫⑭ ➔ >:-⑦ =:-③ <:-⑤\n" ] } ], "source": [ "do(Puzzle(26, 3, '-0'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here's a puzzle with **26 balls** where it is stipulated that either one of the odd-numbered balls is heavier, or one of the even-numbered balls is lighter, or there is no oddball." ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, 1, -2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12, 13, -14, 15, -16, 17, -18, 19, -20, 21, -22, 23, -24, 25, -26]\n" ] } ], "source": [ "odd_even = [(+b if b % 2 else -b) for b in range(27)]\n", "print(odd_even)" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "①⑭⑬②③㉔⑳㉑⑥ ⚖ ⑨⑯㉒㉓⑲⑱⑮⑫④ ➔ \n", " >:⑪⑥㉓⑦⑮②③⑩⑰ ⚖ ㉑⑯⑨⑤⑬①㉕⑳⑱ ➔ \n", " >:⑨⑦①㉔⑯ ⚖ ㉓⑬⑱㉒⑲ ➔ >:-⑱ =:+③ <:-⑯ \n", " =:①②③④⑤ ⚖ ㉒㉓㉔㉕㉖ ➔ >:-㉒ =:-⑫ <:-④ \n", " <:①②③④⑤⑥ ⚖ ㉑㉒㉓㉔㉕㉖ ➔ >:+① =:+⑬ <:+㉑ \n", " =:⑩⑰③㉕⑮④⑫⑱② ⚖ ⑦㉑⑲⑪⑥⑧⑭⑳⑬ ➔ \n", " >:③⑰⑮㉔⑯⑬ ⚖ ㉕㉒⑩④⑤⑭ ➔ >:+⑰ =:-⑧ <:+㉕ \n", " =:⑮⑭⑫⑰⑥⑨⑳㉒⑩②③ ⚖ ㉖㉔⑬㉕㉓⑪⑱⑦①⑤⑲ ➔ >:-㉖ =:0 <:+⑤ \n", " <:①②③④⑤⑥⑦⑧⑨⑩ ⚖ ⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖ ➔ >:+⑦ =:+⑪ <:-⑩ \n", " <:⑰⑯⑫⑤⑭④⑱⑲⑳ ⚖ ⑪㉔⑩⑬⑮㉕②⑦③ ➔ \n", " >:①②③ ⚖ ㉔㉕㉖ ➔ >:-㉔ =:+⑲ <:-② \n", " =:㉔⑤⑦⑫⑰ ⚖ ⑨①㉕⑥⑧ ➔ >:-⑥ =:+㉓ <:+⑨ \n", " <:①②③④⑤⑥⑦⑧⑨⑩⑪⑫ ⚖ ⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖ ➔ >:-⑳ =:-⑭ <:+⑮\n" ] } ], "source": [ "do(Puzzle(26, 3, odd=odd_even))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Another variation: **27 balls, 3 weighings**, the oddball can only be heavier, but one ball (number 27) is poisonous and can't be touched or placed on the balance scale. It might, however be the heavier ball, and you still need to report it as such if it is. \n", "\n", "We describe this situation by defining a puzzle with 26 (weighable) balls, but with the oddballs including the positive ball numbers from +1 to +27, inclusive. Note that when all three weighings are equal, the strategy tree correctly reports `+㉗`." ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "①②③④⑤⑥⑦⑧⑨ ⚖ ⑱⑲⑳㉑㉒㉓㉔㉕㉖ ➔ \n", " >:⑬⑯⑩④㉕②⑧ ⚖ ①⑱⑤⑮㉔㉓⑥ ➔ \n", " >:⑭②⑰ ⚖ ⑧⑳⑥ ➔ >:+② =:+④ <:+⑧ \n", " =:⑱②⑦⑳⑪⑰㉕ ⚖ ③⑭⑩④⑯①⑫ ➔ >:+⑦ =:+⑨ <:+③ \n", " <:⑧⑳⑤ ⚖ ㉖⑩① ➔ >:+⑤ =:+⑥ <:+① \n", " =:①②③④⑤⑥⑦⑧⑨⑩⑪⑫ ⚖ ⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖ ➔ \n", " >:⑧⑮⑳②⑬⑰⑨⑱㉕⑪ ⚖ ①⑭⑥⑯㉒㉔④⑫⑲㉑ ➔ >:+⑪ =:+⑩ <:+⑫ \n", " =:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬ ⚖ ⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖ ➔ >:+⑬ =:+㉗ <:+⑭ \n", " <:㉖⑪⑬⑤⑰ ⚖ ⑯⑲㉓⑦⑧ ➔ >:+⑰ =:+⑮ <:+⑯ \n", " <:⑫⑤⑱⑪㉒㉑ ⚖ ㉔⑳㉖⑯③⑬ ➔ \n", " >:㉖③㉑⑨ ⚖ ㉒⑳⑦⑰ ➔ >:+㉑ =:+⑱ <:+㉒ \n", " =:④③⑫㉕⑪⑩㉖ ⚖ ㉓⑦⑧㉑⑳②⑤ ➔ >:+㉕ =:+⑲ <:+㉓ \n", " <:②⑦⑳⑯㉕⑱① ⚖ ㉖⑭⑪⑰⑬㉒㉑ ➔ >:+⑳ =:+㉔ <:+㉖\n" ] } ], "source": [ "do(Puzzle(26, 3, odd=range(1, 28)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Puzzles with 4 Weighings\n", "\n", "We can tackle larger puzzles. With 4 weighings, we can theoretically handle up to 34 = 81 possibilities. Can we solve for **40 balls**, heavy or light?" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "None\n" ] } ], "source": [ "p40 = Puzzle(40, 4)\n", "\n", "do(p40)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Unfortunately, **no**, we didn't find a solution. That's because the `partition_sizes` always leaves us with a branch of size 28 or more, which can't be handled in the three remaining weighings:" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[26, 28, 26]" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "partition_sizes(p40, 13)" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[28, 24, 28]" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "partition_sizes(p40, 14)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "How about **39 balls, 4 weighings**, heavier or lighter, with the possibility that no ball is odd? That's 39 × 2 + 1 = 79 possibilities, which is less than 81, and the partition sizes are all 27 or less." ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [], "source": [ "p39 = Puzzle(39, 4, '+-0')" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[26, 27, 26]" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "partition_sizes(p39, 13)" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬ ⚖ ㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴ ➔ \n", " >:⑩㉑⑰㉕⑬⑱㊴⑦㉛㉗⑭㉞㊱④ ⚖ ㉒㉘⑲㉚⑥⑮⑨㊲⑪⑯①㉝㉔㉖ ➔ \n", " >:㉟⑦㊳⑧㉘㊴⑰㊲⑨⑬ ⚖ ②⑤⑫④⑭⑱㊱⑯①⑥ ➔ \n", " >:①②③④⑤⑥⑦ ⚖ ㉝㉞㉟㊱㊲㊳㊴ ➔ >:+⑦ =:+⑬ <:() \n", " =:⑥⑩㉘⑯③⑰⑧⑨㉙㉓㉝ ⚖ ㉟㊲④①⑬⑲⑮⑫㊳㉜㉞ ➔ >:+⑩ =:-㉚ <:-㉝ \n", " <:⑱㉜①㉛㉗⑬⑮㉖⑥㊳㉚ ⚖ ④㉝⑯⑲㉟㉘⑤㉕㉔㉑⑳ ➔ >:-㉘ =:-㊲ <:+④ \n", " =:㉛㉘⑦⑭㉖⑤⑯㉜⑫⑩⑮㉞⑬⑧㉙ ⚖ ②㉚㉑④⑳⑪⑥①⑲㉓⑱㉗㉕㉝㊱ ➔ \n", " >:㉟③②㉒㊴㉙㉓⑬㉚⑰㉝⑱⑲⑧ ⚖ ㉑㉛⑮㉕㉔㊱⑳㉗④⑫㊳⑪⑩㊲ ➔ >:+⑧ =:+⑤ <:+⑫ \n", " =:㉓⑮㉒④㉘㉟ ⚖ ㉗㉑㊳㉙㉝⑥ ➔ >:-㊳ =:+③ <:-㉟ \n", " <:⑩㉓①㉕㊱⑫㉗㊴⑦㉟④㉑⑧⑳㉜ ⚖ ㉔㊳⑯③⑪㉛⑤㉖⑲㉘⑮⑥㉝㊲㉙ ➔ >:-㉙ =:+② <:-㉜ \n", " <:⑭⑫㉕⑩㉚㉖⑲㊳⑱㉔㉙㊱㉜②㉗⑮⑥ ⚖ ㉟①㉛㉞㉘⑳㉑③⑧⑯㉓㉝㉒⑤㊲④⑬ ➔ \n", " >:⑭㉗㊲㉜㊴㉟⑨⑬㉔㉘⑮③ ⚖ ⑥④㉝㉕㉛②⑧⑫⑤㊳㉖⑱ ➔ >:-㉛ =:-㉞ <:+⑥ \n", " =:㉙⑧㉑⑲⑤㉜㉗⑩④㉛⑬⑦ ⚖ ⑪⑮㉞②㉖㊲⑰㊴㉒㊳㉓⑫ ➔ >:-㊴ =:+⑨ <:+⑪ \n", " <:㉔㉛ ⚖ ①㉗ ➔ >:-㉗ =:-㊱ <:+① \n", " =:⑦㉑③⑩㉛⑰㉞②㊲⑬⑨⑤㉙㉗ ⚖ ⑳㉕⑱⑪㉜㉘⑮④㉔㉒㉚⑭㊱㉝ ➔ \n", " >:⑬⑩㉖⑰⑥⑧⑫㉛㉔⑨⑳㉚⑲㉕ ⚖ ㊴④㉗㉜㉒㉘㉝⑭⑤①㊲㉟⑪⑦ ➔ \n", " >:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰ ⚖ ㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴ ➔ >:+⑰ =:-㉒ <:-⑭ \n", " =:④㉕㊱⑨㉚㉗⑪⑭⑮①⑬㉘㉛㉙⑥㉟ ⚖ ⑱⑫㉖⑲⑤㉜㊲⑳⑩②㉓⑯⑰㊴⑧㉔ ➔ >:-⑱ =:+㉑ <:-⑮ \n", " <:㉔㉚⑯⑲ ⚖ ㉕②㉑㉘ ➔ >:-㉕ =:-⑳ <:-㉔ \n", " =:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰ ⚖ ㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴ ➔ \n", " >:㉛㉗⑧㊱⑩⑲⑬⑤⑳㉘㉒⑱⑥㉔⑦⑭ ⚖ ㉖㉑①⑨⑪㉟⑯㉞㊴㉜⑫④㊲②③⑮ ➔ >:-㉖ =:-㉓ <:+⑯ \n", " =:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲ ⚖ ㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴ ➔ >:+⑲ =:0 <:-⑲ \n", " <:⑪⑮㉚㉛③⑳⑫⑰④㉑⑱⑯⑧⑭㉓ ⚖ ㉜㉞㉒②⑤⑬㉝⑦①㉘⑲㉟㉗㊲㊳ ➔ >:+㉓ =:+㉖ <:-⑯ \n", " <:㉓㉝㉛⑳⑱㊲㉗㉙ ⚖ ㉒⑤⑪⑰⑭⑲㉕⑯ ➔ \n", " >:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱ ⚖ ㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴ ➔ >:+⑱ =:+⑳ <:-⑰ \n", " =:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯ ⚖ ㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴ ➔ >:+⑮ =:-㉑ <:+㉔ \n", " <:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮ ⚖ ㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴ ➔ >:+⑭ =:+㉒ <:+㉕ \n", " <:㉑⑳㉖㉜㉛⑭⑩㉟⑨㉕⑫⑥⑦ ⚖ ㉚⑲⑪⑱⑮⑧㊴㉙④㉓㊲⑤⑬ ➔ \n", " >:㉖⑳㊱③㉒⑰⑯㉓㊴⑭⑱ ⚖ ④㉛㉔⑤㉝㊳⑩㉜⑧⑥① ➔ \n", " >:㉙㉓㉚⑮㉑㉞㉛⑫⑦⑯⑩⑨④ ⚖ ㉒①⑱⑧③⑳⑬㊱㉘⑭㊲⑰② ➔ >:-⑧ =:-⑤ <:-④ \n", " =:⑲⑰㊴①⑳㉙㉟⑦③㉘⑪ ⚖ ⑨⑮㉛㉝㉖⑧⑫㉒㉔⑥⑱ ➔ >:+㉟ =:-⑬ <:-⑪ \n", " <:①②③④⑤⑥⑦⑧ ⚖ ㉜㉝㉞㉟㊱㊲㊳㊴ ➔ >:() =:+㉛ <:+㉜ \n", " =:㉓④㉔⑥⑮㉞⑳㉘㉒㊱⑬②㉚⑦㊲ ⚖ ㊳㉛⑨㉝⑪⑩⑭⑯㉕⑫⑰㉟㉜⑤⑲ ➔ \n", " >:㊳⑧⑥㉑⑫㉟㊲㉛㉔㉜⑩㉙⑲㉞ ⚖ ⑰⑳③⑤⑬㉒㉘⑨㉖㊴㉚㉝⑱⑯ ➔ >:+㉞ =:+㊱ <:+㉘ \n", " =:㉝⑲⑬⑥④⑭㉚㉑⑮③ ⚖ ⑱②①㉕㉛㊲㉖㊳㉘⑨ ➔ >:-① =:+㉗ <:-③ \n", " <:⑥⑯㉗⑳㉓⑱㉝㉑㊱⑭② ⚖ ㉔㉚㉙㉖③⑲㉕⑰⑦㉘⑤ ➔ >:+㉝ =:+㊳ <:-② \n", " <:①⑮㉙㉟⑱㉝⑥㉗㉘⑩㉜㉑ ⚖ ⑦⑨⑰㊱②㉛㉚④⑧㉔③㉒ ➔ \n", " >:㉗③⑩⑫ ⚖ ㉙⑨⑰㉞ ➔ >:-⑨ =:-⑦ <:+㉙ \n", " =:㉘⑧㉒⑨⑯㉝㉗⑬㉙⑰㊳⑥ ⚖ ㊲㉜④㊱⑫⑱⑮㉖㉛⑭㉟② ➔ >:-⑫ =:+㊴ <:+㊲ \n", " <:⑪㉗㉞㉑①⑱㉛㉒㉟④ ⚖ ⑥㉚⑭㉓⑫㉘㉕②㉜㉖ ➔ >:-⑥ =:-⑩ <:+㉚\n" ] } ], "source": [ "do(p39)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "How about **80 balls, 4 weighings** under the condition that no ball can be heavier (thus, 81 possibilities, the maximum)?" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗ ⚖ ⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓ ➔ \n", " >:ⓑ⑪㉒Ⓟ㊻㉕㉟㊷㊼⑩㉓Ⓥ⑰Ⓛ㉔ⓓ⑦Ⓨ⑥②ⒸⒾ⑱⑮⑤ⒼⓈ ⚖ ㉜ⓍⒿ㊴Ⓓ㊵㊳⑯㊶①㊺ⓇⒷⓏ㉗㊽ⓒⒽⓀ⑧㊱⑲⑳Ⓔ㉞㊾⑫ ➔ \n", " >:③㉖㊶㉒Ⓨⓓⓒ⑰㊺⑲Ⓘ㊼⑬Ⓜ②⑫㊾㉝⑤㉗Ⓝ⑥⑪⑯⑧㉑ⒹⒻⒶⒽ㊸㊽ ⚖ Ⓡ㉛㊴⑨④㉕㉜㉓㊻㉚⑱⑦㉘Ⓟⓑ㊵㊲Ⓢ㊱⑩㉞㉔ⓀⓐⒼ①ⒺⓌ⑳⑭㊳㉙ ➔ \n", " >:ⓊⒾ㉑Ⓑ㉟㊼⑥㊽Ⓞ㊺⑭⑮㉒Ⓠ㊾ⓐ㊷㊵㉔⑳⑲㉖㊴④Ⓙ㉙ⒻⓉⓓⒺ ⚖ Ⓝ①Ⓩ⑫⑬㊿ⓅⓋⓇ⑩㉝Ⓜ㉗⑪⑯㊶㊹㊲㉞⑱Ⓒ㉜Ⓢ⑰ⓌⓒⒹⒽ㉚ⓑ ➔ >:-Ⓡ =:-Ⓚ <:-Ⓔ \n", " =:⑯Ⓖ㊲⑬㉒Ⓚ⑨⑱Ⓣ⑩ⒹⓍ ⚖ ⑭Ⓙ⑳ⓅⓈ㊵⑮Ⓐⓒ㊶㉞④ ➔ >:-Ⓙ =:-Ⓩ <:-Ⓧ \n", " <:⑯㊶㊲㊷ⒽⓊ㉗㊽ⒷⓈ⑩㉜㉑⑱㉝㊵ⒶⓂ㉖① ⚖ ⓒⓅ㉙Ⓡ㊾ⓑⓐⓌⓍ⑧⑪㊴㊿㊱㉟⑤Ⓝ③⑮Ⓘ ➔ >:-ⓒ =:-Ⓓ <:-Ⓗ \n", " =:㉝㊻㉖⑨⑦㊿⑭ⓁⓈⓌ①Ⓡ㊵ⒷⓅⓐ⑲Ⓙ㊳⑳⑥㉞㊷⑮㉗㉕⑧ⓒⓉ ⚖ ㊱⑪Ⓞ⑩Ⓗ㉓ⓏⓃⓋ⑱㊸Ⓕ㊺Ⓔ㊲㊾㊶㊴④ⒾⓀ㉚㉜⑯⑫ⓓ㊹⑬③ ➔ \n", " >:㊱①⑫ⓏⓋⓃ ⚖ ㉔㉕⑪Ⓨ㉙Ⓞ ➔ >:-Ⓞ =:-Ⓕ <:-Ⓝ \n", " =:ⓄⓂⓉⒹ㉕㉘㉖㊴㉑Ⓢ㊳㊵ ⚖ Ⓤ⑫⑳①Ⓝ㊺㉙ⓓ㉝ⓍⒿⓇ ➔ >:-Ⓤ =:-Ⓠ <:-Ⓜ \n", " <:㉝㉞ⒾⓃⓉⓆⓓ⑮ⒻⓅ⑳㉑Ⓙ⑩Ⓖ㊾⑬㉙⑯Ⓩ㉓㊺Ⓢ⑧Ⓗ⑫㉚④㉘ⒷⓁⓀ㊲Ⓤ② ⚖ Ⓦ㉒㊵㊼㊳⑨㉔㉖⑰⑤㊱⑭㊴ⓄⒸ㉟㊷⑥⑦Ⓐ㊶㊿Ⓡ㊸㉛ⓑⓎ㉕Ⓓ①Ⓥ㊹ⓍⒺ㉗ ➔ >:-Ⓦ =:-ⓐ <:-Ⓣ \n", " <:㊷㊶Ⓐ⑳Ⓟ㊵㉞㊹㉚Ⓙ㉒㉙ⓓ㉑⑬Ⓛ㊲ ⚖ Ⓘ㊳ⓊⓍ㊺⑧⑮⑱ⓀⓋⓑ③㉗①㊼㉛⑫ ➔ \n", " >:Ⓣ㉒⑰㉞㉟㊷㉙ⓏⒹ㊼ⓊⒻ⑱⑨⑯⑩㉗ⓒ㊾Ⓨⓐ㉛⑧㉔④⑥㉖ⒾⓓⒸ ⚖ ⓋⒿⓈ⑲ⓍⓌ②㊱⑫⑪㊹ⒷⓆⓇ⑭㊴⑬㉑Ⓚ㊿Ⓜ㉕Ⓝ㊺㊽ⒼⓅ㊻⑤㉜ ➔ >:-Ⓥ =:-ⓑ <:-Ⓘ \n", " =:ⓓⓁ⑨ⓍⓏⒹ㊽⑯Ⓑ②ⓆⒶ㉜Ⓨ⑮㉑㉚Ⓞ㊱Ⓥ㊲⑲㊹㉔ⓇⓉ㊿ⒾⒿ①㊴㉕㊵㊺㊷Ⓟ ⚖ ⓈⒽ④⑫⑰㊸⑭㉞㉗㉙㊻ⓒ⑳Ⓜ㉖⑱ⓑ⑩⑥㉓㉝㉟Ⓔ③Ⓤ⑦㉘ⓀⒻ㊼⑧㊾ⓐ⑤Ⓦ㊶ ➔ >:-Ⓢ =:-Ⓖ <:-Ⓨ \n", " <:ⓄⓈ㊾㊷Ⓦ⑭Ⓥ㉔Ⓗ㉞Ⓔ⑰㊺ⓓ ⚖ Ⓖ㉓Ⓙ㉖㉑⑦㉝Ⓚ㊿㊼ⒸⒶⓁ⑲ ➔ >:-Ⓛ =:-Ⓟ <:-ⓓ \n", " =:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱ ⚖ ㊺㊻㊼㊽㊾㊿ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓ ➔ \n", " >:㊿ⓆⓃ㉙㉘㉛㊺⑧⑲ⓓ㊴Ⓟ⑭Ⓖ㉚ⓒ⑯㉒Ⓢ⑩ⓑ㉖㊻ ⚖ ⓇⒽ②⑱㉔ⓌⓏ㉕Ⓚ⑮Ⓓ⑨ⒾⒶⓁⓎⓊ㊼㉞㉟⑤㊽㉑ ➔ \n", " >:ⓑ㊿ⓓ⑤Ⓥ㉝⑥ⓏⓀⓆ②⑩㉓⑪ⓍⒹⒻ⑬Ⓞ㉞Ⓐ ⚖ ㉑⑯㉗㊻㊺㊱㊼㉟⑮㊴⑦ⓎⓅ⑧ⓁⒺ㊹㉙㉚㊵Ⓡ ➔ >:-㊼ =:-㊽ <:-Ⓐ \n", " =:⑪Ⓐ㉑Ⓨ㉔②㊲⑬㉙Ⓟ㉚ⓑ㊾ ⚖ ㊿ⓄⒷ㊷⑰ⓃⓊⓂⒹ⑯㉟Ⓛ㉖ ➔ >:-Ⓑ =:-Ⓒ <:-㊾ \n", " <:Ⓜ㉝Ⓓ㉞Ⓥ㊽④ⒷⓌ㊴ⓒ⑪㊾㊺ ⚖ ㉒㊼⑯㊿㊵⑤⑰Ⓡ①㉔㉙㉜Ⓠ⑱ ➔ >:-㊿ =:-㊻ <:-㊺ \n", " =:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴ ⚖ ㊷㊸㊹㊺㊻㊼㊽㊾㊿ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓ ➔ \n", " >:⑳⑫㊼㉒Ⓓ㉟㊷ ⚖ ①⑬㊸㊻⑧㊾Ⓑ ➔ >:-㊸ =:-㊹ <:-㊷ \n", " =:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴㊵ ⚖ ㊶㊷㊸㊹㊺㊻㊼㊽㊾㊿ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓ ➔ >:-㊶ =:0 <:-㊵ \n", " <:⑳㉑㊳ⒺⒿⓃ ⚖ ㊲ⓑⓇⒹ⑨⑬ ➔ >:-㊲ =:-㊴ <:-㊳ \n", " <:ⓐⓀⓌ㊻⑦①㉔③④⑯⑫ⓇⓍ⑳㉝㉞Ⓐ㊽㊿②㉒㉕ⓎⓁⓒ⑰⑩ⒷⒿ㊺㊴㉘ ⚖ ㊱ⒽⒻⒾⒼ㉛㉙⑮⑪㉗ⓑ㊲㊶ⓅⓏ㊷Ⓔ㉖Ⓢ⑥⑬ⓓ⑧㊾Ⓒ⑨㉑ⓂⓆ㊼⑤㊸ ➔ \n", " >:㊹⑦⑰⑭㉟⑤㊻㊸㊾㉛㉔ⒾⒺ㊺ⓎⒶ㉖⑥ⓒⓂⒸⒻⓁ ⚖ ㊱㉓ⓏⓍⓌ⑬⑪Ⓟ㉘ⓃⓈ㊽Ⓚⓐ⑯㊼ⒿⒽ㉞ⒹⓉ⑧Ⓞ ➔ >:-㊱ =:-㉙ <:-㉛ \n", " =:Ⓟ㉑⑧Ⓔ㊿⑳Ⓢ⑤Ⓨ㊳ⓒⓓ①②㉒⑭Ⓝ㉚ ⚖ ㊹ⒶⓊⓉⓋ㊸㊴㉝ⓇⓐⒽ㉙ⒹⒸⓂ㉟ⓏⒿ ➔ >:-㉟ =:-㉜ <:-㉚ \n", " <:Ⓡ⑤㊱Ⓜ㉜ⓌⓃⓍ㉒㊹㊵ⓈⓊⓉ㊷㉟⑥Ⓚⓑ㉓Ⓖ㉘㊻④Ⓓ⑨㊳ ⚖ ㉝㊸㉕㉙③㉖㊶㊲ⓎⒽ②⑫⑱⑰⑮㉛⑦ⓐ㊿㉚ⓓⓅⓆⓋ⑩㉑Ⓘ ➔ >:-㉝ =:-㉞ <:-㉘ \n", " <:㊾ⓊⒷⓉ⑰⑤㊷⑪Ⓧ㉘⑧⑯㉓Ⓝ⑦②㊳㊻Ⓙⓒ㊺Ⓕ㉕ ⚖ ⑳③⑩ⓐ①Ⓒ㊱Ⓥ⑱Ⓠ㊹⑫㉙㉗Ⓨ㉞㊼Ⓛ㉖⑭㊶Ⓩ㊴ ➔ \n", " >:ⒹⓊ㉓㊸⑮Ⓣ㉞㊻Ⓑ㊽㊴㊶㊱⑦⑤ⓐ㉜㊺ⓒⓅ㉒⑳ⒼⓀ⑧⑪㉝Ⓜ⑱④③ ⚖ ⓎⓆⓁⓓ⑩ⒶⒽ⑫Ⓞ⑬㊹㊼⑲Ⓒ㉘Ⓦⓑ⑰㊾Ⓩ㊲㉟㉕㉗㉙⑯ⓃⒾⒻⓇ② ➔ \n", " >:㉖㊱㉑㉗㉚Ⓡ㉛⑧⑥Ⓧ㊷ⓅⒾⓃⓆⓁ㊻㊶㊵㊽⑨ⓌⓈ㊼㉕ⓒⓂ㉘Ⓩ㉞⑲Ⓣ㉓ⓐ⑯⑪Ⓓ ⚖ ⑫㉙①⑦Ⓑ⑱ⓎⒶ㊹ⒺⓊⒼ⑰㊴③⑳ⒽⒻ⑮②㉝㉒⑬⑤ⓄⒸ㉜㊾⑭㊿Ⓙ㊲ⓑⓓⓀ㊺Ⓥ ➔ >:-⑫ =:-⑩ <:-㉗ \n", " =:㊶⑥㊽㊸⑮⑭ ⚖ ①㊿ⒽⒷⓆⓋ ➔ >:-① =:-㉖ <:-⑭ \n", " <:ⒽⒾ㉕Ⓑ㉙㉞ⓆⓌ⑩⑯⑲㊺Ⓔ③ ⚖ ㊻⑤⑳⑨㊳Ⓚ㉛Ⓡ㉝⑪⑦Ⓞ⑫Ⓖ ➔ >:-⑳ =:-⑱ <:-③ \n", " =:ⓐⓎ⑨ⓆⓍ⑯Ⓢ㉖㊲Ⓦ⑤③ⒹⓉ⑭Ⓩ①㊴⑫④㊻㉚Ⓘ⑪⑥ ⚖ ⓒⒶ㊾⑲Ⓤ㉟⑩ⓑ㉑ⓁⒻ㉝⑮ⓓⓃ㉛②㊹㊳ⓄⓅ⑰⑦㊷㉗ ➔ \n", " >:Ⓟ㊵Ⓖ㊳㊺ⓐ②Ⓑ㊾⑩㊽㉓㉒㉚⑤Ⓥ⑮ ⚖ ㉔⑦④Ⓘ㊷Ⓓ㊻⑨Ⓞ㉞㉑⑬Ⓔ㊸ⒸⓀⓂ ➔ >:-㉑ =:-⑲ <:-⑮ \n", " =:㉑㊾ⓓ㉞㉓⑧ⓈⒿⒸ⑱ⓃⓁ⑭㉘ⓐ㊱⑨㉚⑬ ⚖ Ⓧ㉙Ⓦⓒ②Ⓣ㊶③Ⓓ㉜ⓅⒼ⑥㊷㉒㊵㊿⑲Ⓘ ➔ >:-㉒ =:-㉔ <:-⑬ \n", " <:Ⓚ㉚⑮ⓑ⑱ⒿⒺ㉙⑩Ⓨ㊼ⓃⓏ⑥⑦Ⓞ㊵⑭㊷⑬ ⚖ ⑨㉘㉜㉒㊴㉓ⓇⓐⒾⒼ㊾㊶Ⓗ㊿⑯Ⓕ⑤③ⓓⓉ ➔ >:-⑨ =:-④ <:-⑥ \n", " <:㉑㉙⑨ⒿⓋ㊶㉕㊿ⒾⓃ㊽②ⓇⓉ㉝㊵⑮Ⓕ⑱Ⓑ㊺ⓂⓄ⑤ ⚖ ㊾㉖㊻ⓀⓎⓁⓈ㊲㉒⑲⑩㉚ⓑ⑰⑧⑪㉗⑥㉟ⒶⓊ㊷⑫㉔ ➔ \n", " >:Ⓧ⑫㊼㉚②㉕⑦㉞ⓉⒻ⑥ⓊⓀ㊾Ⓛ⑪㉘㉒ⓑ㊶㊵㉔㉗ⓋⓌ ⚖ ⑰Ⓜ㊹㊱Ⓢ④㉓Ⓐ⑮Ⓨ㉜㉙㊻㉛ⓅⒾⒿ①⑯⑱㊽ⓓ⑤㊲Ⓝ ➔ >:-⑰ =:-⑧ <:-⑪ \n", " =:Ⓒ③㊹⑨⑦ ⚖ ㊽㊿㉓Ⓘⓒ ➔ >:-㉓ =:-⑯ <:-⑦ \n", " <:㉚㉟ⓂⒸⓓ⑤㉛Ⓞ ⚖ ②㉖⑪㊳㉓㊷⑭⑧ ➔ >:-② =:-㉕ <:-⑤\n" ] } ], "source": [ "do(Puzzle(80, 4, '-0'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Looking good (except that the output is still rather hard to read).\n", "\n", "# Puzzles with 5 Weighings\n", "\n", "With 5 weighings, 35 = 243, so I might be able to handle up to 121 lighter-or-heavier balls (242 possibilities):" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "None\n" ] } ], "source": [ "puzzle5 = Puzzle(121, 5)\n", "do(puzzle5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Nope, that didn't work. Let's check the partition sizes (they need to be 81 or less to solve in 4 more weighings):" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[80, 82, 80]" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "partition_sizes(puzzle5, 40)" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[82, 78, 82]" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "partition_sizes(puzzle5, 41)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's back off to **120 balls, 5 weighings** for 2 × 120 + 1 = 241 possibilities:" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴㊵ ⚖ ⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ⦰⦱⦲⦳⦴⦵⦶⦷⦸⦹⦺⦻⦼⦽⦾⦿⧀⧁ ➔ \n", " >:㊴㊳ⓨ⦸⑫⑩④ⓌⒾⓅⓐⓝⓠ㊽⦲①㉛③ⒺⓣⒶⓦ⦹Ⓞⓙ⦶ⓗ⑨㊹Ⓡ㊱⑰Ⓩ㊿Ⓕ⦴②㉞ ⚖ ㉟㉗Ⓑ⑥⑤⑦⑧ⓜ㉓㉑⦻ⓞⒿⓩⓘ⑬⦳㉖ⓓⓤ㊺ⓚⓥ㊼ⓔ⦰㉕⑯ⓢ⦿㊻Ⓖ⑲⦽Ⓛ⑳ⓊⓍ ➔ \n", " >:⑤ⓙⓦ㊷⑨㉕㉘⦾ⓋⓩⓕⒶ⦲⑥⦱ⓓ⑬㉞Ⓣ㊵ⓑ⑱㉙⧀㉔ⓞ㊻⑪⑧⦸⦺ⓖⓄⓈ㉓⑩㊸⦷ⓘ㉚㉛ⓝ④⦹ ⚖ ⑫㊳ⓂⓥⓍⓌ㉗㊹⦵②ⓠ㉒⑲⑦ⓨⒽⓛ㊾㊿㉜⦳ⓟⓊ⦿①㊽Ⓓⓒ㉑㊴ⓡ㊶ⓐ㊱⦼ⒾⓏⒿⓤⒺⓁ㉖⦴ⓣ ➔ \n", " >:⦹㉚ⓥⓇ①⦱⑧ⓕ㊼Ⓘⓖⓣⓗⓝ㊲㉘㊳⑮Ⓛ㊹Ⓨ㉛ⓜ⑭㉓⧁⑯③ⓔ㊸⑤⦼⦵ⒷⓊⓄ⑨㉜ⓤ ⚖ ㉙Ⓔⓙ⑫㊷ⓦ㉟⦻⑲Ⓒ⧀Ⓟ㊾㉖Ⓩ㊵⦰㉒⑬㊶⑪ⓩⓈ㊿ⓡⓧ⑱㊽㊴⦷④ⓞ⦿⑳Ⓗ⦸㉔ⓘⓛ ➔ \n", " >:⑰Ⓞ㉜㊳㉗㊻ⓊⓚⓋ⑥㉘ⓞⓨⓍ㊱ⓦ⑦⦵⦻⧀㉚⑯㊿⑲Ⓒ②㊾①ⓌⓠⓅⓕ㉛ ⚖ ⓤⓎ⧁⑳ⓒⒺ㊸ⓥⒹ㊵⑨⑫㉔㉓⑭⦾㉝ⓀⓈⓟ㉟㊴Ⓖ⦽ⓙⓉ⦶ⓢⓛⓗⓓ⦼㊺ ➔ >:+㉛ =:-⦿ <:+⑨ \n", " =:㊹ⓙⓎⓘ⑳ⓋⓝⓃ⑭ⓥ㊱ⓐⓛⓨ㊾⦴⑪㉞㉑Ⓣ⦽ ⚖ ⑩㉙Ⓚ⑧㉕⑫ⓁⓍⒷⒾⓂ⑦⦼㊷ⓞ⦿ⓧ㊸㊵㊺㉓ ➔ >:+㉞ =:-⦳ <:+⑩ \n", " <:Ⓞⓣ㉔ⓥⓘⓦ㊼ⓠ⑳⑪Ⓐ⦹㊽Ⓗ⦺ ⚖ ⓤ⦲②⑭⑩⦻⦷Ⓙ㉒Ⓚ㊾⦱㉗㊶ⓖ ➔ >:-ⓤ =:+④ <:-ⓥ \n", " =:Ⓢ㊺ⓛⓠⓄⒻ㉗⦾⧁㉓㉞⦷ⓨ㉖ⓕ⑱③Ⓡ㉚㉑Ⓘ⦵ⓑⓒ⦳㊲ⓓ⑲ⓥⓔⓍⓃ⦼㊼ⓧ㊾ⓂⓀⓖ⑦Ⓗⓢ ⚖ ⓐ⦻㊿⑧Ⓥ㊽⑫⦿⦸Ⓙ㊻㊳㉔⑨ⓩ⑭②Ⓠ㉕Ⓛ㊹Ⓩ㉒④ⓦ⦹ⓣ⦴㊶Ⓟ㉙⦲⑬①Ⓑⓘ⦽ⓟⒹⓉ⦶⑰ ➔ \n", " >:ⒺⓗⓁⓅ⦹Ⓡ⦾Ⓒ㊱Ⓥ㉚Ⓘ㊽⑲㊺ⒻⓌⓒⓟⓍⓥ㊵Ⓢⓙ⦶ⓠ㉛⧁㉕④㊳㉜Ⓖ㉗⑬⑨ⓛ㊻⦽ ⚖ ⓑ⦻ⓦ㊿⦰㊲ⓤ⦵ⓝ㊸⧀⑪Ⓚ㊾ⓜ⑤Ⓜ⦼⑭ⒹⓊⒶ㉖⦱⑧ⓧⓡ②㊶ⓩⓚⓖ㉔ⓨ⦿㊷Ⓠ⦳㉓ ➔ >:-⦻ =:+③ <:-⦽ \n", " =:㉒Ⓨ⦰㊾⑫㉗ⓟ㉚㉔Ⓠⓙⓔ⑮Ⓤ ⚖ ⓜ⑰⦳Ⓒ⑤Ⓞ⦴㊸ⓢ⦶⦱ⓛⓏ② ➔ >:-ⓜ =:-ⓚ <:-⦰ \n", " <:㊵Ⓢ㉑㉜⦱ⓥⓄⒽ㊾ ⚖ ⑰ⓢⓨⒹ㉔⦼⦿ⓜ⑨ ➔ >:-ⓢ =:-ⓔ <:+⑰ \n", " <:⦼ⓔ㉕ⒺⓠⒶⓈⒿ②ⓕ⑩ⓣ㉘⧀⑭⦷⦺①㊸ⓐ⑨⦸⦲Ⓨⓞ ⚖ ⦰Ⓞ⑮㉜⦽ⓤ㊿③ⓑⓋⓩⒾⓍⒽ㊷㊱㉚⦹ⓟ⦿㉗⦻㊴㊲⑲ ➔ \n", " >:Ⓦ㉓ⓨ㉔⦰Ⓢⓔ㉞Ⓕⓟ㉖ⓞⓋ㊿Ⓗ㉒ⓣⓏ㊾㉚㊶⦽㉝ ⚖ ②⦱ⓛ⦷Ⓝ㊱Ⓔ㉑⑬⦵㉟⦸⦹Ⓟ③㊻ⓆⓩⓙⒶ⑥⑱⦼ ➔ >:-ⓩ =:+① <:+② \n", " =:ⓞⒺ⑨ⓘ⑬⦱Ⓒ⦰㉘⦻Ⓞ③ⒾⓌⒶⒼ㊽ⓣ⑥Ⓓ㊸Ⓕ㉒Ⓥ⑫ ⚖ ⑭㉗Ⓨⓤ㊹㉔㉓ⓚⓃ㉙⦲ⓨ⑱Ⓙ㉚Ⓠ⦺ⓦ㉑Ⓑⓝ㊻Ⓢ⑳⑰ ➔ >:+⑫ =:+㊳ <:-ⓘ \n", " <:㊼㊴Ⓚⓠ⦻①㊽ⓛⓚ⦺③㉜⧁ⓩ⦷Ⓢ⦹㉟ⒼⓏ⑨ⓅⒽⒻⓊ④Ⓡ⑧ⒿⓂⓝ⦳⦱Ⓣⓗ⑥ⓥ⑮㊹㉔㊶㉚Ⓥⓞ ⚖ Ⓔ㉝Ⓒ⦵㊿㉗㉛ⒶⓔⓄ⦽ⓒⓡⓢⓆ⑬⦲ⓧ⦼ⓙⓣⓐⓁ㉖⦰Ⓝ㊾⧀⑭ⓘ㊲Ⓨⓤ㊳⑪㉒ⓕⒹⓖⓜ⦶Ⓦ⦿⑫ ➔ >:+㊴ =:+㊱ <:-ⓞ \n", " =:㊶④Ⓝⓧ⦾ⓦⓠⒾ㊺⑬ⓡⓘⓊ㉚Ⓣ㉘⑱ⓞ⦲ⓔⓐ⑧⑥⦳ⓙ⑰ⓎⓈ㊲㊿㉝ⓛ㉕Ⓦ①Ⓧ⧁Ⓟ ⚖ ⦼㉛㊴ⓩ⦹⦶㊷Ⓑ⦵㉔Ⓞ⑩Ⓥ⑲⦱⑫⑮⦸ⓑⓤⓟ㉑⦿㉓ⓁⓆ⑪㊱⑤ⒸⓇ㊹③⦴㉙⑨ⓥⓏ ➔ \n", " >:ⓞ⦻⑨ⓙⓁⓈⓇ⦷⑫ⓄⓊⓐⓘⒸ⑤Ⓓ⑩㉟㊽⑬③ⓕ㉗⦱⑪㊾㊸⑧⦾⦸Ⓕ㉑㉔⧁㉚④ⓟ ⚖ Ⓚ①⦲②Ⓦ⑦㉜ⓝⓨⒿⓍ㉛㉞⦼⑭ⓗⓩⒶ⦵ⓒⓋⓖⓡ㊼Ⓟ⑲⦴㊻⦿⧀⦺ⓉⓣⓂⓚⓆ㉘ ➔ \n", " >:⧁㉚⑫⑧Ⓗ⦼ ⚖ ㉝ⓣⒾ㊵ⓨ⦺ ➔ >:+㉚ =:-⦵ <:-⦼ \n", " =:⑰㊿㉙㉞㊴ⓘ⦻ⒶⓂ㉜⦴⧁㉖⑱ ⚖ ⓨⓅⓐ㉑㉗⑩⦽⑯ⓒⓁ⦸㊱ⓓ㊲ ➔ >:+⑱ =:+㉝ <:+㊲ \n", " <:㉟ⓣⓙⓠⓞ⦴㉚⑮Ⓣ㊺Ⓝ⦶Ⓡ⑪Ⓓ㉝㊾㊱Ⓦⓝ⦾⦹Ⓖ ⚖ ⓟ㉖⦼⑳㉑Ⓨ㊿㉘ⓈⓅⓂ①ⓔⓖ④ⓘ㊶㉕⦸ⓕⓛ⦿⦺ ➔ >:-ⓟ =:-⦱ <:+㉘ \n", " =:⑬Ⓥ㊽⑥ⓚ㊷⦵㊸⦲Ⓦ㉒⑤Ⓓ①Ⓣ㊼Ⓨ⦷㉝⦱ⓛⓈ⦺Ⓟⓖ⑭ ⚖ ⓣⓔⓕ⧁㊿Ⓛ⑯㊲Ⓐⓡ⦻⑪ⓤ㉘Ⓒ③⦹⦿ⓊⓇⓦ⑩⑰⑱ⓑ⑨ ➔ \n", " >:㊴㉗Ⓧ⑮㉖㉟㊺㉘Ⓥ⑩Ⓐ㉛Ⓡ②ⓤ⦱⦴Ⓔⓙ⑳⦸ⓠⓅⓂⓨ㉜⑤㊾ⓡ㉒ⓕ ⚖ ⓐ㊼ⓘ㊳ⓜ㊸ⓝ㊽㉙ⓑ㉓⑰㊵⦻⑨ⒻⓉ⑯ⓀⓏⓥⓞ①Ⓞ⧀Ⓢ⦽⦰㊻⦾㉝ ➔ >:+㉒ =:+⑭ <:-ⓕ \n", " =:㊹⑤ⓙ⑩⦶⑧Ⓢ㉘Ⓦ⑦㉟⦻ⓘⒺⓧ㉛⑮㊵ ⚖ ⒿⓎ㉞ⒶⒻ⑬㊿③⑨⦼㊱㊽㉝①⦷㉗㉜② ➔ >:+㊵ =:-⧀ <:+㉜ \n", " <:㊷㉞⑮㊺㉜㉗㊵ⓦ⦶⑪Ⓐ⑬㊴㊱Ⓨ㊳ⓔⓧⓇ⑱ⓢ㊽㉖㉛ⓀⓄⓌ㉙㉓⦸㊿ⒸⓓⓉⓝⒼ⦷ ⚖ ⑳⦴③⑦⧁ⓤ㊾㉕㉔⦺ⓩⓚ⦽ⓠⓏⒻ⦿ⒹⓍ⑥㊲ⓐ⦱Ⓥⓡ⦻⑨⑫ⓣ㉚㉟⦳Ⓔⓨ⦹⦾⦲ ➔ >:-⦺ =:-ⓖ <:-⦷ \n", " <:ⓒ⦼⦿④⑦⑤ⓓ⦸ⓧⓐ㊸Ⓚⓛⓡ⑩㉝Ⓥ⦳㉞⑮⦴Ⓞ㉚⑯⑪Ⓗ ⚖ ⦾ⓑ⑨㉛ⓩ㊶ⓃⓈⓝ㊽③㉒ⓔⓦⓨ⑳㊷㊼㉑㉓⑱㉗㊵Ⓓⓢ⑰ ➔ \n", " >:Ⓩ㊴Ⓝ⑭㉒ⓢ㉞Ⓔ㊶ⒷⓊ⑥㉓ⓚ⑦Ⓥ⑤㊲ ⚖ ⑮⑫㊱ⓤⓔⓅⓒ⑰ⓧ⑬⦾ⓛ⑧㊺ⓐ㉚㉑⦸ ➔ >:-⦾ =:+⑪ <:+⑮ \n", " =:ⓤⓏⓨ㊾Ⓖⓦ㉓Ⓠ⦽Ⓓ㊽ⓖ㉑㊼⦲⦱⦴ⓠⓍⓅ⑧Ⓞ㉗Ⓛⓐ㉘㊵⑮ⓚ ⚖ ⧁⑩㊴Ⓑ⦼㉔⑫㊲⦺ⓣⒶ⦵ⓞ⑭⦶㉜㉚ⓑ①⧀ⓇⓒⓎⓔⓓ⦿㉞Ⓗ⦷ ➔ >:-⧁ =:+㉙ <:+㉔ \n", " <:ⒻⓤⓐⓇⓣ①⑩ⓞ⦸ⒺⓢⓎ⑬ⓑ㉛㉒㊳⑳ⓕⓠ②㊶ⓄⒿ⑱⦽ⓁⓋⓟ⦵⧀⦱ⓂⓖⓥⒽ㊺⦲Ⓘⓛ ⚖ ㉑㉘㉗ⓧⓘ㊽㊿⦷⑦㊼ⓌⒼ㊻㉞⦿⑮⦹ⓜ㉝ⓒ㊱⦳⦻⑥ⓝⓗ㊷⑪Ⓝ㊹㉖Ⓤ㊾⦴⑭Ⓒ㊲ⓩ⦺⑤ ➔ >:-ⓧ =:-ⓡ <:-ⓛ \n", " <:ⓋⓅ㊲Ⓑ㊱⦾㉙ⓐ㊸㊴Ⓝ⦷⑨Ⓤ㉓⑰⦴Ⓧ㊳③㉚㉒ⓓ㊿⦹⑦ⓩ⦿㉗ⓨ①㊼ⓚ⦻ⓈⓜⓆⒺ㊻Ⓘ⑧ ⚖ ㊺ⓥ⑯㉖④②⧁⧀⦰⑫⑩Ⓜ⦺㉞ⓖⓠ⦳⦵㊹㉟Ⓞⓣⓒ⑲ⓛ㉜ⓘⓢ㉘ⓔ⦸㉝㊷⦽㊽ⓝⓉⒼ⑬Ⓚⓗ ➔ \n", " >:①⦹㊼⦻㊶Ⓝ⑨⑲Ⓦ㉝ⒽⓅ⑫ⓔⓝⓓⓛ⦴Ⓨ㉔⦷Ⓡ⦸Ⓛⓙ⦵⦼㊵⦳⑩⑰㉗ ⚖ ㊸③㊽⦱⑮㊱⦰㉘⑪ⓥ⑦Ⓑⓩ⦺⧀ⓣ㊻ⓟⓀⓍⓠⓈⓜⓒ㊳㉙ⓉⓋⓏ㉑Ⓠⓐ ➔ \n", " >:ⓜ⑨⦱Ⓑ⑤ⓥⒹⓐ㉚Ⓘ㉝①ⓚⓂⓆⒽⓗ㊷㊿ⓠ ⚖ ⓣ㊶㊳㊹ⓄⓀⓅ㊲⑬㉖㉑㉒ⓑⒿ⦿Ⓡ⦵㉙ⓟ⑭ ➔ >:-ⓣ =:+㉗ <:-ⓠ \n", " =:㉘⦾⑪⑬⑥⑧ⓟ⦼Ⓥ②⑤⑨③⦶㊽Ⓐ ⚖ ㉓Ⓦ⦰Ⓒ㊹⑭ⓃⓘⓀⓈⒻⓦ㉙㊵⦴ⓕ ➔ >:+⑧ =:-ⓗ <:+㉓ \n", " <:②ⓣ④Ⓔ⦼Ⓑⓙ㉓㉗Ⓣⓡ㉖⑬Ⓢⓟ㊱⦵⑮⦿⑯⑲㉙㊳ⓒⓎⓌ⑧㊾ⓩ㉕⑰⧁ⓧ⧀㊵⦾Ⓙⓤⓖ⦶⦱⦸Ⓚ⑩ⓑⓨ⦽ⓕ㉚⑤㉝㊴⑦ ⚖ ㊲㉟ⓅⓁⒶ㊽⦺㉞Ⓓ㉔㊿㉑⑫⑱Ⓤ㊶㊹ⒾⓃⓚ③㉜Ⓥ㉘ⓘⓗⓠ㊷㊻⑪㉒⑥⦴㊼Ⓞ⦰⦻ⓛⓔⓢⒼⒸ㊺⦳Ⓡⓞ⑳ⓜⓐ⑭⑨Ⓧⓓ ➔ >:+⑦ =:-ⓝ <:-⦸ \n", " =:Ⓗ⧀⦸ⓖⓩ㉑㊾ⓅⓍⒸ①⦽Ⓠⓒ⑧Ⓖ②⑰Ⓨ⦶ⓟⓇⓈ㉒㊻Ⓞⓑ⑥ ⚖ ⓧ㊴ⓊⓂ㊷⑬Ⓔ⦷⦺⑤ⓚⓤⓓ⑳㉟㉖④⦰㊽ⓦⓕ㊸Ⓐ㉔㊲ⓔⓗ⦾ ➔ \n", " >:Ⓦ㉟ⓑ㉙⑲ⓒⓅ㉓ⓥⓉ⦱ⓩⓆ㉕ⓛ㊷ⓝⓤⓎ⑭⦶Ⓜ⑮ⓦ⑦Ⓑ⦲㉒ⓔ⑱⧀ⓙ㉑ ⚖ ⓞⓏⓓ⑧ⓡⓗ㉗⦼㊶⑩⑫㊴㉖㊺Ⓖⓐ㊵⑪㊻⦿⦾Ⓛ③⑳㉞④㊲⧁ⓋⒹⒿ㊿Ⓚ ➔ >:+㉑ =:+⑥ <:-ⓦ \n", " =:ⓣ⦱Ⓡ㉔⦹㊻⑦ⓚ㉛ⓖⓔ④Ⓛ㊱㊾⑮②ⓠ⦲ ⚖ Ⓝ⑬ⓡ㊳㉗ⓞⓐ㉘Ⓕ⦼ⓥⒾⓛⓎ⦿㉝⧁⑰ⓙ ➔ >:-ⓙ =:+㉕ <:-⦲ \n", " <:⑥ⓛ⦲Ⓖ⑬⑧ⓖⓡⓧⓠ⑩⑫Ⓩ⦾ⓐⓞ⑮ⓨ㉙ⓙ⑨⑪ⒹⓌ②Ⓛ⦽ⓩ⧁Ⓙ④ⓥ⑰⦿ ⚖ ⦶ⓒⒻ⦻Ⓡ⑭㊽Ⓚ㉗㉝㉛㉚ⓑⓈⓆ⦹㊴㉖⦵Ⓒ㉟㉕ⓣⓅ㉓ⓚⒺ㊾①㊳⑳⦷ⓔⓗ ➔ >:-⦶ =:+⑤ <:+⑳ \n", " <:㉙ⓟ㉖ⓡⓇⓊⓚ⦾⦺ⓨ㉞⦷㊼Ⓩ㊳⑮㉚㊸Ⓦⓢ㊲ⓍⒹⓦ㊻ⓩⓅ⑭⦳㉝⦻ⓤⓓⓁⓎ㊷③Ⓜ㊹㉔㊽㊱㊿⦲ⓝ⦽⦶ ⚖ ⑲Ⓢ⑨㊴ⓥⒾⒸⓘ㉗ⓑ⧀㉟ⓜⓗ㉛⧁ⒶⒽⒷⓄ㊶ⓐ㉒⑧㊺ⓕ㊵⦸㉘⑤ⓒ⦴ⓃⓋ㉜Ⓠ⦿ⓣ㊾ⓖⓧ⑰①㉓⦱②⑦ ➔ \n", " >:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭ ⚖ ⦴⦵⦶⦷⦸⦹⦺⦻⦼⦽⦾⦿⧀⧁ ➔ >:-⦴ =:+㉖ <:() \n", " =:Ⓖ㊹⑫⦻㊵⑳ⓤ⦸㉑㉖Ⓡ⦵⦿Ⓗ⦶ⓍⓄⓦ⑯ ⚖ ⓐ⑮㉚Ⓟ㊳㉔㊽⑭ⓙⓔ㉓㊴ⓛ⑬ⓧⒹⒾ⦱⑩ ➔ >:+⑯ =:-⦹ <:+⑬ \n", " <:⦶ⓕ㊸Ⓟ⦾Ⓛ㉒⦰⑫ⓦⒸⓘ⑳ⓥ㉑Ⓩ③⦽ⓤⓄ⑤⑥⦿ⓚ㊱Ⓙ⑰㊶⦳⑱㊵Ⓗ㉚ⓣ㉜㊲Ⓣ⦹Ⓤ⦴Ⓜ ⚖ ⓨ⦲㊴ⓖ㉞ⓓⓜⓎ⦷⧁㊽Ⓡ①⦸㉘㉔⑭㊷ⓑⓈⓙⓗ⦱④ⓩ㊼Ⓥ㉟㉛Ⓕ⑮Ⓘ②Ⓚ⑦ⓧ⑬ⓟⓝ㉝⑪ ➔ >:-ⓨ =:+⑲ <:+㉟ \n", " =:①ⓆⓂ⦵ⓨ㉜ⓙⓔ㉙Ⓖ㉓㉖⦰ⓩ㉞⦹㊹㉛ⓈⒾⓚ⑧Ⓛ⦻⑨ⓧ㊴⦴ⓛⓖⓒⓎ㊳⑭⑬⑦㊿㊱②⧀ⓞ ⚖ Ⓧ㊽④⑱ⓑ⑲⦾Ⓣ㊺Ⓑ⑪⦲③⑳Ⓦ㊻⦶㉒⦳Ⓚ⧁Ⓗ⦼㉟㉚Ⓓ㊶ⓢⓐ㉑㉗ⓘⓕⒺⒶ㉔⦽ⓝⓓ㉝Ⓝ ➔ \n", " >:㉙Ⓧ㉒⧁㊴⑭⑧ⓚ㊲ⓅⓃⓆ㉑⑬⦼⑦Ⓦ⦵㊺Ⓑ⑰㊳ⓢⒿⓀ㉘⑮㉗Ⓖ㊿⑨ ⚖ ⒺⒽ㉜㊵ⓎⓂ⑪㊽ⓠⓕⓥ⑩⧀ⓑⓩ⦿ⓣ⑯②⦱Ⓐⓓ⦸㉞④Ⓛ⑥Ⓡ㉔ⓡ㉓ ➔ \n", " >:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴㊵㊶㊷㊸㊹㊺㊻㊼㊽㊾㊿ⒶⒷⒸⒹ ⚖ ⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ⦰⦱⦲⦳⦴⦵⦶⦷⦸⦹⦺⦻⦼⦽⦾⦿⧀⧁ ➔ \n", " >:㊿ⓇⓂ⦼㉕㉓ⓔ⑪⦽⧀①Ⓖ⦶㉔ⓝ㉘ⓚⒽⒻ㊼Ⓓ㊽Ⓛ⑤⦷⑮㉖㉚ⓙⓩ⦹Ⓔ㊴⑱⦲ⓣⓖⓢ㉟㊸⦺⦻Ⓙ㉝㊲㉗㉒ⓑ ⚖ ⦴Ⓟ㊶⑬Ⓢ⑯Ⓘⓨ②㊱⑦ⓏⓍ⑩ⓥⓊ⑥㊷㉜⦾Ⓒⓠ㊳ⓗⓟⓜ⦰ⓒⓎ㊾⦱㉛Ⓣ⑭Ⓞⓤ④Ⓚ⦳Ⓦⓘ㉑ⓛ⑰⧁Ⓥ⦸㊻ ➔ >:+㊿ =:-ⓓ <:-ⓑ \n", " =:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴㊵㊶㊷㊸㊹㊺㊻㊼㊽㊾㊿ⒶⒷⒸⒹⒺⒻⒼ ⚖ ⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ⦰⦱⦲⦳⦴⦵⦶⦷⦸⦹⦺⦻⦼⦽⦾⦿⧀⧁ ➔ >:+Ⓖ =:-Ⓗ <:-Ⓔ \n", " <:⑩㉑ⓦ㉛㊱⑯㉔⦴㊷⑬㊼Ⓩ㊽ⒹⓈ⧁⦿③⧀ⓥ㉞⑤Ⓤ⦸㊸㉓㊻⦷㊵⦻ ⚖ Ⓐⓟ⑨㊶㉟ⓞⓝⓌ⑧ⓜ⑳ⓡⓖⒼ㉕㉜ⓧ⑲⦵ⓛⓋⒽ㊳⑫⑱Ⓡⓒⓗ㉚㉗ ➔ >:-Ⓐ =:+Ⓠ <:-㊽ \n", " =:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴㊵㊶㊷㊸㊹㊺㊻㊼㊽㊾㊿Ⓐ ⚖ ⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ⦰⦱⦲⦳⦴⦵⦶⦷⦸⦹⦺⦻⦼⦽⦾⦿⧀⧁ ➔ \n", " >:ⓑⓩⓈⓋⓧ⦺ⓞⒿⓔ㊺ⓛ㊸⑥Ⓕⓙ⦼⑩㊾⑯㊼ⓐ⑭㊹ ⚖ ⓕ㊴⦱㉝㉔Ⓡ㊲ⒷⓏ⦷⑦⑬ⓝⒾⓊⓎⒹ⑮ⓃⓁ⑧㉕① ➔ >:+㊹ =:-Ⓣ <:-ⓐ \n", " =:⦲Ⓔ⦶㊲ⓗ㊿ⓘ㊱②ⓒⓧ㉞ⒼⒸ㊼④㊸⦰Ⓤ⦸ⓔ⦹Ⓟⓕ㊷Ⓣ⦼Ⓠ㉖Ⓛ㉟ⓦⒿ⧁ ⚖ Ⓓⓢ⑳㉔⦵⦱Ⓢ㊴⑥Ⓞ㉑⦿㉚⑯㉘⑤ⓤ㊻⑰㉙Ⓐ①⦴⦷Ⓚ㉗ⓑ㊾Ⓑ⦽㉓Ⓩ㉛ⓛ ➔ >:-Ⓓ =:+Ⓘ <:+Ⓢ \n", " <:ⓘⒷⓙ㉙㊻㉛②⑨ⓗⓓ ⚖ ㊶Ⓕ⦻⑲㊴Ⓓ⦹ⓔⒽ⑧ ➔ >:-㊶ =:+ⓒ <:-㊻ \n", " <:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴㊵㊶㊷㊸㊹㊺㊻㊼㊽㊾㊿ⒶⒷⒸⒹⒺⒻⒼ ⚖ ⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ⦰⦱⦲⦳⦴⦵⦶⦷⦸⦹⦺⦻⦼⦽⦾⦿⧀⧁ ➔ \n", " >:⦿㉝㉑ⓆⓠⓉⓓ⑩⦰ⓗⒿ㉛⑤ⓅⒻⓄⒹ㊼㊶⑨⑳⧁ⓐ㉜Ⓒ⦸④⦹⦻㉟⦾㉓Ⓝ ⚖ Ⓩ㉖Ⓐ㊲ⓥ⑰⑯㉗Ⓧ⦷ⓡ㊿⑱Ⓥ③ⓟⓊⓁ⦲ⒺⓒⓈ㊱⑬①ⓦ⦴ⓧ㉒ⓜⓀ⑧㊾ ➔ >:-Ⓧ =:-Ⓦ <:-Ⓝ \n", " =:㉓㉔ⓝⓊⒻⓚ③ⓔ㉒㊳Ⓡⓙⓥ⦰㉗ ⚖ ⓁⒼⓣ㉑Ⓨ⦼㉖㊶ⓤⒺ㉚⑭⦸ⓀⒽ ➔ >:-Ⓚ =:+Ⓜ <:+Ⓛ \n", " <:Ⓜ⑰ⓄⒽⓁ⑩⑧ⓛⓅ⦼㉕Ⓩ⧀㉝Ⓙ⑨ⓦ②④ⓔⓎⓊⓠ㊳ⓨ㊺ ⚖ Ⓘ㊿㊶Ⓝ⧁ⓧ⑤⑥Ⓚ㉞ⓝ⑯Ⓕ㉘㊻ⓐ⦱ⓌⒹⓋⓘ⦰⦷ⓡ⑲Ⓡ ➔ >:+Ⓨ =:-Ⓑ <:-㊺ \n", " =:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴㊵㊶㊷㊸㊹㊺㊻㊼㊽㊾㊿ⒶⒷⒸ ⚖ ⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ⦰⦱⦲⦳⦴⦵⦶⦷⦸⦹⦺⦻⦼⦽⦾⦿⧀⧁ ➔ \n", " >:⑰ⓞⓛⓀ⑨⦰Ⓗ⑫⦾㉙ⓖ⦳Ⓑ㉗Ⓨ⑳Ⓜ㉘⦹ⓉⓄ⑤ⓘⓁⓠ㊾Ⓒ①⑬Ⓓⓣⓩ⦷Ⓤ㉜Ⓔ⑩ⓙ㊵⑪⦺ⓧ⦽⦿⦶⑭⦻㊿ ⚖ ㊷㊳Ⓝ㊺ⓡ⦴ⓚⒻⓈⓓ⑦⧀Ⓐ㉔ⓗⓍ⑮㉚⦵ⓐⓝⒿⓌ㊽ⓤⒾⓦ㉖ⓜ㉑㊹㉞ⓑ③⑱㊼⑲④ⓕ㉛ⓢ⦱⑧㉒⑯⧁⑥Ⓩ ➔ \n", " >:ⓍⒿⓧⓔ⦵㊼ⓉⓐⒶ⦰㉔Ⓨ⦻⦶ⓝ㊸㉛ⓚ⦷⑪Ⓤ⦾㉕ⓖ㉙㉜Ⓜ⦿ⓣⓢ㉑㉘ⓓ㊲Ⓦ⑤ⓤ ⚖ ⓏⓅ⑨㉞㊴ⓡ㉓⑳⑭㊷⧁ⓦ㊾⦳⑩㊻⑧ⓛ㊳⑰⦹⦴Ⓓ⦱ⓨⓆ㊹ⒽⓇ㊿⑦⦽①㊱ⒻⓀ㉝ ➔ >:-Ⓩ =:+Ⓒ <:+㊾ \n", " =:Ⓓⓖⓥ⦱㉒ⓤⓀ㉛㊻ⓎⓌ㊺㉞⑥⦻ⓡ⑮ⓜ⑫⑪Ⓒ㉜Ⓘⓑ㊶㊱⦿⑭⑤ⓍⓗⓈ④ⓐⒺ㊷ⓓ㊼⦾⑯ⓔ⑬⦳ⓠⒼ ⚖ ㊸⑧ⓁⓉⓘ⦹㉗⑰⑲⦰ⓩⓅ⑨Ⓜ⦶ⓄⒿⓟⒶ㊹⦵ⓕ㉓ⓨⓃ㊴ⓞⓇⓏ⦲㉕⑱㉑⦽ⓢⒻⒽⓛ㉔⑩ⓝ①③㉝㉚ ➔ >:-Ⓡ =:-Ⓥ <:+㊸ \n", " <:㊷ⓒ⑰ⓄⓂ㉑Ⓤ ⚖ ⓝ⑥Ⓘ㊳㉒㊺㉜ ➔ >:+㊷ =:+㊼ <:-Ⓤ \n", " =:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴㊵㊶㊷㊸㊹㊺㊻㊼㊽㊾㊿ⒶⒷⒸⒹⒺⒻ ⚖ ⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ⦰⦱⦲⦳⦴⦵⦶⦷⦸⦹⦺⦻⦼⦽⦾⦿⧀⧁ ➔ \n", " >:ⓆⓍ④⑥ⓝⓖ㊴ⓠ⦶㉒ⓌⓇⒸⓜ㉞Ⓓ㉝㊵㉓ⓡⓒ㊷Ⓩ㉘Ⓔ⦷Ⓨ⧁⑰⦽㉚⑭ⓅⓟⒿ㊻⦼②⑳Ⓝⓣ㊽Ⓕ ⚖ ⓢ⦺㊼㉟Ⓛⓩ①Ⓚⓦ㉙㊶③⑲⦴ⓚⓛⒾ㊳⑤⦲ⓗⓐ⑮⑯ⓘ㉔㉛Ⓑ⦰㉑⦸⑦Ⓥ㊹Ⓤ㊱Ⓢ㊸⦾⑬㊾㊿⦱ ➔ >:+Ⓕ =:-Ⓞ <:-Ⓟ \n", " =:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴㊵㊶㊷㊸㊹㊺㊻㊼㊽㊾㊿ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿ ⚖ ⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ⦰⦱⦲⦳⦴⦵⦶⦷⦸⦹⦺⦻⦼⦽⦾⦿⧀⧁ ➔ >:+Ⓙ =:0 <:-Ⓙ \n", " <:⦽Ⓦⓒ⑧㉝㊿Ⓟ⑤⑫ⒿⓁ⦸Ⓕ ⚖ ⓟ㉟㉞Ⓗ⦴㊷⑬⦱⧀ⓡ⑪ⓢⓉ ➔ >:+Ⓟ =:+Ⓞ <:-Ⓕ \n", " <:⑤㊶ⓚ㊲Ⓙ㉒㉛⦶Ⓠ㊵⑯⑦⦹①Ⓓ㊿Ⓣ⑰⑬ⓔⓥ㉜㊱④㉞ⓒⓑⓏⓨⓠⓜⓘ⦳ⓝ㊾㉝Ⓚ⦰ⓞⓂⓄ⦽㉗ⓖⓇ ⚖ ⑫Ⓔ⑳Ⓛ㉑⦼Ⓖ②㊹ⓡⒽ⧁ⓣⓊⒻ⑨㉓⦲⦸⦱ⓧ⑭㊷Ⓧ⦻㉘ⒾⓌⓙ㊴⦺Ⓥ⦴⑲⑮㉖㊻㉔㊽Ⓟⓓⓕ㊺ⓢⓎ ➔ \n", " >:⑪Ⓚⓔ⦱ⒶⓉⓈ㊾㊿⑭④ⓙ⑰㊻㉔⦻Ⓥⓐ㉞ⓑⒽⒾⓌ㊹⦲ⓨⓇⓅⓎ㊷ ⚖ ⓓⓢ⦿㉕ⓘ⑩㉙㊶㉑ⓞ⑯㉝Ⓜ⦴ⓩ㉜㊵①⦶㊳ⓦⓖⓡⓗⓥⓤ⑳Ⓛ㊸Ⓧ ➔ >:+Ⓡ =:+Ⓩ <:-㊷ \n", " =:ⓇⓈ⑦Ⓚ㉟⑳⑮⑬⦶㊹Ⓩ⦼ⓖⓊ⦳ⓠ㊳ⓝⒸ⑨⑫Ⓞⓜ⦽⦷ ⚖ ㊼ⓛ㉝⦲⑪ⓤ⧀⑭ⓔⓙ①⑥Ⓝ⑰㊻㊶ⓦⓩⒶ㉚⦸ⓍⓂ㉕Ⓛ ➔ >:-㊼ =:-㊸ <:-Ⓒ \n", " <:Ⓕ⦼⦲⑪Ⓒ㊸ⓜⓝⓁⓡ㊺ⓧⓦⒼⓍⓈⓞⓓ㊽⧀㉝㉘㊲㉙ⓃⓋ ⚖ ⦱㊴㊳ⓗ㉓ⓊⒹⓐ㉒Ⓡ⑳Ⓑ㉑Ⓘ⑨⦷ⓕⓆ⑤ⓉⓔⓅ④㉗⑦⦺ ➔ >:+Ⓥ =:-㊾ <:+Ⓤ \n", " <:⑭ⓀⓃⒸ㊾㉝⦺Ⓢ⦾⦵㊱⦳ⓟⓐ⑧ⓩⒹ⦸ⓄⓎⒿ⑯㉖Ⓗ㉟Ⓡ⦱㊼⦰ⓦ㉘㊳Ⓦ㊵㊹Ⓥ⑲㉛Ⓘ⦷ ⚖ ⓒ⦻㉜Ⓩ㉑ⓧⓊ㊺⑫⦿ⓝ⑤ⓣⓡ⦶㉚⑰ⓍⓅ㊷⑪⧁ⓢ⦲ⓕ⦹⦼ⓜ㉙ⓁⒷⓚ㊶③Ⓐ⦽Ⓜⓤⓖⓗ ➔ \n", " >:㊸ⓄⓥⓋ⦲ⓠⒷ㉚㊻㉓㊼㉝Ⓤ⦷③⑫⑲Ⓢⓕ⦵Ⓘ②⑥⑤ⓖ⧁ⓛ㊱ⓤ⦺㉛⑪㊿㉔㊽Ⓔ ⚖ ⓐ⦼㊺⑱㊷㊲ⓓ㉗ⓒ㉒ⓝⓉ㊵⑮ⓚ⦹⦻㊶ⓡⒶⓗⓀⓁ⦿⑩ⓜⒽ⑯⦴㉑Ⓟⓧ㉘㊴㉞Ⓜ ➔ \n", " >:⑱Ⓙ㉒ⓟⓑⓖ⑤ⓙ㊴⧀⦼ⓛⓉ②ⓗⓩⒶⒾⒻ㉙⑮⦵㊸㊲ⓋⓁⓐ㉘Ⓟ㉟㊹㊼ⓢ㊻⑰㉝ ⚖ ⓒⓤ⑦⦶⑯④㉜ⓨ⑪⦽ⓘ㉖㊵㊽㉑⑫㉔⑥⦱⑬㊺⦸ⓧ㉞⦷Ⓑ③ⓈⒹ⦰Ⓩ㊱ⓆⓇ⑨ⓠ ➔ >:-ⓒ =:-Ⓜ <:-Ⓛ \n", " =:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴㊵㊶㊷㊸㊹㊺㊻㊼㊽㊾㊿ⒶⒷⒸⒹ ⚖ ⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ⦰⦱⦲⦳⦴⦵⦶⦷⦸⦹⦺⦻⦼⦽⦾⦿⧀⧁ ➔ >:+Ⓓ =:+Ⓝ <:+Ⓦ \n", " <:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴㊵㊶㊷㊸㊹㊺㊻㊼㊽㊾㊿ⒶⒷⒸⒹⒺⒻⒼⒽ ⚖ ⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ⦰⦱⦲⦳⦴⦵⦶⦷⦸⦹⦺⦻⦼⦽⦾⦿⧀⧁ ➔ >:+Ⓗ =:+Ⓚ <:+ⓐ \n", " =:⦳㊳Ⓤ⦷⑱Ⓦⓨⓡ㉔ⓙ⑩㊴⑥⦸㊸㉖ⓣ⑤⦹ⓕ⦼㊾Ⓣ㉚Ⓝ㊺⑬⧀⦽Ⓩ㊵ⒽⒹ⦲Ⓒⓚ㊻ ⚖ ⓦⒺⓋ⑲㊶㊽⑦⧁ⒿⒼ⑭㉒ⓔ⦱ⓠⓘⓓⓢ③②⦺㊹㊱⦻⦾⦴Ⓜⓒ㉜Ⓧ⑪ⓧ⑮Ⓢ⦶Ⓕⓤ ➔ \n", " >:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴㊵㊶㊷㊸㊹㊺㊻㊼㊽㊾㊿Ⓐ ⚖ ⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ⦰⦱⦲⦳⦴⦵⦶⦷⦸⦹⦺⦻⦼⦽⦾⦿⧀⧁ ➔ >:+㊻ =:-Ⓖ <:+Ⓣ \n", " =:②㉘Ⓙ㊴㉕⑲⦲ⓖ㉖⦱⦷ⓆⓇⓘ⑩Ⓧ㊽ⓠ⧁ ⚖ ㊿⧀ⓗ⦽㉜ⓙⒽ㊳ⓕ㊼⑫Ⓕ⦵ⓤ⦹㊷Ⓣ㊸ⓔ ➔ >:-㊿ =:+ⓑ <:-Ⓠ \n", " <:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴㊵㊶㊷㊸㊹㊺㊻㊼㊽ ⚖ ⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ⦰⦱⦲⦳⦴⦵⦶⦷⦸⦹⦺⦻⦼⦽⦾⦿⧀⧁ ➔ >:+㊽ =:+Ⓔ <:+ⓓ \n", " <:⑪⦺㉜Ⓕ⦲ⓗⓂ⑨⑩⦽㊶ⓖ⧁ⓥ⑮⑫ⒿⒼ㉗ⓌⓇⓛⓧⓚ⧀Ⓒⓒ⦼Ⓞ㉔ ⚖ Ⓧ⦰Ⓥ①㉙⑭Ⓠ㊻㉝Ⓢ㉟㉓Ⓣ③⑧ⓑⓊ㊳⦾Ⓐ⑥Ⓘ⑱Ⓑ㉑⑤⦻⦴⑯㉒ ➔ \n", " >:Ⓔⓙ⦱⦺⑮⦴Ⓢ㉔Ⓚ㉚Ⓜ⦳⦿ⓎⓣⒷ⦹ⓩ④ⓥ㉟㉝ⓢ ⚖ Ⓘ⑦Ⓕ⑲ⓨⓆ㊿㉑⑧⦽㊳ⓝ⑥ⓘ㉛㉗⑩ⓗ②⦲ⓛ㊺⑨ ➔ >:-Ⓘ =:+㊶ <:-Ⓢ \n", " =:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴㊵㊶㊷㊸㊹㊺ ⚖ Ⓩⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ⦰⦱⦲⦳⦴⦵⦶⦷⦸⦹⦺⦻⦼⦽⦾⦿⧀⧁ ➔ >:+㊺ =:-Ⓨ <:-㊹ \n", " <:①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴㊵㊶㊷㊸㊹㊺㊻㊼㊽㊾㊿Ⓐ ⚖ ⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ⦰⦱⦲⦳⦴⦵⦶⦷⦸⦹⦺⦻⦼⦽⦾⦿⧀⧁ ➔ >:+Ⓐ =:+Ⓑ <:+Ⓧ \n", " <:㊷⑮⦿⦻ⓌⓆ②③㊱⧁ⓚⓦ㊾⦽⦵㊹Ⓕ⑧Ⓟ㉜ⓠⓟ㉟㉕Ⓓ⦴Ⓚ㉗㊵Ⓩⓗ㉒Ⓝ⑱ⓉⒼⓧⓕ ⚖ Ⓥ⑳⦺㉘⑯Ⓐ⑬㊳⦹㉞㊿㊲ⓤ⦷㉑ⓩ⦰Ⓤ㊴ⓑ⑥ⓛ㉝⦳ⓘⓍ⑤⦸⑫ⓐⒸⒺ㉔㊺⦲ⓖⓞ⦱ ➔ \n", " >:⦷ⓟⓢ㉖⦰⑳ⓛ㉛ⓜ⦸⑲⦱㉕ⓤⓠⒾ⦹Ⓢ㊷㊶ⓆⓄⓙⓩ⑰ⓑ㊿㊾ⓣ㊴⑪ⓖⒹ㊹ⓐ㊻ⓘⓎⓀⓥⓉ⦶ⓔⓍ㉒Ⓐⓡ②㊳⑩ⓧ ⚖ ⑬㉚ⓊⒸ④㉗⧁⦼Ⓟ⦾⦿Ⓥ⑥⑮①ⒻⒿⓞ⑱⑭Ⓛ㉝⧀㉓⦳㊲⦲㊺ⓚⓏⒼ⦴⑨ⓓ㊵ⓨⒺ㊽ⒽⓕⓦⓌⓃⒷ㊼ⓒ③⑯⑧㉜⑤ ➔ \n", " >:ⓕ㊽㉗㊿Ⓡ㉞Ⓗ㊼ⓜ㉑ⒷⓋ⑮㉖㊻⑫⑩⑧⦻ⓏⓁ⑦Ⓢ⦼㉛Ⓞ⑥㊷ⓥ⑰ⓚ⦷⧀㉘ⓟ⑬ ⚖ Ⓝⓝ㉟㊲㊺㊴Ⓚ⦾⦵⑯③⦸⦲ⓅⓛⒸ㊵ⓑ㉕ⓒⒼ㊾Ⓓⓧ⦿⑳㉚⑪ⓊⓂ④ⓙⓣ㊶ⓩ⦰ ➔ \n", " >:Ⓦ㉒⑫㉓⦳㉔⑧Ⓧ②⑨⑤ⓠ㉕㉝⑭⦱Ⓝ⑥ⓗ⑮Ⓘ⦻Ⓒ③⦴⑬ⓤ㊷㊸Ⓣ㊼⦷Ⓖⓘ⦲ⓧ ⚖ ⑯㊿ⒺⓙⓊ⦸ⓄⒹ⦽ⓡ㉘Ⓚ⑪⦼㊱㉟⦶㉗Ⓟ㉞ⒶⓋ⦾ⓖ⑦⑱Ⓕⓝⓨ⦰⑳㊾①ⓜⓟ㊴ ➔ >:-⑯ =:-㊲ <:+ⓟ \n", " =:Ⓖ⦱⑱ⓂⓉ⦰㉖Ⓢ⑥㊼Ⓔ⑮㉕⦺⦶ⓕ㊹ⓃⒿⓧⒷ㊻⑤ ⚖ Ⓐ⑯ⓒ⦳⑩ⓨ㉝ⓞ㊵㉙ⓣ㊳㉞ⓤ㊸㊴㉜ⒻⓘⒸ㊲⧀㊺ ➔ >:-㉝ =:+ⓠ <:-⑤ \n", " <:Ⓞ㊽Ⓟ⦹⑭①ⒷⓌⒼⓀ㉘㊵㊺④⦸Ⓛⓟ⦼⑨ⓘⓂ㊲㊼ⓠ㊶㉛ⓩⓇ㊴㉟ⓚⓞ⑦⑳㉝Ⓩ⑧ⓣ⦽Ⓓⓡ㊾㊻⦺ⓨ㊸㉚ⓝⓗ③Ⓒ ⚖ ⓧ⧀Ⓔ⑤Ⓗ⧁ⓤ⦰Ⓕ㉔ⓢ㉖⦲ⓙⓃ㉜㉑⦵⑲ⓦⓐ⑫Ⓠ㊿Ⓤⓛ⦱⦳⑪⑬㉓Ⓧⓓ㉒ⓑ㊱⑮㉙Ⓘ㉗ⓒⒶ⑯ⓜ㊷⑩⦾㊹⑱㊳Ⓥ ➔ >:-⑬ =:-⑥ <:+ⓧ \n", " =:⦹㊺⑮⑰ⒷⓏⓌ⑤⦾⑨ⓞⓘ⑱㊷ⓩ㉗Ⓡ㊻⑳㉟ⓢⓉⒶ⧁ⓥ⑭ⓨⓍ⦻⑧Ⓓ⑯⑥⦱⑲㊾ⓟ⑫㉔ ⚖ ⦽㊴㉜㊿㊼Ⓖ⦳ⓔⒺ㉖ⓣⓀ㉚ⓝ㊹㊽Ⓛ㉕⑩㉞ⓓ⦰⑬ⓙⓠ①Ⓝ⑪⦷⦲Ⓥ㉑Ⓘ⦺㊳Ⓠ㊶㉛ⓑ ➔ \n", " >:㉗Ⓧ①ⒾⓆ㉛⦲ⓄⓃ⧁Ⓗ㉘ⓘⓋⓉ㉔Ⓢ㊺Ⓩ⑬Ⓑ㊿⦽⦺Ⓟ㊾⑪Ⓡ⑲⦴㊲⑦㊹ⓟ ⚖ ㉞Ⓙⓩ⦳⑤ⓦ⧀㊶③⑳Ⓖ⑮㉜ⓓ㉙⦰⑧ⓑⓡⓠⓝ⦱ⓖⓔ⦻ⓧⓁⓜ④㊼㉝㉒ⓣⒶ ➔ >:-㉞ =:-㉑ <:+⦻ \n", " =:㉑⑳⑰ⓞⓩ⑯④Ⓜ⑨⑱ⓒⓨ⑦㉓Ⓡ㉒㉝㊳ⓋⓎⓥⓍ⦹㊹ⓝⓈ⑭Ⓙⓗⓓ㊻⦷⧁㉜Ⓟ㉛⑧Ⓒ ⚖ ⦵Ⓐⓖ②⦽⑫㉟Ⓔ㊿ⓙ⦾Ⓕ⑥ⓜ⦼⦱⑩Ⓖ㊾Ⓩⓣ㊸㊱⦺⦲㊽⧀㉔Ⓑⓤ⦴Ⓘ③ⓦⓡ㉖①⑤ ➔ >:+ⓗ =:-㉘ <:+⦵ \n", " <:㊿㊲ⓓⓔⓚⒼⓑⓩ⦷ⒷⓈ⑨㊵ⓇⒹⓨⓤⓠ ⚖ ⑫⦱⑤㉚㊾㉝⦾ⓛⒽ⦽㊱⑭⧁⦵⑱ⓝⓎⓁ ➔ >:-⑫ =:-㉔ <:+⦽ \n", " <:ⓦ㊹⑳㊴㊳Ⓧ㉞Ⓘ⑭ⓕ㉕⑨⧁ ⚖ ②⦵ⓑⓞⓌ㉙⦳⑱⦸ⓁⒼⓤⓏ ➔ \n", " >:ⓢ⦾㊼⑤Ⓙ⦸ⓕ⦽⦵ ⚖ ⓦⓤⓈⓐ⦴㉚⑧ⓡⓛ ➔ >:+ⓕ =:+⧁ <:+ⓦ \n", " =:⦿㊾⧁⑩ⒽⒻ㉚ⓖⒼⒾⓨ⑧Ⓞ㉛⑭⧀Ⓜⓛ⦻ⓜ②ⓩⓥⓐ⦶Ⓩ⑪⦰㊺㊲㉓⦸㊽⦹⑳ⓑⓘ㊿ⓙⓡ ⚖ ⦴ⒹⓌ④⦲㊳㉕⑤ⓗ㊶Ⓔ⦵ⓒ⑯㉞⑲Ⓝ㊴ⓤ㊱㊼㉒③ⓝⓧ㊸Ⓑ⑬ⓅⓋ㊷㉝⑥㉜㉔㊹①⦼Ⓒⓠ ➔ >:+⦿ =:+ⓚ <:+⦴ \n", " <:㉛ⓇⒿ⦽ⓕ⑧⦸ⓡⓥⓓⒷⒸ②㉑ⓍⓆⒻⓒⓣ㊹ⓛⓠ⑲Ⓞ㊷⑰Ⓖ⑤ⓗ⑬Ⓦ㊺㉘③ⓙⓞ㊴㉖ⓢ㊽ ⚖ ㊳㉔Ⓐⓨⓘ⦶Ⓘ⑭⦳㊾㊸㉙Ⓥ⦷ⓜⓚ㊲Ⓜ㉓㉜ⓖⓊⓃ⧀⦵⦾⑮ⒺⓎ⦹⑫ⓩ㉞⑯ⓟ㉚㊻Ⓩ⑥㉟ ➔ >:-㊳ =:-⑳ <:-㊴ \n", " =:㊳⑧㊼Ⓗ⦵⦳ⓕ㊲㉖㉟Ⓙⓨ㉑⦻Ⓜ⑮㊹Ⓒ㊷Ⓤ②⦸ⓑ㊱③㉓⑱ⓚⓋ㉜Ⓨⓔ⦹ⓠ⦼㉘㉒㊺⑤⑩㊽ ⚖ ⓝ㊵㉙ⓜ⑰ⓁⓘⓅ㉗⑥Ⓔⓓ⑦⑫ⓩ⑪⦱㉔ⓙ㊸㉚ⓤ⑳⦷ⓣ㉝㊴Ⓚ㉕ⓄⒷⓖⓈ⦺⦾⦶ⒻⓃ㊿⑨⧁ ➔ \n", " >:⑯⦵Ⓚⓥ⑫ⓟⒺⓑ⑮⑧ⓣ⦷⑦㊷㉝㊴⦴⧀㉗㉛⦰ⓒ㉔Ⓐⓧ㊸Ⓨⓔ⦹⦱㊱㉑ⓢⓚ㊹㊳③ ⚖ ⑨ⓩⒾⒹⓨⒼ㉚⦼ⓂⒿⓡⓓⓦ⦿⦶⑬㉜Ⓤ㉟ⓤ㉞ⓝⓍⓗⓈ㊻⦸⦽⦾㉓㉕ⓕ⦺㊿⦲⦳Ⓡ ➔ \n", " >:ⓠⓀⒿⒽⓚ⦻Ⓓ㉜ⓝ㉒⦵㊶ⓉⒷⓜ㉙ⓨ⑲ⓩⓕ⦰㉖㉝㊻⑥ⓧⓅⓑⒺ㉞⑯⑪㊽ⒼⓂ④㉛㊵㊸⦸⦼ⓄⓁⓥ⦴ⓒⓌ㉔㉟㉑㊱ⓢ ⚖ ⑨Ⓩ㊺㊼⦹ⓞ⑰⦷ⓟⓐⓤ⦲㊷⦺⦳⦶⑱ⓇⓔⒶⓛⓋ③⦿⑫⑬⦱㊲⑳⑭Ⓠ㊴ⓙⓗⒾ㉓ⓘ②Ⓢ㉗㊹㊾Ⓕ㉕Ⓧ㊳⑤㉘ⓡⓣⓓ⧀ ➔ >:-⑨ =:-㉚ <:+ⓔ \n", " =:Ⓐ㊹㉗Ⓛ㉔Ⓦ⑪㉘㊳ⓗ⦶㊽ ⚖ ㉙ⒿⓈⓕ㉓㉜Ⓑ㉟ⓢ⦴Ⓟⓟ ➔ >:-㉙ =:-⑰ <:-⑪ \n", " <:ⒷⓥⒶ⑩ⓐⓞ㊶ⒹⓀ⑦ⓔ④ⓣⓝ⦱㊸⑮㉝③⦻ⓧ㊺ⓘⓑⒻ⦺⑤ⒿⓊ㊷Ⓦ⦼ ⚖ Ⓒⓖ㊳Ⓖ⧀Ⓗ⦿㉙ⓜⓃ⑲ⓂⓟⓓⓏ⦲㊿ⓒⓇⓆ⦶⦹㊴㊲⑬ⓛ㉔ⓢⓋⒺ⧁ⓕ ➔ >:+⦼ =:+ⓨ <:-⑦ \n", " =:⦿Ⓒ⑫⦲ⓏⒷⓇⒶⓓ⑱⦶①⧁㉖Ⓘ㊹ⓞ㉞⦴㉕ⓙ⦰⑧⑤㊵⦼⑨Ⓝⓠ㊷ⓘ㉝ⒹⓌ ⚖ ⓡⓧ㉑ⓣ㉓⑦ⓜ⦱㉗㊻㉛⑲Ⓤⓥ㉘⦷㉜㊸㉙⑩ⓐⓍⓑ㉔⑭㉒ⓁⓂⓀ⦹㊶⦵ⓒ㊺ ➔ \n", " >:⑦ⓒ⑳㊼Ⓨ㉙⦹㉛㉘⧀㉗㉝㊺⦶Ⓤ㊻㊲Ⓞ㊴ ⚖ ⑭⦻ⓈⓏ⦳Ⓜ⑫ⓕ㉑⦴②⑩㉔㉒ⓅⓙⓃⓩⓢ ➔ >:-⑭ =:-⑲ <:-㉛ \n", " =:㊻Ⓕ⑲㉑㊹⑫㉟㉜⑤⑨㊴Ⓢⓘ㊲㉒Ⓚ㉖ⓣ㊳ⓥⒷ⦽Ⓘ㉝Ⓜⓝ⑪⦴Ⓤ⑮⦶ⓕ㊷⑯ ⚖ ④②Ⓥ⦷ⓌⒺⓁ㊶⑩ⓉⒽⓟⓄ⑰Ⓟⓞ⑬ⓒⓗ⦸㊱㉙⧀ⓐ⑥⑧㉔ⓠ⑦ⓧⓎⓤⒼ⑭ ➔ >:-④ =:+ⓢ <:+⧀ \n", " <:⦻ⓅⓀ⧁ⓗⒻⓂⒸⓩⓥⓑⓌ㉔⦸㊲ⓖ⑩⑨⦱Ⓧ⑪⦺ⓤⓣ⑰⑳Ⓓ⦽④ ⚖ ⓡ㉘㉗⧀ⓧ⦲ⓕⓛ㊳⑤㊹ⓜⓚ⑧⦾ⓒⒿ⑱ⓠ㊸㊱⦴㉓ⓆⓄⓝⓋ㉛㊽ ➔ >:+ⓥ =:-① <:+ⓡ \n", " <:㉜ⓠⒼ㉒㊵⦰⑰ⓙ㉑㊱⑱ⓟⒽ㉟Ⓜ㉚㊹⦴ⓊⒹⓒ⦽⦻⑦㊸Ⓘ⑮④㉖⦿⧀③ⓐⓘⓎ⦺㉝㊼Ⓐⓑ⦵⦼⑨㉛ⓦ⦶ ⚖ ⑬⑤⑲ⓁⓆⓧ㊲⦾⦷⑧㉞㉕ⓕⒿⓚ㊳ⓨⓋⓀⓏ⦲Ⓣ㊽ⓥⓃⓄ㉓㉙ⓣ㉔⦸⑫ⓗⓞⓩⒸ⦹㊺Ⓟ㊷ⓡ㊴㉘ⓢ⦳㊿ ➔ \n", " >:㊷③㉑Ⓑ㉜㉛ⓝ⑥⦼㊿ⓔⓤ㊹⦸①⑰ⓣ㉖⑮⑪ⓡ⑱⑩㊲Ⓧⓩ㊸ⓑ⦽ⒸⓌ ⚖ ㉓⦺㊽ⓢ⑯㉕⧁㊳ⓊⓕⓇ⦿Ⓖ㊼ⓗⓒⓋ㉟ⓧⒾ⑧⦱⑫ⓙ㉗㉘⦴ⓖ㉚④㊵ ➔ >:-㉓ =:+⦶ <:+ⓙ \n", " =:㊸㉟Ⓙ㊽㉓⑪⑮ⓨⓀⓛ㉕ⓦⓞⓗ㊾ⓜ⧁㉛Ⓤⓚ⑧㊱Ⓛ⧀ⓔ⑫ⓩ㊴㉚⑭⦿⦷ⓢ②Ⓕ⦺㉙Ⓐ⦹㉝⑯㊳㊿ⓥ㉖⑨Ⓢ㊷ⓧⓠ⑩ ⚖ ⦱ⓙ⑤①⑦ⓖ㊻Ⓡⓕⓐ⑲⑰㉞⦾⦲ⓍⓄ㉗ⓑ⑱ⓟ⦴Ⓜⓒ㊵⦰⦳⦻⦽ⓤ③ⓣ㊹㊲Ⓝ⑳ⓌⓏⒾ⦵ⒽⒷ⑥⦸Ⓟ㉜Ⓒ㊶④⦶ⓡ ➔ >:+ⓜ =:+ⓝ <:-⑩ \n", " <:㉛⦵㉘㉞Ⓔ⧀Ⓒ㊾Ⓨ④㊹ⓋⓉⓣ㉕㊸ⓘⓁ⦴⦹⦳⑰Ⓟ⑧㊷㊵ⓇⓤⓠⓗⓈⓓ㊻Ⓦⓙⓚ⦷㉝㉗㊶Ⓙ⑫ⓔ㉔⑩ⓧ⧁㊳ ⚖ ⦾㉑②㉓ⓑ⑳⑭ⓡⓀⓄⓨⒶⓕ㉒⑨ⓩ⦿ⓢ㊿Ⓖ⑬⑮㊱⦽Ⓤ㊼㊴Ⓘ⦶⑯⑱⑲ⓞⓐ⦼Ⓧ⑦Ⓝ⦻Ⓑ⑤Ⓕ⑪⑥㉙ⓛ㊲㉜ ➔ >:+ⓣ =:-㉖ <:+⦾ \n", " <:ⓧⓓ㊷⑳⦺⑲⦳㉛Ⓢⓐⓟ㊲⑯ⓝⓤ⦶⦴㉚⑮Ⓒ㉜ⒹⓅ⑰㊹③㊴⦰㊳ⒷⓆⓥⓠ㉞㉔⑪⦻㉒ ⚖ ㉟ⓑ⦹Ⓞ㉝ⓩ⑬㊸㊵Ⓩ①⦱Ⓡ⦼Ⓖ㉖②ⓣ⦿㊽㊾㉕Ⓥⓒ㉘Ⓔⓡ⧀ⓙⓦⒿ⦷㊼⦸④㉓㊺ⓗ ➔ \n", " >:ⓝ⦶⦰⦽⑱ⓏⓌ⑨⑰Ⓢ⑤㊺ⓢ⑳Ⓥⓒ⑩④Ⓧ㉘⦼⑲⦲①⦱ⓄⓀ⦳ ⚖ ⓑⓡ⑫⑭Ⓠ㉙㊳ⓥⓂⓜⓞ㉒ⓎⒺⒿⓔ⑮㉝⦵㊾⑥㉟⧁㊹ⓠ⦾ⓤ⦺ ➔ \n", " >:㊵⦶⧁㊱Ⓑ⑤Ⓓ㊿⦺⑯ⓥⓟⓠ⑪㊳ⓡ㉔⦴ⓓ⑥⦱ⓒ⦸⦾ⓋⓛⒸⓆ⑫㉕㉓④①㉑Ⓐ⦲㉗㉝ⓙ ⚖ ㉟Ⓙ㉙Ⓤⓖ㊺㉚ⓑ⑭⦵ⓦⓀ⦿Ⓞ⑬⑰ⓎⓈ㉜ⓝ㊷⑱ⓜ⑩㊻Ⓣ㊶㉛⦽㊽Ⓕ⧀⦼⦰㊼ⓩⓞ㉞ⓣ ➔ >:-㉟ =:+⦳ <:+⦰ \n", " =:Ⓒ⦶㊱⑪⦺㉘㉜Ⓙ④Ⓔ⧁ⓘ㊿㉝⑭㉛⑳Ⓛⓙ①ⓀⓐⒻⓅⓎⓚⓡ㊽⦻⑧ⓗ② ⚖ ⧀⦰⑬㊵㊶㉚⦴Ⓢⓒ㊻㊸⑫Ⓝ㉓ⓧ㊺ⓤⒷⓢ㊷ⓖⓊ⦸⦾Ⓥ㉗㉑ⓩⓦ㉞ⓕⓝ ➔ >:-㊵ =:-㉕ <:-② \n", " <:①②③④⑤⑥⑦⑧ ⚖ ⦺⦻⦼⦽⦾⦿⧀⧁ ➔ >:() =:+ⓤ <:+⦺ \n", " =:Ⓟ⦶ⓛⓡ㊼㉕ⓟ㉟⑳⦻㊷㊶ⓈⒺ⑧ⒸⓋ③⦷⑩⑰⑦⦹Ⓛ㊸⦱ⓨ⑮㉘ⓂⓏ⦽ⓑ ⚖ ⑱ⓖ㊿ⓓ⦼ⓚⓕⓄ㉓ⓦⓐⓊ㊾Ⓙ⧁ⓜ⑪㊽㊲㊱㊺ⓘ⦺①②㉖Ⓝ⑫⦳㉝ⓢⓇ⑭ ➔ \n", " >:ⒻⒾ⑥⦺ⓙ㉝⦴⑫ⓝ⑧㊲⦽ⓞ②ⒼⓨⓑⓂ⦼㉜㊶㉞Ⓧ㉟ⓗ⦹㉘⦿⦾Ⓒⓔⓚ⧀⑮ⓥ㉓㊹ⓘⓋⒽⓊ㊺Ⓩ⑯⑪㉛ ⚖ ㊱⦳Ⓔⓟⓦ⦶ⓓⓖⓕ⦷⑬㉑㊽㉒⦱ⓜ㉚Ⓣ㊼Ⓢ⑦ⓤⓩⓌ⑳⧁ⓐⓇ㊻ⓣⓡ㉖③ⓧ㉙ⓛ⦵⑲㉕Ⓟ⦻⦲Ⓐ㉔Ⓞ⦸ ➔ >:-㊱ =:-⑱ <:+ⓛ \n", " =:Ⓚ㊿⑱ⓨ⦼Ⓒ⦱㊶㊹⑳ⓖ③⑧㊼ⓐⓌ⦲㉟Ⓞ㊺②ⓝⒺⓕⓗⓧⓟ㉛㉔㊳Ⓓ⦳⑥⑦⧁ⒽⒷ④ⓜⓦⓥ㉜㉑⦾Ⓕ⦿Ⓝ㉗ ⚖ ⓚ㊻①⦹㉝⑨ⓔ⑲ⓏⓋ㉖Ⓡⓢ⦷Ⓐ㉘㉕Ⓤ⦽⦰ⓍⓣⒾⓩ⑮⑤⦻ⓑ⦸㉓㊾⦵㊽⦶⦺㊴㊱ⓡⓆ㉚Ⓨ⧀㉒⑯Ⓜⓤ㊸Ⓢ ➔ >:+⦲ =:+ⓞ <:-㉗ \n", " <:㉘ⓘ㊶⦻ⓁⓄ㉒⑪㉛㊼⑰⑲㉗⑱⑯㉖ⓀⓎ㉜④⧁ⒼⓏⒹⓣ㊺⑧ ⚖ ⓛ⦸㉕ⓗⓒⒿ⦽⦶Ⓟ⦰㉑⧀⑮ⓧⓋ⑫Ⓦ⑩ⓢ⑨ⓕ㊸Ⓧ㊲ⓂⓈⓩ ➔ >:+ⓘ =:+ⓖ <:-⑧ \n", " <:㊱Ⓞⓙ⑭ⒸⒹ㉒⑮ⓩ⦺⑳⦼ⓃⓛⓈ㉝㊺⦾ⓟ⑤②㊸⑥ⓗ㊽⑧㉙ⓧ㉑㉕Ⓤ㉟Ⓡ⑫㊲⦿ ⚖ ③ⓌⓦⓆ⦰㉜ⓡ㊴Ⓑ⑰Ⓛ⦵ⓢ㉞ⓓ㉚Ⓕ⑪Ⓗ⦷ⓒⓠⓥⒺ㊻ⓨ⑲⧁Ⓟ㉘㉖⑯Ⓩⓐ⑱㊶ ➔ \n", " >:Ⓕ㉜ⓟ①㉛ⓔⓤⓨⓗ㉑㊿⑭ⓢ㉔Ⓢ㉘㊴⑪ⒹⒶⒸⓛ⧀㉕⧁⦺⑧⑦Ⓥ⑩Ⓤⓚⓞⓩ ⚖ ⑨ⓙ⦿ⓥ⦼㉓⦶Ⓡ⦴⦲Ⓜ㊾㊽⦸㊶ⓄⓏ⑳ⓖ㊺㉒ⓓⓁⒷⓆ⦹ⓣⓅⓠ㊼㉞②Ⓨ⑲ ➔ >:+ⓩ =:-③ <:-㉜ \n", " =:㊷⑳Ⓧ⑯⑤㊵ⓖ⑮㊻ⓘ㊾ⓠ②⦳⦰ⓔⓙⓗ㊹ⓟⒻⓣ⑰㉝ⒿⓆⓩ⦻Ⓑ㉑㊲ⓒ㊱③ⓜ⧀㊽⦾㉟㉔⦸ⒹⓕⓨⓌⓃ⧁ⓥ㉕㉚ⓡ ⚖ ⦹ⓝⓀ⦶⑩Ⓖ⦺⑱Ⓔ㊶⑪Ⓐⓚⓢ⦷⑨⦿⦵①㉖⑭⑫ⓑ㊳Ⓣ㊸ⓋⓂ④㊴ⓐ⑦ⓤ㉞㉘Ⓞ㊺⦴㉒⦲⑲㉓ⓞ⑥ⓛ㉜Ⓒ㊿ⓏⓇⓦ ➔ >:+⦸ =:+⦱ <:+⦹ \n", " <:ⓨ㊲ⓐ⦺㉒㉛ⓧ㊵Ⓙ㊼④⦾㉓Ⓤ⑧Ⓨ㉟ⒼⓆ㉙ⓞⒸⒽ⑯ⓟ⦷ ⚖ ⓑ⦼⑤㊽㊷⑩⑥⦶ⓌⓇ⦽㉜ⓓⓜⒾ㊺㊱ⒻⓃⓕ⑲ⓡ⑰⑬Ⓢ⑪ ➔ >:+⦷ =:-⑮ <:-㉒\n" ] } ], "source": [ "do(Puzzle(120, 5, '+-0'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "That works.\n", "\n", "Or, I could solve a puzzle with 243 possibilites (the maximum possible with 5 weighings): **242 balls**, lighter-only, plus the possibility that no ball is odd. \n", "\n", "This would have printed output with lines twice as long as the previous example, so I won't print the tree, just verify `solve` finds a solution:" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "puzzle242 = Puzzle(242, 5, '-0')\n", "\n", "is_solution(solve(puzzle242), puzzle242)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Puzzles with 6 Weighings\n", "\n", "It would be too long and ugly to show the trees for 6 weighings, but I can figure out which puzzles are solvable, and which I fail to solve. 36 = 729, and half that is 364.5, so can I solve a 364-ball puzzle?" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 246 ms, sys: 1.53 ms, total: 247 ms\n", "Wall time: 246 ms\n" ] }, { "data": { "text/plain": [ "False" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "puzzle364 = Puzzle(N=364, weighings=6, odd='+-')\n", "\n", "%time is_solution(solve(puzzle364), puzzle364)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**No**, and the fact that it was so fast suggests that there is no good first partition. We can check the partition sizes, which must be no more than 25 = 243:" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{118: [236, 256, 236],\n", " 119: [238, 252, 238],\n", " 120: [240, 248, 240],\n", " 121: [242, 244, 242],\n", " 122: [244, 240, 244],\n", " 123: [246, 236, 246]}" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "{B: partition_sizes(puzzle364, B) for B in range(118, 124)}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The best partitions are with 121 or 122 balls on each side, but they leave a 244-oddball branch; one too many.\n", "\n", "How about if we drop down to 363 balls, but allow anything for the oddballs (so 2 x 363 + 1 = 727 possible outcomes):" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 5.92 s, sys: 3.51 ms, total: 5.92 s\n", "Wall time: 5.92 s\n" ] }, { "data": { "text/plain": [ "True" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "puzzle363 = Puzzle(N=363, weighings=6, odd='+-0')\n", "\n", "%time is_solution(solve(puzzle363), puzzle363)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Yes**, there is a solution, and it took 6 seconds to find it. \n", "\n", "One last puzzle: 728 possibly heavy balls and 729 possible outcomes (the maximum for 6 weighings):" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 21 s, sys: 13.2 ms, total: 21 s\n", "Wall time: 21 s\n" ] }, { "data": { "text/plain": [ "True" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "puzzle728 = Puzzle(N=728, weighings=6, odd='+0')\n", "\n", "%time is_solution(solve(puzzle728), puzzle728)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Yes**, there is a solution, but it took half a minute to solve; I think that's enough." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# What's Next?\n", "\n", "- What other puzzles can you solve?\n", "- Can you make a table summarizing the space of solved and unsolved puzzles?\n", "- Can you *prove* the unsolved puzzles are unsolvable? \n", "- Can you find trees that minimize the *mean* number of weighings, rather than minimizing the *maximum* number of weighings?\n", "- Can you minimize the number of balls in each weighing? The solutions above sometimes weigh 3 or 4 balls on each side of the scale when only 1 or 2 were necessary.\n", "- Currently, when `solve` returns `None`, it means \"no solution was found, but there's no proof that a solution doesn't exist.\" Can you modify `solve` to return a result that indicates there is no possible solution? (Maybe you can only do this in a reasonable amount of time on smaller puzzles, not all.)\n", "- What about puzzles where your task is to identify *which* ball is odd, but not *how* it is odd? That is, if you get the possible oddballs down to `{-3, +3}` then you're done; you know ball 3 is the odd one, and you don't care if it is heavy or light.\n", "- More generally, can you solve puzzles when it is a possibility (or a requirement) that *two* balls are odd? Or more than two?\n", "- What if you had two or more balance scales that you could use in parallel, and the goal was to minimize the number of weighing time periods, not the total number of weighings?\n", "- What else can you discover?" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.15" } }, "nbformat": 4, "nbformat_minor": 4 }