Why is count_if giving me the total of texts - c++

I was testing the following code, and a bit perplexed as to why count_if is returning me the total of texts?
Match function that takes string of Text as argument and returns true is the Text size is 4
bool Match(string Text)
{
if (Text.size() == 4)
return true;
}
numMatchwes produces the total number of Text in a vector
int numMatches(vector<string>Texts, bool (*Match)(string Text)) // Texts is an array
{
int count = 0;
for (int i = 0; i < Texts.size(); i++)
{
if (Match(Texts[i]) == 1)
// checking every string in vector and returns true
count++;
}
return count;
}
The main function
int main()
{
vector<string> texts;
texts.push_back("Bing");
texts.push_back("Pony");
texts.push_back("Mil");
texts.push_back("Sillty");
texts.push_back("Ballz");
texts.push_back("Mars");
cout << Match("Sind") << endl;
cout << "Matches are: " << numMatches(texts, Match) << endl;
cout << endl;
int num = count_if(texts.begin(), texts.end(), Match); // count_if is STL function
cout << num << endl;
}
Now I’m confused as to why count_if is giving me the total of texts?

The function Match has undefined behavior in case when the passed string does not have a length equal to 4.
Define it the following way
bool Match( const std::string &Text )
{
return Text.size() == 4;
}
Correspondingly the function numMatches can be defined the following way
auto numMatches( const std::vector<std::string> &Texts, bool Match(const std::string & ) )
{
std::vector<std::string>::size_type count = 0;
for ( const auto &s : Texts )
{
if ( Match( s ) ) ++count;
}
return count;
}
Here is your updated program.
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
auto numMatches( const std::vector<std::string> &Texts, bool Match(const std::string & ) )
{
std::vector<std::string>::size_type count = 0;
for ( const auto &s : Texts )
{
if ( Match( s ) ) ++count;
}
return count;
}
bool Match( const std::string &Text )
{
return Text.size() == 4;
}
int main()
{
std::vector<std::string> texts;
texts.push_back( "Bing" );
texts.push_back( "Pony" );
texts.push_back( "Mil" );
texts.push_back( "Sillty" );
texts.push_back( "Ballz" );
texts.push_back( "Mars" );
std::cout << std::boolalpha << Match( "Sind" ) << '\n';
std::cout << "Matches are: " << numMatches( texts, Match ) << '\n';
std::cout << '\n';
auto num = std::count_if( std::begin( texts ), std::end( texts ), Match );
std::cout << num << std::endl;
return 0;
}
The program output is
true
Matches are: 3
3

Related

When testing my c++ code in Xcode, using "Ab cde Fg" as a test string, my code returns "Not Unique"...Why? The code is listed below

I have been practicing interview questions in C++ in Xcode, however I have come across unexpected behavior, yet no compilation error. The code is expected to return whether or not a string contains all unique ASCII characters or not. Testing my code in Xcode on my Mac, with the string "Ab cde Fg" returns "Not Unique". Why is this?
bool isUnique1(std::string str)
{
if (str.length() > 128)
return false;
bool * barr = new bool[128];
for (int i = 0; i < str.length(); i++)
{
int val = str[i];
if (barr[val])
return false;
barr[val] = true;
}
delete[] barr;
return true;
}
int main()
{
std::string name;
bool result1;
std::cout << "Enter a string to test: ";
getline (std::cin, name);
result1 = isUnique1(name);
if (result1)
std::cout << "Unique \n";
else
std::cout << "Not Unique \n";
return 0;
}
The array is not initialized. Write
bool * barr = new bool[128]();
Pay attention to that this string
"Ab cde Fg"
^ ^
contains non-unique spaces.
Maybe you should write the function such a way that it would ignore white spaces.
If to ignore white spaces then the function can be defined for example the following way as it is shown in the demonstrative program below.
#include <iostream>
#include <iomanip>
#include <string>
#include <set>
#include <cctype>
bool isUnique1( const std::string &s )
{
std::set<char> set;
std::pair<std::set<char>::iterator, bool> p( std::set<char>::iterator(), true );
for ( std::string::size_type i = 0; p.second && i < s.size(); i++ )
{
if ( not std::isspace( ( unsigned char )s[i] ) ) p = set.insert( s[i] );
}
return p.second;
}
int main()
{
std::cout << std::boolalpha << isUnique1( "Ab cde Fg" ) << '\n';
return 0;
}
The program output is
true
Otherwise if white spaces must not be ignored then the loop will look like
for ( std::string::size_type i = 0; p.second && i < s.size(); i++ )
{
p = set.insert( s[i] );
}
Or without a loop the function can be written the following way
#include <iostream>
#include <iomanip>
#include <string>
#include <set>
#include <iterator>
#include <cctype>
bool isUnique1( const std::string &s )
{
return std::set<char>( std::begin( s ), std::end( s ) ).size() == s.size();
}
int main()
{
const char *s = "abcdefghijklmnopqrstuvwxyz";
std::cout << std::boolalpha << isUnique1( s ) << '\n';
return 0;
}
The program output is
true

