Lab 1: Message Decryptor

Problem 1 - Get to know each other!

Welcome to CSCI 0111 Lab! We're so excited to work with you. Now that you're with your partner(s), discuss one/some/all of these questions:

  • What is your favorite food?
  • Do you have a favorite type of cow?
  • What do you do for fun?

CHECKPOINT:

Call a TA over to discuss the questions above!


Cracking Encryptors

You're on a top secret mission and need to communicate an encrypted message containing important code. However, the instructions to your encryption machine were accidentally thrown into the pond, and it’s up to you to figure out how it works!

The encryptor machine has 10 black-box functions that encrypt a String. Your first task is to test various inputs and figure out how each function changes the input based on the output.

Once you have an idea of what an encryption function does, write a version of the function that encrypts a String in the same manner and run it through the checks in the support file. If all checks pass, then you’ve successfully built an encryptor for covert communications!

Hint: The encryptors are composed of functions from the Pyret Strings library. Start by reading through it.

Here is an example of what an encryptor looks like under the hood:

provide *
provide-types * 

fun encryptor0(s :: String) -> String:
  doc: "returns the first letter of the string" 
  string-substring(s, 0, 1)
end

check "encryptor0: empty str":
  encryptor0("") raises "index"
end

check "encryptor0: general":
  encryptor0("a") is "a"
  encryptor0(" ") is " "
  encryptor0("hello") is "h"
  encryptor0("1, ") is "1"
end

We created an encryptor called encryptor0 that takes in a string and returns the first letter only. We use check blocks to ensure that it works correctly given empty and non-empty strings.

Instructions

Include this at the top of your program:
import shared-gdrive("lab1-support-2022.arr", "1kS_-rd0eE9-DLndIYw-0Bez8c6J73MRK") as support

Now you will be able to access all of the encryptors and their testers in your Pyret file.

The encryptor functions are named

support.encryptor1,
support.encryptor2,
support.encryptor3,
support.encryptor4,
...
support.encryptor10

The encryptor functions take in Strings as input (e.g: support.encryptor1("mystery")) and produce an encrypted result.

Please keep a record of what Strings you use to test each encryptor – you should be prepared to explain your choice of Strings to a TA. They will be useful for you to reference, too!

The tester functions are named, inspiringly:

support.test-encryptor1,
support.test-encryptor2,
support.test-encryptor3,
support.test-encryptor4,
...
support.test-encryptor10

To use them, you must use the name of your function as an input. For example, after giving some inputs to support.encryptor1, you may think it always returns the String "cs0111" (HINT: it doesn't do this just an example). Then you would write the function:

​fun my-cool-encryptor(str :: String) -> String:
​    "cs0111"
end

You would test whether your function is correct (meaning it does the same thing as encryptor1 for all inputs) by running:

​support.test-encryptor1(my-cool-encryptor)

Hint: The Pyret Strings library will be very helpful when writing your functions!

Hint: When choosing Strings to use as inputs to the encryptors, it will be useful to vary your inputs think about why this could be. In what ways can you vary your Strings?


CHECKPOINT:

1. Call over a TA after you have finished encryptors 1-4.

  1. Code can often be brittle in the face of inputs unforeseen by the programmer (edge cases). Read this short article from the Verge detailing how a novelty license plate exposed a huge flaw in the ticketing system. Algorithms that include these limitations often disproportionately impact marginalized and/or vulnerable individuals and/or groups. Read this article about how the REAL ID Act’s identification requirements create unique obstacles for women, people of color, and low-wage workers. Discuss the importance of edge cases in real life and how you can use them to find the functions of the remaining encryptors with your partner.

3. Call over a TA after you have finished encryptors 5-8.


Now it's time to prove your encryptor expertise - let's solve the final two encryptors in the support code, support.encryptor9 and support.encryptor10.

Hing: Encryptor 9 is one of the trickiest. Try strings of various lengths that start with the same letters. What do you notice?


CHECKPOINT:

Call over a TA once you have finished encryptors 9-10.


Challenge Task:

Now that you're an encryptor expert, try cracking someone else's encryptor! Link to shared spreadsheet.

To share your encryptor in the shared spreadsheet, press 'Publish' in your Pyret file and copy the code that begins with 'import shared-gdrive'. Add that to the sheet. Have fun decrypting!

Task 1: Import another group's encryptor from the encryptor swap spreadsheet using the same format you used to import support.arr call over a TA if you get stuck.

Task 2: Write a function called new-decryptor that takes in the output of the other group's new-encryptor and decrypts it. When you think your decryptor works, consult with the other group.

Success!

Nice! Your new encryptor functions worked! You successfully sent the code and the mission was completed.


Brown University CSCI 0111 (Spring 2024)
Feedback form: tell us about your lab experience today here!