Giter Club home page Giter Club logo

cmsi386-programming-languages's Introduction

CMSI 386: Programming Languages

Homeworks from CMSI 386: Programming Languages course at Loyola Marymount University.

  • homework1: Assignment completed in JavaScript.
  • homework2: Assignment completed in Python.
  • homework3: Assignment completed in Java.
  • homework4: Assignment completed in C++.
  • homework5: Assignment completed in Haskell and TypeScript.

Done in collaboration with Ian Lizarda and Teddy Chu.

cmsi386-programming-languages's People

Contributors

dependabot[bot] avatar dmoini avatar ianlizzo avatar tedzchu avatar

Watchers

 avatar  avatar  avatar

cmsi386-programming-languages's Issues

Homework #5 Grading

module Warmup
    (change
    , stripQuotes
    , firstUppercasedOverLengthFive
    , powers
    , sumOfCubesOfOdds
    , swapAdjacents
    , Shape(Box, Sphere)
    , volume
    , surfaceArea)
    where

import Data.Char

change :: Int -> Either String (Int, Int, Int, Int)
change amount
    | amount < 0 = Left "amount cannot be negative"
    | otherwise = 
        let (quarters, afterQuarters) = amount `divMod` 25
            (dimes, afterDimes) = afterQuarters `divMod` 10
            (nickels, pennies) = afterDimes `divMod` 5
        in Right (quarters, dimes, nickels, pennies)

Excellent use of guards

stripQuotes :: String -> String
stripQuotes s = filter (\c -> c /= '\'' && c /= '"') s

firstUppercasedOverLengthFive :: [String] -> Maybe String
firstUppercasedOverLengthFive [] = Nothing
firstUppercasedOverLengthFive (s:strings) 
    | length s > 5 = Just (map toUpper s)
    | otherwise = firstUppercasedOverLengthFive strings

This does not seem like a good use of guards here. Granted, I am more of an ML expert than a Haskell one, but your logic here subsumes that of the built-in find function. My preference would be to pattern match on the result of find. Going to take off 2 here, but that doesn't mean you are less than awesome, just that I find find to be more natural here.

powers :: Num a => a -> [a]
powers num = map (num^) [0..]

sumOfCubesOfOdds :: [Int] -> Int
sumOfCubesOfOdds [] = 0
sumOfCubesOfOdds (n:nums)
    | n `mod` 2 /= 0 = n * n * n + sumOfCubesOfOdds nums
    | otherwise = sumOfCubesOfOdds nums

Ditto here. This problem rather screams for either a comprehension or a filter/map/sum approach. Doing the even check on the head in a recursive approach just doesn't look Haskellish. Nice idea, but too primitive for this problem. -2

swapAdjacents :: [a] -> [a]
swapAdjacents [] = []
swapAdjacents (a:b:remaining) = b:a:(swapAdjacents remaining)
swapAdjacents [a] = [a]

data Shape 
    = Sphere Double 
    | Box Double Double Double
    deriving (Eq, Show)

volume :: Shape -> Double
volume (Sphere r) = (4 / 3) * pi * r**3
volume (Box l w h) = l * w * h

surfaceArea :: Shape -> Double
surfaceArea (Sphere r) = 4 * pi * r**2
surfaceArea (Box l w h) = 2 * (h * w) + 2 * (h * l) + 2 * (w * l)

SCORE: 96/100. Lovely work as usual!

Homework 1 Grading

const crypto = require('crypto');
const rp = require('request-promise');

function change(cents) {
  if (cents < 0) {
    throw new RangeError('amount cannot be negative');
  }
  const denominations = [25, 10, 5, 1];
  const results = [];
  let remainingChange = cents;
  denominations.forEach((denomination, index) => {
    if (index < denominations.length - 1) {
      results[index] = Math.floor(remainingChange / denomination);
      remainingChange %= denomination;
    } else {
      results[index] = remainingChange;
    }
  });
  return results;
}

