Pipenv Easter Egg

I’ve found this little easter egg hidden in pipenv:

if not environments.PIPENV_HIDE_EMOJIS:
    now = time.localtime()
    # Halloween easter-egg.
    if ((now.tm_mon == 10) and (now.tm_mday == 30)) or (
        (now.tm_mon == 10) and (now.tm_mday == 31)
    ):
        INSTALL_LABEL = "🎃   "
    # Christmas easter-egg.
    elif ((now.tm_mon == 12) and (now.tm_mday == 24)) or (
        (now.tm_mon == 12) and (now.tm_mday == 25)
    ):
        INSTALL_LABEL = "🎅   "

https://github.com/pypa/pipenv/blob/main/pipenv/core.py

2021 – Advent of code – Day 3

Part 1

You need to use the binary numbers in the diagnostic report to generate two new binary numbers (called the gamma rate and
the epsilon rate). The power consumption can then be found by multiplying the gamma rate by the epsilon rate.

Each bit in the gamma rate can be determined by finding the most common bit in the corresponding position of all numbers
in the diagnostic report. For example, given the following diagnostic report:

00100
11110
10110
10111
10101
01111
00111
11100
10000
11001
00010
01010


Considering only the first bit of each number, there are five 0 bits and seven 1 bits. Since the most common bit is 1, the first bit of the gamma rate is 1.

The most common second bit of the numbers in the diagnostic report is 0, so the second bit of the gamma rate is 0.

The most common value of the third, fourth, and fifth bits are 1, 1, and 0, respectively, and so the final three bits of the gamma rate are 110.

So, the gamma rate is the binary number 10110, or 22 in decimal.

The epsilon rate is calculated in a similar way; rather than use the most common bit, the least common bit from each position is used.
So, the epsilon rate is 01001, or 9 in decimal. Multiplying the gamma rate (22) by the epsilon rate (9) produces the power consumption, 198.

Use the binary numbers in your diagnostic report to calculate the gamma rate and epsilon rate, then multiply them together. What is the power consumption of the submarine? (Be sure to represent your answer in decimal, not binary.)

Reading the data

import pandas as pd

df = pd.read_csv("./aoc_day_03_test_data.txt", dtype = str, header=None)
df.columns = ["original"]

Continue reading “2021 – Advent of code – Day 3”

2021 – Advent of code – Day 2

Part 1

Today the puzzle got a bit trickier than Day 1.

The submarine seems to already have a planned course (your puzzle input). You should probably figure out where it's going. For example:

    forward 5
    down 5
    forward 8
    up 3
    down 8
    forward 2

Your horizontal position and depth both start at 0. The steps above would then modify them as follows:

    forward 5 adds 5 to your horizontal position, a total of 5.
    down 5 adds 5 to your depth, resulting in a value of 5.
    forward 8 adds 8 to your horizontal position, a total of 13.
    up 3 decreases your depth by 3, resulting in a value of 2.
    down 8 adds 8 to your depth, resulting in a value of 10.
    forward 2 adds 2 to your horizontal position, a total of 15.

After following these instructions, you would have a horizontal position of 15 and a depth of 10. (Multiplying these together produces 150.)

Calculate the horizontal position and depth you would have after following the planned course. What do you get if you multiply your final horizontal position by your final depth?

So Pandas here we go again: Continue reading “2021 – Advent of code – Day 2”

Argparse

Primer: Arguments vs Parameters

I’m sometimes confused. Is it an argument or a parameter? So here it goes:

A parameter is a variable in a function definition.

When a function is called, the arguments are the data you pass into the function’s parameters.

The same goes for a program: A program has parameters, you call a program with arguments.

Argparse Module

Batteries included! The argparse module provides a nice way to parse your program arguments:

import argparse

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('positional_param')
    parser.add_argument('-o', '--optional_param')
    parser.add_argument('-r', '--required_param', required=True)
    args = parser.parse_args()
    print(args.positional_param)
    print(args.optional_param)
    print(args.required_param)

Positional Parameters

Positional arguments are useful for shorter programs. These parameters do not have a name. You could call them “unnamed parameters” as well.

It is important that you keep the right sequence when calling the program:

parser = argparse.ArgumentParser()
parser.add_argument('positional_param_one')
parser.add_argument('positional_param_two')
args = parser.parse_args()
print(args.positional_param_one)
print(args.positional_param_two)
$ python positional_args.py foo bar
foo
bar

Optional Parameters

Optional parameters have a name you have to use when providing an argument to the program

parser.add_argument('--optional_param')

The double dash indicates an optional parameter

You can provide a shorthand for an optional parameter as well

parser.add_argument('-o', '--optional_param')

When you leave out an optional argument, the value will be defaulted to None

Two ways of calling a program with optional arguments:

$python optional_args.py
None
$python optional_args.py --optional_param foobar
foobar

Required “Optional” Parameters

Now it gets a bit weird: You can make an optional parameter required.

(another strong argument that these should be named “named parameters”)

parser.add_argument('-r', '--required_param', required=True)

If you don not provide the argument you will get:

$ python required_params.py
usage: required_params.py [-h] -r REQUIRED_PARAM
required_params.py: error: the following arguments are required: -r/--required_param
$python required_params.py -r foobar
foobar

Command Line Help

When you start your script with the -h or –help parameter, you will get a nice overview of the usage

$ python main.py -h
usage: main.py [-h] [-o OPTIONAL_PARAM] -r REQUIRED_PARAM positional_param

positional arguments:
positional_param

optional arguments:
-h, --help show this help message and exit
-o OPTIONAL_PARAM, ---optional_param OPTIONAL_PARAM
-r REQUIRED_PARAM, --required_param REQUIRED_PARAM

Sound and music with pygame

pip install pygame

Sound

import pygame

if __name__ == '__main__':
    pygame.mixer.init()
    sound = pygame.mixer.Sound("./sound.wav")
    channel = sound.play()
    while channel.get_busy():
        pygame.time.wait(100)
        print("Playing...")
    print("Finished.")

 

Music

import pygame

if __name__ == '__main__':
    pygame.mixer.init()
    pygame.mixer.music.load("./sound.mp3")
    pygame.mixer.music.play()
    while pygame.mixer.music.get_busy():
        pygame.time.wait(100)  # ms
        print("Playing...")
    print("Finished.")