Some Short Introductory Coding Exercises

by Justin Skycak on

It's assumed that you've had some basic exposure to programming.

This post is a chapter in the book Introduction to Algorithms and Machine Learning: from Sorting to Strategic Agents. Suggested citation: Skycak, J. (2021). Some Short Introductory Coding Exercises. Introduction to Algorithms and Machine Learning: from Sorting to Strategic Agents. https://justinmath.com/some-short-introductory-coding-exercises/


Let’s get started on some introductory coding exercises. It’s assumed that you’ve had some basic exposure to programming and that you know about variables, functions, if statements, for loops, while statements, arrays, strings, and dictionaries. Ideally, you’ve learned some object-oriented programming (classes, attributes, methods) as well. We will speak in terms of Python, but the general ideas are applicable to any programming language.

It’s important to understand that in coding, you should always try to do as much as you can on your own, using Google as a resource if needed. Don’t know what a word means? Google it. Don’t know how to run a file from the command line? Google it. Don’t know how to get the second character of a string? Google it. Our goal is to provide just enough scaffolding to give you direction while avoiding hand-holding.

Exercises

Write the following functions from scratch. Don’t use any external libraries and or any built-in functions that allow you to bypass the use of for loops, while loops, or if statements in nontrivial ways. In particular, don’t use Set or Counter. But you can use primitives like len() and .append.


  1. check_if_symmetric(string)
    Return True if the input string is symmetric (i.e. a palindrome), and False if not. You can ignore capitalization.

  2. convert_to_numbers(string)
    Return an array of numbers corresponding to letters in a string where space = 0, a = 1, b = 2, and so on. For example, convert_to_numbers('a cat') should return [1,0,3,1,20].

  3. convert_to_letters(array)
    This is the inverse of convert_to_numbers. For example, convert_to_letters([1,0,3,1,20]) should return 'a cat'.

  4. get_intersection(array1, array2)
    Return an array consisting of the elements that are in both array1 and array2. There should not be any repeated elements in the output array.

  5. get_union(array1, array2)
    Return an array consisting of the elements that are in either array1 or array2. Again, there should not be any repeated elements in the output array.

  6. count_characters(string)
    Count the number of each character in a string and return the counts in a dictionary. Lowercase and uppercase letters should not be treated differently. For example, count_characters('A cat!!!') should return the dictionary { 'a': 2, 'c': 1, 't': 1, ' ': 1, '!': 3 }.

  7. is_prime(N)
    Check whether an input integer $N>1$ is prime by checking whether there exists some $n \in \left\{ 2, 3, 4, \ldots, \lfloor N/2 \rfloor \right\}$ such that $n$ divides $N.$ (The $\lfloor \,\,\, \rfloor$ symbol denotes the floor function.)


Tests

In another file, write a variety of tests for each function. Two example tests are shown below for check_if_symmetric. You can use these, but you should also write more tests that cover all the edge-cases you can think of. (For example, an empty string is symmetric, and the string '!ab123 4 321ba!' is also symmetric.)


from hello_world import check_if_symmetric

tests = [
    {
        'function': check_if_symmetric,
        'input': 'racecar',
        'output': True
    },
    {
        'function': check_if_symmetric,
        'input': 'batman',
        'output': False
    }
]

num_successes = 0
num_failures = 0

for test in tests:
    function = test['function']
    test_input = test['input']
    desired_output = test['output']
    actual_output = function(test_input)

    if actual_output == desired_output:
        num_successes += 1
    else:
        num_failures += 1 
        function_name = function.__name__
        print('')
        print(f'{function_name} failed on input {test_input}');
        print(f'\tActual output: {actual_output}')
        print(f'\tDesired output: {desired_output}')

print(f'Testing complete: {num_successes} successes and {num_failures} failures.')

Debugging

Run your tests and fix any failures. If you struggle with anything, don’t ask others for help until you’ve made a thorough effort to debug the issue on your own. Here are some debugging tips:

  1. Print out everything. Within the function that you're debugging, print out every manipulation that your code makes, even if you don't think it's making a mistake there. Bugs often show up in places you don't expect. Also, don't just print out the values of variables -- it will help you avoid confusion if you print the names of the variables as well.
  2. Identify the first discrepancy. Manually work out what the printouts should be, and then look for the first instance where the actual printouts deviate from what you're expecting.
  3. If the discrepancy involves a helper function, then isolate the issue in a separate file and return to step 1. If the issue is occurring when you're passing inputs into a helper function, then create a separate file where all you do is pass those inputs into the helper function, and go back to step 1 (print out everything) with the helper function. This way, you can focus entirely on the helper function without worrying about any other pieces of code interacting with it.
  4. If the discrepancy does not involve a helper function and you still can't figure out what's going wrong, then ask for help. Be sure that you can explain what you've done to debug the issue so far, including the furthest point back to which you've traced the bug. Keep your debugging print statements in your function and make sure the printouts are organized so that another person can follow along with them without knowing all the nitty-gritty details of your code.

Code Quality

Your code should be clean and work in general. If you have thorough test coverage, you can be fairly confident that your code works in general. To be confident that your code is clean, do the following:

  • Run your code through a linter (like pep8online) and fix all the issues.
  • Use proper cases. In Python, variables, functions, and files use snake_case (all lowercase with underscores separating words), while classes use PascalCase (no spaces with each separate word capitalized).
  • Make sure that your variable names are clear and appropriate. Variables and classes should be nouns, while functions (including methods) should be verbs. Additionally, names should be descriptive. It's okay to make a name multiple words long if you need. For example, calc_prob() is much better than prob() or cp().


This post is a chapter in the book Introduction to Algorithms and Machine Learning: from Sorting to Strategic Agents. Suggested citation: Skycak, J. (2021). Some Short Introductory Coding Exercises. Introduction to Algorithms and Machine Learning: from Sorting to Strategic Agents. https://justinmath.com/some-short-introductory-coding-exercises/