Learn how to program with Python #1 - Solving Puzzles from Advent of Code 2018

in #utopian-io6 years ago (edited)

banner.png


Repository

https://github.com/python

What will I learn

  • Workspace
  • Virtual environment
  • Reading files
  • Part one: int(), map(), sum()
  • Part two

Requirements

Difficulty

  • basic

Tutorial

Preface

This tutorial is part of a course where solutions to puzzles from Advent of Code 2018 are discussed to explain programming techniques using Python. Each puzzle contains two parts and comes with user specific inputs. It is recommended to try out the puzzle first before going over the tutorial. Puzzles are a great and fun way to learn about programming.

While the puzzles start of relatively easy and get more difficult over time. Basic programming understanding is required. Such as the different type of variables, lists, dicts, functions and loops etc. A course like Learn Python2 from Codeacademy should be sufficient. Even though the course is for Python 2, while Python 3 is used.

This tutorial will jumpstart the course by going over the basic fundamentals while also explaining the first puzzle of Advent of Code. Puzzle 1

Setup

Download the files from Github and install the virtual environment

$ cd ~/
$ git clone https://github.com/Juless89/tutorials-aoc
$ cd tutorials-aoc
$ pipenv install
$ pipenv shell
$ cd part_1

Workspace

A good code editor is essential for any programmer to be able to work effectively. While there are many different editors this course will be using Visual Code Studio. It is not required but highly recommended. A good editor allows for a good overview of the workspace, is dynamic in the sense that addons can be added and comes with error highlighting. Just like Word lets the user know when a word is not spelled correctly an editor will be able to see basic programming errors.

To add the this course go to File>Open Workspace... and add the base folder.

Screenshot-2019-04-05-20.58.29.png

Virtual environment

Python comes in different versions and allows for many different packages to be imported. A virtual environment allows the user to keep track and manage these versions and packages without them interfering with each other. This keeps applications isolated from each other, making changes to one virtual environment won't possible corrupt another.

This course will be using pipenv.

# Linux
pip install pipenv

# mac
brew install pipenv

Create a new virtual environment inside a folder with pipenv install, enter the virtual environment with pipenv shell and exit the virtual evironment with exit. An active virtual evironment is highlighted by (base_folder_)name.

Apr-05-2019 21-02-10.gif

Reading files

As most of the puzzles come with huge inputs best practise is to separate this into a separate file. For each puzzle the input will be stored inside input.txt. When dealing with files the user has to account for closing the file after use and exceptions. This can be simplified by using a with statement.

The with statement simplifies exception handling by encapsulating common preparation and cleanup tasks.

file = open('input.txt', 'r')

lines = list(file)

file.close() 

Is equal to:

# read input file and convert to list
with open('input.txt', 'r') as file:
    lines = list(file)

list() converts the file to a list which makes using the data later on easier.

Part one: int(), map(), sum()

For part one of puzzle one a list with frequency changes is given +1, -2, +3, +1. Where each input represents a change to the current frequency.

Starting with a frequency of zero, what is the resulting frequency after all of the changes in frequency have been applied?

So to solve the puzzle all the inputs will have to be summed up together.

The input has been loaded inside lines, when printing this to the terminal it looks different.

['+3\n',
'+8\n',
'-5\n',
'+15\n',
'+9\n',
'-17\n',
'+11\n']

After each input there is a \n which represents a new line. In addition +5 is not a number while -5 is. Depending on which language the user is using converting these lines to numbers might require additional steps. Luckily Python is quite clever and understands that +5\n equals 5. Converting each line is done by casting them to an int with int().

The most straight forward solution to part 1 would be to loop over all the lines, cast them to an integer and add them to a variable frequency.

def part_1(lines):
    frequency = 0

    # convert each line to an int and 
    # add to frequency
    for line in lines:
        frequency += int(line)

    return frequency

However, a cleaner and much simpler approach would be to use sum(), which returns the total value of all values in a list. For this to work each value needs to be a number though. int() is a function, and as such can be used with map() to convert each value inside the list to an int. map() applies a function to each value of a list.

