Searching through a vector - c++

I have a vector, vector<Gate*> PI_Gates, that can contain the characters 0, 1, D, D` (D Not), and X. Depending on the combination of characters in the vector, I will set an output to some value. Here is a example of what I have done so far:
if(GateType== GATE_NAND)
{
for(int i=0; i<PI_Gates.size(); i++)
{
if(PI_Gates[i]->getValue() == LOGIC_DBAR)
{
MyGate->setValue(LOGIC_D);
}
else if(PI_Gates[i]->getValue() == LOGIC_ZERO)
{
MyGate->setValue(LOGIC_ONE);
}
else if(PI_Gates[i]->getValue() == LOGIC_X)
{
MyGate->setValue(LOGIC_X);
}
else if(PI_Gates[i]->getValue() == LOGIC_ONE)
{
}
}
This code is for analyzing a circuit at the gate level and outputting the results. For the cases where the input value is D, 0, or X, my output determined at that time since they will have logic priority. However, for this particular logic gate, if all my inputs are logic 1, then my output will be logic zero. Likewise, when all the inputs are logic D, my output will be logic D not. If the inputs are a combination of logic 1 and logic D, the output is still logic D not. As a result, I need to find a way to search through my vector and determine if my inputs are the following: all logic 1, all logic D, combination of logic 1 and D. And this is where I am stuck. I cannot come up with a good approach to this.
I guess im simpler terms, its like you have a vector that contains the numbers 1, 2, 3, 4, and 5 and you want to check if all the values are either 4 or 5 and if they are, do some operation when you are done iterating through the vector. The solution may be something simple but I think i am over complicating it in my head.
Thanks in advance.

For what you are doing, a simple lookup would work:
const std::string valid_values[] =
{ "0", "1", "D", "/D" /* D Not */, "X"};
//...
std::string * const end_ptr = &valid_values[sizeof(valid_values)];
const std::string value = PI_Gates[i]->getValue();
size_t position = find(&valid_values[0], // begin
end_ptr, // End
value);
if (position != end_ptr)
{
// The gate name was found
MyGate->setValue(value);
}
If you want more versatility, you could use a std::map<string, function pointer> and associate functions with gate names. A table of structures containing the gate name and function pointer would work too.

Related

Manipulating array's values in a certain way

So I was asked to write a function that changes array's values in a way that:
All of the values that are the smallest aren't changed
if, let's assume, the smallest number is 2 and there is no 3's and 4's then all 5's are changed for 3's etc.
for example, for an array = [2, 5, 7, 5] we would get [2, 3, 4, 3], which generalizes to getting a minimal value of an array which remains unchanged, and every other minimum (not including the first one) is changed depending on which minimum it is. On our example - 5 is the first minimum (besides 2), so it is 2 (first minimum) + 1 = 3, 7 is 2nd smallest after 2, so it is 2+2(as it is 2nd smallest).
I've come up with something like this:
int fillGaps(int arr[], size_t sz){
int min = *min_element(arr, arr+sz);
int w = 1;
for (int i = 0; i<sz; i++){
if (arr[i] == min) {continue;}
else{
int mini = *min_element(arr+i, arr+sz);
for (int j = 0; j<sz; j++){
if (arr[j] == mini){arr[j] = min+w;}
}
w++;}
}
return arr[sz-1];
}
However it works fine only for the 0th and 1st value, it doesnt affect any further items. Could anyone please help me with that?
I don't quite follow the logic of your function, so can't quite comment on that.
Here's how I interpret what needs to be done. Note that my example implementation is written to be as understandable as possible. There might be ways to make it faster.
Note that I'm also using an std::vector, to make things more readable and C++-like. You really shouldn't be passing raw pointers and sizes, that's super error prone. At the very least bundle them in a struct.
#include <algorithm>
#include <set>
#include <unordered_map>
#include <vector>
int fillGaps (std::vector<int> & data) {
// Make sure we don't have to worry about edge cases in the code below.
if (data.empty()) { return 0; }
/* The minimum number of times we need to loop over the data is two.
* First to check which values are in there, which lets us decide
* what each original value should be replaced with. Second to do the
* actual replacing.
*
* So let's trade some memory for speed and start by creating a lookup table.
* Each entry will map an existing value to its new value. Let's use the
* "define lambda and immediately invoke it" to make the scope of variables
* used to calculate all this as small as possible.
*/
auto const valueMapping = [&data] {
// Use an std::set so we get all unique values in sorted order.
std::set<int> values;
for (int e : data) { values.insert(e); }
std::unordered_map<int, int> result;
result.reserve(values.size());
// Map minimum value to itself, and increase replacement value by one for
// each subsequent value present in the data vector.
int replacement = *values.begin();
for (auto e : values) { result.emplace(e, replacement++); }
return result;
}();
// Now the actual algorithm is trivial: loop over the data and replace each
// element with its replacement value.
for (auto & e : data) { e = valueMapping.at(e); }
return data.back();
}

C++ if statement order

A portion of a program needs to check if two c-strings are identical while searching though an ordered list (e.g.{"AAA", "AAB", "ABA", "CLL", "CLZ"}). It is feasible that the list could get quite large, so small improvements in speed are worth degradation of readability. Assume that you are restricted to C++ (please don't suggest switching to assembly). How can this be improved?
typedef char StringC[5];
void compare (const StringC stringX, const StringC stringY)
{
// use a variable so compareResult won't have to be computed twice
int compareResult = strcmp(stringX, stringY);
if (compareResult < 0) // roughly 50% chance of being true, so check this first
{
// no match. repeat with a 'lower' value string
compare(stringX, getLowerString() );
}
else if (compareResult > 0) // roughly 49% chance of being true, so check this next
{
// no match. repeat with a 'higher' value string
compare(stringX, getHigherString() );
}
else // roughly 1% chance of being true, so check this last
{
// match
reportMatch(stringY);
}
}
You can assume that stringX and stringY are always the same length and you won't get any invalid data input.
From what I understand, a compiler will make the code so that the CPU will check the first if-statement and jump if it's false, so it would be best if that first statement is the most likely to be true, as jumps interfere with the pipeline. I have also heard that when doing a compare, a[n Intel] CPU will do a subtraction and look at the status of flags without saving the subtraction's result. Would there be a way to do the strcmp once, without saving the result into a variable, but still being able to check that result during the both of the first two if-statements?
std::binary_search may help:
bool cstring_less(const char (&lhs)[4], const char (&rhs)[4])
{
return std::lexicographical_compare(std::begin(lhs), std::end(lhs),
std::begin(rhs), std::end(rhs));
}
int main(int, char**)
{
const char cstrings[][4] = {"AAA", "AAB", "ABA", "CLL", "CLZ"};
const char lookFor[][4] = {"BBB", "ABA", "CLS"};
for (const auto& s : lookFor)
{
if (std::binary_search(std::begin(cstrings), std::end(cstrings),
s, cstring_less))
{
std::cout << s << " Found.\n";
}
}
}
Demo
I think using hash tables can improve the speed of comparison drastically. Also, if your program is multithreaded, you can find some useful hash tables in intel thread building blocks library. For example, tbb::concurrent_unordered_map has the same api as std::unordered_map
I hope it helps you.
If you try to compare all the strings to each other you'll get in a O(N*(N-1)) problem. The best thing, as you have stated the lists can grow large, is to sort them (qsort algorithm has O(N*log(N))) and then compare each element with the next one in the list, which adds a new O(N) giving up to O(N*log(N)) total complexity. As you have the list already ordered, you can just traverse it (making the thing O(N)), comparing each element with the next. An example, valid in C and C++ follows:
for(i = 0; i < N-1; i++) /* one comparison less than the number of elements */
if (strcmp(array[i], array[i+1]) == 0)
break;
if (i < N-1) { /* this is a premature exit from the loop, so we found a match */
/* found a match, array[i] equals array[i+1] */
} else { /* we exhausted al comparisons and got out normally from the loop */
/* no match found */
}

confused on uniqueness in permutation calculation

Working on below problem as an algorithm puzzle. Referred a few similar solutions (and post one of them below), tried and they worked. The question is, for the line "swap(num[i], num[k]);", how do we ensure we could always swap to a number which never tried before (e.g. suppose we swap 1 with 2 in current iteration of the for loop, then it is possible later we swap 2 back with 1 in next iterations of the same for loop of the same level/layer of recursive call)? I have the confusion since we pass num by reference, and it is very possible later (lower level/layer) recursive calls modify content of num, which cause numbers we already evaluated swap back. However, I tried and it works for all of my test cases. Wondering if below solution is 100% correct, or happened to pass my test cases? :)
Here are detailed problem statement and code I am debugging,
Given a collection of numbers that might contain duplicates, return all possible unique permutations.
For example,
[1,1,2] have the following unique permutations:
[1,1,2], [1,2,1], and [2,1,1]
class Solution {
public:
void recursion(vector<int> num, int i, int j, vector<vector<int> > &res) {
if (i == j-1) {
res.push_back(num);
return;
}
for (int k = i; k < j; k++) {
if (i != k && num[i] == num[k]) continue;
swap(num[i], num[k]);
recursion(num, i+1, j, res);
}
}
vector<vector<int> > permuteUnique(vector<int> &num) {
sort(num.begin(), num.end());
vector<vector<int> >res;
recursion(num, 0, num.size(), res);
return res;
}
};
thanks in advance,
Lin
As #notmyfriend said in the comments, num is actually copied each function call.
So now it boils down to:
Of all array values, select one to be the first one and place it there.
That in a loop for each value one time, and then recursively:
Of all values after the first one, select one to be the first and place it there...
...and so on, combined with a check to filter out swaps where nothing changes, ie. filter out duplicates.
If num were a real reference, it won't work anymore (at least not without additional steps).
Eg. 1 1 2 is an easy conterexample, it would give the results:
112, 121, 211, 112, 121
ie. there are duplicates despite the check (and probably there
are examples where some permutations are not generated at all, too).
About the comment:
Per default, every normal function parameter in C++ is copied
(normal = without explicit reference symbol '&' etc.).
Maybe you're thinking of C-style arrays: Essentially, what is passed there is a pointer (to the first value). The pointer is copied, but both original and copied pointer point to the same memory location.
While the purpose of std::vector is (too) to contain an array, the vector itself is a single class object (which contains a pointer to the values somewhere). A class can define itself how it should be copied (with a copy constructor).
Technically, the vector class could implement copying as pointer copying, then it would have the same effect as passing the whole vector as reference; but the C++ creators wanted to keep the copy semantics, ie. that copying a container class should make a real copy with all values duplicated.
For non-copying, there are references already...
Below you can find a solution written in Java. Sorry for not providing a solution in C++, I'm not using it for a long time. But the syntax would be similar.
Solution is using Backtracking (https://en.wikipedia.org/wiki/Backtracking)
Also I'm using hashset to check uniqueness, may be there is a solution which does not use any hashset type data structure, becase my solution is using extra memory in order to provide unique solutions.
Sample input and output;
input : [1, 1, 2]
output : [1, 1, 2]
[1, 2, 1]
[2, 1, 1]
And the solution is;
public class permutation {
public static void main(String[] args) {
permutation p = new permutation();
p.permute(new int[] { 1, 1, 2 });
}
HashSet<String> set = new HashSet<String>();
private void permute(int[] arr) {
set.clear();
this.permute(arr, 0, arr.length - 1);
}
private void permute(int[] arr, int l, int r) {
if (l == r) {
String key = Arrays.toString(arr);
if (set.contains(key))
return;
set.add(key);
System.out.println(key);
} else {
for (int i = l; i <= r; i++) {
swap(arr, l, i);
permute(arr, l + 1, r);
swap(arr, i, l);
}
}
}
private void swap(int[] arr, int l, int r) {
int tmp = arr[l];
arr[l] = arr[r];
arr[r] = tmp;
}
}

Need suggestion to improve speed for word break (dynamic programming)

The problem is: Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words.
For example, given
s = "hithere",
dict = ["hi", "there"].
Return true because "hithere" can be segmented as "leet code".
My implementation is as below. This code is ok for normal cases. However, it suffers a lot for input like:
s = "aaaaaaaaaaaaaaaaaaaaaaab", dict = {"aa", "aaaaaa", "aaaaaaaa"}.
I want to memorize the processed substrings, however, I cannot done it right. Any suggestion on how to improve? Thanks a lot!
class Solution {
public:
bool wordBreak(string s, unordered_set<string>& wordDict) {
int len = s.size();
if(len<1) return true;
for(int i(0); i<len; i++) {
string tmp = s.substr(0, i+1);
if((wordDict.find(tmp)!=wordDict.end())
&& (wordBreak(s.substr(i+1), wordDict)) )
return true;
}
return false;
}
};
It's logically a two-step process. Find all dictionary words within the input, consider the found positions (begin/end pairs), and then see if those words cover the whole input.
So you'd get for your example
aa: {0,2}, {1,3}, {2,4}, ... {20,22}
aaaaaa: {0,6}, {1,7}, ... {16,22}
aaaaaaaa: {0,8}, {1,9} ... {14,22}
This is a graph, with nodes 0-23 and a bunch of edges. But node 23 b is entirely unreachable - no incoming edge. This is now a simple graph theory problem
Finding all places where dictionary words occur is pretty easy, if your dictionary is organized as a trie. But even an std::map is usable, thanks to its equal_range method. You have what appears to be an O(N*N) nested loop for begin and end positions, with O(log N) lookup of each word. But you can quickly determine if s.substr(begin,end) is a still a viable prefix, and what dictionary words remain with that prefix.
Also note that you can build the graph lazily. Staring at begin=0 you find edges {0,2}, {0,6} and {0,8}. (And no others). You can now search nodes 2, 6 and 8. You even have a good algorithm - A* - that suggests you try node 8 first (reachable in just 1 edge). Thus, you'll find nodes {8,10}, {8,14} and {8,16} etc. As you see, you'll never need to build the part of the graph that contains {1,3} as it's simply unreachable.
Using graph theory, it's easy to see why your brute-force method breaks down. You arrive at node 8 (aaaaaaaa.aaaaaaaaaaaaaab) repeatedly, and each time search the subgraph from there on.
A further optimization is to run bidirectional A*. This would give you a very fast solution. At the second half of the first step, you look for edges leading to 23, b. As none exist, you immediately know that node {23} is isolated.
In your code, you are not using dynamic programming because you are not remembering the subproblems that you have already solved.
You can enable this remembering, for example, by storing the results based on the starting position of the string s within the original string, or even based on its length (because anyway the strings you are working with are suffixes of the original string, and therefore its length uniquely identifies it). Then, in the beginning of your wordBreak function, just check whether such length has already been processed and, if it has, do not rerun the computations, just return the stored value. Otherwise, run computations and store the result.
Note also that your approach with unordered_set will not allow you to obtain the fastest solution. The fastest solution that I can think of is O(N^2) by storing all the words in a trie (not in a map!) and following this trie as you walk along the given string. This achieves O(1) per loop iteration not counting the recursion call.
Thanks for all the comments. I changed my previous solution to the implementation below. At this point, I didn't explore to optimize on the dictionary, but those insights are very valuable and are very much appreciated.
For the current implementation, do you think it can be further improved? Thanks!
class Solution {
public:
bool wordBreak(string s, unordered_set<string>& wordDict) {
int len = s.size();
if(len<1) return true;
if(wordDict.size()==0) return false;
vector<bool> dq (len+1,false);
dq[0] = true;
for(int i(0); i<len; i++) {// start point
if(dq[i]) {
for(int j(1); j<=len-i; j++) {// length of substring, 1:len
if(!dq[i+j]) {
auto pos = wordDict.find(s.substr(i, j));
dq[i+j] = dq[i+j] || (pos!=wordDict.end());
}
}
}
if(dq[len]) return true;
}
return false;
}
};
Try the following:
class Solution {
public:
bool wordBreak(string s, unordered_set<string>& wordDict)
{
for (auto w : wordDict)
{
auto pos = s.find(w);
if (pos != string::npos)
{
if (wordBreak(s.substr(0, pos), wordDict) &&
wordBreak(s.substr(pos + w.size()), wordDict))
return true;
}
}
return false;
}
};
Essentially one you find a match remove the matching part from the input string and so continue testing on a smaller input.

Count the number of matching elements in two arrays C++

I'm working on a homework assignment for Comp Sci I, and I've tried literally everything I could find on the internet and in my textbook in an attempt to count the number of matching elements in two C++ arrays. I simply can't find a way to make my code count the number of matching elements in two arrays of the same size (same value, same position). For instance, if array1 has 5, 4, 3, 2, 1, and array2 has 1, 2, 3, 4, 5, there is one matching element, the 3. How can I get my code to perform this seemingly simple task?
Couldn't find an answer anywhere. My textbook only shows how to see if the arrays match exactly without counting the number of matches, and I haven't been able to find anyone else with this exact question for C++.
Here's my function so far:
int matchCounter(int lottery[5], int user[5], int matches, int SIZE)
{
int count = 0;
for (count < SIZE; count++;)
{
if (lottery[count] == user[count])
{
matches++;
}
}
return matches;
} // end matchCounter
SIZE is a constant that equals 5, by the way. It would seem that this should work, but every time I run the program, it displays 0 matches, even in there are some matches. If anyone could help me out, I would be forever in your debt. Seriously, there's got to be some incredibly simple thing I'm just not seeing. Thanks for you help in advance.
Your for statement is garbled. Try this:
int matchCounter(int lottery[5], int user[5], int matches, int SIZE)
{
for (int count = 0; count < SIZE; count++)
{
...
For reason why your program always fails: count++ is put in the position of the condition in the for loop, so every time this for loop is executed, count is evaluated and considered to be the condition, and then count is incremented by 1. However, every time count starts from 0 (as in int count = 0;), so the for loop actually never gets executed, and matches remain zero.
EDIT:
From your source code, you're not using your return value, which is also suggested by #jimhark. Change the function signature to:
int matchCounter(int lottery[5], int user[5], int SIZE)
And call with:
matches = matchCounter(lottery, user, 5);
Otherwise, your return value of the function matchCounter is ignored, while int matches only plays the role of a local variable in the function.
Read this about why the matches doesn't work: http://www.cs.utsa.edu/~wagner/CS2213/swap/swap.html (in a similar setting)
Since this is a homework, I will try to point the errors without giving the solution.
The form of a for loop is:
for (INIT; COND; STEP) {
BODY;
}
which is equivalent to:
INIT;
while (COND) {
BODY;
STEP;
}
The way you did, your INIT is count < SIZE, which doesn't do anything. Your "COND" is count++, which returns 0 on the first iteration. As you may know, 0 is false, in the context of a boolean. Therefore, your for loop body is not being executed at all.
Also, you should not pass matches as an argument. It should be a local variable initialized with 0.
Your may not be using your return value. Change sig to:
int matchCounter(int lottery[5], int user[5], int SIZE)
{
matches = 0;
And make sure your're calling with:
matches = matchCounter(lottery, user, 5);
If you need a running sum, use:
matches += matchCounter(lottery, user, 5);
In any case matchCounter doesn't care what running total is, so why pass it in?
Also you may need to sort the lists first.
Maybe this can help:
int matches=0;
for(int i=0;i<ARRAY.SIZE;i++) {
for(int j=0;j<ARRAY.SIZE;j++) {
if(arr1[i]==arr2[j]) {
matches++;
arr2[j]=NULL;
}
}
}