how to access vector of map of ( int and vector of strings )

how do i access map of int and vectors of string in the passed_vector function.
I just want to print them in that function.
#include <iostream>
#include <vector>
#include <map>
#include <string>
using namespace std;
typedef vector< map< int, vector<string> > > vmis;
typedef map< int, vector<string> > mis;
typedef vector<string> vstr;
void passing_vector(const vmis &meetings);
//return size of vector
template< typename A > size_t n_elements( const A& a )
{
return sizeof a / sizeof a[ 0 ];
}
int main()
{
vmis meeting_info;
mis meeting_members;
vstr sw_vec;
vstr sys_vec;
string sw_team[] = {"Ricky", "John", "David"};
string sys_team[] = {"Simmon", "Brad", "Schmidt", "Fizio"};
sw_vec.insert(sw_vec.begin(), sw_team, sw_team + n_elements(sw_team) );
sys_vec.insert(sys_vec.begin(), sys_team, sys_team + n_elements(sys_team) );
meeting_members.insert(make_pair(520, sw_vec));
meeting_members.insert(make_pair(440, sys_vec));
meeting_info.push_back(meeting_members);
passing_vector(meeting_info);
return 0;
}
void passing_vector(const vmis &meetings)
{
vmis::iterator itvmis = meetings.begin();
//how do i access map of int and vectors of string.
//I just want to print them.
}
I know how to print them in main function.
vmis::iterator itvims = meeting_info.begin();
for( int i = 0; i < meeting_info.size(); i++ )
{
mis::iterator itm = meeting_members.begin();
for(itm; itm != meeting_members.end(); itm++ )
{
cout << itm->first << " : ";
vstr::iterator it = itm->second.begin();
for(it; it != itm->second.end(); it++)
cout << *it << " ";
cout << endl;
}
}
desired output
440 : Simmon Brad Schmidt Fizio
520 : Ricky John David
if there is a better way of doing this suggestions are always welcome.
The easiest aproach is to use auto, also since your meetings is const, you need to use const_iterator:
void passing_vector(const vmis &meetings)
{
vmis::const_iterator itvims = meetings.begin();
//how do i access map of int and vectors of string.
//I just want to print them.
for (;itvims != meetings.end(); ++itvims)
{
const auto& map_item = *itvims;
for (const auto& map_it : map_item)
{
int map_key = map_it.first;
const auto& str_vec = map_it.second;
for (const auto& str : str_vec)
{
std::cout << map_key << " - " << str << "\n";
}
}
}
}
[edit]
c++98 version:
void passing_vector(const vmis &meetings)
{
vmis::const_iterator itvims = meetings.begin();
//how do i access map of int and vectors of string.
//I just want to print them.
for (;itvims != meetings.end(); ++itvims)
{
const mis& map_item = *itvims;
for (mis::const_iterator map_it = map_item.begin(); map_it != map_item.end(); ++map_it)
{
int map_key = map_it->first;
const vstr& str_vec = map_it->second;
for (vstr::const_iterator sitr = str_vec.begin(); sitr != str_vec.end(); ++sitr)
{
std::cout << map_key << " - " << *sitr << "\n";
}
}
}
}

Recursive Function that returns all substrings of a string

