Skip to main content

Programming practice exercises in pattern recognition, written in Python. Ideal for beginner programmers.

Project description

programmedpatterns

Practice exercises in pattern recognition, ideal for beginner and intermediate programmers.

This uses the patterns at https://www.visualpatterns.org/ by Fawn Nguyen. The site and this module are licensed under a Creative Commons Attribution license.

The patterns are not in order of difficulty. Many are simple, some are incredibly hard.

THIS MODULE IS CURRENTLY UNDER CONSTRUCTION AND NOT WORKING YET.

Installation

To install with pip, from the Command Prompt/terminal run:

python -m pip install programmedpatterns

Solving the Programming Exercises

After installing, you can find the 461 programming exercises by calling progpat.exercise(X) where X is 1 to 461. For example:

>>> import progpat
>>> progpat.exercise(1)
    Exercise #1
    1  2   3    4     5      6       7        8
    O  OO  OOO  OOOO  OOOOO  OOOOOO  OOOOOOO  OOOOOOOO
       OO  OOO  OOOO  OOOOO  OOOOOO  OOOOOOO  OOOOOOOO
           OOO  OOOO  OOOOO  OOOOOO  OOOOOOO  OOOOOOOO
                OOOO  OOOOO  OOOOOO  OOOOOOO  OOOOOOOO
                      OOOOO  OOOOOO  OOOOOOO  OOOOOOOO
                             OOOOOO  OOOOOOO  OOOOOOOO
                                     OOOOOOO  OOOOOOOO
                                              OOOOOOOO
    Number of Os:
    1  4   9    16    25     36      49       64

Each exercise has a visual string component and a numeric math component. To solve the exercise you must write two functions. The visual string component function must have a name visX() where X is the exercise number. The numeric math component functionmust have a name numX() where X is the exercise number.

For example, vis1(3) would return the string 'OOO\nOOO\nOOO' because that is the visual string pattern for step 3 of exercise #1. Meanwhile, num1(3) should return 9 because that is the numeric math component for step 3 of exercise #1. Your two functions should return the correct answers for any integer (greater than 0) passed to them.

You can identify what you're supposed to count in the string displayed by progpat.exercise(). For example, exercise #1 asks for the number of Os. Most exercises ask for the number of Os, but some exercises have other characters or ask for a number of line segments.

The visual strings don't have trailing whitespace on their lines. They use period (.) characters instead of spaces to make the spacing easier to count.

To check if your code is correct, run the following from the .py file that contains your visX() and numX() functions:

import progpat
progpat.check(1, vis1, num1)  # Checks the vis1() and num1() functions for correctness.

Notice that you are passing the functions themselves, not calling them. This is why they don't have the () parentheses after their names.

Eventually, I'd like to make a website to track people's solutions (similar to what Advent of Code does).

Contribute

Currently a lot of basic programming work is needed (in Python and other languages) to make Programmed Patterns work.

First, we need the solutions for all 468 patterns. Each solution is comprised of a visX(n) function that returns a multiline string for pattern X at iteration n, and a numX(n) function that returns a numeric count of the number of shapes in pattern X at iteration n.

For example, here's pattern #5 which has a medium level of difficulty:

Pattern #5
    1    2      3        4          5            6
    .OO  ..OOO  ...OOOO  ....OOOOO  .....OOOOOO  ......OOOOOOO
    O.O  ...OO  ....OOO  .....OOOO  ......OOOOO  .......OOOOOO
    OOO  O..OO  ....OOO  .....OOOO  ......OOOOO  .......OOOOOO
         OOOO   O...OOO  .....OOOO  ......OOOOO  .......OOOOOO
         OOO    OOOOO    O....OOOO  ......OOOOO  .......OOOOOO
                OOOO     OOOOOO     O.....OOOOO  .......OOOOOO
                OOOO     OOOOO      OOOOOOO      O......OOOOOO
                         OOOOO      OOOOOO       OOOOOOOO
                         OOOOO      OOOOOO       OOOOOOO
                                    OOOOOO       OOOOOOO
                                    OOOOOO       OOOOOOO
                                                 OOOOOOO
                                                 OOOOOOO
    Number of Os:
    7    15     27       43         63           87

The vis5() function you write should take an integer n and return a multiline string for the pattern at iteraton n:

def vis5(n):
    result = ''
    result += ('.' * n) + ('O' * (n + 1)) + '\n'
    for i in range(n - 1):
        result += ('.' * (n + 1)) + ('O' * n) + '\n'
    result += 'O' + ('.' * n) + ('O' * n) + '\n'
    result += 'O' * (n + 2) + '\n'
    for i in range(n - 1):
        result += 'O' * (n + 1) + '\n'
    return result

The num5() function you write should take an integer n and return the number of 'O' characters in the pattern at iteration n:

def num5(n):
    return 3 + (2 * ((n + 1) * n))

These functions will be used to check student solutions. Each pattern puzzle has a visual string-manipulation component and a mathematical algebra component. This provides a lot of practice for intermediate-level programmers who have learned language syntax but need to become more skillful at writing code.

Where you can help is by writing the solution functions for the unsolved patterns. Check out https://visualpatterns.org and find a pattern to write function solutions for. To avoid working on patterns that other people may be working on, pick patterns to solve randomly by running random.randint(1, 468) in Python (or some other random selection method) and then check the GitHub repo to make sure it hasn't already been solved.

