Write a shell command to search all the files in the working directory with names containing one
character extension for the lines that does not start with a character A or character B.
Solution
Answer:
#!/bin/bash
# to search all the files in the working directory with names containing one character extension
#for the lines that does not start with a character A or character B
find . -type f -name \"*.?\" | -not -name \'[ac]*\' -type f.
Write CC++ a program that inputs a weighted undirected graph and fi.pdf
1. Write C/C++ a program that inputs a weighted undirected graph and finds the shortest path
between two vertices using Dijkstra’s algorithm, using indices to order the branching. The
program should take three command-line arguments: the name of the graph file, followed by a
source vertex, followed by a destination vertex. It should output to standard output the vertices in
a shortest path in order, including both the source and destination vertices, as well as the total
weight of the path. You may assume that any input graphs will have no negative-weight edges. A
user should see something very similar to the following when invoking your program.
> ./dijkstra graph.txt 2 3
2 5 6 1 0 3
3.51
>
Graph.txt:
7 9 //Represents number of vertices and edges, respectively.
Solution
main.cpp
#include "Dij.h"
#include
/*---------------------------------------------------------
* Name: main
* Purpose: driver module for testing Dij.h
* Param: filename, source vertex id, destination vertex id
*---------------------------------------------------------*/
int main(int argc, char **argv)
{
string filename;
if ( 1 < argc ) filename.assign( argv[1] );
Graph testGraph; // create Graph object
//string filename = argv[1]; // get filename
testGraph.createGraph(filename); // populate Graph
int source; // source index
2. int destination; // destination index
// convert strings to integers
stringstream s1(argv[2]);
s1 >> source;
stringstream s2(argv[3]);
s2 >> destination;
// find the shortest path
testGraph.findPath(source,destination);
// print the shortest path
testGraph.outputPath();
std::cout << std::endl;
}
Dij.h
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "Vertex.h"
#define infinity DBL_MAX
using namespace std;
/*-----------------------------------------------------------
* Name: Graph
* Purpose: Represent a graph G{V,E} alongside implementation
* of Dijkstra's algorithm
3. *-----------------------------------------------------------*/
class Graph
{
public:
Graph();
~Graph();
void createGraph(std::string);
void findPath(int, int);
void outputPath();
void relaxVertex(Vertex*);
// set the vertex of which the shortest path is being found
void setDestination(Vertex* destination){mDestination = destination;}
// get the vertex of which the shortest path is being found
Vertex* getDestination(){return mDestination;}
// set the vertex that is the starting point of the search
void setSource(Vertex* source){mSource = source;}
// get the vertex that is the starting point of the search
Vertex* getSource(){return mSource;}
private:
std::vector mVertices; //vector of vertices
std::map mWeights; //table of shortest path weights
Vertex* mDestination; //destination vertex
Vertex* mSource; //source vertex
};
/*---------------------------------------------------------
* Name: Default Constructor
*---------------------------------------------------------*/
4. Graph::Graph()
{
mDestination = NULL;
mSource = NULL;
}
/*---------------------------------------------------------
* Name: Destructor
*---------------------------------------------------------*/
Graph::~Graph()
{
//Free memory
if(!mVertices.empty())
{
while(mVertices.size())
{
Vertex * vertex = mVertices.back();
delete vertex;
mVertices.pop_back();
}
}
}
/*----------------------------------------------------------
* Name: createGraph
* Purpose: parse text file and construct graph
* Param: string - name of file to parse
*----------------------------------------------------------*/
void Graph::createGraph(std::string filename)
{
std::ifstream myfile; // ifstream object for opening file
myfile.open(filename.c_str(), ios::in); // open file
// if file does not exist or failed to open, return
5. if(!myfile.is_open())
{
cout << "File failed to open" << endl;
return;
}
// get lines from file for parsing
for(std::string line; std::getline(myfile, line);)
{
std::istringstream ss(line);
int index, value; //first node and node pointed at
double weight; //edge weight betweeen first and second nodes
// Get values from stream
ss >> index;
ss >> value;
ss >> weight;
// Add vertex to vertices list if not present
if(!mWeights.count(index))
{
Vertex * vertex = new Vertex(index);
vertex->addEdge(value, weight);
mVertices.push_back(vertex);
mWeights[index] = vertex; //record vertex in weight map
vertex->setWeight(infinity); //intialize weight to infinity
}
// Otherwise the vertice is present - add another edge
6. else
{
(mWeights[index])->addEdge(value, weight);
}
// If vertex has no edges, add to graph
if(!mWeights.count(value))
{
Vertex * vertex = new Vertex(value);
mVertices.push_back(vertex);
mWeights[value] = vertex; //record vertex in weight map
vertex->setWeight(infinity); //initialize weight to infinity
}
}
// close the file
myfile.close();
}
/*------------------------------------------------------------
* Name: findPath
* Purpose: Implements Dijkstra's algorithm with minHeap
* Param: ID of source and destination vertices
*------------------------------------------------------------*/
void Graph::findPath(int source, int destination)
{
// lambda functor for comparing vertices
auto compare = [](Vertex*lhs,Vertex*rhs)
{
return lhs->getWeight() > rhs->getWeight();
};
// index to minimum weight vertex
int index = 0;
// if the source of destination does not exist, there is no path
7. if(mWeights.count(source) && mWeights.count(destination))
{
// initialize source vertex to weight of zero
(mWeights[source])->setWeight(0);
// heapify
std::make_heap(mVertices.begin(), mVertices.end(), compare);
// set source node
this->setSource(mWeights[source]);
// search the graph and update shortest paths
while(index+1 != mVertices.size())
{
Vertex * vertex = mVertices[index]; //vertex of min weight with edges to search
// shortest path found if it has correct id and has been updated
if(vertex->getId() == destination && vertex->getWeight() != infinity)
{
this->setDestination(vertex); //set the destination node
break;
}
// shortest path has not been found, relax edges
else
{
this->relaxVertex(vertex);
}
//Heapify everything apart from extracted value
index+=1;
std::make_heap(mVertices.begin() + index, mVertices.end(), compare);
}
}
}
/*--------------------------------------------------------------
* Name: relaxVertex
8. * Purpose: update total path weight of a vertex in the graph
* Param: vertex whose edges are being searched
*-------------------------------------------------------------*/
void Graph::relaxVertex(Vertex* vertex)
{
std::map* edges = vertex->getEdges();
// search edges of current min vertex
for(auto iter = edges->begin(); iter != edges->end(); iter++)
{
// if the edges have not been seen, update weight
if((mWeights[iter->first])->getWeight() == infinity)
{
// weight is updated to current path weight + edge weight
(mWeights[iter->first])->setWeight((mWeights[vertex->getId()])->getWeight() +
iter->second);
(mWeights[iter->first])->setParent(vertex);
}
// if the vertex has been updated already, compare current path
// if new path is now minimal, update path
else if((mWeights[iter->first])->getWeight() > iter->second +
(mWeights[vertex->getId()])->getWeight())
{
(mWeights[iter->first])->setWeight((mWeights[vertex->getId()])->getWeight() +
iter->second);
(mWeights[iter->first])->setParent(vertex);
}
}
}
/*-----------------------------------------------------------------
* Name: outputPath
* Purpose: output shortest path for destination node
*-----------------------------------------------------------------*/
void Graph::outputPath()
{
9. Vertex* vertex = this->getDestination(); // destination node
// if the node has a shortest path, output it
if(vertex != NULL)
{
// if id and vertex are the same, output zero weight
if(vertex->getId() == this->getSource()->getId())
{
std::cout << vertex->getId() << "->" << vertex->getId() << " ";
}
// create stack using parent vertices
else
{
std::stack path;
while(vertex != this->getSource())
{
path.push(vertex->getId());
vertex = vertex->getParent();
}
if(vertex == this->getSource())
{
path.push(vertex->getId());
}
// pop elements from stack and print
while(path.size())
{
int id = path.top();
path.pop();
if(id == this->getDestination()->getId())
{
std::cout << id << " ";
10. }
else
{
std::cout << id << "->";
}
}
}
// print out weight to two degrees of precision
double weight = (mWeights[this->getDestination()->getId()])->getWeight();
std::cout << std::fixed << std::setprecision(2) << weight << std::endl;
}
else
{
std::cout << "NO PATH FOUND" << std::endl;
}
}
Vertex.h
/*-----------------------------------------------------------
* Name: Vertex
* Purpose: Represent vertex in a graph
*-----------------------------------------------------------*/
class Vertex
{
public:
// default constructor
Vertex(){mParent = NULL;}
// constructor with defined id
Vertex(int id){mId = id; mParent = NULL;}
~Vertex(){}
// set the vertex id
void setId(int id){mId = id;}
// get the vertex id
int getId() const {return mId;}
11. // set the total current path weight for a vertex
void setWeight(double weight){mWeight = weight;}
// get the total current path weight for a vertex
double getWeight()const{return mWeight;}
// set a vertex that points to the current vertex
void setParent(Vertex* parent){mParent = parent;}
//get the vertex that points at the current vertex
Vertex* getParent(){return mParent;}
// add an edge to the current vertex
void addEdge(int, double);
// return the map of edges that the current vertex contains
std::map* getEdges(){return &mEdges;}
private:
int mId; //unique id of vertex
double mWeight; //current path weight of vertex
std::map mEdges; //edges from current vertex
Vertex* mParent; //parent vertex
};
/*--------------------------------------------------------
* Name: addEdge
* Purpose: add edge to list of edges to given vertex
*-------------------------------------------------------*/
void Vertex::addEdge(int index, double weight)
{
mEdges.insert(std::make_pair(index,weight));
}
graph.txt
0 3 1
0 1 .51
5 0 3.0
2 5 0.2
5 6 0.8
1 6 1.0
2 4 1.30