I need to implement a function in C++,
vector<string> generateSubstrings(string s),
that returns a vector of all substrings of a string. For example, the substrings of the string “rum” are the seven strings
“r”, “ru”, “rum”, “u”, “um”, “m”, “”.
The function has to be recursive and has to return the results as a vector.
Here is my code so far. It's only printing "r", "ru" and "rm". I'm having alot of trouble implementing this function. I've been working on this for the past few hours but I just can't figure out how to get it working as stated, so any help would be appreciated.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
vector<string> generateSubstrings(string s, int num){
int index = num;
int SIZE = s.size();
vector<string> substrings;
if(index == s.size()){//BASE CASE
string temp = s.substr(index,1);
substrings.push_back(temp);
}
else{
for(int i = 0; i < SIZE; ++i){
string temp = s.at(index) + s.substr(i,i);
substrings.push_back(temp);
}
generateSubstrings(s, num + 1);
}
return substrings;
}
int main() {
vector<string> vec(20);
vec = generateSubstrings("rum", 0);
cout << endl << endl;cout << "PRINTING VECTOR" << endl;
for ( int i = 0; i<vec.size();++i){
cout << vec.at(i);
cout << endl;
}
cout << "DONE";
}
In your assignment there is written that the recursive function has to be declared like
vector<string> generateSubstrings(string s),
But you are trying to make another function recursive that declared like
vector<string> generateSubstrings(string s, int num);
So in any case your solution does not satisfy the requirement of the assignment.
The function can look the following way
#include <iostream>
#include <string>
#include <vector>
std::vector<std::string> generateSubstrings( std::string s )
{
if ( s.empty() ) return {};
std::vector<std::string> v;
v.reserve( s.size() * ( s.size() + 1 ) / 2 );
for ( std::string::size_type i = 0; i < s.size(); i++ )
{
v.push_back( s.substr( 0, i + 1 ) );
}
for ( const std::string &t : generateSubstrings( s.substr( 1 ) ) )
{
v.push_back( t );
}
return v;
}
int main()
{
std::string s( "rum" );
for ( const std::string &t : generateSubstrings( s ) )
{
std::cout << t << std::endl;
}
return 0;
}
Its output is
r
ru
rum
u
um
m
If you need also to include an empty string then you should change condition
if ( s.empty() ) return {};
in appropriate way. For example
if ( s.empty() ) return { "" };
Also in this case you should write
v.reserve( s.size() * ( s.size() + 1 ) / 2 + 1 );
Also you can replace the loop in the shown function with method insert. For example
#include <iostream>
#include <string>
#include <vector>
std::vector<std::string> generateSubstrings( std::string s )
{
if ( s.empty() ) return {};
std::vector<std::string> v;
v.reserve( s.size() * ( s.size() + 1 ) / 2 );
for ( std::string::size_type i = 0; i < s.size(); i++ )
{
v.push_back( s.substr( 0, i + 1 ) );
}
std::vector<std::string> v2 = generateSubstrings( s.substr( 1 ) );
v.insert( v.end(), v2.begin(), v2.end() );
return v;
}
int main()
{
std::string s( "rum" );
for ( const std::string &t : generateSubstrings( s ) )
{
std::cout << t << std::endl;
}
return 0;
}
The program output will be the same as shown above.
Here is a program modification that includes an empty string in the vector.
#include <iostream>
#include <string>
#include <vector>
std::vector<std::string> generateSubstrings( std::string s )
{
if ( s.empty() ) return { "" };
std::vector<std::string> v;
v.reserve( s.size() * ( s.size() + 1 ) / 2 + 1 );
for ( std::string::size_type i = 0; i < s.size(); i++ )
{
v.push_back( s.substr( 0, i + 1 ) );
}
std::vector<std::string> v2 = generateSubstrings( s.substr( 1 ) );
v.insert( v.end(), v2.begin(), v2.end() );
return v;
}
int main()
{
std::string s( "rum" );
for ( const std::string &t : generateSubstrings( s ) )
{
std::cout << t << std::endl;
}
return 0;
}
Here's an answer using Python. It prints the correct result for "rum", but for "rumm" it prints two "m" substrings for obvious reasons:
def substrings(s):
result = []
if len(s) == 0:
result.append("")
if len(s) > 0:
result += substrings(s[1:])
for n in range(1,len(s)+1):
result.append(s[0:n])
return result
print substrings("rum")
print substrings("rumm")
The idea of the algorithm is the following: for "rum", the substrings are the substrings of "um" followed by "r", "ru" and "rum". For "um", the substrings are the substrings of "m" followed by "u" and "um". For "m", the substrings are the substrings of "" followed by "m". For "", the substrings are simply "". So, the final list is "", "m", "u", "um", "r", "ru", "rum".
Although this isn't C++, you should be able to translate the code to C++. But that may not necessarily be what you want as "rumm" has two "m" substrings. If you think that "rumm" should have only one "m" substring, please leave a comment and I'll post another answer.
First, you should pay attention about code indent.
Then, I don't look your code, I wrote some code to achieve your aim, as follow:
void generateSubstrings(string s, int num, vector<string> &sta)
{
if (num == s.size())
return;
auto b = begin(s) + num;
string temp = "";
temp += *b;
sta.push_back(temp);
b++;
while (b != end(s))
{
temp += *b;
sta.push_back(temp);
b++;
}
generateSubstrings(s, num + 1, sta);
}

