CS50 pset 3: Tideman sort_pairs function - quicksort

I need some assistance in understanding the logic behind this function. This is my current sort_pairs function in Tideman:
// Sort pairs in decreasing order by the strength of victory
void sort_pairs(void)
{
qsort(pairs, pair_count, sizeof(pair), compare);
return;
}
// Function for sort_pairs
int compare(const void *a, const void *b)
{
const pair *p1 = (const pair *) a;
const pair *p2 = (const pair *) b;
if (p1->winner < p2->winner)
{
return -1;
}
else if (p1->winner > p2->winner)
{
return 1;
}
else
{
return 0;
}
}
This does not clear check50 and I looked online to find how to approach this problem. It seems that most functions compare the values from the preferences array instead (eg preferences[pairs[i].winner][pairs[i].loser]) . My previous functions vote, record_preferences, and add_pairs all clear check50. I have not advanced beyond sort_pairs yet.
Why can't I compare the strength of victory directly from the pairs array instead since I already have the data stored there?

You don't need to make this so complex, you can use your own sorting here. Let's try a simple insertion sort-
void sort_pairs()
{
pair temp;
for (int i = 1, j; i < pair_count; i++)
{
temp = pairs[i];
j = i - 1;
for (; j >= 0 && preferences[pairs[j].winner][pairs[j].loser] < preferences[temp.winner][temp.loser]; j--)
{
pairs[j + 1] = pairs[j];
}
pairs[j + 1] = temp;
}
}
The pair struct looks like-
typedef struct
{
int winner;
int loser;
}
pair;
Explanation:-
We go through each pair of elements inside the pairs array - starting at 1 since I'm going to compare with the previous element (j = i - 1)
Now we check all the previous elements from the current element and compare them with the key - preferences[pairs[INDEX].winner][pairs[INDEX].loser]
This is the key you should be sorting by. preferences[WINNER_ID][LOSER_ID] means the amount of people that prefer WINNER_ID over LOSER_ID.
And that's pretty much it!, it's simply a insertion sort but the key is the important part.

Related

How to write a local branch predictor?

I am trying to use runspec test my local branch predictor, but only find a disappointing result.
By now I have tried use a 64 terms LHT, and when the LHT is full, I use FIFO tactics replace a terms in LHT.I don't know if I use a tiny LHT or my improper replacement tactics makes it a terrible precision, anyway it's only 60.9095.
for (int i = 0; i < 1 << HL; i++)
{
if (tag_lht[i] == (addr&(1-(1<<HL))))
{
addr = addr ^ LHT[i].getVal();
goto here;
break;
}
}
index_lht = index_lht%(1<<HL);
tag_lht[index_lht] = (addr&(1-(1<<HL)));
LHT[index_lht] = ShiftReg<2>();
addr = addr ^ LHT[index_lht].getVal();
index_lht++;
here:
for (int i = 0; i < 1 << L; i++)
{
if (tag[i] == (addr))
{
return bhist[i].isTaken();
}
}
index = index % (1 << L);
tag[index] = (addr);
bhist[index].reset();
return bhist[index++].isTaken();
Here I make some explain about the code. bhist is a table store 2-bit status about each branch instructions when the table is full, use FIFO replacement tactics. tag is where the table store address of each instruction. Besides, likely I use tag_lht to store address of each instruction that stored in LHT. Function isTaken() can easily get the predict result.
Thank you all guys, I find that stupid mistake I make, and the code above is correct, but may not seem work prefect. The mistake bellow:
for (int i = 0; i < (1 << L); i++)
{
if (tag[i] == (addr))
{
if (takenActually)
{
LHT[j].shiftIn(1);
bhist[i].increase();
}
else
{
LHT[j].shiftIn(0);
bhist[i].decrease();
}
}
break;
}
But it should be like this:
for (int i = 0; i < (1 << L); i++)
{
if (tag[i] == (addr))
{
if (takenActually)
{
LHT[j].shiftIn(1);
bhist[i].increase();
}
else
{
LHT[j].shiftIn(0);
bhist[i].decrease();
}
break;
}
}
I am so stupid that I waste you helpful people' s time, I spent so much time to figure out why it don't work, at first I thought that wrong variable or argument are used, now I just think I am a careless man.
Again I thank all you ardent fellows. Then I will answer the question with my full code.
PS. wish that my terrible English have not confuse anyone.:)

