pushing what I hace currently.
This commit is contained in:
parent
52fcda3b1a
commit
46d724dd9d
16 changed files with 11383 additions and 0 deletions
BIN
hw1/.hw1pr1.cpp.swp
Normal file
BIN
hw1/.hw1pr1.cpp.swp
Normal file
Binary file not shown.
5000
hw1/.hw1pr2_data.txt
Normal file
5000
hw1/.hw1pr2_data.txt
Normal file
File diff suppressed because it is too large
Load diff
133
hw1/420hw1-17fall.txt
Normal file
133
hw1/420hw1-17fall.txt
Normal file
|
@ -0,0 +1,133 @@
|
|||
(Print this page as a cover sheet for your printouts)
|
||||
|
||||
CSCE 420 HOMEWORK 1 (UPDATED)
|
||||
Dr. Daugherity
|
||||
Section: ______________
|
||||
Due: 11:59 P.M. Monday, October 2, 2017
|
||||
|
||||
"On my honor, as an Aggie, I have neither given nor received any unauthorized
|
||||
aid on any portion of the academic work included in this assignment."
|
||||
|
||||
|
||||
________________________________ ________________________________
|
||||
Typed or printed name of student Signature of student
|
||||
|
||||
NOTE: Please follow your lab instructor's directions for submitting your
|
||||
assignment through CSNET. ONLY ASSIGNMENTS SUBMITTED TO CSNET WILL BE GRADED!
|
||||
Make a printout of each source file and staple it behind this cover sheet.
|
||||
Sign it and turn it in in class Tuesday. IF YOU DO NOT TURN IN A SIGNED COVER
|
||||
SHEET YOUR WORK WILL NOT BE GRADED!
|
||||
|
||||
NOTE: Homework will be graded on build.tamu.edu, using g++ 7.2.0 with
|
||||
-std=c++17, or javac and java, or python3.6 (not python or python2 or python3).
|
||||
|
||||
You are free to develop your programs on any other platform, but it is your
|
||||
responsibility to make sure your programs also compile and execute correctly on
|
||||
build.tamu.edu as specified.
|
||||
|
||||
NOTE: Each file submitted (hw1pr1.cpp, etc.--see below) must begin as follows:
|
||||
//Your name and UIN
|
||||
//CSCE 420
|
||||
//Due: Ocotber 2, 2017
|
||||
//hw1pr1.cpp (or whatever this file name is)
|
||||
|
||||
NOTE: Also write a README.txt file with whatever information is needed to
|
||||
compile and run your programs. Zip the README.txt and the homework files into
|
||||
a single file named hw1.zip and submit to CSNET.
|
||||
|
||||
The grade for this lab will be based on style (formatting, variable names,
|
||||
comments, etc.), syntax (no compilation or link errors), and correctness
|
||||
(passes all test cases). Your grade for this lab is:
|
||||
Problem # 1 2 3 4
|
||||
Style /2 /4 /4 /2
|
||||
Syntax /3 /6 /6 /3
|
||||
Correctness /5 /10 /10 /5
|
||||
-------------------------------------------------------------------
|
||||
Total /10 /20 /20 /10
|
||||
Grand total _____/50
|
||||
|
||||
1. (10 points) Given a file containing a list of points (x,y) in the plane,
|
||||
write a greedy best-first search to find a closed path connecting all the
|
||||
points (the "Travelling Salesperson Problem") and output its length. You may
|
||||
assume that x and y are non-negative integers that will fit in a 32-bit int.
|
||||
Each line of input will be the x and y coordinates for a point; keep reading
|
||||
until EOF. You may assume there will be no more than 10000 points and that
|
||||
the input file will be named hw1pr1_data.txt.
|
||||
|
||||
For example, if the input file contains
|
||||
0 0
|
||||
0 1
|
||||
1 1
|
||||
1 2
|
||||
|
||||
the output to the screen is (probably)
|
||||
0 0
|
||||
0 1
|
||||
1 1
|
||||
1 2
|
||||
5.236
|
||||
|
||||
The run time should be 60 seconds or less for up to 10000 points. Hint: use
|
||||
the UNIX timeout command to automatically stop execution after 60 seconds.
|
||||
Name your program hw1pr1.cpp or Hw1Pr1.java or hw1pr1.py.
|
||||
|
||||
2. (20 points) The shortest closed path for the example points in problem 1 is
|
||||
actually 4.828. In other words, greeedy best-first search did not find the
|
||||
shortest path. Modify your program for problem 1 to do an iterative deepening
|
||||
search to the depth of the number of points, with the path cost the total
|
||||
distance. To keep the search space manageable only include the 4 nearest
|
||||
unvisited points as successors when you expand a node.
|
||||
|
||||
The run time should be 60 seconds or less for up to 10000 points. Hint: use
|
||||
the UNIX timeout command to automatically stop execution after 60 seconds.
|
||||
Name your program hw1pr2.cpp or Hw1Pr2.java or hw1pr2.py.
|
||||
|
||||
3. (20 points) Write a breadth-first search program to solve 15-puzzle problems
|
||||
in the same way as the 8-puzzle in Figure 3.4 on page 71. Keep track of the
|
||||
number of nodes expanded and print that out along with the steps to solve the
|
||||
problem. Define the legal moves as "swap the blank with an adjacent tile,"
|
||||
resulting in the blank's moving up, down, left, or right. A sample run should
|
||||
look like this:
|
||||
|
||||
Enter 15-puzzle starting state by rows (0 for blank):
|
||||
1,2,3,4,5,6,7,8,9,10,0,11,13,14,15,12
|
||||
Enter ending state by rows (0 for blank):
|
||||
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0
|
||||
Solution:
|
||||
Start 1 2 3 4
|
||||
5 6 7 8
|
||||
9 10 0 11
|
||||
13 14 15 12
|
||||
Swap the blank
|
||||
Right 1 2 3 4
|
||||
5 6 7 8
|
||||
9 10 11 0
|
||||
13 14 15 12
|
||||
|
||||
Down 1 2 3 4
|
||||
5 6 7 8
|
||||
9 10 11 12
|
||||
13 14 15 0
|
||||
|
||||
Done! Generated xx states.
|
||||
|
||||
Note: To keep the time and memory requirements reasonable, your program only
|
||||
needs to solve 15-puzzle problems which have a solution in 10 moves or less.
|
||||
Name your program Hw1Pr3.java or hw1pr3.cpp or hw1pr3.py.
|
||||
|
||||
OPTIONAL EXTRA CREDIT
|
||||
=====================
|
||||
4. (10 points) Modify problem 3 to use A* or IDA* search with Manhattan
|
||||
distance for h; e.g., the starting state on page 103 has a Manhattan distance
|
||||
of 18 from the goal state (the sum of the number of rows and columns each tile
|
||||
must move from its starting position to its ending position). You should see
|
||||
a marked reduction in the number of states generated, especially for problems
|
||||
which require more moves. Here is a puzzle which requires 80 moves:
|
||||
|
||||
Enter 15-puzzle starting state by rows (0 for blank):
|
||||
0,12,11,13,15,14,10,9,3,7,6,2,4,8,5,1
|
||||
Enter ending state by rows (0 for blank):
|
||||
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0
|
||||
|
||||
Your program should solve it in 60 seconds or less. Name your program
|
||||
Hw1Pr4.java or hw1pr4.cpp or hw1pr4.py.
|
15
hw1/README.txt
Normal file
15
hw1/README.txt
Normal file
|
@ -0,0 +1,15 @@
|
|||
reference for async pthreads: http://www.cplusplus.com/reference/future/future/wait_for/
|
||||
|
||||
All other references used pretty much came from cplusplus.com
|
||||
|
||||
To compile and run:
|
||||
|
||||
I made a makefile that should compile the program regardless of the OS, but only tested linux.
|
||||
|
||||
commands should be:
|
||||
|
||||
compile: make, make clean
|
||||
|
||||
run: ./hw1prX
|
||||
|
||||
where X is the problem number.
|
BIN
hw1/hw1.zip
Normal file
BIN
hw1/hw1.zip
Normal file
Binary file not shown.
225
hw1/hw1pr1/hw1pr1.cpp
Normal file
225
hw1/hw1pr1/hw1pr1.cpp
Normal file
|
@ -0,0 +1,225 @@
|
|||
// Alexander Huddleston
|
||||
// 10/2/17
|
||||
// hw1pr1.cpp
|
||||
// Read a file of points, compute greedy best-first of a closed path between points.
|
||||
|
||||
#include<stdio.h>
|
||||
#include<iostream>
|
||||
#include<fstream>
|
||||
#include<cmath>
|
||||
#include<future>
|
||||
#include<chrono>
|
||||
#include<vector>
|
||||
#include<climits>
|
||||
#include<unordered_set>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Double vector used to store list of squared distances between points.
|
||||
vector<vector<long int>> dmat;
|
||||
|
||||
vector<tuple<int, int>> points;
|
||||
|
||||
unordered_set<long int> relaxed_edges;
|
||||
|
||||
void store_points(ifstream *input, string filename)
|
||||
{
|
||||
input->open(filename);
|
||||
|
||||
string line = "";
|
||||
|
||||
string token = "";
|
||||
|
||||
tuple<int, int> temp_point;
|
||||
get<0>(temp_point) = 0.0;
|
||||
get<1>(temp_point) = 0.0;
|
||||
|
||||
while(getline(*input, line))
|
||||
{
|
||||
for(char c : line)
|
||||
{
|
||||
if(c == ' ')
|
||||
{
|
||||
get<0>(temp_point) = stof(token);
|
||||
token = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
token = token + c;
|
||||
}
|
||||
}
|
||||
|
||||
get<1>(temp_point) = stof(token);
|
||||
|
||||
token = "";
|
||||
|
||||
points.push_back(temp_point);
|
||||
}
|
||||
|
||||
input->close();
|
||||
}
|
||||
|
||||
void store_distances()
|
||||
{
|
||||
long int d1 = 0.0;
|
||||
long int d2 = 0.0;
|
||||
|
||||
tuple< int, int> x;
|
||||
tuple< int, int> y;
|
||||
get<0>(x) = 0.0;
|
||||
get<1>(x) = 0.0;
|
||||
get<0>(y) = 0.0;
|
||||
get<1>(y) = 0.0;
|
||||
|
||||
vector<long int> tempvec;
|
||||
|
||||
for(int r = points.size() - 1; r >= 0; --r)
|
||||
{
|
||||
for(int c = 0; c < points.size() - (points.size() - r); ++c)
|
||||
{
|
||||
x = points.at(r);
|
||||
y = points.at(c);
|
||||
|
||||
d1 = (get<0>(x) - get<0>(y));
|
||||
d2 = (get<1>(x) - get<1>(y));
|
||||
|
||||
tempvec.push_back(d1*d1 + d2*d2);
|
||||
}
|
||||
|
||||
dmat.push_back(tempvec);
|
||||
tempvec.clear();
|
||||
}
|
||||
}
|
||||
|
||||
bool is_visited(vector<int> relaxed_edges, int index)
|
||||
{
|
||||
for(int x : relaxed_edges)
|
||||
{
|
||||
if(x == index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
long double best_first(ifstream *input, string filename)
|
||||
{
|
||||
// First, store the points from the file into global vector.
|
||||
store_points(input, filename);
|
||||
|
||||
// Small optomization so we don't have to call points.size() so much.
|
||||
long int n = points.size();
|
||||
|
||||
// Store squared distances into dmat.
|
||||
// Ignore duplicate distances, 0 vectors.
|
||||
store_distances();
|
||||
|
||||
// Find best-first shortest path.
|
||||
|
||||
// Keep edges we've already visited.
|
||||
|
||||
// Store distance up to this point.
|
||||
long double current_distance = 0;
|
||||
|
||||
// Using this to keep track of selected node.
|
||||
long int current_node = 0;
|
||||
|
||||
long int selected_node = 0;
|
||||
|
||||
// Using this to keep track of min distance.
|
||||
long int min_distance = 0;
|
||||
|
||||
while(relaxed_edges.size() < (n - 1))
|
||||
{
|
||||
min_distance = INT_MAX;
|
||||
for(int i = 0; i < (n - 1); ++i)
|
||||
{
|
||||
while(relaxed_edges.find(i) != relaxed_edges.end())
|
||||
{
|
||||
++i;
|
||||
if(i == current_node)
|
||||
{
|
||||
++i;
|
||||
}
|
||||
}
|
||||
if(i > (n - 1))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(i < current_node)
|
||||
{
|
||||
if(min_distance > dmat.at(i).at((n - 1) - current_node))
|
||||
{
|
||||
selected_node = ((n - 1) - i);
|
||||
min_distance = dmat.at(i).at((n - 1) - current_node);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(i == current_node)
|
||||
{
|
||||
++i;
|
||||
if(i > (n - 1))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(min_distance > dmat.at(current_node).at((n - 1) - i))
|
||||
{
|
||||
selected_node = ((n - 1) - i);
|
||||
min_distance = dmat.at(current_node).at((n - 1) - i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
relaxed_edges.insert((n - 1) - current_node);
|
||||
current_node = selected_node;
|
||||
current_distance += sqrt(min_distance);
|
||||
}
|
||||
|
||||
current_distance += sqrt(dmat.at(current_node).at(0));
|
||||
return current_distance;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
ifstream input;
|
||||
|
||||
string filename = "hw1pr1_data.txt";
|
||||
|
||||
future<long double> fut = async(best_first, &input, filename);
|
||||
|
||||
chrono::milliseconds span(60000);
|
||||
|
||||
while((fut.wait_for(span)==future_status::timeout) || input.is_open())
|
||||
{
|
||||
}
|
||||
|
||||
if(input.is_open())
|
||||
{
|
||||
input.close();
|
||||
}
|
||||
|
||||
long double total = fut.get();
|
||||
|
||||
tuple<int, int> tempx;
|
||||
tuple<int, int> tempy;
|
||||
|
||||
long int temp;
|
||||
|
||||
for(long int i : relaxed_edges)
|
||||
{
|
||||
tempx = points.at(temp);
|
||||
tempy = points.at(i);
|
||||
cout << get<0>(tempx) << "\t" << get<1>(tempx) << "\t" << get<0>(tempy) << "\t" << get<1>(tempy) << endl;
|
||||
temp = i;
|
||||
}
|
||||
|
||||
cout << total << endl;
|
||||
|
||||
return 0;
|
||||
}
|
5000
hw1/hw1pr1/hw1pr1_data.txt
Normal file
5000
hw1/hw1pr1/hw1pr1_data.txt
Normal file
File diff suppressed because it is too large
Load diff
5
hw1/hw1pr1/makefile
Normal file
5
hw1/hw1pr1/makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
all: main.o
|
||||
main.o: hw1pr1.cpp
|
||||
g++ -std=c++17 -lpthread hw1pr1.cpp -o hw1pr1
|
||||
clean:
|
||||
rm -rf *.o hw1pr1
|
225
hw1/hw1pr2.cpp
Normal file
225
hw1/hw1pr2.cpp
Normal file
|
@ -0,0 +1,225 @@
|
|||
// Alexander Huddleston
|
||||
// 10/2/17
|
||||
// hw1pr2.cpp
|
||||
// Read a file of points, compute interative best-first of a closed path between points.
|
||||
|
||||
#include<stdio.h>
|
||||
#include<iostream>
|
||||
#include<fstream>
|
||||
#include<cmath>
|
||||
#include<future>
|
||||
#include<chrono>
|
||||
#include<vector>
|
||||
#include<climits>
|
||||
#include<unordered_set>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Double vector used to store list of squared distances between points.
|
||||
vector<vector<long int>> dmat;
|
||||
|
||||
vector<tuple<int, int>> points;
|
||||
|
||||
unordered_set<long int> relaxed_edges;
|
||||
|
||||
void store_points(ifstream *input, string filename)
|
||||
{
|
||||
input->open(filename);
|
||||
|
||||
string line = "";
|
||||
|
||||
string token = "";
|
||||
|
||||
tuple<int, int> temp_point;
|
||||
get<0>(temp_point) = 0.0;
|
||||
get<1>(temp_point) = 0.0;
|
||||
|
||||
while(getline(*input, line))
|
||||
{
|
||||
for(char c : line)
|
||||
{
|
||||
if(c == ' ')
|
||||
{
|
||||
get<0>(temp_point) = stof(token);
|
||||
token = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
token = token + c;
|
||||
}
|
||||
}
|
||||
|
||||
get<1>(temp_point) = stof(token);
|
||||
|
||||
token = "";
|
||||
|
||||
points.push_back(temp_point);
|
||||
}
|
||||
|
||||
input->close();
|
||||
}
|
||||
|
||||
void store_distances()
|
||||
{
|
||||
long int d1 = 0.0;
|
||||
long int d2 = 0.0;
|
||||
|
||||
tuple< int, int> x;
|
||||
tuple< int, int> y;
|
||||
get<0>(x) = 0.0;
|
||||
get<1>(x) = 0.0;
|
||||
get<0>(y) = 0.0;
|
||||
get<1>(y) = 0.0;
|
||||
|
||||
vector<long int> tempvec;
|
||||
|
||||
for(int r = points.size() - 1; r >= 0; --r)
|
||||
{
|
||||
for(int c = 0; c < points.size() - (points.size() - r); ++c)
|
||||
{
|
||||
x = points.at(r);
|
||||
y = points.at(c);
|
||||
|
||||
d1 = (get<0>(x) - get<0>(y));
|
||||
d2 = (get<1>(x) - get<1>(y));
|
||||
|
||||
tempvec.push_back(d1*d1 + d2*d2);
|
||||
}
|
||||
|
||||
dmat.push_back(tempvec);
|
||||
tempvec.clear();
|
||||
}
|
||||
}
|
||||
|
||||
bool is_visited(vector<int> relaxed_edges, int index)
|
||||
{
|
||||
for(int x : relaxed_edges)
|
||||
{
|
||||
if(x == index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
long double best_first(ifstream *input, string filename)
|
||||
{
|
||||
// First, store the points from the file into global vector.
|
||||
store_points(input, filename);
|
||||
|
||||
// Small optomization so we don't have to call points.size() so much.
|
||||
long int n = points.size();
|
||||
|
||||
// Store squared distances into dmat.
|
||||
// Ignore duplicate distances, 0 vectors.
|
||||
store_distances();
|
||||
|
||||
// Find best-first shortest path.
|
||||
|
||||
// Keep edges we've already visited.
|
||||
|
||||
// Store distance up to this point.
|
||||
long double current_distance = 0;
|
||||
|
||||
// Using this to keep track of selected node.
|
||||
long int current_node = 0;
|
||||
|
||||
long int selected_node = 0;
|
||||
|
||||
// Using this to keep track of min distance.
|
||||
long int min_distance = 0;
|
||||
|
||||
while(relaxed_edges.size() < (n - 1))
|
||||
{
|
||||
min_distance = INT_MAX;
|
||||
for(int i = 0; i < (n - 1); ++i)
|
||||
{
|
||||
while(relaxed_edges.find(i) != relaxed_edges.end())
|
||||
{
|
||||
++i;
|
||||
if(i == current_node)
|
||||
{
|
||||
++i;
|
||||
}
|
||||
}
|
||||
if(i > (n - 1))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(i < current_node)
|
||||
{
|
||||
if(min_distance > dmat.at(i).at((n - 1) - current_node))
|
||||
{
|
||||
selected_node = ((n - 1) - i);
|
||||
min_distance = dmat.at(i).at((n - 1) - current_node);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(i == current_node)
|
||||
{
|
||||
++i;
|
||||
if(i > (n - 1))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(min_distance > dmat.at(current_node).at((n - 1) - i))
|
||||
{
|
||||
selected_node = ((n - 1) - i);
|
||||
min_distance = dmat.at(current_node).at((n - 1) - i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
relaxed_edges.insert((n - 1) - current_node);
|
||||
current_node = selected_node;
|
||||
current_distance += sqrt(min_distance);
|
||||
}
|
||||
|
||||
current_distance += sqrt(dmat.at(current_node).at(0));
|
||||
return current_distance;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
ifstream input;
|
||||
|
||||
string filename = "hw1pr_data.txt";
|
||||
|
||||
future<long double> fut = async(best_first, &input, filename);
|
||||
|
||||
chrono::milliseconds span(60000);
|
||||
|
||||
while((fut.wait_for(span)==future_status::timeout) || input.is_open())
|
||||
{
|
||||
}
|
||||
|
||||
if(input.is_open())
|
||||
{
|
||||
input.close();
|
||||
}
|
||||
|
||||
long double total = fut.get();
|
||||
|
||||
tuple<int, int> tempx;
|
||||
tuple<int, int> tempy;
|
||||
|
||||
long int temp;
|
||||
|
||||
for(long int i : relaxed_edges)
|
||||
{
|
||||
tempx = points.at(temp);
|
||||
tempy = points.at(i);
|
||||
cout << get<0>(tempx) << "\t" << get<1>(tempx) << "\t" << get<0>(tempy) << "\t" << get<1>(tempy) << endl;
|
||||
temp = i;
|
||||
}
|
||||
|
||||
cout << total << endl;
|
||||
|
||||
return 0;
|
||||
}
|
335
hw1/hw1pr2/hw1pr2.cpp
Normal file
335
hw1/hw1pr2/hw1pr2.cpp
Normal file
|
@ -0,0 +1,335 @@
|
|||
// Alexander Huddleston 223000555
|
||||
// CSCE420
|
||||
// Due: October 2, 2017 (changed to 4)
|
||||
// hw1pr2.cpp
|
||||
|
||||
// Purpose: Read a file of points, compute interative best-first of a closed path between points.
|
||||
|
||||
#include<stdio.h>
|
||||
#include<iostream>
|
||||
#include<fstream>
|
||||
#include<cmath>
|
||||
#include<future>
|
||||
#include<chrono>
|
||||
#include<vector>
|
||||
#include<climits>
|
||||
#include<unordered_set>
|
||||
#include<algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Double vector used to store list of squared distances between points.
|
||||
vector<vector<long int>> dmat;
|
||||
|
||||
// Used to store the points from file.
|
||||
vector<tuple<int, int>> points;
|
||||
|
||||
// Used to store the paths each iteration has traveled.
|
||||
vector<unordered_set<long int>> relaxed_edges;
|
||||
|
||||
// Used to store the distance values of the respective paths.
|
||||
vector<long int> shortest_paths;
|
||||
|
||||
void store_points(ifstream *input, string filename)
|
||||
{
|
||||
input->open(filename);
|
||||
|
||||
string line = "";
|
||||
|
||||
string token = "";
|
||||
|
||||
tuple<int, int> temp_point;
|
||||
get<0>(temp_point) = 0.0;
|
||||
get<1>(temp_point) = 0.0;
|
||||
|
||||
while(getline(*input, line))
|
||||
{
|
||||
for(char c : line)
|
||||
{
|
||||
if(c == ' ')
|
||||
{
|
||||
get<0>(temp_point) = stof(token);
|
||||
token = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
token = token + c;
|
||||
}
|
||||
}
|
||||
|
||||
get<1>(temp_point) = stof(token);
|
||||
|
||||
token = "";
|
||||
|
||||
points.push_back(temp_point);
|
||||
}
|
||||
|
||||
input->close();
|
||||
}
|
||||
|
||||
void store_distances()
|
||||
{
|
||||
long int d1 = 0.0;
|
||||
long int d2 = 0.0;
|
||||
|
||||
tuple< int, int> x;
|
||||
tuple< int, int> y;
|
||||
get<0>(x) = 0.0;
|
||||
get<1>(x) = 0.0;
|
||||
get<0>(y) = 0.0;
|
||||
get<1>(y) = 0.0;
|
||||
|
||||
vector<long int> tempvec;
|
||||
|
||||
for(int r = points.size() - 1; r >= 0; --r)
|
||||
{
|
||||
for(int c = 0; c < points.size() - (points.size() - r); ++c)
|
||||
{
|
||||
x = points.at(r);
|
||||
y = points.at(c);
|
||||
|
||||
d1 = (get<0>(x) - get<0>(y));
|
||||
d2 = (get<1>(x) - get<1>(y));
|
||||
|
||||
tempvec.push_back(d1*d1 + d2*d2);
|
||||
}
|
||||
|
||||
dmat.push_back(tempvec);
|
||||
tempvec.clear();
|
||||
}
|
||||
}
|
||||
|
||||
bool tuple_sort(tuple<long int, long int> t1, tuple<long int, long int> t2)
|
||||
{
|
||||
return (get<1>(t1) < get<1>(t2));
|
||||
}
|
||||
|
||||
tuple<vector<int>, long double> iterate_path(int p)
|
||||
{
|
||||
// Find best-first shortest path for this iteration.
|
||||
|
||||
// Small optomization so we don't have to call points.size() so much.
|
||||
long int n = points.size();
|
||||
|
||||
// In this variation, I want to keep track of the 4 closest points to root.
|
||||
vector<int> closest;
|
||||
vector<tuple<long int, long int>> first;
|
||||
long int temp_counter = n - 1;
|
||||
if(dmat.at(p).size() > 0)
|
||||
{
|
||||
for(long int b : dmat.at(p))
|
||||
{
|
||||
|
||||
tuple<long int, long int> t (temp_counter, b);
|
||||
first.push_back(t);
|
||||
--temp_counter;
|
||||
}
|
||||
}
|
||||
for(int a = 0; a < (temp_counter); ++a)
|
||||
{
|
||||
tuple<long int, long int> t ((temp_counter - a), (dmat.at(a).at((n - 1) - p)));
|
||||
first.push_back(t);
|
||||
}
|
||||
sort(first.begin(), first.end(), tuple_sort);
|
||||
|
||||
temp_counter = 0;
|
||||
for(tuple<long int, long int> te : first)
|
||||
{
|
||||
if(temp_counter > 3)
|
||||
{
|
||||
break;
|
||||
}
|
||||
closest.push_back(get<0>(te));
|
||||
++temp_counter;
|
||||
}
|
||||
|
||||
// Store distance up to this point.
|
||||
long double current_distance = 0;
|
||||
|
||||
// Using this to keep track of selected node.
|
||||
long int current_node = 0;
|
||||
|
||||
long int selected_node = 0;
|
||||
|
||||
// Using this to keep track of min distance.
|
||||
long int min_distance = 0;
|
||||
|
||||
while(relaxed_edges.at(p).size() < (n - 1))
|
||||
{
|
||||
min_distance = INT_MAX;
|
||||
for(int i = 0; i < (n - 1); ++i)
|
||||
{
|
||||
while(relaxed_edges.at(p).find(i) != relaxed_edges.at(p).end())
|
||||
{
|
||||
++i;
|
||||
if(i == current_node)
|
||||
{
|
||||
++i;
|
||||
}
|
||||
}
|
||||
if(i > (n - 1))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(i < current_node)
|
||||
{
|
||||
if(min_distance > dmat.at(i).at((n - 1) - current_node))
|
||||
{
|
||||
selected_node = ((n - 1) - i);
|
||||
min_distance = dmat.at(i).at((n - 1) - current_node);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(i == current_node)
|
||||
{
|
||||
++i;
|
||||
if(i > (n - 1))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(min_distance > dmat.at(current_node).at((n - 1) - i))
|
||||
{
|
||||
selected_node = ((n - 1) - i);
|
||||
min_distance = dmat.at(current_node).at((n - 1) - i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
relaxed_edges.at(p).insert((n - 1) - current_node);
|
||||
current_node = selected_node;
|
||||
current_distance += sqrt(min_distance);
|
||||
}
|
||||
|
||||
current_distance += sqrt(dmat.at(current_node).at(0));
|
||||
|
||||
tuple<vector<int>, long double> output;
|
||||
|
||||
get<0>(output) = closest;
|
||||
get<1>(output) = current_distance;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
long double best_first(ifstream *input, string filename)
|
||||
{
|
||||
// First, store the points from the file into global vector.
|
||||
store_points(input, filename);
|
||||
|
||||
// Store squared distances into dmat.
|
||||
// Ignore duplicate distances, 0 vectors.
|
||||
store_distances();
|
||||
|
||||
// This is how we know depth.
|
||||
long int depth = 1;
|
||||
|
||||
// Which node iteration are we on?
|
||||
int n = 0;
|
||||
|
||||
unordered_set<long int> empty;
|
||||
relaxed_edges.push_back(empty);
|
||||
|
||||
while(depth < points.size() - 1)
|
||||
{
|
||||
// Find shortest path with given path.
|
||||
tuple<vector<int>, long double> ip = iterate_path(n);
|
||||
shortest_paths.push_back(get<1>(ip));
|
||||
vector<int> closest = get<0>(ip);
|
||||
|
||||
unordered_set<long int> one;
|
||||
unordered_set<long int> two;
|
||||
unordered_set<long int> three;
|
||||
unordered_set<long int> four;
|
||||
|
||||
long int temp = 0;
|
||||
|
||||
for(long int i : relaxed_edges.at(n))
|
||||
{
|
||||
++temp;
|
||||
one.insert(i);
|
||||
two.insert(i);
|
||||
three.insert(i);
|
||||
four.insert(i);
|
||||
if(temp == depth)
|
||||
{
|
||||
if(closest.size() > 0)
|
||||
{
|
||||
one.insert(closest.at(0));
|
||||
}
|
||||
if(closest.size() > 1)
|
||||
{
|
||||
two.insert(closest.at(1));
|
||||
}
|
||||
if(closest.size() > 2)
|
||||
{
|
||||
three.insert(closest.at(2));
|
||||
}
|
||||
if(closest.size() > 3)
|
||||
{
|
||||
four.insert(closest.at(3));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
relaxed_edges.push_back(one);
|
||||
relaxed_edges.push_back(two);
|
||||
relaxed_edges.push_back(three);
|
||||
relaxed_edges.push_back(four);
|
||||
|
||||
if(n <= 1)
|
||||
{
|
||||
depth = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
depth = 2 + ((int)(log(n + 1)/log(4)));
|
||||
}
|
||||
|
||||
++n;
|
||||
}
|
||||
|
||||
return shortest_paths.at(0);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
ifstream input;
|
||||
|
||||
string filename = "hw1pr2_data.txt";
|
||||
|
||||
future<long double> fut = async(best_first, &input, filename);
|
||||
|
||||
chrono::milliseconds span(60000);
|
||||
|
||||
while((fut.wait_for(span)==future_status::timeout) || input.is_open())
|
||||
{
|
||||
}
|
||||
|
||||
if(input.is_open())
|
||||
{
|
||||
input.close();
|
||||
}
|
||||
|
||||
long double total = fut.get();
|
||||
|
||||
tuple<int, int> tempx;
|
||||
tuple<int, int> tempy;
|
||||
|
||||
long int temp = 0;
|
||||
|
||||
// Change 0 to shortest path.
|
||||
for(long int i : relaxed_edges.at(0))
|
||||
{
|
||||
tempx = points.at(temp);
|
||||
tempy = points.at(i);
|
||||
cout << get<0>(tempx) << "\t" << get<1>(tempx) << "\t" << get<0>(tempy) << "\t" << get<1>(tempy) << endl;
|
||||
temp = i;
|
||||
}
|
||||
|
||||
cout << total << endl;
|
||||
|
||||
return 0;
|
||||
}
|
4
hw1/hw1pr2/hw1pr2_data.txt
Normal file
4
hw1/hw1pr2/hw1pr2_data.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
0 0
|
||||
0 1
|
||||
1 1
|
||||
1 2
|
5
hw1/hw1pr2/makefile
Normal file
5
hw1/hw1pr2/makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
all: main.o
|
||||
main.o: hw1pr2.cpp
|
||||
g++ -std=c++17 -lpthread hw1pr2.cpp -o hw1pr2
|
||||
clean:
|
||||
rm -rf *.o hw1pr2
|
4
hw1/hw1pr2_data.txt
Normal file
4
hw1/hw1pr2_data.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
0 0
|
||||
0 1
|
||||
1 1
|
||||
1 2
|
317
hw1/hw1pr3/hw1pr3.cpp
Normal file
317
hw1/hw1pr3/hw1pr3.cpp
Normal file
|
@ -0,0 +1,317 @@
|
|||
// Alexander Huddleston 223000555
|
||||
// CSCE420
|
||||
// Due: October 2, 2017 (changed to 4)
|
||||
// hw1pr3.cpp
|
||||
|
||||
// Purpose: A breadth-first search program solving a 15-puzzle problem.
|
||||
|
||||
#include<iostream>
|
||||
#include<vector>
|
||||
#include<queue>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// I could move this into a separate header file, due to time
|
||||
// constrains I am keeping it in main for now.
|
||||
class GameBoard
|
||||
{
|
||||
private:
|
||||
// A string representing the state of the board.
|
||||
string state = "";
|
||||
// Which index the blank tile is at.
|
||||
int blank = 0;
|
||||
// List of game moves so far.
|
||||
vector<string> moves;
|
||||
public:
|
||||
// Should only be used at the beginning to set initial state.
|
||||
void setBoardState(string s)
|
||||
{
|
||||
state = s;
|
||||
blank = s.find('a');
|
||||
}
|
||||
// Return the current board state.
|
||||
string getBoardState()
|
||||
{
|
||||
return state;
|
||||
}
|
||||
// Return the vector of move strings.
|
||||
vector<string> getMoves()
|
||||
{
|
||||
return moves;
|
||||
}
|
||||
// Change board state, make move. Not necessarily in that order.
|
||||
void swap(char c)
|
||||
{
|
||||
char temp = 'p';
|
||||
switch(c)
|
||||
{
|
||||
case 'l':
|
||||
temp = state[blank - 1];
|
||||
state[blank - 1] = 'a';
|
||||
state[blank] = temp;
|
||||
blank = --blank;
|
||||
break;
|
||||
case 'r':
|
||||
temp = state[blank + 1];
|
||||
state[blank + 1] = 'a';
|
||||
state[blank] = temp;
|
||||
blank = ++blank;
|
||||
break;
|
||||
case 'u':
|
||||
temp = state[blank - 4];
|
||||
state[blank - 4] = 'a';
|
||||
state[blank] = temp;
|
||||
blank = blank - 4;
|
||||
break;
|
||||
case 'd':
|
||||
temp = state[blank + 4];
|
||||
state[blank + 4] = 'a';
|
||||
state[blank] = temp;
|
||||
blank = blank + 4;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// Debugging
|
||||
//print_move(c, state);
|
||||
moves.push_back(c + state);
|
||||
}
|
||||
// Check if a move is legal.
|
||||
bool isLegal(char c)
|
||||
{
|
||||
if(c == 'l')
|
||||
{
|
||||
return ((blank % 4) > 0);
|
||||
}
|
||||
if(c == 'r')
|
||||
{
|
||||
return ((blank % 4) < 3);
|
||||
}
|
||||
if(c == 'u')
|
||||
{
|
||||
return (blank > 3);
|
||||
}
|
||||
if(c == 'd')
|
||||
{
|
||||
return (blank < 12);
|
||||
}
|
||||
}
|
||||
// Check if we have solved the puzzle
|
||||
bool isSolved(string s)
|
||||
{
|
||||
if(moves.size() > 0)
|
||||
{
|
||||
return !(moves[moves.size() - 1].substr(1).compare(s));
|
||||
}
|
||||
else
|
||||
{
|
||||
return !(state.compare(s));
|
||||
}
|
||||
}
|
||||
// Useful if we want the previous board state back.
|
||||
void resetLastMove()
|
||||
{
|
||||
if(moves.size() > 0)
|
||||
{
|
||||
moves.pop_back();
|
||||
moves.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "Nothing to reset." << endl;
|
||||
}
|
||||
}
|
||||
} gb;
|
||||
|
||||
// Global GameBoard queue.
|
||||
queue<GameBoard> gbq;
|
||||
|
||||
string get_input_game_board()
|
||||
{
|
||||
string input = "";
|
||||
getline(cin, input);
|
||||
string output = "";
|
||||
|
||||
string token = "";
|
||||
|
||||
for(char c : input)
|
||||
{
|
||||
if(c == ',')
|
||||
{
|
||||
output += (char)(stoi(token) + 97);
|
||||
token = "";
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
token += c;
|
||||
}
|
||||
}
|
||||
output += (char)(stoi(token) + 97);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
void print_move(char m, string gb)
|
||||
{
|
||||
string move = "";
|
||||
switch(m)
|
||||
{
|
||||
case 'l':
|
||||
move = "Left";
|
||||
break;
|
||||
case 'r':
|
||||
move = "Right";
|
||||
break;
|
||||
case 'u':
|
||||
move = "Up";
|
||||
break;
|
||||
case 'd':
|
||||
move = "Down";
|
||||
break;
|
||||
default:
|
||||
move = "Start";
|
||||
break;
|
||||
}
|
||||
|
||||
for(int x = 0; x < 16; ++x)
|
||||
{
|
||||
if(x == 0)
|
||||
{
|
||||
cout << "\t" << move << "\t";
|
||||
}
|
||||
else if(x % 4 == 0)
|
||||
{
|
||||
cout << "\n\t\t";
|
||||
}
|
||||
|
||||
if(((int)gb[x]) - 97 < 10)
|
||||
{
|
||||
cout << ((int)gb[x] - 97) << " ";
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << ((int)gb[x] - 97) << " ";
|
||||
}
|
||||
}
|
||||
if(m == 's')
|
||||
{
|
||||
cout << "\nSwap the blank\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
GameBoard solve_game(GameBoard gb, string solved)
|
||||
{
|
||||
gbq.pop();
|
||||
if(gb.isSolved(solved))
|
||||
{
|
||||
return gb;
|
||||
}
|
||||
if(gb.isLegal('l'))
|
||||
{
|
||||
gb.swap('l');
|
||||
gbq.push(gb);
|
||||
if(gb.isSolved(solved))
|
||||
{
|
||||
return gb;
|
||||
}
|
||||
else
|
||||
{
|
||||
gb.swap('r');
|
||||
gb.resetLastMove();
|
||||
}
|
||||
}
|
||||
if(gb.isLegal('r'))
|
||||
{
|
||||
gb.swap('r');
|
||||
gbq.push(gb);
|
||||
if(gb.isSolved(solved))
|
||||
{
|
||||
return gb;
|
||||
}
|
||||
else
|
||||
{
|
||||
gb.swap('l');
|
||||
gb.resetLastMove();
|
||||
}
|
||||
}
|
||||
if(gb.isLegal('u'))
|
||||
{
|
||||
gb.swap('u');
|
||||
gbq.push(gb);
|
||||
if(gb.isSolved(solved))
|
||||
{
|
||||
return gb;
|
||||
}
|
||||
else
|
||||
{
|
||||
gb.swap('d');
|
||||
gb.resetLastMove();
|
||||
}
|
||||
}
|
||||
if(gb.isLegal('d'))
|
||||
{
|
||||
gb.swap('d');
|
||||
gbq.push(gb);
|
||||
if(gb.isSolved(solved))
|
||||
{
|
||||
return gb;
|
||||
}
|
||||
else
|
||||
{
|
||||
gb.swap('u');
|
||||
gb.resetLastMove();
|
||||
}
|
||||
}
|
||||
return solve_game(gbq.front(), solved);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// Initializing with simple test case just in case something goes wrong.
|
||||
string solved = "bcdefghijklmnopa";
|
||||
string init = "bcdefghijkalnopm";
|
||||
|
||||
// Getting input.
|
||||
cout << "Enter 15-puzzle starting state by rows (0 for blank):" << endl;
|
||||
init = get_input_game_board();
|
||||
|
||||
cout << "Enter ending state by rows (0 for blank):" << endl;
|
||||
solved = get_input_game_board();
|
||||
|
||||
// Push starting board into queue, start recursion.
|
||||
gb.setBoardState(init);
|
||||
gbq.push(gb);
|
||||
gb = solve_game(gbq.front(), solved);
|
||||
|
||||
// Print the solution.
|
||||
cout << "Solution:" << endl;
|
||||
print_move('s', init);
|
||||
|
||||
if(gb.getMoves().size() > 0)
|
||||
{
|
||||
for(string m : gb.getMoves())
|
||||
{
|
||||
char c = m[0];
|
||||
string state = m.substr(1);
|
||||
print_move(c, state);
|
||||
}
|
||||
}
|
||||
|
||||
// I added various pieces of code to help the program
|
||||
// if the user decides to put in an already solved puzzle.
|
||||
if(gb.getMoves().size() > 0)
|
||||
{
|
||||
cout << "Done!\tGenerated " << gb.getMoves().size() << " states." << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "You gave me a solved puzzle." << endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
5
hw1/hw1pr3/makefile
Normal file
5
hw1/hw1pr3/makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
all: main.o
|
||||
main.o: hw1pr3.cpp
|
||||
g++ -std=c++17 hw1pr3.cpp -o hw1pr3
|
||||
clean:
|
||||
rm -rf *.o hw1pr3
|
110
hw2/420hw2-17fall.txt
Normal file
110
hw2/420hw2-17fall.txt
Normal file
|
@ -0,0 +1,110 @@
|
|||
(Print this page as a cover sheet for your printouts)
|
||||
|
||||
CSCE 420 HOMEWORK 2
|
||||
Dr. Daugherity
|
||||
Due: 11:59 P.M. Monday, October 30, 2017
|
||||
|
||||
"On my honor, as an Aggie, I have neither given nor received any unauthorized
|
||||
aid on any portion of the academic work included in this assignment."
|
||||
|
||||
|
||||
________________________________ ________________________________
|
||||
Typed or printed name of student Signature of student
|
||||
|
||||
NOTE: Please follow your lab instructor's directions for submitting your
|
||||
assignment through CSNET. ONLY ASSIGNMENTS SUBMITTED TO CSNET WILL BE GRADED!
|
||||
Make a printout of each source file and staple it behind this cover sheet.
|
||||
Sign it and turn it in in class Tuesday. IF YOU DO NOT TURN IN A SIGNED COVER
|
||||
SHEET YOUR WORK WILL NOT BE GRADED!
|
||||
|
||||
NOTE: Homework will be graded on build.tamu.edu, using g++ 7.2.0 with
|
||||
-std=c++17, or javac and java, or python3.
|
||||
|
||||
You are free to develop your programs on any other platform, but it is your
|
||||
responsibility to make sure your programs also compile and execute correctly on
|
||||
build.tamu.edu as specified.
|
||||
|
||||
NOTE: Each file submitted (hw2pr1.cpp, etc.--see below) must begin as follows:
|
||||
//Your name and UIN
|
||||
//CSCE 420
|
||||
//Due: Ocotber 2, 2017
|
||||
//hw2pr1.cpp (or whatever this file name is)
|
||||
|
||||
NOTE: Also write a README.txt file with whatever information is needed to
|
||||
compile and run your programs. Zip the README.txt and the homework files into
|
||||
a single file named hw2.zip and submit to CSNET.
|
||||
|
||||
The grade for this lab will be based on style (formatting, variable names,
|
||||
comments, etc.), syntax (no compilation or link errors), and correctness
|
||||
(passes all test cases). Your grade for this lab is:
|
||||
Problem # 1 2 3 4
|
||||
Style /2 /4 /4 /2
|
||||
Syntax /3 /6 /6 /3
|
||||
Correctness /5 /10 /10 /5
|
||||
-------------------------------------------------------------------
|
||||
Total /10 /20 /20 /10
|
||||
Grand total _____/50
|
||||
|
||||
1. (10 points) Code the mutually-recursive max_value and min_value functions
|
||||
specified in Figure 5.3 and use them to find the max (root's value)
|
||||
of a tree read in from the keyboard as a nested list. For example, the tree in Figure 5.2 would be input as
|
||||
((3,12,8),(2,4,6),(14,5,2))
|
||||
Name your program hw2pr1.cpp, etc.
|
||||
|
||||
2. (20 points) Modify problem 1 to do both alpha and beta pruning according to
|
||||
Figure 5.7 and print a message "alpha pruning" or "beta pruning" each time that
|
||||
occurs (in addition to the max of the tree). For example, the tree
|
||||
((3,8,(7,(3,0,7),(8,8,2))),
|
||||
(4,(7,9,8),8),
|
||||
(((3,6,4),2,6),((9,2,9),4,7,(6,4,5) ),4,(6,4,5))
|
||||
)
|
||||
would print "alpha pruning" 3 times and "beta pruning" 3 times.
|
||||
Name your program hw2pr2.cpp, etc.
|
||||
|
||||
3. (20 points) Write a Horn clause inference engine which accepts a filename
|
||||
from the user, reads Horn clauses from that file, and then makes all possible
|
||||
deductions using forward chaining. The format of the input file will be one
|
||||
Horn clause per line in PROLOG notation (see section 9.4.2). For example, if
|
||||
the data file contains
|
||||
|
||||
B:-A.
|
||||
D:-B,C.
|
||||
A.
|
||||
C.
|
||||
|
||||
then the program will deduce B and D are true. For another test file use
|
||||
Fig. 7.15.
|
||||
|
||||
Name your program hw2pr3.cpp etc. Hint: Fig. 7.14 gives the pseudocode.
|
||||
|
||||
OPTIONAL EXTRA CREDIT
|
||||
=====================
|
||||
4. (10 points) Write a backtracking prover based on the DPLL_satisfiable
|
||||
function in Fig. 7.17 which first reads Horn clauses as in the example from
|
||||
problem 3, then a query preceded by a question mark (that is, what you are
|
||||
asking to be proven).
|
||||
|
||||
B:-A.
|
||||
D:-B,C.
|
||||
A.
|
||||
C.
|
||||
?D
|
||||
|
||||
To prove D is equivalent to saying the Horn clauses entail (imply) D. Since an
|
||||
implication is only false if the "if" side is true and the "then" side is false,
|
||||
we add "not D" to the list of Horn clauses and call DPLL_satisfiable. If it
|
||||
returns false, that means "not not D" must be true, which is D, which is what
|
||||
we were trying to prove, so output "Proven!" If the query had been E then
|
||||
adding "not E" and calling DPLL_satisfiable would result in true, so output
|
||||
"Cannot prove."
|
||||
|
||||
Hint: In PROLOG notation "not D" can be written
|
||||
:-D.
|
||||
Since the "then" side can always be or'ed with false, this is equivalent to
|
||||
D --> false
|
||||
which is equivalent to "not D." Another way of thinking about it is that the
|
||||
"then" side of a Horn clause is false or'ed with whatever terms are there (in
|
||||
this case none).
|
||||
|
||||
Name your program hw2pr4.cpp etc.
|
||||
|
Reference in a new issue