C++: read dataset and check if vector<Class> is subset of vector<Class>

I have the following piece of code. The code creates a vector Dataset, each element of which is a vector. It also creates a vector S.
I want to check which vector of Dataset contain vector of S. Apparently I am doing something wrong, because for the following example,
Dataset is:
a b c
a d
a b d
and S:
a b
it should print: 0 2
and for me it prints: 0 1 2
#include <iostream>
#include <fstream>
#include <sstream>
#include <string.h>
#include <string>
#include <time.h>
#include <vector>
#include <algorithm>
using namespace std;
class StringRef
{
private:
char const* begin_;
int size_;
public:
int size() const { return size_; }
char const* begin() const { return begin_; }
char const* end() const { return begin_ + size_; }
StringRef( char const* const begin, int const size )
: begin_( begin )
, size_( size )
{}
bool operator<(const StringRef& obj) const
{
return (strcmp(begin(),obj.begin()) > 0 );
}
};
/************************************************
* Checks if vector B is subset of vector A *
************************************************/
bool isSubset(std::vector<StringRef> A, std::vector<StringRef> B)
{
std::sort(A.begin(), A.end());
std::sort(B.begin(), B.end());
return std::includes(A.begin(), A.end(), B.begin(), B.end());
}
vector<StringRef> split3( string const& str, char delimiter = ' ' )
{
vector<StringRef> result;
enum State { inSpace, inToken };
State state = inSpace;
char const* pTokenBegin = 0; // Init to satisfy compiler.
for(auto it = str.begin(); it != str.end(); ++it )
{
State const newState = (*it == delimiter? inSpace : inToken);
if( newState != state )
{
switch( newState )
{
case inSpace:
result.push_back( StringRef( pTokenBegin, &*it - pTokenBegin ) );
break;
case inToken:
pTokenBegin = &*it;
}
}
state = newState;
}
if( state == inToken )
{
result.push_back( StringRef( pTokenBegin, &str.back() - pTokenBegin ) );
}
return result;
}
int main() {
vector<vector<StringRef> > Dataset;
vector<vector<StringRef> > S;
ifstream input("test.dat");
long count = 0;
int sec, lps;
time_t start = time(NULL);
cin.sync_with_stdio(false); //disable synchronous IO
for( string line; getline( input, line ); )
{
Dataset.push_back(split3( line ));
count++;
};
input.close();
input.clear();
input.open("subs.dat");
for( string line; getline( input, line ); )
{
S.push_back(split3( line ));
};
for ( std::vector<std::vector<StringRef> >::size_type i = 0; i < S.size(); i++ )
{
for(std::vector<std::vector<StringRef> >::size_type j=0; j<Dataset.size();j++)
{
if (isSubset(Dataset[j], S[i]))
{
cout << j << " ";
}
}
}
sec = (int) time(NULL) - start;
cerr << "C++ : Saw " << count << " lines in " << sec << " seconds." ;
if (sec > 0) {
lps = count / sec;
cerr << " Crunch speed: " << lps << endl;
} else
cerr << endl;
return 0;
}
Your StringRef type is dangerous because it contains a const char * pointer, but no concept of ownership. So the pointer could be invalidated at some point after the object is constructed.
And indeed this is what happens here: You have a single string (line) and create StringRefs with pointers to its internal data. When the string is later modified, these pointers are invalidated.
You should create a vector<std::string> instead to prevent this problem.