function stripQuotes(s) {
  return s.split(/['"]+/g).join('');
}

function scramble(s) {
  const array = s.split('');
  let currentIndex = array.length;
  let randomIndex;
  while (currentIndex !== 0) {
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;
    [array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
  }
  return array.join('');
}

function powers(base, limit, callback) {
  let currentValue = 1;
  while (currentValue <= limit) {
    callback(currentValue);
    currentValue *= base;
  }
}

function* powersGenerator(base, limit) {
  let currentPower = 0;
  while (base ** currentPower <= limit) {
    yield base ** currentPower;

Duplicated base ** currentPower -2

    currentPower += 1;
  }
}

function say(word) {
  return !word ? '' : nextWord => (nextWord ? say(`${word} ${nextWord}`) : word);

Nice

}

function interleave(a, ...b) {
  const [aLen, bLen, minLength] = [a.length, b.length, Math.min(a.length, b.length)];
  const interleaved = a.slice(0, minLength)
    .map((v, i) => [v, b[i]])
    .reduce((x, y) => [...x, ...y], []);
  return [...interleaved, ...(aLen < bLen ? b : a).slice(minLength)];
}

Not my favorite names but okay


function cylinder(spec) {
  let { radius = 1, height = 1 } = spec;
  const volume = () => (Math.PI * (radius ** 2) * height);
  const surfaceArea = () => (2 * Math.PI * radius * height) + (2 * Math.PI * (radius ** 2));
  const widen = (factor) => { radius *= factor; };
  const stretch = (factor) => { height *= factor; };
  const toString = () => `Cylinder with radius ${radius} and height ${height}`;
  return Object.freeze({
    get radius() { return radius; },
    get height() { return height; },
    volume,
    surfaceArea,
    widen,
    stretch,
    toString,
  });
}

// https://www.w3schools.com/nodejs/ref_crypto.asp
function makeCryptoFunctions(cryptoKey, cryptoAlgorithm) {
  function encrypt(s) {
    const cipher = crypto.createCipher(cryptoAlgorithm, cryptoKey);
    let encryption = cipher.update(s, 'utf8', 'hex');
    encryption += cipher.final('hex');
    return encryption;
  }

  function decrypt(s) {
    const decipher = crypto.createDecipher(cryptoAlgorithm, cryptoKey);
    let decryption = decipher.update(s, 'hex', 'utf8');
    decryption += decipher.final('utf8');
    return decryption;
  }
  return [encrypt, decrypt];
}

function randomName(info) {
  const { gender, region } = info;
  const options = {
    method: 'GET',
    uri: 'https://uinames.com/api/',
    qs: {
      gender,
      region,
      amount: 1,
    },
    headers: {
      'User-Agent': 'Request-Promise',
    },
    json: true, // Automatically stringifies the body to JSON
  };
  return rp(options).then(data => `${data.surname}, ${data.name}`);
}

module.exports = {
  change,
  stripQuotes,
  scramble,
  powers,
  powersGenerator,
  say,
  interleave,
  cylinder,
  makeCryptoFunctions,
  randomName,
};
Awesome 98/100

Homework 3 Grading

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.Map;
import java.util.TreeMap;
import java.util.HashMap;
import java.util.regex.Pattern;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.Comparator;

public class StreamPractice {

    static Pattern nonWord = Pattern.compile("[^\\p{L}']+");

    public static Map<Integer, Long> wordCountByLength(BufferedReader reader) {
        // Return a tree map whose keys are word lengths
        // and corresponding values are the number of words
        // in the reader with that length.

Don't comment like this in Java. Java has Javadoc. So that is what you should use.

        return reader.lines()
            .flatMap(line -> nonWord.splitAsStream(line.toLowerCase()))
            .filter(word -> !word.isEmpty())
            .collect(Collectors.groupingBy(w->w.length(), TreeMap::new, Collectors.counting()));
    }

    public static class Batter {
        String name;
        String team;
        int atBats;
        int hits;
        double average;
        Batter(String line) {
            String[] components = line.split("\\s*,\\s*");
            this.name = components[0];
            this.team = components[1];
            this.atBats = Integer.parseInt(components[2]);
            this.hits = Integer.parseInt(components[3]);
            this.average = (double)this.hits / (double)this.atBats;
        }

        @Override public String toString() {
          return this.name + " " + this.average;
        }
    }

    public static Map<String, Optional<Batter>> bestBatterByTeam(BufferedReader reader) {
        // Return a map that records, for each team, the b with
        // the highest average over all batters that have at least
        // 100 at-bats.
  
        return reader.lines()
            .map(b -> new Batter(b))
            .filter(a -> a.atBats >= 100)
            .collect(Collectors.groupingBy(b -> b.team, HashMap::new, Collectors.maxBy(Comparator.comparing(b -> b.average))));
    }

It uses a map by default, so you can be simpler

}

Score 100/100

Homework #3 Grading

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.Map;
import java.util.TreeMap;
import java.util.HashMap;
import java.util.regex.Pattern;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.Comparator;

public class StreamPractice {

    static Pattern nonWord = Pattern.compile("[^\\p{L}']+");

    public static Map<Integer, Long> wordCountByLength(BufferedReader reader) {
        // Return a tree map whose keys are word lengths
        // and corresponding values are the number of words
        // in the reader with that length.

        return reader.lines()
            .flatMap(line -> nonWord.splitAsStream(line.toLowerCase()))
            .filter(word -> !word.isEmpty())
            .collect(Collectors.groupingBy(w->w.length(), TreeMap::new, Collectors.counting()));
    }

Perfect

    public static class Batter {
        String name;
        String team;
        int atBats;
        int hits;
        double average;
        Batter(String line) {
            String[] components = line.split("\\s*,\\s*");
            this.name = components[0];
            this.team = components[1];
            this.atBats = Integer.parseInt(components[2]);
            this.hits = Integer.parseInt(components[3]);
            this.average = (double)this.hits / (double)this.atBats;
        }

        @Override public String toString() {
          return this.name + " " + this.average;
        }
    }

    public static Map<String, Optional<Batter>> bestBatterByTeam(BufferedReader reader) {
        // Return a map that records, for each team, the b with
        // the highest average over all batters that have at least
        // 100 at-bats.
  
        return reader.lines()
            .map(b -> new Batter(b))
            .filter(a -> a.atBats >= 100)
            .collect(Collectors.groupingBy(b -> b.team, HashMap::new, Collectors.maxBy(Comparator.comparing(b -> b.average))));
    }
}

maxBy is slightly easier, but OK here

SCORE 100/100

Homework #2 Grading

# Homework2
import math
from random import sample
from cryptography.fernet import Fernet
import requests
from itertools import product


def change(cents):
    if cents < 0:
        raise ValueError('amount cannot be negative')
    denominations = [25, 10, 5, 1]
    results = [0] * len(denominations)
    remaining_change = cents
    for index, coin in enumerate(denominations):
        if index < len(denominations) - 1:
            results[index], remaining_change = divmod(remaining_change, coin)
        else:
            results[index] = remaining_change
    return tuple(results)


def strip_quotes(s):
    return s.replace('"', '').replace('\'', '')

Replace in one step with a regex -2


def scramble(s):
    return ''.join(sample(s, k=len(s)))

Using k as a kwarg does not help. k is not meaningful.


def say(word=None):
    return '' if not word else lambda next=None: (say(f'{word} {next}') if next else word)


def triples(limit):
    return [(a, b, c) for a, b, c in product(range(1, limit + 1), repeat=3)
            if a < b < c and a ** 2 + b ** 2 == c ** 2]

I appreciate the golfing but you are running the loop variables through too many iterations. -2


def powers(base, limit):
    current_power = 0
    while base ** current_power <= limit:
        yield base ** current_power
        current_power += 1

Don't repeat the exponentiation expression -2



def interleave(a, *b):
    min_len = min(len(a), len(b))
    interleaved = [val for pair in zip(a, b) for val in pair]
    return interleaved + (a[min_len:] if len(a) > len(b) else list(b)[min_len:])


class Cylinder():
    def __init__(self, radius=1, height=1):
        self.radius = radius
        self.height = height

    @property
    def volume(self):
        return math.pi * (self.radius ** 2) * self.height

    @property
    def surface_area(self):
        return (2 * math.pi * self.radius * self.height) + (2 * math.pi * (self.radius ** 2))

    def widen(self, factor):
        self.radius *= factor
        return self

    def stretch(self, factor):
        self.height *= factor
        return self


# https://cryptography.io/en/latest/
def make_crypto_functions(fernet_key):
    cipher = Fernet(fernet_key)

    def encrypt(bytes):
        return cipher.encrypt(bytes)

    def decrypt(bytes):
        return cipher.decrypt(bytes)
    return (encrypt, decrypt)

Unneccessary local functions -1



# https://www.dataquest.io/blog/python-api-tutorial/
def random_name(**data):
    params = {'amount': 1}
    if 'gender' in data:
        params.update({'gender': data['gender']})
    if 'region' in data:
        params.update({'region': data['region']})
    r = requests.get('https://uinames.com/api/', params=params)
    info = r.json()
    if 'error' in info:
        # raise ValueError(f'{{"error": "{info["error"]}"}}') ... f-string version
        raise ValueError('{"error": "' + info['error'] + '"}')
    return info['surname'] + ", " + info['name']

Use interpolation instead of concatenation -1

Score 93/100

Homework #4 Grading

  1. You have a bit/byte confusion. Each array element is 8 bytes, not 1 byte. -2

  2. OK

  3. OK

  4. Careful with your words. You write "be more explicitly called." Don't overuse the word "call." That word is for invoking functions.

  5. OK

  6. std::arrays need a length template parameter -2

  7. Don't write out "Please enter a sentence" -- this pollutes standard output. -1
    You only accept one line -1
    You don't get the last word on the line -1
    Better to use a map than a vector of pairs

  8. OK

  9. You are not making the tail pointer null when deleting the last node -2
    << could should the whole queue -1

Score 90 / 100

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.