Bad address error when comparing Strings within BPF

I have an example program I am running here to see if the substring matches the string and then print them out. So far, I am having trouble running the program due to a bad address. I am wondering if there is a way to fix this problem? I have attached the entire code but my problem is mostly related to isSubstring.
#include <uapi/linux/bpf.h>
#define ARRAYSIZE 64
struct data_t {
char buf[ARRAYSIZE];
};
BPF_ARRAY(lookupTable, struct data_t, ARRAYSIZE);
//char name[20];
//find substring in a string
static bool isSubstring(struct data_t stringVal)
{
char substring[] = "New York";
int M = sizeof(substring);
int N = sizeof(stringVal.buf) - 1;
/* A loop to slide pat[] one by one */
for (int i = 0; i <= N - M; i++) {
int j;
/* For current index i, check for
pattern match */
for (j = 0; j < M; j++)
if (stringVal.buf[i + j] != substring[j])
break;
if (j == M)
return true;
}
return false;
}
int Test(void *ctx)
{
#pragma clang loop unroll(full)
for (int i = 0; i < ARRAYSIZE; i++) {
int k = i;
struct data_t *line = lookupTable.lookup(&k);
if (line) {
// bpf_trace_printk("%s\n", key->buf);
if (isSubstring(*line)) {
bpf_trace_printk("%s\n", line->buf);
}
}
}
return 0;
}
My python code here:
import ctypes
from bcc import BPF
b = BPF(src_file="hello.c")
lookupTable = b["lookupTable"]
#add hello.csv to the lookupTable array
f = open("hello.csv","r")
contents = f.readlines()
for i in range(0,len(contents)):
string = contents[i].encode('utf-8')
print(len(string))
lookupTable[ctypes.c_int(i)] = ctypes.create_string_buffer(string, len(string))
f.close()
b.attach_kprobe(event=b.get_syscall_fnname("clone"), fn_name="Test")
b.trace_print()
Edit: Forgot to add the error: It's really long and can be found here: https://pastebin.com/a7E9L230
I think the most interesting part of the error is near the bottom where it mentions:
The sequence of 8193 jumps is too complex.
And a little bit farther down mentions: Bad Address.
The verifier checks all branches in your program. Each time it sees a jump instruction, it pushes the new branch to its “stack of branches to check”. This stack has a limit (BPF_COMPLEXITY_LIMIT_JMP_SEQ, currently 8192) that you are hitting, as the verifier tells you. “Bad Address” is just the translation of kernel's errno value which is set to -EFAULT in that case.
Not sure how to fix it though, you could try:
With smaller strings, or
On a 5.3+ kernel (which supports bounded loops): without unrolling the loop with clang (I don't know if it would help).

Google/OR-Tools Get Duration And Distance

I'm trying to understand the solution call in the MVRP examples
I have two matrixes, duration and distance that have been returned via calls to google
My solution is based on distance but given that i have the data already returned i want to find the index associated with the duration.
unfortunately I'm not sure completely what is going on under the hood of the the Routing Calls so hoping for a simple fast answer for look up and what index to use
for simplicity sake I will show the google example rather than my code and highlight what im looking for:
public string PrintSolution()
{
// Inspect solution.
string ret = "";
long maxRouteDistance = 0;
for (int i = 0; i < _data.Drivers; ++i)
{
ret += $"Route for Vehicle {i}:";
ret += Environment.NewLine;
long routeDistance = 0;
var index = _routing.Start(i);
while (_routing.IsEnd(index) == false)
{
ret += $"{_manager.IndexToNode((int) index)} -> ";
var previousIndex = index;
index = _solution.Value(_routing.NextVar(index));
long legDistance = _routing.GetArcCostForVehicle(previousIndex, index, i);
//LOOKING FOR
//long legDuration = ??? what index am is using here to find in my duration matrix which is built the same as indexes as distance
ret += " leg distance: " + legDistance;
routeDistance += legDistance;
}
ret += $"{_manager.IndexToNode((int) index)}";
ret += Environment.NewLine;
ret += $"Distance of the route: {routeDistance}m";
ret += Environment.NewLine;
ret += Environment.NewLine;
maxRouteDistance = Math.Max(routeDistance, maxRouteDistance);
}
ret += $"Maximum distance of the routes: {maxRouteDistance}m";
ret += Environment.NewLine;
return ret;
}
#Mizux
disclaimer: This is a simplification but should help you to understand.
In OR-Tools Routing there is a primal "hidden" dimension without name but you can retrieve the cost using RoutingModel::GetArcCostForVehicle()
For any "regular" dimension you can get inspect the CumulVar at each node.
e.g. supposing you have created two dimensions using RoutingModel::AddDimension() whose name were "Distance" and "Duration".
note: CumulVar is an accumulator so if you want the "arc cost" you'll need something like this dim.CumulVar(next_index) - dim.CumulVar(index)
Then in you PrintFunction you can use:
public string PrintSolution()
{
...
RoutingDimension distanceDimension = routing.GetMutableDimension("Distance");
RoutingDimension durationDimension = routing.GetMutableDimension("Duration");
for (int i = 0; i < _manager.getNumberOfVehicles(); ++i)
{
while (_routing.IsEnd(index) == false)
{
...
IntVar distanceVar = distanceDimension.CumulVar(index);
IntVar durationVar = durationDimension.CumulVar(index);
long distance = _solution.Value(distanceVar);
long duration = _solution.Value(durationVar);
...
}
}
}

Querying Mongodb Key and Value using C driver

mongo_cursor *cursor=mongo_find(conn,TEST_NS,query,NULL,0,0,0);
count_matched=0;
bson *doc;
while(mongo_cursor_next(cursor)==MONGO_OK)
{
count_matched++;
doc=(bson *)mongo_cursor_bson(cursor);
bson_iterator_init(&it,doc);
while(bson_iterator_next(&it) != BSON_EOO)
{
fprintf(stderr,"%s : %s\n\n",bson_iterator_key(&it),bson_iterator_string(&it));
}
}
This code is working perfectly and i can see the matched documents (Key + Value) but now i want to save the matched document's key and value to a string. Can any tell me how i can save the return value of key and value in to a string?
One document includes (all strings)
Total Key=10
Total value=10
and i want to save 10 document's key and value at one time. I am using C driver of mongodb.
The following code shows how you would be doing copy of the key and values from the bson iterator into your key-value arrays temp_key and temp_value. The specific block of code is in between the comments marked START and END.
Additionally, you can find documentation for accessing BSON document contents at http://api.mongodb.org/c/current/bson.html .
mongo_cursor *cursor = mongo_find(&conn, TEST_NS, &query, NULL, 0, 0, 0);
int count_matched = 0;
bson *doc;
// Assuming you are just looking for 100 key / value pair of max length of 99 characters
const unsigned KV_ARRAY_LENGTH = 100;
const unsigned MAX_KV_LENGTH = 105;
char temp_key[KV_ARRAY_LENGTH][MAX_KV_LENGTH + 1], temp_value[KV_ARRAY_LENGTH][MAX_KV_LENGTH + 1];
int i = 0;
while (mongo_cursor_next(cursor) == MONGO_OK) {
count_matched++;
doc=(bson *)mongo_cursor_bson(cursor);
bson_iterator it;
bson_iterator_init(&it,doc);
while (bson_iterator_next(&it) != BSON_EOO) {
fprintf(stderr,"%s : %s\n", bson_iterator_key(&it), bson_iterator_string(&it));
/******* START - Code to capture key-value into appropriate array */
if (i < KV_ARRAY_LENGTH) {
/* - Collect key-value pairs only if there is space in the array
* - Key / Value woud be captured only till the max amount of space available for them i.e. MAX_KV_LENGTH in this case
* */
strncpy(temp_key[i], bson_iterator_key(&it), MAX_KV_LENGTH);
strncpy(temp_value[i], bson_iterator_string(&it), MAX_KV_LENGTH);
temp_key[i][MAX_KV_LENGTH] = temp_value[i][MAX_KV_LENGTH] = '\0';
++i;
} else {
/* whatever need to be done if there is no room in the array */
}
/******* END - Code to capture key-value into appropriate array */
}
}
/* Test iterating through the key-value pair constructed in query iteration */
fprintf(stdout, "--- Fields collected ---\n");
int keyIndex = 0;
for ( ; keyIndex < i; ++keyIndex) {
fprintf(stdout, "{key: %s, value: %s}\n", temp_key[keyIndex], temp_value[keyIndex]);
}
mongo_cursor *cursor=mongo_find(conn,TEST_NS,query,NULL,0,0,0);
count_matched=0;
bson *doc;
//Answer
const char* temp_key[100][100],temp_value[100][100];
int i=0;
while(mongo_cursor_next(cursor)==MONGO_OK)
{
count_matched++;
doc=(bson *)mongo_cursor_bson(cursor);
bson_iterator_init(&it,doc);
while(bson_iterator_next(&it) != BSON_EOO)
{
fprintf(stderr,"%s : %s\n\n",bson_iterator_key(&it),bson_iterator_string(&it));
temp[i][0]=bson_iterator_key[&it]; //Answer
temp_value[i][0]=bson_iterator_key[&it]; //Answer
i++; //Answer
}
}
Just for the record, this is the rough sketch and i know about corruption of the temp variables and their overflow but i will remove it according to my code.

does boost python support a function returning a vector, by ref or value?

I am new to python, I have looked at boost python, and it looks very
impressive. However going through the introduction I can not find
any examples where, vector of objects are returned as python list/tuples.
i.e Take this example, I want to expose class X, Cont and all its functions.
critical bit being return a vector of X's or strings to python
class X {};
class Cont {
.....
// how can this be exposed using boost python
const std::vector<X>& const_ref_x_vec() const { return x_vec_;}
std::vector<X> value_x_vec() const { return x_vec;}
const std::vector<std::string>& const_ref_str_vec() const { return str_vec_;}
std::vector<std::string> value_str_vec() const { return str_vec_; }
...
private:
std::vector<X> x_vec_;
std::vector<std::string> str_vec_;
};
My own fruitless attempt at trying to expose the functions like
const_ref_x_vec(), value_x_vec(),etc just leads to compile errors.
from googling around I have not seen any example that support returning vectors
by value or reference. Is this even possible with boost python?
are there any workarounds ? should I be using SWIG for this case ?
Any help appreciated.
Avtar
Autopulated's reason was essentially correct, but the code was more complicated then necessary.
The vector_indexing_suite can do all that work for you:
class_< std::vector<X> >("VectorOfX")
.def(vector_indexing_suite< std::vector<X> >() )
;
There is a map_indexing_suite as well.
Because you can't expose template types to python you have to explicitly expose each sort of vector that you want to use, for example this is from my code:
Generic template to wrap things:
namespace bp = boost::python;
inline void IndexError(){
PyErr_SetString(PyExc_IndexError, "Index out of range");
bp::throw_error_already_set();
}
template<class T>
struct vec_item{
typedef typename T::value_type V;
static V& get(T& x, int i){
static V nothing;
if(i < 0) i += x.size();
if(i >= 0 && i < int(x.size())) return x[i];
IndexError();
return nothing;
}
static void set(T& x, int i, V const& v){
if(i < 0) i += x.size();
if(i >= 0 && i < int(x.size())) x[i] = v;
else IndexError();
}
static void del(T& x, int i){
if(i < 0) i += x.size();
if(i >= 0 && i < int(x.size())) x.erase(x.begin() + i);
else IndexError();
}
static void add(T& x, V const& v){
x.push_back(v);
}
};
Then, for each container:
// STL Vectors:
// LineVec
bp::class_< std::vector< Line > >("LineVec")
.def("__len__", &std::vector< Line >::size)
.def("clear", &std::vector< Line >::clear)
.def("append", &vec_item< std::vector< Line > >::add,
bp::with_custodian_and_ward<1, 2>()) // let container keep value
.def("__getitem__", &vec_item< std::vector< Line > >::get,
bp::return_value_policy<bp::copy_non_const_reference>())
.def("__setitem__", &vec_item< std::vector< Line > >::set,
bp::with_custodian_and_ward<1,2>()) // to let container keep value
.def("__delitem__", &vec_item< std::vector< Line > >::del)
.def("__iter__", bp::iterator< std::vector< Line > >())
;
// ...
A similar approach is possible for std::map.
I used lots of help from wiki.python.org when writing this.