I have been trying to solve this problem for quite a bit now and have not been able to come up with anything other than a naive solution. Basically, I am given a character grid of size N in which I have to find the number of distinct paths from the upper-left to the top-right when only traveling down and to the right that give a palindrome.
Here is an example of a grid:
ABCD
BXZX
CDXB
WCBA
There are 12 palindromes in this grid such as "ABXZXBA". My solution was to walk through all paths in the grid and check if that string was a palindrome by keeping a character stack for the first N characters and popping each character for the next N characters and checking if they were the same. This solution times out when N gets too big and I am not sure how to proceed. Any psuedocode or suggestions would be much appreciated.
Just a theory - I haven't tried to work out the code yet:
You could start at the top left and bottom right and keep the paths in sync. As it is a palindrome there would need to be the same letters in the path from the bottom as from the top.
Each time you look for the next step in a path, check to see that there is a matching letter in the reverse step.
The reverse step's available path can be further constrained in that it can't get to the left or above the forward step.
Stop when the paths meet, which is complicated by the fact that they might end up on the same grid location (odd number of rows), or they might just meet up (even number of rows).
The back tracking and stack keeping may be a bit more complicated, as you have to account for (possibly) several choices of reverse step, but it should cut down the number of possibilities. It might be better to think of it as each step in the forward and reverse paths gives you a new (smaller) grid to check for palindromes.
Something like this?
(At least it stops if the path is not forming a palindrome or is out of bounds/sync.)
JavaScript code:
function f(m){
var stack = [[0,0,m.length - 1,m.length - 1,""]],
count = 0;
while(stack.length > 0){
var next = stack.pop(),
y = next[0],
x = next[1],
yr = next[2]
xr = next[3];
if (y - yr > 0 || x - xr > 0){
continue;
} else if (m[y][x] != m[yr][xr]){
continue;
} else if (y == yr && x == xr){
count++;
} else {
stack.push([y + 1,x,yr - 1,xr]);
stack.push([y + 1,x,yr,xr - 1]);
stack.push([y,x + 1,yr - 1,xr]);
stack.push([y,x + 1,yr,xr - 1]);
}
}
return count;
}
Output:
var t = [["A","B","C","D"]
,["B","X","Z","X"]
,["C","D","X","B"]
,["W","C","B","A"]];
console.log(f(t));
12
Related
The task is to justify text within a certain width.
user inputs: Hello my name is Harrry. This is a sample text input that nobody
will enter.
output: What text width do you want?
user inputs: 15
output: |Hello my name|
|is Harrry. This|
|is a sample|
|text that|
|nobody will|
|enter. |
Basically, the line has to be 15 spaces wide including blank spaces. Also, if the next word in the line cant fit into 15, it will skip entirely. If there are multiple words in a line, it will try to distribute the spaces evenly between each word. See the line that says "Is a sample" for example.
I created a vector using getline(...) and all that and the entire text is saved in a vector. However, I'm kind of stuck on moving forward. I tried using multiple for loops, but I just cant seem to skip lines or even out the spacing at all.
Again, not looking or expecting anyone to solve this, but I'd appreciate it if you could guide me into the right direction in terms of logic/algorithm i should think about.
You should consider this Dynamic programming solution.
Split text into “good” lines
Since we don't know where we need to break the line for good justification, we start guessing where the break to be done to the paragraph. (That is we guess to determine whether we should break between two words and make the second word as start of the next line).
You notice something? We brutefore!
And note that if we can't find a word small enought to fit in the remaining space in the current line, we insert spaces inbetween the words in the current line. So, the space in the current line depends on the words that might go into the next or previous line. That's Dependency!
You are bruteforcing and you have dependency,there comes the DP!
Now lets define a state to identify the position on our path to solve this problem.
State: [i : j] ,which denotes line of words from ith word to jth word in the original sequence of words given as input.
Now, that you have state for the problem let us try to define how these states are related.
Since all our sub-problem states are just a pile of words, we can't just compare the words in each state and determine which one is better. Here better delineates to the use of line's width to hold maximum character and minimum spaces between the words in the particular line. So, we define a parameter, that would measure the goodness of the list of words from ith to jth words to make a line. (recall our definition of subproblem state). This is basically evaluating each of our subproblem state.
A simple comparison factor would be :
Define badness(i, j) for line of words[i : j].
For example,
Infinity if total length > page width,
else (page width − total length of words in current line)3
To make things even simple consider only suffix of the given text and apply this algorithm. This would reduce the DP table size from N*N to N.
So, For finishing lets make it clear what we want in DP terms,
subproblem = min. badness for suffix words[i :]
=⇒ No.of subproblems = Θ(n) where n = no of words
guessing = where to end first line, say i : j
=⇒ no. of choices for j = n − i = O(n)
recurrence relation between the subproblem:
• DP[i] = min(badness (i, j) + DP[j] for j in range (i + 1, n + 1))
• DP[n] = 0
=⇒ time per subproblem = Θ(n)
so, total time = Θ(n^2).
Also, I'll leave it to you how insert spaces between words after determining the words in each line.
Logic would be:
1) Put words in array
2) Loop though array of words
3) Count the number of chars in each word, and check until they are the text width or less (skip if more than textwidth). Remember the number of words that make up the total before going over 15 (example remember it took 3 words to get 9 characters, leaving space for 6 spaces)
4) Divide the number of spaces required by (number of words - 1)
5) Write those words, writing the same number of spaces each time.
Should give the desired effect I hope.
You obviously have some idea how to solve this, as you have already produced the sample output.
Perhaps re-solve your original problem writing down in words what you do in each step....
e.g.
Print text asking for sentence.
Take input
Split input into words.
Print text asking for width.
...
If you are stuck at any level, then expand the details into sub-steps.
I would look to separate the problem of working out a sequence of words which will fit onto a line.
Then how many spaces to add between each of the words.
Below is an example for printing one line after you find how many words to print and what is the starting word of the line.
std::cout << "|";
numOfSpaces = lineWidth - numOfCharsUsedByWords;
/*
* If we have three words |word1 word2 word3| in a line
* ideally the spaces to print between then are 1 less than the words
*/
int spaceChunks = numOfWordsInLine - 1;
/*
* Print the words from starting point to num of words
* you can print in a line
*/
for (j = 0; j < numOfWordsInLine; ++j) {
/*
* Calculation for the number of spaces to print
* after every word
*/
int spacesToPrint = 0;
if (spaceChunks <= 1) {
/*
* if one/two words then one
* chunk of spaces between so fill then up
*/
spacesToPrint = numOfSpaces;
} else {
/*
* Here its just segmenting a number into chunks
* example: segment 7 into 3 parts, will become 3 + 2 + 2
* 7 to 3 = (7%3) + (7/3) = 1 + 2 = 3
* 4 to 2 = (4%2) + (4/2) = 0 + 2 = 2
* 2 to 1 = (2%1) + (2/1) = 0 + 2 = 2
*/
spacesToPrint = (numOfSpaces % spaceChunks) + (numOfSpaces / spaceChunks);
}
numOfSpaces -= spacesToPrint;
spaceChunks--;
cout << words[j + lineStartIdx];
for (int space = 0; space < spacesToPrint; space++) {
std::cout << " ";
}
}
std::cout << "|" << std::endl;
Hope this code helps. Also you need to consider what happens if you set width less then the max word size.
int trees = 3;
int tree_x, tree_y;
for(int r = 0; r < m_townsize; r++)
{
for(int c = 0; c < m_townsize; c++)
{
if(r == 0 || c == 0 || r == (m_townsize - 1) || c == (m_townsize - 1))
m_town[r][c] = 'W';
while(trees > 0)
{
tree_x = random() % m_townsize;
tree_y = random() % m_townsize;
cout << tree_y << "," << tree_x << endl;
if(m_town[tree_y][tree_x] == ' ')
{
m_town[tree_y][tree_x] = 'T';
trees -= 1;
}
}
}
}
According the code I have written, if there is a space character at the coordinate of the tree, it should place a tree and lower the tree count by 1.
If there is not a space there, it should skip placing a tree, thus not decrementing. This should cause it to pick another set of coordinates and run through again.
However, if you look at this particular output it is running to the if-statement skipping the first option to replace it with a T--since it is a W--but still decrementing by 1. I don't get it. It should skip the statement all together, not skip just the first line. Netbeans tells me my brackets are right, so it shouldn't be an issue with the assignment belonging to the if and the decrement belonging to the while.
If I make a do-while loop it places a whole bunch. I don't know what's happening.
This output placed 2 trees.
You are walking over each coordinate.
If it is on the edge you put a 'W'. Then you randomly place a tree 'T'.
Then you proceed to the next coordinate.
This means you can place some trees in squares before you overwrite with a 'W'.
Finish all the walls before placing trees. Consider a more efficient way to place walls to, like doing each edge instead of loopimg over the middle abd doing nothing.
In my c++ class, we got assigned pairs. Normally I can come up with an effective algorithm quite easily, this time I cannot figure out how to do this to save my life.
What I am looking for is someone to explain an algorithm (or just give me tips on what would work) in order to get this done. I'm still at the planning stage and want to get this code done on my own in order to learn. I just need a little help to get there.
We have to create histograms based on a 4 or 5 integer input. It is supposed to look something like this:
Calling histo(5, 4, 6, 2) should produce output that appears like:
*
* *
* * *
* * *
* * * *
* * * *
-------
A B C D
The formatting to this is just killing me. What makes it worse is that we cannot use any type of arrays or "advanced" sorting systems using other libraries.
At first I thought I could arrange the values from highest to lowest order. But then I realized I did not know how to do this without using the sort function and I was not sure how to go on from there.
Kudos for anyone who could help me get started on this assignment. :)
Try something along the lines of this:
Determine the largest number in the histogram
Using a loop like this to construct the histogram:
for(int i = largest; i >= 1; i--)
Inside the body of the loop, do steps 3 to 5 inclusive
If i <= value_of_column_a then print a *, otherwise print a space
Repeat step 3 for each column (or write a loop...)
Print a newline character
Print the horizontal line using -
Print the column labels
Maybe i'm mistaken on your q, but if you know how many items are in each column, it should be pretty easy to print them like your example:
Step 1: Find the Max of the numbers, store in variable, assign to column.
Step 2: Print spaces until you get to column with the max. Print star. Print remaining stars / spaces. Add a \n character.
Step 3: Find next max. Print stars in columns where the max is >= the max, otherwise print a space. Add newline. at end.
Step 4: Repeat step 3 (until stop condition below)
when you've printed the # of stars equal to the largest max, you've printed all of them.
Step 5: add the -------- line, and a \n
Step 6: add row headers and a \n
If I understood the problem correctly I think the problem can be solved like this:
a= <array of the numbers entered>
T=<number of numbers entered> = length(a) //This variable is used to
//determine if we have finished
//and it will change its value
Alph={A,B,C,D,E,F,G,..., Z} //A constant array containing the alphabet
//We will use it to print the bottom row
for (i=1 to T) {print Alph[i]+" "}; //Prints the letters (plus space),
//one for each number entered
for (i=1 to T) {print "--"}; //Prints the two dashes per letter above
//the letters, one for each
while (T!=0) do {
for (i=1 to N) do {
if (a[i]>0) {print "*"; a[i]--;} else {print " "; T--;};
};
if (T!=0) {T=N};
}
What this does is, for each non-zero entered number, it will print a * and then decrease the number entered. When one of the numbers becomes zero it stops putting *s for its column. When all numbers have become zero (notice that this will occur when the value of T comes out of the for as zero. This is what the variable T is for) then it stops.
I think the problem wasn't really about histograms. Notice it also doesn't require sorting or even knowing the
In my program I need to search in a quite big string (~1 mb) for a relatively small substring (< 1 kb).
The problem is the string contains simple wildcards in the sense of "a?c" which means I want to search for strings like "abc" or also "apc",... (I am only interested in the first occurence).
Until now I use the trivial approach (here in pseudocode)
algorithm "search", input: haystack(string), needle(string)
for(i = 0, i < length(haystack), ++i)
if(!CompareMemory(haystack+i,needle,length(needle))
return i;
return -1; (Not found)
Where "CompareMemory" returns 0 iff the first and second argument are identical (also concerning wildcards) only regarding the amount of bytes the third argument gives.
My question is now if there is a fast algorithm for this (you don't have to give it, but if you do I would prefer c++, c or pseudocode). I started here
but I think most of the fast algorithms don't allow wildcards (by the way they exploit the nature of strings).
I hope the format of the question is ok because I am new here, thank you in advance!
A fast way, which is kind of the same thing as using a regexp, (which I would recommend anyway), is to find something that is fixed in needle, "a", but not "?", and search for it, then see if you've got a complete match.
j = firstNonWildcardPos(needle)
for(i = j, i < length(haystack)-length(needle)+j, ++i)
if(haystack[i] == needle[j])
if(!CompareMemory(haystack+i-j,needle,length(needle))
return i;
return -1; (Not found)
A regexp would generate code similar to this (I believe).
Among strings over an alphabet of c characters, let S have length s and let T_1 ... T_k have average length b. S will be searched for each of the k target strings. (The problem statement doesn't mention multiple searches of a given string; I mention it below because in that paradigm my program does well.)
The program uses O(s+c) time and space for setup, and (if S and the T_i are random strings) O(k*u*s/c) + O(k*b + k*b*s/c^u) total time for searching, with u=3 in program as shown. For longer targets, u should be increased, and rare, widely-separated key characters chosen.
In step 1, the program creates an array L of s+TsizMax integers (in program, TsizMax = allowed target length) and uses it for c lists of locations of next occurrences of characters, with list heads in H[] and tails in T[]. This is the O(s+c) time and space step.
In step 2, the program repeatedly reads and processes target strings. Step 2A chooses u = 3 different non-wild key characters (in current target). As shown, the program just uses the first three such characters; with a tiny bit more work, it could instead use the rarest characters in the target, to improve performance. Note, it doesn't cope with targets with fewer than three such characters.
The line "L[T[r]] = L[g+i] = g+i;" within Step 2A sets up a guard cell in L with proper delta offset so that Step 2G will automatically execute at end of search, without needing any extra testing during the search. T[r] indexes the tail cell of the list for character r, so cell L[g+i] becomes a new, self-referencing, end-of-list for character r. (This technique allows the loops to run with a minimum of extraneous condition testing.)
Step 2B sets vars a,b,c to head-of-list locations, and sets deltas dab, dac, and dbc corresponding to distances between the chosen key characters in target.
Step 2C checks if key characters appear in S. This step is necessary because otherwise a while loop in Step 2E will hang. We don't want more checks within those while loops because they are the inner loops of search.
Step 2D does steps 2E to 2i until var c points to after end of S, at which point it is impossible to make any more matches.
Step 2E consists of u = 3 while loops, that "enforce delta distances", that is, crawl indexes a,b,c along over each other as long as they are not pattern-compatible. The while loops are fairly fast, each being in essence (with ++si instrumentation removed) "while (v+d < w) v = L[v]" for various v, d, w. Replicating the three while loops a few times may increase performance a little and will not change net results.
In Step 2G, we know that the u key characters match, so we do a complete compare of target to match point, with wild-character handling. Step 2H reports result of compare. Program as given also reports non-matches in this section; remove that in production.
Step 2I advances all the key-character indexes, because none of the currently-indexed characters can be the key part of another match.
You can run the program to see a few operation-count statistics. For example, the output
Target 5=<de?ga>
012345678901234567890123456789012345678901
abc1efgabc2efgabcde3gabcdefg4bcdefgabc5efg
# 17, de?ga and de3ga match
# 24, de?ga and defg4 differ
# 31, de?ga and defga match
Advances: 'd' 0+3 'e' 3+3 'g' 3+3 = 6+9 = 15
shows that Step 2G was entered 3 times (ie, the key characters matched 3 times); the full compare succeeded twice; step 2E while loops advanced indexes 6 times; step 2I advanced indexes 9 times; there were 15 advances in all, to search the 42-character string for the de?ga target.
/* jiw
$Id: stringsearch.c,v 1.2 2011/08/19 08:53:44 j-waldby Exp j-waldby $
Re: Concept-code for searching a long string for short targets,
where targets may contain wildcard characters.
The user can enter any number of targets as command line parameters.
This code has 2 long strings available for testing; if the first
character of the first parameter is '1' the jay[42] string is used,
else kay[321].
Eg, for tests with *hay = jay use command like
./stringsearch 1e?g a?cd bc?e?g c?efg de?ga ddee? ddee?f
or with *hay = kay,
./stringsearch bc?e? jih? pa?j ?av??j
to exercise program.
Copyright 2011 James Waldby. Offered without warranty
under GPL v3 terms as at http://www.gnu.org/licenses/gpl.html
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
//================================================
int main(int argc, char *argv[]) {
char jay[]="abc1efgabc2efgabcde3gabcdefg4bcdefgabc5efg";
char kay[]="ludehkhtdiokihtmaihitoia1htkjkkchajajavpajkihtijkhijhipaja"
"etpajamhkajajacpajihiatokajavtoia2pkjpajjhiifakacpajjhiatkpajfojii"
"etkajamhpajajakpajihiatoiakavtoia3pakpajjhiifakacpajjhkatvpajfojii"
"ihiifojjjjhijpjkhtfdoiajadijpkoia4jihtfjavpapakjhiifjpajihiifkjach"
"ihikfkjjjjhijpjkhtfdoiajakijptoik4jihtfjakpapajjkiifjpajkhiifajkch";
char *hay = (argc>1 && argv[1][0]=='1')? jay:kay;
enum { chars=1<<CHAR_BIT, TsizMax=40, Lsiz=TsizMax+sizeof kay, L1, L2 };
int L[L2], H[chars], T[chars], g, k, par;
// Step 1. Make arrays L, H, T.
for (k=0; k<chars; ++k) H[k] = T[k] = L1; // Init H and T
for (g=0; hay[g]; ++g) { // Make linked character lists for hay.
k = hay[g]; // In same loop, could count char freqs.
if (T[k]==L1) H[k] = T[k] = g;
T[k] = L[T[k]] = g;
}
// Step 2. Read and process target strings.
for (par=1; par<argc; ++par) {
int alpha[3], at[3], a=g, b=g, c=g, da, dab, dbc, dac, i, j, r;
char * targ = argv[par];
enum { wild = '?' };
int sa=0, sb=0, sc=0, ta=0, tb=0, tc=0;
printf ("Target %d=<%s>\n", par, targ);
// Step 2A. Choose 3 non-wild characters to follow.
// As is, chooses first 3 non-wilds for a,b,c.
// Could instead choose 3 rarest characters.
for (j=0; j<3; ++j) alpha[j] = -j;
for (i=j=0; targ[i] && j<3; ++i)
if (targ[i] != wild) {
r = alpha[j] = targ[i];
if (alpha[0]==alpha[1] || alpha[1]==alpha[2]
|| alpha[0]==alpha[2]) continue;
at[j] = i;
L[T[r]] = L[g+i] = g+i;
++j;
}
if (j != 3) {
printf (" Too few target chars\n");
continue;
}
// Step 2B. Set a,b,c to head-of-list locations, set deltas.
da = at[0];
a = H[alpha[0]]; dab = at[1]-at[0];
b = H[alpha[1]]; dbc = at[2]-at[1];
c = H[alpha[2]]; dac = at[2]-at[0];
// Step 2C. See if key characters appear in haystack
if (a >= g || b >= g || c >= g) {
printf (" No match on some character\n");
continue;
}
for (g=0; hay[g]; ++g) printf ("%d", g%10);
printf ("\n%s\n", hay); // Show haystack, for user aid
// Step 2D. Search for match
while (c < g) {
// Step 2E. Enforce delta distances
while (a+dab < b) {a = L[a]; ++sa; } // Replicate these
while (b+dbc < c) {b = L[b]; ++sb; } // 3 abc lines as many
while (a+dac > c) {c = L[c]; ++sc; } // times as you like.
while (a+dab < b) {a = L[a]; ++sa; } // Replicate these
while (b+dbc < c) {b = L[b]; ++sb; } // 3 abc lines as many
while (a+dac > c) {c = L[c]; ++sc; } // times as you like.
// Step 2F. See if delta distances were met
if (a+dab==b && b+dbc==c && c<g) {
// Step 2G. Yes, so we have 3-letter-match and need to test whole match.
r = a-da;
for (k=0; targ[k]; ++k)
if ((hay[r+k] != targ[k]) && (targ[k] != wild))
break;
printf ("# %3d, %s and ", r, targ);
for (i=0; targ[i]; ++i) putchar(hay[r++]);
// Step 2H. Report match, if found
puts (targ[k]? " differ" : " match");
// Step 2I. Advance all of a,b,c, to go on looking
a = L[a]; ++ta;
b = L[b]; ++tb;
c = L[c]; ++tc;
}
}
printf ("Advances: '%c' %d+%d '%c' %d+%d '%c' %d+%d = %d+%d = %d\n",
alpha[0], sa,ta, alpha[1], sb,tb, alpha[2], sc,tc,
sa+sb+sc, ta+tb+tc, sa+sb+sc+ta+tb+tc);
}
return 0;
}
Note, if you like this answer better than current preferred answer, unmark that one and mark this one. :)
Regular expressions usually use a finite state automation-based search, I think. Try implementing that.
My C++ program creates a binary search tree. I know how to print out the values in pre-order, post-order, and in-order.
However, I want to do something a little more difficult. I want to print out the values the way they would look if someone drew the tree on paper. It would have the root at the center at the top, it's left child right under and to the left of it, and it's right child right under and to the right of it. The rest of the nodes would be drawn accordingly.
How can I do that?
This article contains code for what you need, it seems:
alt text http://www.cpp-programming.net/wp-content/uploads/2007/12/ascii_tree.jpg
Edit: that site went offline
Here's another one exploring some other options.
Here's approximate pseudo-code to do it. The basic idea is walk the tree layer-by-layer, printing all the node in each layer on one line. Each node is separated by twice as much space as the nodes below it. Since the tree is not all of uniform depth, it is artificially padded with virtual nodes to take up the blank spaces where nodes don't exist.
measure the depth of the tree, call that D
have two queues, called Q1 and Q2
enque the top node of the tree in Q1
for (i = D; --i>=0; ){
foreach node in Q1 {
on first iteration of this inner loop, print 2^i - 1 spaces,
else print 2^(i+1) - 1 spaces.
if node == null print blank
else print node.value
if node.left exists enque node.left in Q2
else enque null in Q2
if node.right exists enque node.right in Q2
else enque null in Q2
}
copy Q2 to Q1
clear Q2
print end-of-line
}
Each space that is printed is the width of one numeric field. Suppose the tree has depth D = 4. Then the printing goes like this:
// it looks like this, and the space sequences are
i = 3: -------n 7
i = 2: ---n-------n 3 7
i = 1: -n---n---n---n 1 3 3 3
i = 0: n-n-n-n-n-n-n-n 0 1 1 1 1 1 1 1
void print(node *p,int start)
{
start++;
if (p->right != NULL)
{
print(p->right,start);
}
for (int i = 0; i <= start; i++)
{
cout<<" ";
}
cout << p->value<<endl;
if (p->left != NULL)
{
print(p->left, start);
}
}
One way is to use graphviz. Specifically, use its "dot" program, but getting the output to look exactly as you describe may not be possible.
well, in a terminal it's hard...since it may not fit. But there are graph drawing libraries out there that can make nice pictures for you. There is graphvis that is one of the most popular.
edit:
if you really just wan to print text, graphvis has a markup language that a user can pass to graphvis that in turn makes the nice pictures.