The source code file has boilerplate visX() and numX() functions that you can fill in with your solution. You can then run _getPatternMultilineString(X, 1, 10) (where X is the pattern number) to verify that the solution looks correct for iterations 1 through 10.

While the strings returned by the visX() functions have multiple lines (that is, they contain \n newline charactrs) each line should remove all trailing whitespace for their canonical answer. For example, this pattern:

O
OO
OOO

....should be represented as 'O\nOO\nOOO' and not 'O \nOO \nOOO\n'.

You should also draw each pattern as far up and to the left as possible. For example, pattern #22's 2nd iteration should be 'O\nOO' and not '\n\nO\nOO'.

Once you have finished the visual and numeric functions for a pattern and ensured they are correct, add a # DONE comment to the def statement for the functions and update the visual function's docstring to the output of getPatternMultilineString(patternNum, 1, endIteration), where patternNum is the integer of the pattern number and endIteration is as large of an integer as you can make without the output being wider than about 70 or so characters. (This is usually 3 to 6.) It's important that you use the naming pattern visX() and numX() for your solution functions or getPatternMultilineString() won't work.

Special Case Patterns

Most of the patterns involve a progressive growth of generic shapes which are represented by 'O' strings. For example:

Pattern #9:

O    OO    OOO    OOOO    OOOOO
OO   OOO   OOOO   OOOOO   OOOOOO
OOO  OOOO  OOOOO  OOOOOO  OOOOOOO
Number of Os:
6    9     12     15      18

Pattern #11:

O   O    O     O      O
OO  O    O     O      O
    OOO  O     O      O
         OOOO  O      O
               OOOOO  O
                      OOOOOO
Number of Os:
3   5    7     9      11

Pattern #14:

O       O       O       O       O
OOOOOO  OOOOOO  OOOOOO  OOOOOO  OOOOOO
        OOOOOO  OOOOOO  OOOOOO  OOOOOO
                OOOOOO  OOOOOO  OOOOOO
                        OOOOOO  OOOOOO
                                OOOOOO
Number of Os:
7       13      19      25      31

But some patterns have multiple kinds of shapes. For example, pattern #15:

Pattern #15
1    2      3        4          5            6
.O   .O.O   .O.O.O   .O.O.O.O   .O.O.O.O.O   .O.O.O.O.O.O
OXO  OXOXO  OXOXOXO  OXOXOXOXO  OXOXOXOXOXO  OXOXOXOXOXOXO
.O   .O.O   .O.O.O   .O.O.O.O   .O.O.O.O.O   .O.O.O.O.O.O
Number of Os, Xs:
(4, 1)(7, 2) (10, 3)  (13, 4)    (16, 5)      (19, 6)

In these cases, other letters such as 'X' are used in addition to 'O' for the visual component. For the numerical component, the numX() function doesn't return a simple integer but a tuple of integers. For pattern #15, the tuple returned is in the format (number of Os, number of Xs).

Other patterns have line drawings rather than discreet shapes. For example, pattern #44 looks like this:

Pattern #44
1           2                 3
....__      ....__....__      ....__....__....__
.__/##\__   .__/##\__/##\__   .__/##\__/##\__/##\__
/##\##/##\  /##\##/##\##/##\  /##\##/##\##/##\##/##\
\##/..\##/  \##/..\##/..\##/  \##/..\##/..\##/..\##/
/##\__/##\  /##\__/##\__/##\  /##\__/##\__/##\__/##\
\##/##\##/  \##/##\##/##\##/  \##/##\##/##\##/##\##/
...\##/     ...\##/..\##/     ...\##/..\##/..\##/
Number of filled hexagons:
6           10                14

These patterns often use /, \, _, and | for line-drawing characters. In many programming languages, the \ forward slash must be escaped as \\ when written in string literals in your code. In Python, raw strings are a helpful shortcut that allows you to write forward slashes without escaping them: print(r'Hello\\world') will print Hello\\world and not Hello\world.

However, Python has a slight bug in its language design where \ slashes cannot be the last character in a raw string. The code print(r'\Hello\') produces a syntax error instead of displaying \Hello\. You cannot use raw strings in these cases and instead must use normal strings with escape characters: print('\\Hello\\')

Please contact me at al@inventwithpython.com or on Twitter @AlSweigart if you'd like to contribute to this git repo.

How to Solve Programmed Patterns

TODO - Finish this section with advice on how to tackle these problems. (i.e. notice the changes between iterations including amounts, recall that you'll print things left-to-right, break it down line by line, use loops for multiple lines and string replication for multiple characters on a line, etc.)

Support

If you find this project helpful and would like to support its development, consider donating to its creator on Patreon.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ProgrammedPatterns-0.1.0.tar.gz (13.9 kB view details)

Uploaded Source

File details

Details for the file ProgrammedPatterns-0.1.0.tar.gz.

File metadata

  • Download URL: ProgrammedPatterns-0.1.0.tar.gz
  • Upload date:
  • Size: 13.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.7.1 importlib_metadata/4.8.2 pkginfo/1.8.2 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.10.2

File hashes

Hashes for ProgrammedPatterns-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c99ec26b24d914207408f696a49cdbaf9052864eb7d9ff68662b3086a0e0f5c6
MD5 29a9b563e82679834459ac6683c673a0
BLAKE2b-256 66428934bb75c8b00036327c2e8222ed5bfb9f506baef185a6160e1a29dbd9e4

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page