Note you will need both your Ryerson and your CS (moon) login credentials!
Follow these instructions to access the exam environment:
- Leave your bag, any electronics, etc. at the edges of the lab (or under your chair in a plastic bag). Keep your student ID card. You may keep blank paper, pen/pencil, ear-plugs, but no electronics. Any brimmed hat must point backwards.
- You need to login with your CS (moon) username and password to the lab machine. You will be in Windows.
- Open a browser "Microsoft Edge or Chrome" then go to: https://cps506.cs.ryerson.ca/ then final, then to this page.
- Open another tab in the browser and go to: https://vdi.cs.ryerson.ca
- You have to login with two factor authentication using your Ryerson username and password.
- Once you are authenticated you will be redirected to the actual vdi page
- Click on "VMware Horizon HTML Access"
- Login using your CS username and password. Same as you did with the workstation at the beginning
- Choose the domain "SCS.RYERSON.CA" and you will see pools named "CPS506-Windows" & "CPS506-Linux", click on one and a machine will be assigned to you.
You will be accessing a virtual Windows or Linux machine. You can choose either one.
- On Windows
- Use the
H:
drive - that is where you will see your home directory (which will have a folder calledExamQuestions
- you will also have a home directory on Windows - this will disappear when you log off and will not be seen by marking. DO NOT USE THIS!!!!!
- Open a powershell, and immediately go to the
H:
- There you will see a folder with all the exam questions in it. You can see a sample below
- Even though all your files are on the
H:
drive, some of the editors may default toC:
- For Pharo,
cd Smalltalk
, then you can open Pharo withpharo CPS506Exam.image
(note slight difference from Linux)
- Use the
- On Linux
- It's a lot more straghtforward
- In your home directory, you will see a folder with all the exam questions in it. You can see a sample below
- For Pharo,
cd Smalltalk
, then you can open Pharo withpharo-ui CPS506Exam.image
(note slight difference from windows)
- In both environments
- Edit only the files in the
ExamQuestions
folder/directory and subfolders/subdirectories. - All the mix/cabal/cargo folders have been created. You jus need to edit the files and run the tests (see below)
- There are 5 questions in each of the first 3 languages, 4 in Rust, and 6 in the ShortAnswer section.
- In Smalltalk, when you open the image (see above) you'll see an exam-specific help page that will link you directly to the appropriate classes
- In the other directories, you will see
.txt
files... which you simply edit and leave your answers in the files. - ...or there are sub-directories, which you can
cd
to and then run the appropriate test command for the language (see below for reminder) - When you're done, whatever is in the home directories (on
H:
for Windows) is what will be marked - There is no "submit" or "fossil" or "git" or "Iceberg" required... write your code, save it, test it, repeat until it works, then move on to the next.
- From the shell/terminal
emacs file
orvi file
will open the editor on the file. vscode may need to be opened from the GUI.
- Edit only the files in the
The following tools will be available:
- Pharo 9 - with an image that will already have test cases defined. Open it, work on the Smalltalk questions, Save often, Save and Quit when you are done.
- Elixir - with a pre-loaded test script. Edit, run
mix test
until all tests pass. - Haskell - with a pre-loaded test script. Edit, run
cabal test
until all tests pass. - Rust - with a pre-loaded test script. Edit, run
cargo test
until all tests pass. - Editors (they should all have highlighting for the languages):
emacs
vim
orvi
vscode
notepad++
- on Windows
- Powershell and cmd - on Windows
- the full Linux shell environment - on Linux
The following documentation resources will be available:
- Both Dave's and Alex's slide decks as PDFs
- Smalltalk
- the interactive Prof Stef tutorial
- Learn Smalltalk in Y minutes
- Elixir
- Haskell
- Learn Haskell in Y minutes
- The PDF version of A Gentle Introduction to Haskell
- Haskell Cheat Sheet
- Rust
- Learn Rust in Y minutes
- Rust cheat sheet - but not the things linked from it
- Zig
Sample Questions
Note that for each language there is a somewhat increasing level of difficulty as you go from sq0 to sq4. Everybody should be able to do the simpler problems in each language. Realistically, not everyone will be able to do all questions easily, but there is no fixed order to working on problems or languages - leave questions that you find challenging (don't delete the code... we can't give part marks for no code!) and come back to them.
Smalltalk/CPS506Exam
sumSquare: aCollection " return the sum of the squares of the elements in the collection " self shouldBeImplemented.
weird: a with: b " note that a can be a character collection (String) " " or it can be a collection of any value that understands > and negated " " you should test with several kinds of collection and collections of several kinds of values " | temp | temp := a select: [: v | v > b ]. ^ b isCharacter ifTrue: [ temp capitalized ] ifFalse: [ temp negated ]
Smalltalk/CPS506MarkExam
You won't change this... it will be test cases that we use to mark your code. (We will actually use different values, but the same basic tests. If your code passes the tests here without hard-coding answers, it will work with our tests.)testSumSquare self assert: (exam sumSquare: #()) equals: 0. self assert: (exam sumSquare: #(1 2 3)) equals: 14. self assert: (exam sumSquare: (-2 to: 3)) equals: 19.
Smalltalk/CPS506TestExam
Write a test for #weird:with:Elixir/sq1/lib/sq1.ex
defmodule Sq1 do @moduledoc """ Documentation for `Sq1`. """ @doc """ CPS506 Elixir sample question 1 isAscending?/1 should return true if the elements of the input list 'items' are strictly ascending. Each element must be strictly larger (not merely equal to) than the element that precedes it. Return True if the list of items is strictly ascending, and return False otherwise. Note that the empty list is ascending, as is every list containing only a single element. """ end
Elixir/sq1/test/sq1_test.exs
defmodule Sq1Test do use ExUnit.Case doctest Sq1 test "Testing []" do assert Sq1.isAscending?([]) == true end test "Testing [-5, 10, 99, 123456]" do assert Sq1.isAscending?([-5, 10, 99, 123456]) == true end test "Testing [2, 3, 3, 4, 5]" do assert Sq1.isAscending?([2, 3, 3, 4, 5]) == false end test "Testing [-99]" do assert Sq1.isAscending?([-99]) == true end test "Testing [4, 5, 6, 7, 3, 7, 9]" do assert Sq1.isAscending?([4, 5, 6, 7, 3, 7, 9]) == false end test "Testing [1, 1, 1, 1]" do assert Sq1.isAscending?([1, 1, 1, 1]) == false end test "Testing [4, 3, 2, 1]" do assert Sq1.isAscending?([4, 3, 2, 1]) == false end test "Testing [1, 2, 3, 3]" do assert Sq1.isAscending?([1, 2, 3, 3]) == false end end
Elixir/sq1/test/test_helper.exs
ExUnit.start()
Elixir/sq2/lib/sq2.ex
defmodule Sq2 do @moduledoc """ Documentation for `Sq2`. """ @doc """ CPS506 Elixir sample question 2 onlyOddDigits?/1 should return true if the provided integer argument contains only odd digits (1, 3, 5, 7, 9) and false otherwise. Note that the digit '0' is considered even. Hint: The functions rem/2 and div/2 will serve you well """ end
Elixir/sq2/test/sq2_test.exs
defmodule Sq2Test do use ExUnit.Case doctest Sq2 test "Testing 8" do assert Sq2.onlyOddDigits?(8) == false end test "Testing 1" do assert Sq2.onlyOddDigits?(1) == true end test "Testing 13579753" do assert Sq2.onlyOddDigits?(13579753) == true end test "Testing 42" do assert Sq2.onlyOddDigits?(42) == false end test "Testing 71358" do assert Sq2.onlyOddDigits?(71358) == false end test "Testing 0" do assert Sq2.onlyOddDigits?(0) == false end end
Elixir/sq2/test/test_helper.exs
ExUnit.start()
Haskell/sq1/app/Main.hs
module Main where import qualified SQ1 (main) main :: IO () main = SQ1.main
Haskell/sq1/src/SQ1.hs
module SQ1 (main, is_cyclops) where main :: IO () main = do contents <- getLine putStrLn $ show $ is_cyclops (read contents::Int) {-- CPS506 Haskell sample question 1 A non-negative integer is a cyclops number if its middle digit, and ONLY its middle digit, is '0'. If a number does not have a middle digit, i.e. it has an even number of digits, it cannot be a cyclops number. Hint: Perhaps it's easier to solve this if the integer were represented as a String/[Char]... -}
Haskell/sq1/src/TestSuite.hs
module Main where import Test.HUnit import qualified SQ1 import qualified System.Exit as Exit main = do status <- runTestTT tests if failures status > 0 then Exit.exitFailure else return () - run tests with: - cabal test - here are some standard tests - you should augment them with your own tests for development purposes is_cyclops = SQ1.is_cyclops tests = test [ "0" ~: True ~=? is_cyclops 0, "101" ~: True ~=? is_cyclops 101, "98053" ~: True ~=? is_cyclops 98053, "777888999" ~: False ~=? is_cyclops 777888999, "1056" ~: False ~=? is_cyclops 1056, "675409820" ~: False ~=? is_cyclops 675409820 ]
Haskell/sq2/app/Main.hs
module Main where import qualified SQ2 (main) main :: IO () main = SQ2.main
Haskell/sq2/src/SQ2.hs
module SQ2 (main, domino_cycle) where main :: IO () main = do putStrLn "Hello" {-- CPS506 Haskell sample question 2 A domino is represented as a 2-tuple containing two integer values, such as (2, 5) or (6, 6). Given a list of dominos, determine if the list of dominos forms a cycle, so that each domino ends with the same number that the next domino starts with. This property wraps around the list. That is, the last domino must end with the same number that the first domino begins with. You may assume the list contains at list one domino. Return True if the dominos form a cycle, and False otherwise Hint: The tuple functions fst and snd will come in handy... -}
Haskell/sq2/src/TestSuite.hs
module Main where import Test.HUnit import qualified SQ2 import qualified System.Exit as Exit main = do status <- runTestTT tests if failures status > 0 then Exit.exitFailure else return () - run tests with: - cabal test - here are some standard tests - you should augment them with your own tests for development purposes domino_cycle = SQ2.domino_cycle tests = test [ "[(3, 5), (5, 2), (2, 3)]" ~: True ~=? domino_cycle [(3, 5), (5, 2), (2, 3)], "[(4, 4)]" ~: True ~=? domino_cycle [(4, 4)], "[(2, 6)]" ~: False ~=? domino_cycle [(2, 6)], "[(5, 2), (2, 3), (4, 5)]" ~: False ~=? domino_cycle [(5, 2), (2, 3), (4, 5)], "[(4, 3), (3, 1)]" ~: False ~=? domino_cycle [(4, 3), (3, 1)] ]
Rust/sq1/src/main.rs
#![allow(non_snake_case,non_camel_case_types,dead_code)] // This is at the harder end of the Rust questions // You must not change the types of the functions or the test code, // so part of the requirement is to get the types correct fn pairList1<a,b,c>(f:fn(a)->b,g:fn(b)->c,xs:Vec<a>) -> Vec<(b,c)> where a : Copy { // map f and g over the values of the vector in the way that makes the types work } fn pairList2<a,b,c>(f:fn(a)->b,g:fn(a)->c,xs:Vec<a>) -> Vec<(b,c)> where a : Copy { // map f and g over the values of the vector in the way that makes the types work } fn ff(x:i8) -> i32 { // return x plus 1 } fn gg(x:i32) -> i64 { // return x times 2 } #[cfg(test)] #[path = "tests.rs"] mod tests;
Rust/sq1/src/tests.rs
#[cfg(test)] mod tests { // we adjust the path to: use super::super::{*}; #[test] fn ff_test() { assert_eq!(ff(1),2); assert_eq!(ff(10),11); assert_eq!(ff(-5),-4); } #[test] fn gg_test() { assert_eq!(gg(1),2); assert_eq!(gg(10),20); assert_eq!(gg(-5),-10); } #[test] fn pairList1_test() { assert_eq!(pairList1(ff,gg,vec![1,2,3]), vec![(2, 4), (3, 6), (4, 8)]); assert_eq!(pairList1(ff,hh,vec![2,3,4,5]), vec![(3, 9), (4, 12), (5, 15), (6,18)]); } fn hh(x:i32) -> i64 { (x*3) as i64 } #[test] fn pairList2_test() { assert_eq!(pairList2(ff,ii,vec![1,2,3]), vec![(2, 3), (3, 6), (4, 9)]); } fn ii(x:i8) -> i64 { (x*3) as i64 } }
ShortAnswer/q1.txt
Explain some of the important differences between tracing garbage collection and reference counting. -
ShortAnswer/q2.txt
Explain 2 advantages of static typing and 2 advantages of dynamic typing: -