Compare commits

...

4 Commits

30 changed files with 2567 additions and 1 deletions

BIN
Assignment1/lenna.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

116
Assignment1/report1.tex Normal file
View File

@ -0,0 +1,116 @@
%! TeX program = lualatex
\RequirePackage[l2tabu,orthodox]{nag}
\DocumentMetadata{lang=en-US}
\documentclass[a4paper]{scrarticle}
\usepackage{geometry}
%\usepackage{tikz}
%\usepackage{tikz-uml}
\usepackage{hyperref}
\usepackage{caption}
\usepackage{bookmark}
\usepackage{fontspec}
\usepackage{microtype}
\usepackage{graphicx}
% Math packages
%\usepackage{amsmath}
%\usepackage{mathtools}
%\usepackage{amsthm}
%\usepackage{thmtools}
%\usepackage{lualatex-math}
% Unicode Math
\usepackage[warnings-off={mathtools-colon,mathtools-overbracket},math-style=ISO]{unicode-math}
\usepackage{newcomputermodern}
\newcommand*{\figref}[2][]{%
\hyperref[{fig:#2}]{%
Figure~\ref*{fig:#2}%
\ifx\\#1\\%
\else
\,#1%
\fi
}%
}
%\DeclarePairedDelimiter\ceil{\lceil}{\rceil}
%\DeclarePairedDelimiter\floor{\lfloor}{\rfloor}
%\declaretheorem[within=chapter]{definition}
%\declaretheorem[sibling=definition]{theorem}
%\declaretheorem[sibling=definition]{corollary}
%\declaretheorem[sibling=definition]{principle}
\usepackage{polyglossia}
\usepackage[backend=biber]{biblatex}
\setdefaultlanguage[variant=american,ordinalmonthday=true]{english}
\day=7
\month=2
\year=2024
\title{Assignment 1 Report}
\subtitle{Imperative Programming in C}
\author{Juan Pablo Zendejas}
\date{\today}
\begin{document}
\maketitle
%\tableofcontents
In this assignment, I was tasked with performing image manipulation
using an imperative programming style in C. Using the provided PGM file,
I wrote a program to do a threshold and rotation transformation by
reading the image into a 2D matrix and writing the resulting 2D matrices
to separate files.
\begin{figure}[h]
\centering
\begin{minipage}{0.3\textwidth}
\centering
\includegraphics[width=0.7\linewidth]{lenna.png}
\captionof{figure}{Input file}
\label{fig:lenna}
\end{minipage}%
\begin{minipage}{0.3\textwidth}
\centering
\includegraphics[width=0.7\linewidth]{rotate.png}
\captionof{figure}{Transposed}
\label{fig:transpose}
\end{minipage}%
\begin{minipage}{0.3\textwidth}
\centering
\includegraphics[width=0.7\linewidth]{threshold.png}
\captionof{figure}{Threshold}
\label{fig:thresh}
\end{minipage}%
\end{figure}
In \figref{lenna}, we see the provided input file. \figref{transpose}
represents a transposed or rotated version of the image. Finally,
\figref{thresh} is the image with a threshold value of 80 applied.
Values above 80 in the 0-255 range become white while values below 80
become black.
The assignment did not take too long to complete. While I was creating
the transformation code, I ran into a segmentation fault issue when
attempting to duplicate the matrix with the \texttt{memcpy} function.
Eventually, I discovered that I forgot to use \texttt{malloc} on the
rows to create the 2nd level of the 2D matrix. Once I solved that issue,
the math was fairly simple.
Due to the way the rotation operation was performed using a transpose,
rotating twice would result in the original image. Mathematically, this
is because the transformation is the inverse of itself. Swapping $x$ and
$y$ coordinates twice will result in the coordinates ending in the same
order. Rotating twice would not cause the image to be upside down
because it is not a 90° rotation, but rather a mirroring along the
diagonal of the image.
I did not collaborate during this assignment. I used the UNIX
\texttt{man} pages for documentation on the standard library and did not
use any external library.
\end{document}

BIN
Assignment1/rotate.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

BIN
Assignment1/threshold.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

46
Assignment3/Circle.m Normal file
View File

@ -0,0 +1,46 @@
% Represents a circle.
classdef Circle < Shape & ColorMixin
properties
Radius
end
methods
% The constructor takes a radius and calculates the area.
function obj = Circle(radius)
obj = obj@Shape("Circle")
obj@ColorMixin("blue")
obj.Radius = radius;
obj.Area = obj.CalculateArea();
end
% pi * r^2
function area = CalculateArea(obj)
obj.Area = pi * obj.Radius^2;
area = obj.Area;
end
function Display(obj)
% Call the super method
Display@Shape(obj)
% Add on the radius property
fprintf("\tRadius = %f\n", obj.Radius);
end
function Draw(obj)
Draw@Shape(obj);
% Use a curved rectangle to draw a circle
rectangle( ...
'Position',[0 0 obj.Radius*2 obj.Radius*2],...
'Curvature', [1 1], ...
'FaceColor', obj.Color);
% Center dot
plot(obj.Radius, obj.Radius, '.', Color='black');
% Radius line
plot([obj.Radius obj.Radius*2], [obj.Radius obj.Radius]);
% Put text denoting the radius above that line
text(obj.Radius*1.5,obj.Radius, sprintf("r = %g", obj.Radius), HorizontalAlignment="center", VerticalAlignment="bottom");
% Put text denoting the area
text(obj.Radius, obj.Radius*1.5, sprintf("A = %g", obj.Area), HorizontalAlignment="center", VerticalAlignment="middle");
end
end
end

BIN
Assignment3/Circle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

23
Assignment3/ColorMixin.m Normal file
View File

@ -0,0 +1,23 @@
classdef ColorMixin < handle
properties
Color
end
methods
function obj = ColorMixin(color)
if nargin == 0
obj.Color = "red";
else
obj.Color = color;
end
end
function color = GetColor(obj)
color = obj.Color;
end
function SetColor(obj, color)
obj.Color = color;
end
end
end

BIN
Assignment3/EquiTri.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

@ -0,0 +1,24 @@
classdef EquilateralTriangle < Triangle & ColorMixin
properties
SideLength
end
methods
function obj = EquilateralTriangle(sidelength)
obj@Triangle(sidelength, sqrt(3) * sidelength/2);
obj@ColorMixin("cyan")
obj.Name = "Equilateral Triangle";
obj.SideLength = sidelength;
end
function Display(obj)
Display@Triangle(obj);
fprintf("\tSide Length: %f units\n", obj.SideLength);
end
function Draw(obj)
Draw@Triangle(obj);
text(cos(pi/3)*obj.SideLength/2, sin(pi/3)*obj.SideLength/2, sprintf("l = %g", obj.SideLength), HorizontalAlignment="center", VerticalAlignment="bottom", Rotation=60);
end
end
end

29
Assignment3/MyShapes.m Normal file
View File

@ -0,0 +1,29 @@
disp("Welcome to the Shapes script.")
disp("Here are the following shapes you can make:")
disp("Circle, Square, Rectangle, EquiTri, Triangle.")
shapen = input("Which shape? ", "s");
color = input("Color (use quotes or rgb vector)? ");
shape = Shape("BAD SHAPE.");
switch (shapen)
case "Circle"
radius = input("Radius? ");
shape = Circle(radius);
case "Square"
len = input("Side length? ");
shape = Square(len);
case "Rectangle"
len = input("Length? ");
h = input("Height? ");
shape = Rectangle(len, h);
case "EquiTri"
len = input("Side Length? ");
shape = EquilateralTriangle(len);
case "Triangle"
base = input("Base? ");
height = input("Height? ");
shape = Triangle(base, height);
end
shape.SetColor(color)
shape.Draw

39
Assignment3/Rectangle.m Normal file
View File

@ -0,0 +1,39 @@
classdef Rectangle < Shape & ColorMixin
properties
Length, Width
end
methods
function obj = Rectangle(l,w)
obj@Shape("Rectangle")
obj@ColorMixin("red")
obj.Length = l;
obj.Width = w;
obj.Area = obj.CalculateArea;
end
function area = CalculateArea(obj)
area = obj.Length*obj.Width;
obj.Area = area;
end
function Display(obj)
Display@Shape(obj)
fprintf("\tLength = %f\n", obj.Length);
fprintf("\tWidth = %f\n", obj.Width);
end
function Draw(obj)
Draw@Shape(obj);
% Draw a rectangle
rectangle('Position',[0 0 obj.Length obj.Width], ...
'FaceColor', obj.Color);
% Draw length text
text(obj.Length / 2, 0, sprintf("l = %g", obj.Length), HorizontalAlignment="center", VerticalAlignment="bottom");
% Draw width text
text(obj.Length, obj.Width/2, sprintf("w = %g", obj.Width), Rotation=90, HorizontalAlignment="center", VerticalAlignment="bottom");
% Draw area text
text(obj.Length/2, obj.Width/2, sprintf("A = %g", obj.Area), HorizontalAlignment="center", VerticalAlignment="middle");
end
end
end

BIN
Assignment3/Rectangle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

43
Assignment3/Shape.m Normal file
View File

@ -0,0 +1,43 @@
% To let the shapes be in an array, they have to derive from the
% Hetereogeneous mixin
classdef Shape < ColorMixin & matlab.mixin.Heterogeneous & handle
% These properties are shared by all Shapes.
properties
Name, Area
end
methods
% Base constructor to create a new shape with a specific name
function obj = Shape(name)
obj.Name = name;
end
% Base method to display the shape in a readable format.
function Display(obj)
fprintf("%s shape with\n\tArea = %f square units\n\tColor = ", obj.Name, obj.Area);
disp(obj.Color);
end
% Base method that creates a figure with the title being the
% shape's name.
function Draw(obj)
figure('Name',obj.Name)
% Equal axes to preserve shape.
axis equal
% Prevents plot commands from resetting the figure.
hold on
end
end
methods (Static)
function CalculateStatistics(shapes)
% Shapes input is an array of shape values.
% Collect all their areas into an array.
areas = [shapes.Area];
% Call datastats with the column vector of all the areas.
stats = datastats(areas(:));
% Show output
fprintf("Mean area: %f square units\nMedian area: %f square units\nStandard deviation: %f square units\n", stats.mean, stats.median, stats.std);
end
end
end

20
Assignment3/Square.m Normal file
View File

@ -0,0 +1,20 @@
classdef Square < Rectangle & ColorMixin
properties
SideLength
end
methods
function obj = Square(sidelen)
obj@Rectangle(sidelen, sidelen);
obj@ColorMixin("green");
obj.Name = "Square";
obj.SideLength = sidelen;
obj.Area = obj.CalculateArea;
end
function Display(obj)
Display@Shape(obj)
fprintf("\tSide Length = %f\n", obj.SideLength);
end
end
end

36
Assignment3/Triangle.m Normal file
View File

@ -0,0 +1,36 @@
classdef Triangle < Shape & ColorMixin
properties
Base, Height
end
methods
function obj = Triangle(base,height)
obj@Shape("Triangle")
obj@ColorMixin("yellow")
obj.Base = base;
obj.Height = height;
obj.Area = obj.CalculateArea;
end
function area = CalculateArea(obj)
area = (obj.Base*obj.Height)/2;
obj.Area = area;
end
function Display(obj)
Display@Shape(obj)
fprintf("\tBase = %f units\n", obj.Base);
fprintf("\tHeight = %f units\n", obj.Height);
end
function Draw(obj)
Draw@Shape(obj);
ps = polyshape([0 0; obj.Base/2 obj.Height; obj.Base 0; 0 0]);
plot(ps, FaceColor=obj.Color);
plot([obj.Base/2 obj.Base/2],[0 obj.Height]);
text(obj.Base/2, obj.Height/2, sprintf("h = %g", obj.Height), Rotation=90, HorizontalAlignment="center", VerticalAlignment="bottom");
text(obj.Base/4,0,sprintf("b = %g", obj.Base), HorizontalAlignment="center", VerticalAlignment="bottom");
text(obj.Base*(3/4),0,sprintf("A = %g", obj.Area), HorizontalAlignment="center", VerticalAlignment="bottom");
end
end
end

BIN
Assignment3/Triangle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

BIN
Assignment3/report3.pdf Normal file

Binary file not shown.

583
Assignment3/report3.tex Normal file
View File

@ -0,0 +1,583 @@
%! TeX program = lualatex
\RequirePackage[l2tabu,orthodox]{nag}
\DocumentMetadata{lang=en-US}
\documentclass[a4paper]{scrartcl}
\usepackage{geometry}
\usepackage{graphicx}
%\usepackage{tikz}
%\usepackage{tikz-uml}
\usepackage{hyperref}
\usepackage{caption}
\usepackage{subcaption}
\usepackage{newfloat}
\usepackage{fancyvrb}
\usepackage{minted}[newfloat=true]
\usepackage{bookmark}
\usepackage{fontspec}
\usepackage{microtype}
% Math packages
\usepackage{amsmath}
%\usepackage{mathtools}
%\usepackage{amsthm}
%\usepackage{thmtools}
\usepackage{lualatex-math}
\usepackage[warnings-off={mathtools-colon,mathtools-overbracket},math-style=ISO,bold-style=ISO]{unicode-math}
% Fonts
\usepackage{newcomputermodern}
\setmonofont{0xProto}[Scale=MatchLowercase]
\newcommand*{\figref}[2][]{%
\hyperref[{fig:#2}]{%
Figure~\ref*{fig:#2}%
\ifx\\#1\\%
\else
\,#1%
\fi
}%
}
\newcommand*{\lstref}[2][]{%
\hyperref[{lst:#2}]{%
Listing~\ref*{lst:#2}%
\ifx\\#1\\%
\else
\,#1%
\fi
}%
}
\setminted{breaklines=true,frame=single}
\newenvironment{longlisting}{\captionsetup{type=listing}}{}
\newenvironment{longfigure}{\captionsetup{type=figure}}{}
\DefineVerbatimEnvironment{CommandWindow}{Verbatim}{frame=lines,
label={Command Window}}
\setlength{\belowcaptionskip}{10pt}
\setlength{\abovecaptionskip}{8pt}
%\DeclarePairedDelimiter\ceil{\lceil}{\rceil}
%\DeclarePairedDelimiter\floor{\lfloor}{\rfloor}
%\declaretheorem[within=chapter]{definition}
%\declaretheorem[sibling=definition]{theorem}
%\declaretheorem[sibling=definition]{corollary}
%\declaretheorem[sibling=definition]{principle}
\usepackage{polyglossia}
\usepackage[backend=biber]{biblatex}
\setdefaultlanguage[variant=american,ordinalmonthday=true]{english}
\day=15
\month=4
\year=2024
\title{Programming Assignment 3}
\subtitle{CS-420 Spring 2024}
\author{Juan Pablo Zendejas}
\date{\today}
\begin{document}
\maketitle
%\listoftheorems[ignoreall,onlynamed={theorem,corollary,principle}]
%\listoftheorems[ignoreall,onlynamed={definition},title={List of Definitions}]
%\tableofcontents
\section{Introduction}
For this assignment, I was tasked with implementing object-oriented
programming principles in the MATLAB language. This includes inheritance
in single, multiple, and multi-level forms. I also had to practice the
concept of calling super-class methods and overriding methods. This
involved creating a group of classes that represented different shapes,
and implementing methods and providing properties for these classes.
\section{Task One: Class Creation and Constructors}
My first task was to create a base class called \texttt{Shape}. It holds
properties \texttt{Name} and \texttt{Area}, a constructor to set the
name, and a \texttt{Display} method. The code is displayed in
\lstref{shape}.
Originally, it consisted of just the properties, the constructor, and
the \texttt{Display} method. The other methods were added in the next
tasks and will be discussed then. The output for the task is given in
\figref{taskone}.
\begin{longfigure}
\begin{CommandWindow}
>> shape1 = Shape("Timmy")
shape1 =
Shape with properties:
Name: "Timmy"
Area: []
Color: "red"
>> shape2 = Shape("Jimmy")
shape2 =
Shape with properties:
Name: "Jimmy"
Area: []
Color: "red"
>> shape1.Display
Timmy shape with
Area = square units
Color = red
>> shape2.Display
Jimmy shape with
Area = square units
Color = red
>>
\end{CommandWindow}
\caption{Output from testing Task 1.}
\label{fig:taskone}
\end{longfigure}
\section{Task Two: Inheritance and Constructor Overloading}
This task involved creating new classes that derived from Shape, calling
the super constructor to set the name. The code listings for the 3 classes are
shown in \lstref{circle}, \lstref{rectangle}, and \lstref{triangle}.
When I started this task, it was a bit difficult at first to figure out
how MATLAB's class inheritance works. A lot of MATLAB syntax is very
different to me coming from other languages. Eventually, I figured out
that you need to use the \texttt{<} less than symbol and the
\texttt{\&}
ampersand to define inheritance with the \texttt{classdef}.
All of the three constructors call the \texttt{Shape} constructor using
the \texttt{@}-sign notation. This was another strange thing to me
coming from other languages, and I'm still getting used to it. In
MATLAB, the super-constructor calls have to come first and can't be in
conditionals. However, all I needed it to do was set the shape name, so
that wasn't a problem here.
Finally, I had to add a \texttt{CalculateArea} method to all of the
classes. This method would calculate the area of the shape and save it
to the \texttt{Area} property on the object. While attempting to
implement this method, I found out that by default MATLAB classes are
passed by value. This was annoying because the area wasn't being saved
by the CalculateArea class and I couldn't figure out why. Eventually, I
found out that to get behavior like which I'm used to from other
languages, \texttt{Shape} had to derive from the \texttt{handle} class
built-in to MATLAB. Deriving the \texttt{handle} class, as shown in
\lstref{shape} on line 3, makes the class' instances pass by reference
instead of by value. Then, assigning class properties became easy.
This \texttt{CalculateArea} method was called in the constructor to
assign the correct value right after the object was constructed. See
\figref{tasktwo} for the command window output and testing.
\begin{longfigure}
\begin{CommandWindow}
>> rect1 = Rectangle(5,6)
rect1 =
Rectangle with properties:
Length: 5
Width: 6
Name: "Rectangle"
Area: 30
Color: "red"
>> rect2 = Rectangle(6,7)
rect2 =
Rectangle with properties:
Length: 6
Width: 7
Name: "Rectangle"
Area: 42
Color: "red"
>> tri1 = Triangle(5,6)
tri1 =
Triangle with properties:
Base: 5
Height: 6
Name: "Triangle"
Area: 15
Color: "yellow"
>> tri2 = Triangle(2,7)
tri2 =
Triangle with properties:
Base: 2
Height: 7
Name: "Triangle"
Area: 7
Color: "yellow"
>> circ1 = Circle(5)
circ1 =
Circle with properties:
Radius: 5
Name: "Circle"
Area: 78.5398
Color: "blue"
>> circ2 = Circle(10)
circ2 =
Circle with properties:
Radius: 10
Name: "Circle"
Area: 314.1593
Color: "blue"
\end{CommandWindow}
\caption{Testing for Task Two.}
\label{fig:tasktwo}
\end{longfigure}
\section{Task Three: Method Overriding}
In this task, I wrote the \texttt{Display} methods for the
\texttt{Circle}, \texttt{Rectangle}, and \texttt{Triangle} class. These
methods override the original \texttt{Display} method defined in
\texttt{Shape}, and are shown in the corresponding listings
\lstref{circle}, \lstref{rectangle}, and \lstref{triangle}.
To make the implementation more consistent, I created them as an
extension of the \texttt{Shape}'s \texttt{Display} method. I had to
figure out the syntax for calling super methods in MATLAB, which was
very similar to the method of calling super constructors. Thus, I had to
write \texttt{Display@Shape(obj)} to first call the super method. Then,
I used more \texttt{fprintf} function calls to add on appropriate
information for the class. The test output is shown in
\figref{taskthree}.
\begin{longfigure}
\begin{CommandWindow}
>> rect1.Display
Rectangle shape with
Area = 30.000000 square units
Color = red
Length = 5.000000
Width = 6.000000
>> circ1.Display
Circle shape with
Area = 78.539816 square units
Color = blue
Radius = 5.000000
>> tri1.Display
Triangle shape with
Area = 15.000000 square units
Color = yellow
Base = 5.000000 units
Height = 6.000000 units
\end{CommandWindow}
\caption{Test output for Task 3.}
\label{fig:taskthree}
\end{longfigure}
\section{Task Four: Multi-Level Inheritance}
Multi-level inheritance is when you create a subclass of a subclass,
which increases the level of separation and grouping. For our Shapes, I
had to create classes that represent an Equilateral Triangle and a
Square. Thus, they would derive from \texttt{Triangle} and
\texttt{Rectangle} respectively. The code for these classes is shown in
\lstref{equitri} and \lstref{square}.
In these classes, the constructor called their respective super class
constructor, with appropriate properties calculated from the given
value. Thus, the area would be properly assigned. All that was left was
to change the name. While I would have simply called the \texttt{Shape}
constructor, it was already in use by the super class. And, as explained
in the static method section, it would have caused issues with the later
implementation. Thus, I decided to simply overwrite it with an
assignment for these classes.
I did not have to override the \texttt{CalculateArea} method since the
calculation method is the same for the derived shapes. However, I did
override the \texttt{Display} method, calling the super-class version
and adding on the specialized properties. The test output is shown in
\figref{taskfour}.
\begin{longfigure}
\begin{CommandWindow}
>> eqtri1 = EquilateralTriangle(5);
>> sq1 = Square(4);
>> eqtri1.Display
Equilateral Triangle shape with
Area = 10.825318 square units
Color = cyan
Base = 5.000000 units
Height = 4.330127 units
Side Length: 5.000000 units
>> sq1.Display
Square shape with
Area = 16.000000 square units
Color = green
Side Length = 4.000000
\end{CommandWindow}
\caption{Test output for Task 4.}
\label{fig:taskfour}
\end{longfigure}
\section{Task Five: Multiple Inheritance}
Multiple inheritance differs from multi-level inheritance, as multiple
inheritance is when one class derives from multiple super-classes. For
this task, I had to create a new class called \texttt{ColorMixin} that
simply defined a new property, \texttt{Color}, and some methods to
change it. The class is shown in \lstref{color}. As I fixed bugs, it
turned out that all classes on an object had to be \texttt{handle}s, so
I had to make \texttt{ColorMixin} derive from that class.
Also, I had to make \texttt{ColorMixin} have a default color value. This
was achieved by reading the MATLAB documentation, and using the
\texttt{nargin} variable. This variable contains the number of arguments
given to the function. When it's 0, I simply set \texttt{Color} to be
red by default.
In addition, I discovered that MATLAB colors can either be a string or a
vector of RGB values. So, the set and get color methods have no
restriction on the type of the parameter.
Finally, I had to make all the shapes derive from the
\texttt{ColorMixin} class so I could use its constructor in the shape
constructors. Each shape has a different default color based on what I
feel that shape's color is. The test output for this task is shown in
\figref{taskfive}.
\begin{longfigure}
\begin{CommandWindow}
>> circ1.Display
Circle shape with
Area = 78.539816 square units
Color = red
Radius = 5.000000
>> circ1.SetColor("blue")
>> tri1.Display
Triangle shape with
Area = 15.000000 square units
Color = yellow
Base = 5.000000 units
Height = 6.000000 units
>> tri1.SetColor([0.5 0.3 0.9])
>> tri1.Display
Triangle shape with
Area = 15.000000 square units
Color = 0.5000 0.3000 0.9000
Base = 5.000000 units
Height = 6.000000 units
\end{CommandWindow}
\caption{Test output for Task 5.}
\label{fig:taskfive}
\end{longfigure}
\section{Task Six: Static Method}
This task involves creating a static method to determine some statistics
about a list of shapes' area values. To achieve this, the \texttt{Shape}
class has to derive from the \texttt{Heterogeneous} mixin, in order
for heterogeneous arrays of shapes to be created. This also adds the
restriction that classes can only derive from one heterogeneous class;
which is why Equilateral Triangle and Square could not also derive from
Shape.
To implement this method, I used the MATLAB \texttt{datastats} method,
which returns a dictionary containing some common statistic parameters.
In particular, we're looking at the mean, median, and standard
deviation. Look at \lstref{shape} to see the implementation. In essence,
I can use the vectorization properties of MATLAB to use the common
``parameter get'' dot notation, which actually collects the
\texttt{Area} property of all the shapes in the array. I then collect it
into another array by wrapping it in square brackets.
Finally, to collect the array into a column vector that
\texttt{datastats} requires, I use the spread operator \texttt{(:)} with
null parameters to get the entire array in a column vector.
\texttt{datastats} will calculate the statistics, which are then printed
out. An example is shown in \figref{tasksix}.
\begin{longfigure}
\begin{CommandWindow}[breaklines=true]
>> shapes = [Triangle(4,5), Circle(5), Rectangle(4,5), EquilateralTriangle(6), Square(10)]
shapes =
1x5 heterogeneous Shape (Triangle, Circle, Rectangle, ...) array with properties:
Name
Area
Color
>> Shape.CalculateStatistics(shapes)
Mean area: 44.825655 square units
Median area: 20.000000 square units
Standard deviation: 41.427063 square units
\end{CommandWindow}
\caption{Test output for Task 6.}
\label{fig:tasksix}
\end{longfigure}
\section{Task Seven: Visualization}
For this task, I had to use MATLAB's built-in visualization methods to
create a \texttt{Draw} method that displays a figure representing the
shape. I achieved this primarily using the \texttt{plot}, \texttt{text},
and \texttt{rectangle} functions included in MATLAB.
I first created a base \texttt{Draw} method in the \texttt{Shape} class.
By reading the documentation, I found out that I could use the
\texttt{figure} function to start a new figure and give it a name, which
I set to the shape's name. To preserve the outline of the shape, I used
\texttt{axis equal}, and to prevent future \texttt{plot} calls from
changing the options, I used \texttt{hold on}.
For the circle in \lstref{circle}, I used a call to \texttt{rectangle}
with a curvature of 1. I added some lines to draw a point and a line,
then some text for the area and radius.
For the triangle, I used the \texttt{polyshape} method I found in some
documentation examples. I passed it a matrix of coordinates that defined
the points of the shape, and then used the \texttt{plot} command to fill
it in. Finally, I added some text and lines to represent the base,
height, and area. The equilateral triangle class uses the triangle draw
method, but adds the side length as text on the figure.
For the rectangle, I just used the \texttt{rectangle} method to fill in
the shape. Then, I had 3 calls to \texttt{text} to add length, width,
and area. The square doesn't add anything new to the figure.
Some example figures are shown in \figref{circle}, \figref{triangle},
\figref{equitri}, and \figref{rectangle}.
\begin{figure}[!hbt]
\centering
\subcaptionbox{A circle.\label{fig:circle}}[.475\linewidth]
{\includegraphics[width=\linewidth]{Circle.png}}\hfill %
\subcaptionbox{A triangle.\label{fig:triangle}}[.475\linewidth]
{\includegraphics[width=\linewidth]{Triangle.png}}
\medskip
\subcaptionbox{An equilateral triangle.\label{fig:equitri}}[.475\linewidth]
{\includegraphics[width=\linewidth]{EquiTri.png}}\hfill %
\subcaptionbox{A rectangle.\label{fig:rectangle}}[.475\linewidth]
{\includegraphics[width=\linewidth]{Rectangle.png}}
\caption{Shapes as generated by MATLAB.}
\label{fig:shapes}
\end{figure}
\section{Task Eight: User Interaction}
The final task was to create an interactive script that lets a user
create a shape and type out the parameters. This code is shown in
\lstref{script}. The script is fairly simple. I use the \texttt{input}
method of MATLAB to ask for a name of a shape. I need the \texttt{"s"}
operator to get a simple string. However, for the color and for the
parameter inputs, I don't use that so the user can input an expression,
or for the color, a vector of RGB values. An example of its use is found
in \figref{script}. At the end, a window opens showing the shape as
found in \figref{shapes}.
\begin{longfigure}
\begin{CommandWindow}
>> MyShapes
Welcome to the Shapes script.
Here are the following shapes you can make:
Circle, Square, Rectangle, EquiTri, Triangle.
Which shape?
Circle
Color (use quotes or rgb vector)?
[0.9 0.4 0.2]
Radius?
10
\end{CommandWindow}
\caption{Output of MyShapes script.}
\label{fig:script}
\end{longfigure}
\section{Conclusion}
This was certainly an interesting project. To be honest, the PDF given
was a little confusing with the instructions, but I believe I was able
to learn all that I needed about MATLAB's standard library and its uses.
I had a lot of fun making this document look nice and pretty, especially
\figref{shapes} which took a bit of digging. Also, the MATLAB
documentation is immense but easy to search through and has plenty of
examples.
\section{Source Code}
\begin{longlisting}
\inputminted[label={Shape.m}]{matlab}{Shape.m}
\caption[Shape.m]{Shape class.}
\label{lst:shape}
\end{longlisting}
\begin{longlisting}
\inputminted[label={Circle.m}]{matlab}{Circle.m}
\caption[Circle.m]{Circle class.}
\label{lst:circle}
\end{longlisting}
\begin{longlisting}
\inputminted[label={Rectangle.m}]{matlab}{Rectangle.m}
\caption[Rectangle.m]{Rectangle class.}
\label{lst:rectangle}
\end{longlisting}
\begin{longlisting}
\inputminted[label={Triangle.m}]{matlab}{Triangle.m}
\caption[Triangle.m]{Triangle class.}
\label{lst:triangle}
\end{longlisting}
\begin{longlisting}
\inputminted[label={EquilateralTriangle.m}]{matlab}{EquilateralTriangle.m}
\caption[EquilateralTriangle.m]{EquilateralTriangle class.}
\label{lst:equitri}
\end{longlisting}
\begin{longlisting}
\inputminted[label={Square.m}]{matlab}{Square.m}
\caption[Square.m]{Square class.}
\label{lst:square}
\end{longlisting}
\begin{longlisting}
\inputminted[label={ColorMixin.m}]{matlab}{ColorMixin.m}
\caption[ColorMixin.m]{ColorMixin class.}
\label{lst:color}
\end{longlisting}
\begin{longlisting}
\inputminted[label={MyShapes.m}]{matlab}{MyShapes.m}
\caption[MyShapes.m]{MyShapes script.}
\label{lst:script}
\end{longlisting}
\end{document}

103
Assignment4/Assign4.pl Normal file
View File

@ -0,0 +1,103 @@
:- style_check(-singleton).
% DO NOT MODIFY
:- consult('ReadCSV.pl').
:- use_module(library(date)).
:- read_csv_and_store('EmployeeData.csv').
% DO NOT MODIFY
is_seattle_employee(Name) :- person(_, Name, _, _, _, _, _, _, _, _, _, _, 'Seattle',_).
is_senior_manager_in_IT(Name) :- person(_, Name, 'Sr. Manger', 'IT', _, _, _, _, _, _, _, _, _, _).
is_director_finance_miami(Name) :- person(_, Name, 'Director', 'Finance', _, _, _, _, _, _, _, _, 'Miami', _).
is_asian_US_manufacturing_40M(Name, Unit, Gender, Ethnicity, Age) :- person(_, Name, _, _, Unit, Gender, Ethnicity, Age, _, _, _, _, _, _), Age > 40, Unit = 'Manufacturing', Gender = 'Male', Ethnicity = 'Asian'.
% format calls write internally
greet(EEID) :- person(EEID, Name, Job, Dept, Unit, _, _, _, _, _, _, _, _, _), format('Hello, ~w, ~w, ~w, ~w!~n', [Name, Job, Dept, Unit]).
years_until_retirement(Name, Age, Until) :- person(_, Name, _, _, _, _, _, Age, _, _, _, _, _, _), Until is 65-Age.
is_rd_black_midAge(Name, Unit, Ethnicity, Age) :- person(_, Name, _, _, Unit, _, Ethnicity, Age, _, _, _, _, _, _), Ethnicity = 'Black', Unit = 'Research & Development', Age >= 25, Age =< 50.
is_ITorFin_PHXorMIAorAUS(Name, Dept, City) :- person(_, Name, _, Dept, _, _, _, _, _, _, _, _, City, _),
(Dept = 'IT'; Dept = 'Finance'),
(City = 'Phoenix'; City = 'Miami'; City = 'Austin').
is_female_senior_role(Name, Title) :- person(_, Name, Title,_,_,'Female',_,_,_,_,_,_,_,_), atom_concat('Sr.', _, Title).
% Helper predicate that converts a salary string to a number
% Remove $.
convert_salary(In, Out) :- atom_concat('$', NoDollar, In),
% Split by commas, and additionally remove trailing whitespace
split_string(NoDollar, ',', '\t\s', NoCommaList),
% Concatenate the list back into an atom.
atomic_list_concat(NoCommaList, SalaryAtom),
% Convert the atom into a number.
atom_number(SalaryAtom, Out).
is_highly_paid_senior_manager(Name, Salary) :- person(_, Name, 'Sr. Manger', _, _, _, _, _, _, Salary, _, _, _, _),
convert_salary(Salary, SalaryN),
SalaryN > 120000.
% Divisibility test
divides(N,X) :- 0 is X mod N.
% prime/2 is helper predicate.
% it is a recursive algorithm that tests all the numbers from N up to x,
% ensuring they all do not divide N.
% Base case.
prime(N, N) :- true, !.
% X should not divide N, and the next number also should not.
prime(X, N) :- not(divides(X, N)), Next is X+1, prime(Next, N).
% prime/1 calls prime/2.
prime(N) :- prime(2,N).
is_prime_age(Name, Age) :- person(_, Name, _, _, _, _, _, Age, _, _, _, _, _, _), prime(Age).
% Uses convert_salary.
total_salary(Name, Salary) :- person(_, Name, _, _, _, _, _, _, _, AnnSal, BonusP, _, _, _),
convert_salary(AnnSal, AnnSalN), atom_concat(Bonus, '%', BonusP), atom_number(Bonus, BonusN),
Salary is AnnSalN + (AnnSalN * (BonusN / 100)).
takehome_salary(Name, Title, Salary) :- person(_, Name, Title,_,_,_,_,_,_,_,_,_,_,_),
% Get the total salary.
total_salary(Name, AS),
% Semicolon causes backtracking.
(
% "One of these clauses should be true"
AS =< 50000, Tax = 20/100;
AS > 50000, AS =< 100000, Tax = 25/100;
AS > 100000, AS =< 200000, Tax = 30/100;
AS > 200000, Tax = 35/100
% Unified value for Tax is then used here.
), Salary is AS - (AS * Tax).
total_years(Name, Years) :- person(_,Name,_,_,_,_,_,_,Hire,_,_,_,_,Exit),
% parse timestamp to get the year number
split_string(Hire, '/', '', [_,_,HireYrS]),
atom_number(HireYrS, HireYrShort),
% since it's a short number, add 1900 if > 50
% but otherwise add 2000
(HireYrShort < 50, HireYr is HireYrShort + 2000;
HireYr is HireYrShort + 1900),
% find "exit" year
(Exit = '', get_time(T), stamp_date_time(T, DT, local), date_time_value(year, DT, CurYear), Years is CurYear - HireYr, !;
% parse exit year
split_string(Exit, '/', '', [_,_,ExitYrS]),
atom_number(ExitYrS, ExitYrShort),
(ExitYrShort < 50, ExitYr is ExitYrShort + 2000;
ExitYr is ExitYrShort + 1900),
Years is ExitYr - HireYr, !).
title_salary(Title, Salary) :- person(_,_,Title,_,_,_,_,_,_,SalaryS,_,_,_,_), convert_salary(SalaryS, Salary).
% bagof() gets al the possible salaries for a title. Then, i use foldl
% to sum up all of the salaries, and divide by the number of salaries,
% which is the formula for the average.
average_salary(Title, AvgSalary) :- bagof(Salary, title_salary(Title, Salary), SalList), foldl(plus, SalList, 0, Total), length(SalList, N), AvgSalary is Total / N.

1001
Assignment4/EmployeeData.csv Normal file

File diff suppressed because it is too large Load Diff

17
Assignment4/ReadCSV.pl Normal file
View File

@ -0,0 +1,17 @@
:- use_module(library(csv)).
% Predicate to read data from a CSV file and store it as rules
read_csv_and_store(Filename) :-
csv_read_file(Filename, [_|Rows], []),
process_rows(Rows).
% Process each row in the CSV file and store data as rules
process_rows([]).
process_rows([Row|Rows]) :-
process_row(Row),
process_rows(Rows).
% Store data from a row as a rule
process_row(row(EEID, Name, Job, Department, Unit, Gender, Ethnicity, Age, Hired, Salary, Bonus, Country, City, Exited)) :-
assert(person(EEID, Name, Job, Department, Unit, Gender, Ethnicity, Age, Hired, Salary, Bonus, Country, City, Exited)).

BIN
Assignment4/report4.pdf Normal file

Binary file not shown.

343
Assignment4/report4.tex Normal file
View File

@ -0,0 +1,343 @@
%! TeX program = lualatex
\RequirePackage[l2tabu,orthodox]{nag}
\DocumentMetadata{lang=en-US}
\documentclass[a4paper]{scrartcl}
\usepackage{geometry}
\usepackage{graphicx}
%\usepackage{tikz}
%\usepackage{tikz-uml}
\usepackage{hyperref}
\usepackage{caption}
\usepackage{subcaption}
\usepackage{newfloat}
\usepackage{fancyvrb}
\usepackage{minted}[newfloat=true]
\usepackage{bookmark}
\usepackage{fontspec}
\usepackage{microtype}
% Math packages
%\usepackage{amsmath}
%\usepackage{mathtools}
%\usepackage{amsthm}
%\usepackage{thmtools}
%\usepackage{lualatex-math}
%\usepackage[warnings-off={mathtools-colon,mathtools-overbracket},math-style=ISO,bold-style=ISO]{unicode-math}
% Fonts
\usepackage{newcomputermodern}
\setmonofont{0xProto}[Scale=MatchLowercase]
\newcommand*{\figref}[2][]{%
\hyperref[{fig:#2}]{%
Figure~\ref*{fig:#2}%
\ifx\\#1\\%
\else
\,#1%
\fi
}%
}
\newcommand*{\lstref}[2][]{%
\hyperref[{lst:#2}]{%
Listing~\ref*{lst:#2}%
\ifx\\#1\\%
\else
\,#1%
\fi
}%
}
\setminted{breaklines=true,frame=single,linenos=true}
\newenvironment{longlisting}{\captionsetup{type=listing}}{}
\newenvironment{longfigure}{\captionsetup{type=figure}}{}
\setlength{\belowcaptionskip}{10pt}
\setlength{\abovecaptionskip}{8pt}
%\DeclarePairedDelimiter\ceil{\lceil}{\rceil}
%\DeclarePairedDelimiter\floor{\lfloor}{\rfloor}
%\declaretheorem[within=chapter]{definition}
%\declaretheorem[sibling=definition]{theorem}
%\declaretheorem[sibling=definition]{corollary}
%\declaretheorem[sibling=definition]{principle}
\usepackage{polyglossia}
\usepackage[backend=biber]{biblatex}
\setdefaultlanguage[variant=american,ordinalmonthday=true]{english}
\day=3
\month=5
\year=2024
\title{Logical Programming in Prolog}
\subtitle{Assignment 4}
\author{Juan Pablo Zendejas}
\date{\today}
\begin{document}
\maketitle
%\listoftheorems[ignoreall,onlynamed={theorem,corollary,principle}]
%\listoftheorems[ignoreall,onlynamed={definition},title={List of Definitions}]
%\tableofcontents
In this assignment, I was tasked with creating Prolog predicates that
query the database of employees given in a CSV file. I created 15 rules
as specified in the assignment PDF. Overall, this assignment was very
interesting to me. Prolog is very different from any other programming
language I've used, even Haskell. Getting used to the eccentricities of
SWI-Prolog and reading its documentation gave me a lot of insight. In
addition, my background of formal logic from Discrete Mathematics taken
here at SDSU gave me a lot of parallels that helped me understand how to
write code.
I did not receive any external help except from consulting the SWI
Prolog handbook/documentation found on their website. This documentation
was very useful to figure out what predicates to use to transform some
of the data.
\section{CSV File Importing}
First I had to change the \texttt{ReadCSV.pl} file to import all the
rows from the CSV, ignoring the first title row. The source code is
displayed in \lstref{readcsv}.
\begin{listing}
\inputminted[label={ReadCSV.pl}]{prolog}{ReadCSV.pl}
\caption{CSV reader.}
\label{lst:readcsv}
\end{listing}
This part wasn't too bad. I simply had to ignore the first row, which I
did by using Pattern Matching on the \texttt{csv\_read\_file} predicate to
ignore the first entry of the list and simply take the tail as the
\texttt{Rows} variable.
Then, on \texttt{process\_row}, I simply filled in the \texttt{assert}
call with all the names of the columns.
\section{Writing Rules}
Now, I was tasked with using the imported facts from the CSV and writing
rules that would be used as queries to the dataset.
\subsection{Rule One}
Simple rule, displayed in \lstref{seattleempl}. The \texttt{:-} symbol
is reminiscent of ``yields'' from mathematics. I use the underscore to
discard the variables from the \texttt{people} predicate that I don't
need, and just check if a person exists with that name and is from
Seattle.
\begin{listing}
\inputminted[label={is\_seattle\_employee},firstline=10,lastline=10]{prolog}{Assign4.pl}
\caption{Rule to determine if an employee is from Seattle.}
\label{lst:seattleempl}
\end{listing}
\subsection{Rule Two}
Very similar to rule one, displayed in \lstref{seniormangerit}. Now, we
just have more filters to apply, which is done by replacing some of the
underscores with concrete values.
\begin{listing}
\inputminted[label={is\_senior\_manager\_in\_it},firstline=12,lastline=12]{prolog}{Assign4.pl}
\caption{Rule to determine if an employee is a senior manager in IT.}
\label{lst:seniormangerit}
\end{listing}
\subsection{Rule Three}
Displayed in \lstref{rule3}. Standard like the previous rules.
\begin{listing}
\inputminted[label={is\_director\_finance\_miami},firstline=14,lastline=14]{prolog}{Assign4.pl}
\caption{Rule to determine if an employee is a Director of Finance
in Miami.}
\label{lst:rule3}
\end{listing}
\subsection{Rule Four}
This rule is a little more complicated. It's displayed in
\lstref{rule4}. Since this predicate has more arguments, I have them
directly wired into the \texttt{person} predicate. Then, I simply have
conditions that specify the values of those predicates. In addition, I
had to do this for \texttt{Age} because I need to check if it's greater
than 40.
\begin{listing}
\inputminted[label={is\_asian\_US\_manufacturing\_40M},firstline=16,lastline=16]{prolog}{Assign4.pl}
\caption{Rule to determine if an employee is a 40 or older Asian
male working in manufacturing in the US.}
\label{lst:rule4}
\end{listing}
\subsection{Rule Five}
This rule is given an employee ID, and should print a greeting for that
employee. The source code is displayed in \lstref{rule5}. I looked in
the SWI-Prolog documentation to figure out how to format a string, and I
found the \texttt{format/2} predicate. It basically uses the ~ symbol to
define placeholders. Then, using the \texttt{person} predicate to get
the data from the employee ID and outputting it with \texttt{format/2}
was pretty easy.
\begin{listing}
\inputminted[label={greet},firstline=19,lastline=19]{prolog}{Assign4.pl}
\caption{Rule to greet an employee from their ID.}
\label{lst:rule5}
\end{listing}
\subsection{Rule Six}
This rule calculates an employee's number of years until retirement. The
retirement age is given as 65. This was fairly simple, I had to use the
\texttt{is} operator to calculate a value and unify it with the
predicate's argument. The source code is displayed in \lstref{rule6}.
\begin{listing}
\inputminted[label={years\_until\_retirement},firstline=21,lastline=21]{prolog}{Assign4.pl}
\caption{Rule to determine an employee's years until retirement.}
\label{lst:rule6}
\end{listing}
\subsection{Rule Seven}
This rule is similar to the previous ones, but now I define two
conditions on the age, using the less than and greater than operators.
Prolog is interesting in this regard because it has the order of the
symbols swapped from what it usually is. Something to remember for sure.
The source code is displayed in \lstref{rule7}.
\begin{listing}
\inputminted[label={is\_rd\_black\_midAge},firstline=23,lastline=23]{prolog}{Assign4.pl}
\caption{Rule to determine if an employee is middle-aged, black, and
in research and development.}
\label{lst:rule7}
\end{listing}
\subsection{Rule Eight}
This rule introduced me to the semicolon operator, and how to use it to
make more complicated rules. Basically, the semicolon operator tells
Prolog to backtrack and try other possibilities if one of the dependent
propositions is false. I can wrap stuff in parentheses and use the
semicolon to define ``or''-like statements. The source code is displayed in
\lstref{rule8}.
\begin{listing}
\inputminted[label={is\_ITorFin\_PHXorMIAorAUS},firstline=25,lastline=27]{prolog}{Assign4.pl}
\caption{Rule to determine if an employee is in IT or finance, and
in Phoenix or Miami or Austin.}
\label{lst:rule8}
\end{listing}
\subsection{Rule Nine}
This rule introduced me to the \texttt{atom\_concat} predicate. It was
really interesting to learn that in Prolog, predicates like these can
work in different ways based on which variable needs to be unified.
Thus, even though the predicate is called \texttt{concat}, it can also
split. That's what I did here to remove the `Sr.' from the employee's
title. The predicate is only true (can be unified) when the title starts
with Sr. The source code is displayed in \lstref{rule9}.
\begin{listing}
\inputminted[label={is\_female\_senior\_role},firstline=29,lastline=29]{prolog}{Assign4.pl}
\caption{Rule to determine if an employee is both female and in a
senior role.}
\label{lst:rule9}
\end{listing}
\subsection{Rule Ten}
For this rule, I had to create a helper predicate
\texttt{convert\_salary/2}, which is shown in \lstref{convertsalary}.
Now, I had to write predicates that reasoned with numbers instead of
just atom equality. The source code is shown in \lstref{rule10}. This
can be done with typical symbols like less than, greater than. I also
have to write code to convert the string representation of the salary
into a number; this was done by first removing the dollar sign, then
removing the comma and parsing it into a number. The SWI Prolog
documentation helped here.
\begin{listing}
\inputminted[label={convert\_salary},firstline=33,lastline=39]{prolog}{Assign4.pl}
\caption{Rule to convert a salary string to a number.}
\label{lst:convertsalary}
\end{listing}
\begin{listing}
\inputminted[label={is\_highly\_paid\_senior\_manager},firstline=41,lastline=43]{prolog}{Assign4.pl}
\caption{Rule to determine if an employee is a highly paid senior
manager.}
\label{lst:rule10}
\end{listing}
\subsection{Rule Eleven}
This rule determines if an employee has an age that's prime. This one
was difficult. I thought I could use an algorithm similar to Haskell,
but that was a generator. I ended up using a naive recursive algorithm
that checks if all the numbers less than the age do NOT divide the age.
Probably inefficient, but it works. The source code is shown in
\lstref{rule11}.
\begin{listing}
\inputminted[label={is\_prime\_age},firstline=45,lastline=59]{prolog}{Assign4.pl}
\caption{Rule to determine if an employee has a prime age.}
\label{lst:rule11}
\end{listing}
\subsection{Rule Twelve}
This rule calculates an employee's salary after bonuses, but before
taxes. Now that I wrote \texttt{convert\_salary/2}, this predicate has a
fairly simple and easy to read implementation. It is displayed in
\lstref{rule12}.
\begin{listing}
\inputminted[label={total\_salary},firstline=62,lastline=64]{prolog}{Assign4.pl}
\caption{Rule to determine an employee's total salary.}
\label{lst:rule12}
\end{listing}
\subsection{Rule Thirteen}
Now, this rule calculates the take-home salary of an employee. This is
done by using a tax bracketed system based on the employee's total
salary. Again, I had to use the semicolon to provide backtracking and
alternatives for Prolog, which worked as a conditional to set the tax
level. The code is displayed in \lstref{rule13}.
\begin{listing}
\inputminted[label={takehome\_salary},firstline=66,lastline=77]{prolog}{Assign4.pl}
\caption{Rule to determine an employee's take-home salary.}
\label{lst:rule13}
\end{listing}
\subsection{Rule Fourteen}
This was a pretty complicated predicate to write, but it was fun. The
source code is displayed in \lstref{rule14}. I used the SWI-Prolog
documentation to figure out how to use the date-time objects and
predicates. One of the difficult parts is the strange date format in the
CSV, which I had to parse using \texttt{split\_string/4} and some pattern
matching. Then, I had to convert the short year number into a year in
the 20th or 21st century.
\begin{listing}
\inputminted[label={total\_years},firstline=79,lastline=94]{prolog}{Assign4.pl}
\caption{Rule to determine an employee's years of service.}
\label{lst:rule14}
\end{listing}
\subsection{Rule Fifteen}
Finally, I had to write a rule to determine the average salary for an
entire job title. The source code is displayed in \lstref{rule15}.
Using the ways of Prolog backtracking, this actually
wasn't too bad. Essentially, I wrote a predicate that simply gets the
salary for a specific person with a title. There are many ways to unify
the Salary variable that make the predicate true. Then, I use the Prolog
\texttt{bagof/3} predicate to collect every possible value that
satisfies the predicate into a list. Then, getting the average is easy.
\begin{listing}
\inputminted[label={average\_salary},firstline=97,lastline=102]{prolog}{Assign4.pl}
\caption{Rule to determine the average salary for a job title.}
\label{lst:rule15}
\end{listing}
\end{document}

11
Week12/knowledge.pl Normal file
View File

@ -0,0 +1,11 @@
parent(john, mary).
parent(john, tom).
parent(mary, lisa).
parent(tom, jerry).
male(john).
male(tom).
male(jerry).
female(mary).
female(lisa).

18
Week12/lecture1.pl Normal file
View File

@ -0,0 +1,18 @@
eats(elephant, shrub).
eats(tiger, deer).
eats(lion, zebra).
eats(panda, bamboo).
eats(cow, grass).
plant(shrub).
plant(bamboo).
plant(grass).
meat(deer).
meat(zebra).
herbivore(X) :- eats(X, Y), plant(Y).
carnivore(X) :- eats(X, Y), meat(Y).

6
Week13/lecture.pl Normal file
View File

@ -0,0 +1,6 @@
take(0, _, []).
take(_, [], []).
take(Count, [F|Rest], List) :- Next is Count-1, List = [F | Part], take(Next, Rest, Part).
member(X, [C|Rest]) :- X = C; member(X, Rest).

View File

@ -6,4 +6,3 @@ fibs :: [Int]
-- F_n+2 = 1 + sum(F_1 .. F_n)
fibs = 1 : scanl (+) 1 fibs

96
Week9/lecture1.hs Normal file
View File

@ -0,0 +1,96 @@
import System.IO
import Data.List( delete )
-- A definition for zipWith:
zipWith' :: (a->b->c) -> [a] -> [b] -> [c]
zipWith' f (x:xs) (y:ys) = f x y : zipWith' (f) xs ys
zipWith' _ _ _ = []
-- Solution for fibs:
-- 0 1 2 3 5 8
-- 1 2 3 5 8
-- ^ one off, so we zipWith (+) with the list and the tail half of the
-- list.
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
-- An example of an impure IO function.
act :: IO (Char, Char)
act = do x <- getChar
getChar
y <- getChar
return (x,y)
-- How to get a line
getLine' :: IO String
getLine' = do x <- getChar
if x == '\n' then
return []
else
do xs <- getLine'
return (x:xs)
-- How to put a String
putStr' :: String -> IO ()
putStr' [] = return ()
putStr' (x:xs) = do putChar x
putStr' xs
putStrLn' :: String -> IO ()
putStrLn' xs = do putStr' xs
putChar '\n'
-- Now, an example of an interactive program
strlen :: IO ()
strlen = do putStr "Enter a string: "
xs <- getLine
putStr "The string has "
putStr (show (length xs))
putStrLn " characters."
-- how to do a hangman game?
getCh :: IO Char
getCh = do hSetEcho stdin False
x <- getChar
hSetEcho stdin True
return x
sgetLine :: IO String
sgetLine = do x <- getCh
if x == '\n' then
do putChar x
return []
else
do putChar '-'
xs <- sgetLine
return (x:xs)
replace xs i r =
match :: String -> String -> String
match _ [] = []
match word@(w:ws) (x:xs) = if w == x then '!' : match ws xs
else if elem x word then
'?' : match (delete x word) xs
else '-' : match word xs
--match word guess = [if g == w then '!' else if elem g word then '?' else '-' | (w,g) <- zip word guess]
play :: String -> Int -> IO ()
play word 0 = do putStr "Out of guesses... The word was "
putStrLn word
play word guesses = do putStr "? "
guess <- getLine
if guess == word then
putStrLn "You got it!"
else
do putStrLn (match word guess)
play word (guesses - 1)
hangman :: IO ()
hangman = do putStr "Think of a word: "
word <- sgetLine
putStrLn "Try to guess it:"
play word 6

8
Week9/week9.hs Normal file
View File

@ -0,0 +1,8 @@
-- Backtracking
minCost :: [Int] -> Int
minCost [] = 0
minCost (_:[]) = 0
minCost (x:y:xs) = min x y + minCost xs

5
haskell/tree.hs Normal file
View File

@ -0,0 +1,5 @@
data Tree a = Leaf | Branch a (Tree a) (Tree a)
leftside :: Tree a -> a
leftside (Branch x Leaf _) = x
leftside (Branch _ a _) = leftside a