def part_1(lines):
    # convert each value to an int
    # return sum
    return sum(map(int, lines))

Part two

You notice that the device repeats the same frequency change list over and over. To calibrate the device, you need to find the first frequency it reaches twice.

Like mentioned in the puzzle the same list gets repeated over and over. And while that is happening the old frequencies have to be stored to know if a frequency is reached twice.

def part_2(lines):
    # start frequency
    frequency = 0
    frequency_list = [frequency]

    # loop forever
    while True:

        # convert each line to an int
        # add to frequency
        for line in lines:
            frequency += int(line)

            # check if frequency already seen
            if frequency not in frequency_list:
                frequency_list.append(frequency)
            else:
                # break loop with return
                return(frequency)

A new variable frequency_list is added where all frequencies will be stored in. while True will make a loop that lasts forever.

Each new frequency is compared with the frequency_list with if frequency not in frequency_list: it gets added if this is not the case with .append(). To break out of the while True loop the function is set to return the frequency that is reached twice. A normal break statement would not work in this case.

Running the code

if __name__ == "__main__":
    # read input file and convert to list
    with open('input.txt', 'r') as file:
        lines = list(file)

    print(f'Part 1 Answer: {part_1(lines)}')
    print(f'Part 2 Answer: {part_2(lines)}')

Run the code with:

python main.py

It takes a while for the 2nd answer to be calculated.

Screenshot 2019-04-05 20.54.50.png


The code for this tutorial can be found on Github!

This tutorial was written by @juliank.

Sort:  

Thank you for your contribution @steempytutorials.
After reviewing your tutorial we suggest the following points listed below:

  • Very interesting and well explained tutorial. We really like how you explain the contribution structure and the GIFs of your tutorial.

Thank you for your work in developing this tutorial.
Looking forward to your upcoming tutorials.

Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, click here.


Need help? Chat with us on Discord.

[utopian-moderator]

Thank you for your review, @portugalcoin! Keep up the good work!

nothing to do with this specific tutorial but i am breaking my head on the following. Can you tell me what makes the difference between a normal post and one that is only visible through steemd, ic a json post, how do i make a json only post that is not visible in my blog? I am using beem, thanks.

Posted using Partiko Android

Hi @bubke, to be honest I do not know. I'm not sure it's possible. As far as I know a custom json is a special type of operation used to register things like: follow, reblog etc

You can find all the operation types here: https://developers.steem.io/apidefinitions/#apidefinitions-condenser-api

This is what I could find with a quick look:

Screenshot 2019-04-06 at 03.29.52.png

Screenshot 2019-04-06 at 03.30.28.png

Congratulations @steempytutorials! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :

You published more than 80 posts. Your next target is to reach 90 posts.

You can view your badges on your Steem Board and compare to others on the Steem Ranking
If you no longer want to receive notifications, reply to this comment with the word STOP

To support your work, I also upvoted your post!

Do not miss the last post from @steemitboard:

The Steem blockchain survived its first virus plague!
Vote for @Steemitboard as a witness to get one more award and increased upvotes!

Great quality perspective on the world of programming.

Hi @steempytutorials!

Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your post is eligible for our upvote, thanks to our collaboration with @utopian-io!
Feel free to join our @steem-ua Discord server

Hey, @steempytutorials!

Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!

Get higher incentives and support Utopian.io!
Simply set @utopian.pay as a 5% (or higher) payout beneficiary on your contribution post (via SteemPlus or Steeditor).

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!

Hi, @steempytutorials!

You just got a 0.23% upvote from SteemPlus!
To get higher upvotes, earn more SteemPlus Points (SPP). On your Steemit wallet, check your SPP balance and click on "How to earn SPP?" to find out all the ways to earn.
If you're not using SteemPlus yet, please check our last posts in here to see the many ways in which SteemPlus can improve your Steem experience on Steemit and Busy.

Coin Marketplace

STEEM 0.23
TRX 0.21
JST 0.035
BTC 96557.13
ETH 3328.16
USDT 1.00
SBD 3.18