HashTable... error: static assertion failed: std::hash is not specialized for this type

I posted earlier today and was able to work out a lot of my errors. However, I still have one error that I cannot figure out for the life of me. I'm basically just trying to insert a Symbol object into a HashTable and I'm constantly getting this message back:
In file included from /opt/local/include/gcc47/c++/bits/basic_string.h:3032:0,
from /opt/local/include/gcc47/c++/string:54,
from /opt/local/include/gcc47/c++/bits/locale_classes.h:42,
from /opt/local/include/gcc47/c++/bits/ios_base.h:43,
from /opt/local/include/gcc47/c++/ios:43,
from /opt/local/include/gcc47/c++/ostream:40,
from /opt/local/include/gcc47/c++/iostream:40,
from Driver.cpp:1:
/opt/local/include/gcc47/c++/bits/functional_hash.h: In instantiation of 'struct std::hash<Symbol>':
SeparateChaining.h:143:33: required from 'size_t HashTable<HashedObj>::myhash(const HashedObj&) const [with HashedObj = Symbol; size_t = long unsigned int]'
SeparateChaining.h:56:51: required from 'bool HashTable<HashedObj>::insert(HashedObj&) [with HashedObj = Symbol]'
Driver.cpp:135:26: required from here
/opt/local/include/gcc47/c++/bits/functional_hash.h:60:7: error: static assertion failed: std::hash is not specialized for this type
More specifically though.... The error:
error: static assertion failed: std::hash is not specialized for this type
Here is my Driver.cpp file:
#include <iostream>
#include <iomanip>
#include <cassert>
#include <fstream>
#include <string>
#include <vector>
#include <time.h>
#include <unistd.h>
#include <map>
#include <cstdlib>
#include <cmath>
#include "SeparateChaining.h"
using namespace std;
int TABLE_SIZE; //I know it's a global, but it allows the Table Size to be taken in within main() and used in hash()
size_t hash(const string & key);
class Symbol
{
private:
int key;
int type;
string data;
public:
const string & getData() const
{
return data;
}
int getType()
{
return type;
}
int getKey()
{
return labs(key);
}
void setType(int Type)
{
type = Type;
}
void setData(string Data)
{
data = Data;
}
void setKey(int Key)
{
key = Key;
}
bool operator== (const Symbol & rhs) const
{
return getData() == rhs.getData();
}
bool operator!= (const Symbol & rhs) const
{
return !(*this == rhs);
}
};
int main()
{
HashTable<Symbol> hashtable(TABLE_SIZE);
Symbol temp;
vector<Symbol> symbols;
string s;
int t;
int hash_key_array[TABLE_SIZE]; //array to hold hash key values
ifstream file;
file.open("symbols.txt");
if(!file)
{
cout << "System failed to open file.";
}
else
{
cout << "File successfully opened" << endl;
}
//for loop to read in the string name and the integer that follows the string name from symbols.txt
while(file >> s)
{
temp.setData(s);
file >> t;
temp.setType(t);
symbols.push_back(temp);
}
for(int i = 0; i < symbols.size(); i++)
{
cout << symbols[i].getData() << "\n";
cout << symbols[i].getType() << "\n";
}
cout << "What would you like the table size to be?" << endl;
cout << "Note: If the table size is greater than the number of objects" <<
" in the symbols.txt file, it will inevitably throw a segmentation fault" << endl;
cin >> TABLE_SIZE;
for(int j = 0; j < TABLE_SIZE; j++)
{
temp.setData(symbols[j].getData());
cout << temp.getData() << endl;
temp.setType(symbols[j].getType());
cout << temp.getType() << endl;
temp.setKey(::hash(symbols[j].getData()));
cout << "The key is: " << temp.getKey() << endl;
cout << endl;
hash_key_array[j] = temp.getKey();
for (int i = 0; i < TABLE_SIZE; i++)
{
if (i != j)
{
if (hash_key_array[i] == hash_key_array[j])
{
cout << endl;
cout << "Collision occurred at " << hash_key_array[i] << endl;
//rehash();
//cout << "The new key is: " << temp.getKey() << endl;
break;
}
}
}
hashtable.insert(temp);
}
}
size_t hash(const string & key)
{
size_t hashVal = 0;
for(char ch : key)
{
hashVal = 37 * hashVal + ch;
}
return labs(hashVal);
}
And my Header File.... SeperateChaining.h:
#ifndef SEPARATE_CHAINING_H
#define SEPARATE_CHAINING_H
#include <vector>
#include <list>
#include <string>
#include <algorithm>
#include <functional>
//#include "Hash.h"
using namespace std;
// SeparateChaining Hash table class
//
// CONSTRUCTION: an approximate initial size or default of 101
//
// ******************PUBLIC OPERATIONS*********************
// bool insert( x ) --> Insert x
// bool remove( x ) --> Remove x
// bool contains( x ) --> Return true if x is present
// void makeEmpty( ) --> Remove all items
int nextPrime( int n );
bool isPrime( int n );
template <typename HashedObj>
class HashTable
{
public:
//Uses the whatever value table_size has
//Otherwise, it will make a hash table of size 101
explicit HashTable( int TABLE_SIZE )
{
currentSize = 0;
theLists.resize(TABLE_SIZE);
}
bool contains( const HashedObj & x ) const
{
//represents the correct list in the hash table vector to start looking through
auto & whichList = theLists[ myhash( x ) ];
//returns whatever you wanted to search for in the table provided it is there
return find( begin( whichList ), end( whichList ), x ) != end( whichList );
}
void makeEmpty( )
{
for( auto & thisList : theLists )
thisList.clear( );
}
bool insert(HashedObj & temp )
{
//represents the correct list in the hash table vector to start looking through
auto & whichList = theLists[myhash( temp )];
//goes through the beginning and end of the list, and if it
//doesn't get to the end, then it found the object you wanted to insert in the hash table already
//prevents duplicate insertions
if( find( begin( whichList ), end( whichList ), temp ) != end( whichList) )
return false;
//otherwise, it has gotten to the end of the list without finding a duplicate
//and puts what you want to insert in the list
whichList.push_back( temp );
// Rehash; see Section 5.5
if( ++currentSize > theLists.size( ) )
rehash( );
return true;
}
bool insert(const HashedObj && x )
{
auto & whichList = theLists[ myhash( x ) ];
if( find( begin( whichList ), end( whichList ), x ) != end( whichList ) )
return false;
whichList.push_back( std::move( x ) );
// Rehash; see Section 5.5
if( ++currentSize > theLists.size( ) )
rehash( );
return true;
}
bool remove( const HashedObj & x )
{
//represents the correct list in the hash table vector to start looking through
auto & whichList = theLists[ myhash( x ) ];
//trying to find x within the list
//the iterator points to the slot in the list that contains x
auto itr = find( begin( whichList ), end( whichList ), x );
//if it gets to the end of the list without finding what you want to remove, then it returns false
if( itr == end( whichList ) )
{
return false;
}
//if it finds x, it removes it from the list
whichList.erase( itr );
--currentSize;
return true;
}
/*
void printTable()
{
for(int i=0; i < symbols.size(); i++)
{
cout << "The hash table contains: " << symbols[i] << endl;
}
}
*/
private:
vector<list<HashedObj>> theLists; // The array of Lists
int currentSize;
void rehash( )
{
vector<list<HashedObj>> oldLists = theLists;
// Creates new double-sized, empty table
theLists.resize( nextPrime( 2 * theLists.size( ) ) );
for( auto & thisList : theLists )
thisList.clear( );
// Copies the old table into the new table
currentSize = 0;
for( auto & thisList : oldLists )
for( auto & x : thisList )
insert( std::move( x ) );
}
size_t myhash( const HashedObj & x ) const
{
static hash<HashedObj> hf;
return hf( x ) % theLists.size( );
}
};
int nextPrime( int n )
{
if( n % 2 == 0 )
{
++n;
}
for( ; !isPrime( n ); n += 2 )
{
}
return n;
}
bool isPrime( int n )
{
if( n == 2 || n == 3 )
return true;
if( n == 1 || n % 2 == 0 )
return false;
for( int i = 3; i * i <= n; i += 2 )
if( n % i == 0 )
return false;
return true;
}
#endif
I would really appreciate you guys helping me out!
You are doing this:
static hash<HashedObj> hf;
but you have not provided a hash template, or have not specialized std::hash for HashedObj.
You should avoid using namespace std;. Amongst other things, it is difficult to figure out which hash you want to get.