I am writing a code for famous algorithm Huffman Encoding. I am getting a fatal error which turn system into blue screen and then restart. This error occurs in display_Codes which have recursive calls. The error occurs on the following lines:
display_Codes(root->l, s + "0");
display_Codes(root->r, s + "1" );
Following is the complete code.
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
class HeapNode_Min {
public:
char d;
unsigned f;
HeapNode_Min *l, *r;
HeapNode_Min(char d, unsigned f)
{
this->d = d;
this->f = f;
}
~HeapNode_Min()
{
delete l;
delete r;
}
};
class Analyze {
public:
bool operator()(HeapNode_Min* l, HeapNode_Min* r)
{
return (l->f > r->f);
}
};
void display_Codes(HeapNode_Min* root, string s)
{
if(!root)
return;
if (root->d != '$')
cout << root->d << " : " << s << "\n";
display_Codes(root->l, s + "0");
display_Codes(root->r, s + "1" );
}
void HCodes(char data[], int freq[], int s)
{
HeapNode_Min *t,*r, *l ;
priority_queue<HeapNode_Min*, vector<HeapNode_Min*>, Analyze> H_min;
int a=0;
while (a<s){H_min.push(new HeapNode_Min(data[a], freq[a])); ++a;}
while (H_min.size() != 1) {
l = H_min.top(); H_min.pop();
r = H_min.top(); H_min.pop();
t = new HeapNode_Min('$', r->f + l->f);
t->r = r; t->l = l;
H_min.push(t);
}
display_Codes(H_min.top(), "");
}
int main()
{
try
{
int frequency[] = { 3, 6, 11, 14, 18, 25 }; char alphabet[] = { 'A', 'L', 'O', 'R', 'T', 'Y' };
int size_of = sizeof(alphabet) / sizeof(alphabet[0]);
cout<<"Alphabet"<<":"<<"Huffman Code\n";
cout<<"--------------------------------\n";
HCodes(alphabet, frequency, size_of);
}
catch(...)
{
}
return 0;
}
You never set l or r to nullptr, but your code relies on the pointers being either valid or nullptr:
void display_Codes(HeapNode_Min* root, string s)
{
if(!root)
return;
if (root->d != '$')
cout << root->d << " : " << s << "\n";
display_Codes(root->l, s + "0");
display_Codes(root->r, s + "1" );
}
Pass a root with no left and no right node, then neither root->l nor root->r have a value that you could use for anything. Passing them to the next recursion lets you dereference them which invokes undefined behavior.
To fix that you need to initialize the pointers, eg in the constructor:
HeapNode_Min(char d, unsigned f) : d(d),f(f),l(nullptr),r(nullptr) { }
Also your class does not follow the rule of 3/5/0.
Related
I want to get full path in adjacency list Dijkstra algorithm using C++ queue. Graph edges are oriented.
Dijkstra algorithm works fine and I understand why. However getting full path is a bit more complicated to me, this usually described much less than Dijkstra algorithm itself. I tried to reused a few solutions (this, for example) I've found for square matrix, but it didn't worked for my adjacency list implementation.
Part I'm stucked with:
int dijkstra(int start, int finish)
{
//some code
parent.resize(vertex_count(), -1);
while (!q.empty()) {
//some code
for (auto edge : link[current]) {
if (dist[current] + edge.weight < dist[edge.to]) {
dist[edge.to] = dist[current] + edge.weight;
parent[edge.to] = start;
q.push(QueueVertex(edge.to,dist[edge.to]));
}
}
}
path(parent);
return dist[finish];
}
void path(vector<int> parent) {
for (auto i = 0; i < parent.size(); i++) {
if (parent[i] != -1)
cout << i << ' ';
}
cout << endl;
}
Full code:
#include <iostream>
#include <queue>
#include <algorithm>
#include <vector>
#include <climits>
#define INF INT_MAX
using namespace std;
struct Edge
{
int to;
int weight;
Edge() {}
Edge(int to, int weight) : to(to), weight(weight) {}
void read() {
cin >> to >> weight;
}
};
struct QueueVertex
{
int number;
int dist;
QueueVertex(int number, int dist) : number(number), dist(dist) {}
};
bool operator<(const QueueVertex& v1, const QueueVertex& v2) {
return v1.dist > v2.dist;
}
class Graph
{
vector<vector<Edge>> link;
vector <int> dist;
vector<int> parent = {};
public:
Graph(int vertex_count) :
link(vertex_count) {}
void add_edge_u(int from, int to, int weight) { //unoriented
link[from].push_back(Edge(to, weight));
link[to].push_back(Edge(from, weight));
}
void add_edge_o(int from, int to, int weight) { //oriented
link[from].push_back(Edge(to, weight));
}
int vertex_count() const {
return link.size();
}
int dijkstra(int start, int finish)
{
dist.resize(vertex_count(), INF);
dist[start] = 0;
parent.resize(vertex_count(), -1);
priority_queue <QueueVertex> q;
q.push(QueueVertex(start, 0));
while (!q.empty()) {
int current = q.top().number;
int current_dist = q.top().dist;
q.pop();
if (current_dist > dist[current]) {
continue;
}
for (auto edge : link[current]) {
if (dist[current] + edge.weight < dist[edge.to]) {
dist[edge.to] = dist[current] + edge.weight;
parent[edge.to] = start;
q.push(QueueVertex(edge.to,dist[edge.to]));
}
}
}
path(parent);
return dist[finish];
}
void path(vector<int> parent) {
for (auto i = 0; i < parent.size(); i++) {
if (parent[i] != -1)
cout << i << ' ';
}
cout << endl;
}
};
int main()
{
{
int n = 3, m = 3, start = 1, finish = 0;
Graph gr(n);
gr.add_edge_o(0, 1, 1);
gr.add_edge_o(1, 2, 2);
gr.add_edge_o(2, 3, 5);
gr.add_edge_o(3, 0, 4);
int dist = gr.dijkstra(start, finish);
cout << dist << endl;
return 0;
}
Desirable output (program getting 11 just fine, but not 1 2 3 0 part):
1 2 3 0
11
Thank you.
Your path function makes no sense. You should be using the parent array to walk backwards from the goal state to the start. As written, this function simply outputs all the parents. Consider something like this:
deque<int> path;
while(finish != -1)
{
path.push_front(finish);
finish = (finish == start) ? -1 : parent[finish];
}
for (int node : path) cout << (node + 1) << ' ';
cout << endl;
Note that the above uses a std::deque for convenience, since the path is built in reverse. But you can use a std::vector if you wish, and either reverse it or walk over it with a reverse_iterator.
Now that the path is being built correctly, you'll quickly see another problem, which is that your parent table is not being built correctly. You're doing this:
parent[edge.to] = start; //<-- incorrect
That looks like a copy/paste error, because you don't want every node's parent to point back at the start. The parent of the edge being examined is stored in current:
parent[edge.to] = current; //<-- correct
I have a list of {a,b} and i need all possible combinatations where say n=3.
so:
[a,b,a],
[b,a,b]
[a,a,a]
[b,b,b]
etc.
Is there a name of such a problem
My current solution just uses random sampling and is very inefficient:
void set_generator(const vector<int>& vec, int n){
map<string, vector<int>> imap;
int rcount = 0;
while(1){
string ms = "";
vector<int> mset;
for(int i=0; i<n; i++){
int sampled_int = vec[rand() % vec.size()];
ms += std::to_string(sampled_int);
mset.emplace_back(sampled_int);
}
if(rcount > 100)
break;
if(imap.count(ms)){
rcount += 1;
//cout << "*" << endl;
continue;
}
rcount = 0;
imap[ms] = mset;
cout << ms << endl;
}
}
set_generator({1,2},3);
Let us call b the size of the input vector.
The problem consists in generating all numbers from 0 to b^n - 1, in base b.
A simple solution increments the elements of an array one by one, each from 0 to b-1.
This is performed by the function increment in the code hereafter.
Output:
111
211
121
221
112
212
122
222
The code:
#include <iostream>
#include <vector>
#include <string>
#include <map>
void set_generator_op (const std::vector<int>& vec, int n){
std::map<std::string, std::vector<int>> imap;
int rcount = 0;
while(1){
std::string ms = "";
std::vector<int> mset;
for(int i=0; i<n; i++){
int sampled_int = vec[rand() % vec.size()];
ms += std::to_string(sampled_int);
mset.emplace_back(sampled_int);
}
if(rcount > 100)
break;
if(imap.count(ms)){
rcount += 1;
//cout << "*" << endl;
continue;
}
rcount = 0;
imap[ms] = mset;
std::cout << ms << "\n";
}
}
// incrementation of a array of int, in base "base"
// return false if max is already attained
bool increment (std::vector<int>& cpt, int base) {
int n = cpt.size();
for (int i = 0; i < n; ++i) {
cpt[i]++;
if (cpt[i] != base) {
return true;
}
cpt[i] = 0;
}
return false;
}
void set_generator_new (const std::vector<int>& vec, int n){
int base = vec.size();
std::vector<int> cpt (n, 0);
while (true) {
std::string permut = "";
for (auto &k: cpt) {
permut += std::to_string (vec[k]);
}
std::cout << permut << "\n";
if (!increment(cpt, base)) return;
}
}
int main() {
set_generator_op ({1,2},3);
std::cout << "\n";
set_generator_new ({1,2},3);
}
Following advices of Jarod42, I have
suppressed the useless conversion to a string
used a more elegant do ... while instead of the while true
inversed the iterators for printing the result
Moreover, I have created a templated version of the program.
New output:
111
112
121
122
211
212
221
222
aaa
aab
aba
abb
baa
bab
bba
bbb
And the new code:
#include <iostream>
#include <vector>
#include <string>
#include <map>
// incrementation of a array of int, in base "base"
// return false if max is already attained
bool increment (std::vector<int>& cpt, int base) {
int n = cpt.size();
for (int i = 0; i < n; ++i) {
cpt[i]++;
if (cpt[i] != base) {
return true;
}
cpt[i] = 0;
}
return false;
}
template <typename T>
void set_generator_new (const std::vector<T>& vec, int n){
int base = vec.size();
std::vector<int> cpt (n, 0);
do {
for (auto it = cpt.rbegin(); it != cpt.rend(); ++it) {
std::cout << vec[*it];
}
std::cout << "\n";
} while (increment(cpt, base));
}
int main() {
set_generator_new<int> ({1,2}, 3);
std::cout << "\n";
set_generator_new<char> ({'a','b'}, 3);
}
Besides the concrete answer for integer usage, I want to provide a generic way I needed during test case construction for scenarios with a wide spread of various parameter variations. Maybe it's helpful to you too, at least for similar scenarios.
#include <vector>
#include <memory>
class SingleParameterToVaryBase
{
public:
virtual bool varyNext() = 0;
virtual void reset() = 0;
};
template <typename _DataType, typename _ParamVariationContType>
class SingleParameterToVary : public SingleParameterToVaryBase
{
public:
SingleParameterToVary(
_DataType& param,
const _ParamVariationContType& valuesToVary) :
mParameter(param)
, mVariations(valuesToVary)
{
if (mVariations.empty())
throw std::logic_error("Empty variation container for parameter");
reset();
}
// Step to next parameter value, return false if end of value vector is reached
virtual bool varyNext() override
{
++mCurrentIt;
const bool finished = mCurrentIt == mVariations.cend();
if (finished)
{
return false;
}
else
{
mParameter = *mCurrentIt;
return true;
}
}
virtual void reset() override
{
mCurrentIt = mVariations.cbegin();
mParameter = *mCurrentIt;
}
private:
typedef typename _ParamVariationContType::const_iterator ConstIteratorType;
// Iterator to the actual values this parameter can yield
ConstIteratorType mCurrentIt;
_ParamVariationContType mVariations;
// Reference to the parameter itself
_DataType& mParameter;
};
class GenericParameterVariator
{
public:
GenericParameterVariator() : mFinished(false)
{
reset();
}
template <typename _ParameterType, typename _ParameterVariationsType>
void registerParameterToVary(
_ParameterType& param,
const _ParameterVariationsType& paramVariations)
{
mParametersToVary.push_back(
std::make_unique<SingleParameterToVary<_ParameterType, _ParameterVariationsType>>(
param, paramVariations));
}
const bool isFinished() const { return mFinished; }
void reset()
{
mFinished = false;
mNumTotalCombinationsVisited = 0;
for (const auto& upParameter : mParametersToVary)
upParameter->reset();
}
// Step into next state if possible
bool createNextParameterPermutation()
{
if (mFinished || mParametersToVary.empty())
return false;
auto itPToVary = mParametersToVary.begin();
while (itPToVary != mParametersToVary.end())
{
const auto& upParameter = *itPToVary;
// If we are the very first configuration at all, do not vary.
const bool variedSomething = mNumTotalCombinationsVisited == 0 ? true : upParameter->varyNext();
++mNumTotalCombinationsVisited;
if (!variedSomething)
{
// If we were not able to vary the last parameter in our list, we are finished.
if (std::next(itPToVary) == mParametersToVary.end())
{
mFinished = true;
return false;
}
++itPToVary;
continue;
}
else
{
if (itPToVary != mParametersToVary.begin())
{
// Reset all parameters before this one
auto itBackwd = itPToVary;
do
{
--itBackwd;
(*itBackwd)->reset();
} while (itBackwd != mParametersToVary.begin());
}
return true;
}
}
return true;
}
private:
// Linearized parameter set
std::vector<std::unique_ptr<SingleParameterToVaryBase>> mParametersToVary;
bool mFinished;
size_t mNumTotalCombinationsVisited;
};
Possible usage:
GenericParameterVariator paramVariator;
size_t param1;
int param2;
char param3;
paramVariator.registerParameterToVary(param1, std::vector<size_t>{ 1, 2 });
paramVariator.registerParameterToVary(param2, std::vector<int>{ -1, -2 });
paramVariator.registerParameterToVary(param3, std::vector<char>{ 'a', 'b' });
std::vector<std::tuple<size_t, int, char>> visitedCombinations;
while (paramVariator.createNextParameterPermutation())
visitedCombinations.push_back(std::make_tuple(param1, param2, param3));
Generates:
(1, -1, 'a')
(2, -1, 'a')
(1, -2, 'a')
(2, -2, 'a')
(1, -1, 'b')
(2, -1, 'b')
(1, -2, 'b')
(2, -2, 'b')
For sure, this can be further optimized/specialized. For instance you can simply add a hashing scheme and/or an avoid functor if you want to avoid effective repetitions. Also, since the parameters are held as references, one might consider to protect the generator from possible error-prone usage via deleting copy/assignement constructors and operators.
Time complexity is within the theoretical permutation complexity range.
I'm having trouble with a scrabble-like game I'm making. My goal was to have 5 random letters that possibly match at least one word in a dictionary I made so the game can start. I've done this but since the 5 letters are random there's probably a slim chance it will match one of the words in the dictionary. I've done test runs and got random letters but no match every time (it works hardcoded however). I figure if I can find a partial match, I can keep the letter(s) that do form part of a word and get different letters for the ones that don't. The thing is, I don't know how to go about doing this.
This is my code for the five random letters:
void fiveLetters()
{
srand(time(NULL));
for (int i =0; i<=4; i++) // display 5 random letters
{
int n = rand()%26;
char letter = (char)(n+97);
letters[i] = letter;
cout << letters[i]<< " ";
}
letters[5] = '\0'; // last value in char array null value so I can convert to string
attempt = letters; // the 4 letters
checkWords();
}
For checking if it matches a word I use:
void checkWords()
{
if (find(words.begin(),words.end(), attempt) != words.end()) // if matches word in set
{
cout << " Words found" << endl;
}
else // if it doesn't match
{
cout << "cannot find word " << endl;
attempt.clear();
fiveLetters();
}
}
The dictionary is a text file with a lot of words however since I'm just trying to get things working before I implement it, I used 5-10 words and put them in a set<string>. Sorry for the long read, any help is appreciated!
This example demonstrates using a Trie to recursively search for words loaded into it, using search criteria like counts of available letters, minimum word length, and a maximum number of "missing" letters -- letters which are used without being included as an "available" letter.
This Trie is a 26-ary tree, so each node has 26 child nodes, one for each letter in the alphabet. The root node's children are selected using the first letter in a word, the second letter chooses one of this child's children, and so on. A node contains a boolean value indicating that a word ends as that node. Such a node is not a "leaf", however, because the terminated word might be a prefix of a longer word (node terminates "ball", but still has a child branch for "balloon").
The Trie, along with a recursive search is amazingly rapid for your particular task. (By the way, the recursive search doesn't use a recursive function, it stores each level's context on a vector-based stack).
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
#include <fstream>
#include <random>
#include <algorithm>
class Trie {
// branch_count defines the number of characters which are combined to make words
// 26 is the number of letters, interpreted case-insensitively
static const int branch_count = 26;
// index_map takes a character and returns a number between 0 and branch_count-1
static int index_map(char c) {
if((c >= 'a') & (c <= 'z')) return c - 'a';
if((c >= 'A') & (c <= 'Z')) return c - 'A';
return -1;
}
// index_unmap takes an index, between 0 and branch_count-1, and returns
// the canonical character representation for that index
static char index_unmap(int index) {
return char('a' + index);
}
// verify_word returns true if all characters in the string map to an index
// returns false if at least one character is not recognized
static bool verify_word(const std::string& word) {
for(auto&& c : word) {
if(index_map(c) == -1) return false;
}
return true;
}
// Node is the Trie's branch_count-ary tree node class
struct Node {
Node* child_nodes[branch_count];
bool terminates_word;
Node() : terminates_word(false) {
for(auto& p : child_nodes) { p = nullptr; }
}
};
// make_lower(str) changes upper-case letters in str to lower-case (in-place)
static void make_lower(std::string& str) {
for(auto& c : str) {
if((c >= 'A') & (c <= 'Z')) {
c += 'a' - 'A';
} } }
// is_space_char(x) returns true when c is some kind of
// unprintable or blank, but nonzero, character
static bool is_space_char(char c) { return (c > 0) & (c <= ' '); }
// trim(str) removes whitespace from the left and right sides
// of str (str is modified in-place)
static void trim(std::string& str) {
const auto len = str.length();
if(!len) return;
auto i = len-1;
if(is_space_char(str[i])) {
for(--i; i+1; --i) {
if(!is_space_char(str[i])) {
str.resize(i+1);
break;
} } }
if(!(i+1)) {
str.clear();
return;
}
i=0;
if(is_space_char(str[i])) {
for(++i;; ++i) {
if(!is_space_char(str[i])) {
str = str.substr(i);
return;
} } } }
Node *root;
int node_count;
int word_count;
public:
// Trie::AddWord(word) stores a string in the Trie
void AddWord(std::string word) {
if(word.empty()) return;
make_lower(word);
if(!verify_word(word)) return;
Node *p = root;
for(const auto c : word) {
const int child_index = index_map(c);
if(child_index == -1) {
// verify_word(word) should have caught this.
// Well-behaved, but might use excess memory.
return;
}
Node *pchild = p->child_nodes[child_index];
if(!pchild) {
p->child_nodes[child_index] = pchild = new Node;
++node_count;
}
p = pchild;
}
if(!p->terminates_word) {
p->terminates_word = true;
++word_count;
} }
// LoadWords(input_stream) loads all line-delimited words from
// the stream into the Trie
int LoadWords(std::istream& stream_in) {
const int start_count = word_count;
std::string line;
while(std::getline(stream_in, line)) {
trim(line);
AddWord(line);
}
return word_count - start_count;
}
// LoadWords(filename) loads all line-delimited words from
// the file at the given path
int LoadWords(const std::string& file_path) {
std::ifstream stream_in(file_path.c_str());
return LoadWords(stream_in);
}
// WordCount() returns the number of words loaded so far
int WordCount() const { return word_count; }
// select_type is a helper for specifying iterator behavior
template <bool select_A, typename A, typename B>
struct select_type { typedef A type; };
template <typename A, typename B>
struct select_type<false, A, B> { typedef B type; };
template <bool select_A, typename A, typename B>
using select_type_t = typename select_type<select_A, A, B>::type;
// The iterator class is used for begin() and end(), as a minimal
// implementation compatible with range-based for,
// as well as by the destructor when destroying the
// tree's Node objects.
template <bool is_const=true, bool delete_iter=false>
class iterator {
friend class Trie;
typedef select_type_t<is_const, const Node*, Node*> pnode_t;
struct context {
pnode_t node;
int child_index;
};
std::vector<context> stack;
pnode_t advance() {
for(;;) {
if(stack.empty()) return nullptr;
pnode_t p = stack.back().node;
int &child_index = stack.back().child_index;
while(++child_index < branch_count) {
pnode_t pchild = p->child_nodes[child_index];
if(pchild) {
stack.push_back({pchild, -1});
if(!delete_iter && pchild->terminates_word) return nullptr;
break;
} }
if(stack.back().child_index == branch_count) {
stack.pop_back();
if(delete_iter) return p;
} } }
public:
iterator(pnode_t root) {
stack.push_back({root, -1});
if(!delete_iter) advance();
}
iterator() {}
std::string operator * () const {
if(stack.empty()) return std::string();
std::string word;
for(int i=0; stack[i].child_index != -1; ++i) {
word += index_unmap(stack[i].child_index);
}
return word;
}
iterator& operator ++ () {
advance();
return *this;
}
bool operator != (const iterator& iter) const {
if(stack.size() != iter.stack.size()) return true;
const int size = static_cast<int>(stack.size());
for(int i=0; i<size; ++i) {
if(stack[i].node != iter.stack[i].node) return true;
}
return false;
}
};
// ctor
Trie() : root(new Node), node_count(1), word_count(0) {}
// dtor
~Trie() {
iterator<false, true> iter(root);
int count = 0;
while(auto pn = iter.advance()) {
delete pn;
++count;
}
//std::cout << "Final word count: " << word_count << '\n';
//std::cout << count << " of " << node_count << " Node objects deleted\n";
}
// const_iterator defined from iterator with template parameter
// for selecting const Node pointers
typedef iterator<true> const_iterator;
const_iterator begin() const { return const_iterator(root); }
const_iterator end() const { return const_iterator(); }
// FindWords:
// * takes an unordered map with char keys and int values
// (counts[ch] = <how many ch may be used>)
// * takes a "max_missing" count (number of substituted characters which
// may be used when none remain in "counts")
// * takes a "min_length", the minimum length a word
// must have to be added to the results
std::vector<std::string> FindWords(const std::unordered_map<char, int>& counts, int max_missing=0, int min_length=0) {
struct context {
const Node* node;
int child_index;
std::unordered_map<char, int> counts;
int missing_count;
bool missing_letter;
context(const Node* node, const std::unordered_map<char, int>& counts, int missing_count) :
node(node),
child_index(-1),
counts(counts),
missing_count(missing_count),
missing_letter(false)
{}
};
std::vector<context> stack;
stack.push_back(context(root, counts, 0));
std::vector<std::string> match_list; // results are added to this
// This walks the tree just like the iterator's advance() function
// however, this function's context includes more info, like
// each level's available letter counts and whether a letter
// was used by taking one of the available "missing" letters.
while(!stack.empty()) {
context& ctx = stack.back();
while(++ctx.child_index < branch_count) {
const Node* pchild = ctx.node->child_nodes[ctx.child_index];
if(!pchild) continue;
const char c = index_unmap(ctx.child_index);
if(ctx.counts[c] > 0) {
ctx.missing_letter = false;
context child_ctx(pchild, ctx.counts, ctx.missing_count);
--child_ctx.counts[c];
stack.push_back(child_ctx); // ctx made invalid here
break;
}
else if(ctx.missing_count < max_missing) {
ctx.missing_letter = true;
context child_ctx(pchild, ctx.counts, ctx.missing_count + 1);
stack.push_back(child_ctx); // ctx made invalid here
break;
} }
context& fresh_ctx = stack.back();
if(fresh_ctx.child_index == branch_count) {
stack.pop_back();
continue;
}
// After a new level is pushed on the stack, check if the last node
// completes a word from the tree, then check various conditions
// required for adding it to the results.
if(static_cast<int>(stack.size()) > min_length && fresh_ctx.node->terminates_word) {
std::string word;
for(const auto& entry : stack) {
if(entry.child_index != -1) {
char c = index_unmap(entry.child_index);
if(entry.missing_letter) {
// modify the character to show it was substituted
if(c >= 'a' && c <= 'z') {
// capitalize missing lower-case letters
word += c + 'A' - 'a';
} else {
// put funky square brackets around other types of missing characters
word += '[';
word += c;
word += ']';
}
} else {
word += c;
} } }
match_list.push_back(word);
} }
return match_list;
}
// FindWords(letters, max_missing, min_length) creates a "counts" map
// from the "letters" string and uses it to call FindWords(counts...)
std::vector<std::string> FindWords(std::string letters, int max_missing=0, int min_length=0) {
std::unordered_map<char, int> counts;
for(auto c : letters) {
switch(c) {
case '?': ++max_missing; break; // '?' is a wildcard (blank tile)
default: ++counts[c]; break;
} }
return FindWords(counts, max_missing, min_length);
}
// DumpAllWords dumps all words contained in the Trie to cout (in alphabetical order)
void DumpAllWords() {
for(auto&& s : *this) {
std::cout << s << '\n';
} }
};
class DrawPool {
std::mt19937 rng;
std::string letters;
int last_count = 1;
struct arg_is_int { char i[4]; };
static arg_is_int argtype(int);
static char argtype(char);
void Add() {}
template <typename T, typename ...Args>
void Add(T arg, Args ...args) {
if(sizeof(argtype(arg)) == sizeof(arg_is_int)) {
last_count = arg;
} else {
letters += std::string(last_count, arg);
}
Add(args...);
}
public:
void Shuffle() {
letters.clear();
Add(2, '?',
12,'e', 9, 'a', 'i', 8, 'o', 6, 'n', 'r', 't',
4, 'l', 's', 'u', 'd', 3, 'g',
2, 'b', 'c', 'm', 'p', 'f', 'h', 'v', 'w', 'y',
1, 'k', 'j', 'x', 'q', 'z');
std::shuffle(letters.begin(), letters.end(), rng);
}
int Count() const { return static_cast<int>(letters.length()); }
std::string Get(int count) {
if(count > Count()) count = Count();
const std::string draw = letters.substr(0, count);
letters.erase(0, count);
return draw;
}
DrawPool() {
std::random_device rd;
std::seed_seq seed = {rd(), rd(), rd(), rd(), rd()};
rng.seed(seed);
Shuffle();
}
};
int main() {
Trie trie;
// Call trie.LoadWords(filename) with each filename in the list
// The names here are files from the SCOWL word lists.
// These may be replaced with your own file name(s).
for(auto s : {
"english-words.10",
"english-words.20",
"english-words.35",
"english-words.40",
"english-words.50",
"english-words.55",
"english-words.60",
"english-words.70",
"english-words.80",
"english-words.95"
}) {
int count = trie.LoadWords(s);
std::cout << "Loaded " << count << " new words from " << s << '\n';
}
std::cout << "\nLoaded a total of " << trie.WordCount() << " words\n";
//trie.DumpAllWords(); // send all words to cout
// match a set of 7 randomly-drawn letters
// draw one more letter each time no matches found
DrawPool draw_pool;
std::string rack;
std::vector<std::string> word_list;
do {
rack += draw_pool.Get(rack.empty() ? 7 : 1);
std::cout << "\nRack: " << rack << '\n';
// find words at least 3 letters long, using the letters
// from "rack". The only "missing" matches allowed are
// 1 for each wildcard ('?') in "rack".
word_list = trie.FindWords(rack, 0, 3);
} while(word_list.empty() && draw_pool.Count());
// Dump the results to cout
std::cout << "\nFound " << word_list.size() << " matches\n";
for(auto&& word : word_list) {
std::cout << " " << word << '\n';
}
}
This is something from my class
if (Variable_name.find(thing to check for) != string::npos)
example
if (myname.find(james) != string::npos)
{
found=true;
//do something
}
This question already has answers here:
How to use an array index as an operator?
(4 answers)
Closed 6 years ago.
please look at my c++ program.
#include<stdio.h>
int main()
{
char sign[]={'+','-','/','*'};
int i,j,k,l=0;
for(i=0;i<=3;i++)
{
for(j=0;j<=3;j++)
{
for(k=0;k<=3;k++)
{
if(sign[j]!=sign[i]&&sign[k]!=sign[i]&&sign[k]!=sign[j])
{
printf("%c %c %c\n",sign[i],sign[j],sign[k],l);
}
}
}
}
return 0;
}
the output of this program is like this..
+ - /
+ - *
+ / -
+ / *
....
I want to use them between numbers...
like this..
#include<stdio.h>
int main()
{
char sign[]={'+','-','/','*'};
int i,j,k,l=0;
for(i=0;i<=3;i++)
{
for(j=0;j<=3;j++)
{
for(k=0;k<=3;k++)
{
if(sign[j]!=sign[i]&&sign[k]!=sign[i]&&sign[k]!=sign[j])
{
int l;
l=18sign[i]12sign[j]4sign[k]5;
printf("18%c12%c4%c5=%d",sign[i],sign[j],sign[k],l);
}
}
}
}
return 0;
}
I want the output like this..
18+12-4/5=29
18+12-4*5=10
18+12/4-5=16
18+12/4*5=33
.....
then what will be the code for this??
[I can't use switch tag because for that I will have to declare 24 cases. Is there any way to use the indexes as operator??]
No.
C (and C++) are static compiled languages. You can't make decisions at run-time that require different code to be present, since the compiler is no longer around to generate that code.
In C++ you can do various template tricks to make the compiler generate code for various cases at compile-time, but it's not quite clear how that would apply, here.
You have to use an expression parser in order to handle the correct operator precedence. Look at Infix Calculator Expression Parser for a possible solution.
Following may help:
int main()
{
int numbers[] = {18, 12, 4, 5};
char signs[] = {'+', '-', '/', '*'};
std::map<char, std::function<int(int, int)>> m = {
{'+', [](int a, int b){ return a + b; }},
{'-', [](int a, int b){ return a - b; }},
{'/', [](int a, int b){ return a / b; }},
{'*', [](int a, int b){ return a * b; }},
};
std::sort(std::begin(signs), std::end(signs));
do {
int res = m[signs[2]](m[signs[1]](m[signs[0]](numbers[0], numbers[1]), numbers[2]), numbers[3]);
std::cout << numbers[0] << signs[0] << numbers[1] << signs[1]
<< numbers[2] << signs[2] << numbers[3] << " = " << res << std::endl;
} while (std::next_permutation(std::begin(signs), std::end(signs)));
return 0;
}
Live demo
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct exp {
char op;
char *term;
struct exp *left;
struct exp *right;
} Exp;
Exp *make_exp2(char *str){
if(!str || !*str) return NULL;//*str == '\0' is format error.
char *mul = strrchr(str, '*');
char *div = strrchr(str, '/');
Exp *node = malloc(sizeof(*node));
if(mul == NULL && div == NULL){
node->op = '\0';
node->term = str;
node->left = node->right = NULL;
return node;
}
char *op;
op = mul < div ? div : mul;
node->op = *op;
*op = '\0';
node->left = make_exp2(str );
node->right = make_exp2(op+1);
return node;
}
Exp *make_exp(char *str){
if(!str || !*str) return NULL;//*str == '\0' is format error.
char *minus = strrchr(str, '-');
char *plus = strrchr(str, '+');
if(minus == NULL && plus == NULL)
return make_exp2(str);
char *op;
Exp *node = malloc(sizeof(*node));
op = minus < plus ? plus : minus;
node->op = *op;
*op = '\0';
node->left = make_exp(str );
node->right = make_exp(op+1);
return node;
}
int multiplication(int a, int b){
return a * b;
}
int division(int a, int b){
return a / b;
}
int addition(int a, int b){
return a + b;
}
int subtraction(int a, int b){
return a - b;
}
int calc(Exp *exp){
switch(exp->op){
case '*' :
return multiplication(calc(exp->left), calc(exp->right));
case '/' :
return division(calc(exp->left), calc(exp->right));
case '+' :
return addition(calc(exp->left), calc(exp->right));
case '-' :
return subtraction(calc(exp->left), calc(exp->right));
default :
return atoi(exp->term);
}
}
void drop_exp(Exp *exp){
if(exp){
drop_exp(exp->left);
drop_exp(exp->right);
free(exp);
}
}
int main(void) {
char expstr[128];
sprintf(expstr, "18%c12%c4%c5", '+', '-', '/');//18+12-4/5
Exp *exp = make_exp(expstr);
printf("%d\n", calc(exp));//30
drop_exp(exp);
return 0;
}
I'm trying to use a Lua file as a config or an ini. I have succeeded but my solution irritates me. Specifically, get_double, get_int and get_string functions needs to be done in a reusable way.
I ran into problems creating function templates that don't have arguments.
Also, I'm not sure how to generalize lua_is... and lua_to.... My idea was to us if(is_same<T,double>::value) return (double)lua_isnumber(L,-1); but it didn't work.
Here is the working code:
main.cc:
#include <iostream>
#include <lua.hpp>
using namespace std;
class Lua_vm
{
private:
lua_State *L;
public:
double get_double(const char *var_name) {
lua_getglobal(L,var_name);
if (!lua_isnumber(L,-1)) {
cout << "error: " << var_name << " is of a wrong type\n";
}
return (double)lua_tonumber(L,-1);
lua_pop(L,1);
}
int get_int(const char *var_name) {
lua_getglobal(L,var_name);
if (!lua_isnumber(L,-1)) {
cout << "error: " << var_name << " is of a wrong type\n";
}
return (int)lua_tonumber(L,-1);
lua_pop(L,1);
}
string get_string(const char *var_name) {
lua_getglobal(L,var_name);
if (!lua_isstring(L,-1)) {
cout << "error: " << var_name << " is of a wrong type\n";
}
return string(lua_tostring(L,-1));
lua_pop(L,1);
}
Lua_vm(const char *lua_config_filename) {
L = lua_open();
if (luaL_loadfile(L, lua_config_filename) || lua_pcall(L, 0,0,0)) {
cout << "error: " << lua_tostring(L,-1) << "\n";
}
lua_pushnil(L);
}
~Lua_vm() {
lua_close(L);
}
};
int main(int argc, char** argv)
{
Lua_vm lvm("config.lua");
cout << "vol is " << lvm.get_double("vol") << "\n";
cout << "rho is " << lvm.get_int("rho") << "\n";
cout << "method is " << lvm.get_string("method") << "\n";
return 0;
}
config.lua:
method = "cube"
len = 3.21
rho = 13
vol = len*len*len
mass = vol*rho
It compiles with g++ main.C -I/usr/include/lua5.1/ -llua5.1 ; ./a.out
Here is code I use for that purpose (more: http://tom.rethaller.net/wiki/projects/prologue/lua)
class LuaState
{
private:
lua_State *L;
// [...]
public:
// get function
template<typename T>
T get(const char * varname) {
char temp[64];
memset(temp, 0, sizeof(temp));
int i=0;
int j=0;
int n=0;
while (varname[i] != '\0') {
char c = varname[i];
if (c == '.') {
if (n == 0)
lua_getglobal(L, temp);
else
lua_getfield(L, -1, temp);
++n;
memset(temp, 0, sizeof(temp));
j = 0;
if (lua_isnil(L, -1))
return 0;
}
else {
temp[j] = c;
++j;
}
++i;
}
if (n == 0)
lua_getglobal(L, temp);
else
lua_getfield(L, -1, temp);
return lua_get<T>();
}
// Generic get
template<typename T>
T lua_get() {
return 0;
}
// Specializations
template <> float lua_get<float>() {
return lua_tonumber(L, -1);
}
template <> double lua_get<double>() {
return lua_tonumber(L, -1);
}
template <> bool lua_get<bool>() {
return lua_toboolean(L, -1);
}
template <> int lua_get<int>() {
return lua_tointeger(L, -1);
}
template <> unsigned int lua_get<unsigned int>() {
return (unsigned int)lua_tonumber(L, -1);
}
template <> const char * lua_get<const char *>() {
return lua_tostring(L, -1);
}
};
-- Edit - To illustrate how to use it, you just have to call:
bool use_blur = lua_state.get<bool>("config.render.effects.blur");
to get the value of:
config = {
render = {
effects = {
blur = false,
}
}
}