{"id":"randomness-choice-shuffle","slug":"choice-and-shuffle","title":"Choosing and shuffling","text":"Random numbers are often just a way to pick something: a question, a card, a player. The `random` module has functions that do the picking directly.\n\n### choice\n\n`random.choice(items)` picks one item of a list, each with the same chance. It works on a string too, and then picks one character:\n\n```python\nimport random\n\nrandom.seed(3)\nsnacks = [\"apple\", \"nuts\", \"yogurt\", \"carrot sticks\"]\nprint(\"Today's snack:\", random.choice(snacks))\nprint(\"A random letter:\", random.choice(\"ABCDEFG\"))\n```\n\n```output\nToday's snack: nuts\nA random letter: E\n```\n\nYou could get the same with `snacks[random.randint(0, len(snacks) - 1)]`, but `choice` is shorter, and there's no index to get wrong.\n\n### shuffle\n\n`random.shuffle(items)` puts the items of a list in a random order. Like the `sort` method, it changes the list itself, **in place**, and returns nothing:\n\n```python\nimport random\n\nrandom.seed(4)\ncards = [\"ace\", \"king\", \"queen\", \"jack\"]\nrandom.shuffle(cards)\nprint(cards)\n```\n\n```output\n['queen', 'ace', 'jack', 'king']\n```\n\nSince it returns nothing, a common mistake is to store its result. `shuffle` returns `None`, so the next line replaces the list with `None`, and the program fails when it uses the list:\n\n```python\nimport random\n\ncards = [\"ace\", \"king\", \"queen\", \"jack\"]\ncards = random.shuffle(cards)\nprint(cards[0])\n```\n\n```crash\nTraceback (most recent call last):\n  File \"main.py\", line 5, in <module>\n    print(cards[0])\n          ~~~~~^^^\nTypeError: 'NoneType' object is not subscriptable\n```\n\nCall it on a line of its own: `random.shuffle(cards)`.\n\n### Keeping the original order\n\nBecause `shuffle` changes the list, the original order is gone. When you need both, shuffle a copy. As you saw with references, `cards[:]` makes a new list with the same items:\n\n```python\nimport random\n\nrandom.seed(4)\ncards = [\"ace\", \"king\", \"queen\", \"jack\"]\ndeck = cards[:]\nrandom.shuffle(deck)\nprint(\"Shuffled:\", deck)\nprint(\"Original:\", cards)\n```\n\n```output\nShuffled: ['queen', 'ace', 'jack', 'king']\nOriginal: ['ace', 'king', 'queen', 'jack']\n```\n\nA string can't be shuffled at all: strings can't be changed, and `shuffle` works by moving items around inside the list it's given.\n","task":"What does this program print? Type each line it prints. (You can answer without knowing the random order.)\n","kind":"predict","seed":"import random\n\ncards = [\"A\", \"K\", \"Q\"]\nresult = random.shuffle(cards)\nprint(result)\nprint(len(cards))\nprint(sorted(cards))\n","solution":"import random\n\ncards = [\"A\", \"K\", \"Q\"]\nresult = random.shuffle(cards)\nprint(result)\nprint(len(cards))\nprint(sorted(cards))\n","hints":["`shuffle` changes the list in place. What does it return?","Shuffling only moves the items around, so the list still has the same items.","`sorted` puts them back in order, whatever order the shuffle left them in. Capital letters sort alphabetically."],"tests":[{"name":"Output","stdin":"","expect":"None\n3\n['A', 'K', 'Q']","hidden":false}],"require":[],"forbid":[],"lines":["None","3","['A', 'K', 'Q']"],"more":[{"task":"Write a function `random_greeting(name)` that picks one greeting from the list `greetings` with `random.choice` and returns it with the name, such as `\"Hi, Ada!\"`.\n\nThe checks set the seed themselves before they call the function.\n","kind":"code","seed":"import random\n\ngreetings = [\"Hello\", \"Hi\", \"Welcome\", \"Good to see you\"]\n\n\ndef random_greeting(name):\n    pass\n\n\nif __name__ == \"__main__\":\n    print(random_greeting(\"Ada\"))\n","solution":"import random\n\ngreetings = [\"Hello\", \"Hi\", \"Welcome\", \"Good to see you\"]\n\n\ndef random_greeting(name):\n    greeting = random.choice(greetings)\n    return f\"{greeting}, {name}!\"\n\n\nif __name__ == \"__main__\":\n    print(random_greeting(\"Ada\"))\n","hints":["`random.choice(greetings)` picks one of the greetings.","Return an f-string with the greeting, a comma, the name and an exclamation mark: `f\"{greeting}, {name}!\"`."],"tests":[{"name":"Test 1","stdin":"","call":"import random\nrandom.seed(1)\nprint(random_greeting(\"Ada\"))\nprint(random_greeting(\"Linus\"))\n","expect":"Hi, Ada!\nHello, Linus!","hidden":false},{"name":"Test 2","stdin":"","call":"import random\nrandom.seed(6)\nprint(random_greeting(\"Grace\"))\nprint(random_greeting(\"Guido\"))\nprint(random_greeting(\"Margaret\"))\n","expect":"Hello, Grace!\nGood to see you, Guido!\nWelcome, Margaret!","hidden":true},{"name":"Test 3","stdin":"","call":"import random\nrandom.seed(10)\nprint(random_greeting(\"Alan\"))\n","expect":"Hello, Alan!","hidden":true}],"require":[{"pattern":"\\bchoice\\s*\\(","message":"Pick the greeting with `random.choice`."}],"forbid":[]},{"task":"Write a function `shuffled(items)` that returns a new list with the items of `items` in a random order, made with `random.shuffle`. The list given as the argument must stay as it was.\n","kind":"code","seed":"import random\n\n\ndef shuffled(items):\n    pass\n\n\nif __name__ == \"__main__\":\n    letters = [\"a\", \"b\", \"c\", \"d\"]\n    print(shuffled(letters))\n    print(letters)\n","solution":"import random\n\n\ndef shuffled(items):\n    mixed = items[:]\n    random.shuffle(mixed)\n    return mixed\n\n\nif __name__ == \"__main__\":\n    letters = [\"a\", \"b\", \"c\", \"d\"]\n    print(shuffled(letters))\n    print(letters)\n","hints":["If you shuffle `items` itself, the caller's list changes too. Make a copy first: `mixed = items[:]`.","Shuffle the copy on a line of its own, then return the copy."],"tests":[{"name":"Test 1","stdin":"","call":"import random\nrandom.seed(8)\nletters = [\"a\", \"b\", \"c\", \"d\", \"e\"]\nmixed = shuffled(letters)\nprint(mixed)\nprint(letters)\n","expect":"['d', 'a', 'e', 'c', 'b']\n['a', 'b', 'c', 'd', 'e']","hidden":false},{"name":"print(sorted(shuffled([3, 1, 2])))","stdin":"","call":"print(sorted(shuffled([3, 1, 2])))\n","expect":"[1, 2, 3]","hidden":true},{"name":"Test 3","stdin":"","call":"import random\nrandom.seed(2)\nnumbers = [1, 2, 3, 4, 5, 6]\nprint(shuffled(numbers))\nprint(numbers)\n","expect":"[3, 4, 2, 5, 6, 1]\n[1, 2, 3, 4, 5, 6]","hidden":true}],"require":[{"pattern":"\\bshuffle\\s*\\(","message":"Shuffle the list with `random.shuffle`."}],"forbid":[]}]}