Redis Lexicographical Range Search Inconsistent Results - search

I am trying to do a lexicographical range search on a Redis sorted set, but getting inconsistent results based on my understanding of how this feature works. The results are similar when using ZRANGECOUNT, ZRANGEBYLEX, and ZREMRANGEBYLEX.
Working Queries
This is an example of my set with 3 elements just using ZRANGE.
redis> ZRANGE myset 0 -1
0 00000000022xm26hax001
1 00000000022xm26hax002
2 00000000022xm26hax003
I can also get all of the elements lexicographically.
redis> ZRANGEBYLEX myset - +
0 00000000022xm26hax001
1 00000000022xm26hax002
2 00000000022xm26hax003
Doing a range search by leaving off the last 3 characters also works as expected.
redis> ZRANGEBYLEX myset [00000000022xm26hax [00000000022xm26hax\xff
0 00000000022xm26hax001
1 00000000022xm26hax002
2 00000000022xm26hax003
Adjusting the range arguments I can select just the first two elements as well.
redis> ZRANGEBYLEX myset [00000000022xm26hax001 [00000000022xm26hax002\xff
0 00000000022xm26hax001
1 00000000022xm26hax002
A short start seems to be acceptable:
redis> ZRANGEBYLEX myset [00000000022x [00000000022xm26hax001\xff
0 00000000022xm26hax001
Problem Queries
I run into problems however when I try to select using a shorter version of the string - these all return 0 results when I would expect them to return 3.
ZRANGEBYLEX myset [00000000022xm26h [00000000022xm26h\xff
ZRANGEBYLEX myset [00000000022x [00000000022x\xff
But then adding back just the "m" makes it return all three elements again.
redis> ZRANGEBYLEX myset [00000000022xm [00000000022xm\xff
0 00000000022xm26hax001
1 00000000022xm26hax002
2 00000000022xm26hax003
Can someone explain this behavior? What is the correct way to get back all elements that start with "00000000022x" given my example dataset?
Why does ZRANGEBYLEX myset [00000000022x [00000000022x\xff return no results but ZRANGEBYLEX myset [00000000022xm [00000000022xm\xff returns all the results - just adding the "m" seems to make it work as expected?

If you would like Redis to resolve escape codes in your strings (like the \xff in your examples), you need to wrap the strings in quotation marks.
In other words, this will treat \xff as byte 255:
127.0.0.1:6379> ZRANGEBYLEX myset [00000000022xm26hax001 "[00000000022xm26ha\xff"
1) "00000000022xm26hax001"
2) "00000000022xm26hax002"
3) "00000000022xm26hax003"
Whereas this treats \xff as four bytes (92, 120, 102, 102):
127.0.0.1:6379> ZRANGEBYLEX myset [00000000022xm26hax001 [00000000022xm26ha\xff
(empty list or set)
This explains your confusing results.

The solution to this could ultimately not be determined by the question I posted. For clarity I left out the score of each sorted set entry which was meant to be an expiration timestamp. Unfortunately the documentation for ZRANGEBYLEX says:
When all the elements in a sorted set are inserted with the same score, in order to force lexicographical ordering, this command returns all the elements in the sorted set at key with a value between min and max.
My entries did not have the same score so they were not being sorted lexicographically.

Related

String permutations in lexigraphic order without inversions/reversions

The problem:
I would like to generate a list of permutations of strings in lexigraphical but excluding string inversions. For instance, if I have the following string: abc, I would like to generate the following list
abc
acb
bac
instead of the typical
abc
acb
bac
bca
cab
cba
An alternative example would look something like this:
100
010
instead of
100
010
001
Currently, I can generate the permutations using perl, but I am not sure on how to best remove the reverse duplicates.
I had thought of applying something like the following:
create map with the following:
1) 100
2) 010
3) 001
then perform the reversion/inversion on each element in the map and create a new map with:
1') 001
2') 010
3') 100
then compare and if the primed list value matches the original value, leave it in place, if it is different, if it's index is greater than the median index, keep it, else remove.
Trouble is, I am not sure if this is an efficient approach or not.
Any advice would be great.
Two possibilities represented by examples are for permutations where all elements are different (abcd), or for variations of two symbols where one appears exactly once (1000). More general cases are addressed as well.
Non-repeating elements (permutations)
Here we can make use of Algorithm::Permute, and of the particular observation:
Each permutation where the first element is greater than its last need be excluded. It comes from this post, brought up in the answer by ysth.
This rule holds as follows. Consider substrings of a string without its first and last elements. For each such substring, all permutations of the string must contain its inverse. One of these, padded with last and first, is thus the inverse of the string. By construction, for each substring there is exactly one inverse. Thus permutations with swapped first and last elements of each string need be excluded.
use warnings;
use strict;
use feature 'say';
use Algorithm::Permute;
my $size = shift || 4;
my #arr = ('a'..'z')[0..$size-1]; # 1..$size for numbers
my #res;
Algorithm::Permute::permute {
push #res, (join '', #arr) unless $arr[0] gt $arr[-1]
} #arr;
say for #arr;
Problems with repetead elements (abbcd) can be treated the exact same way as above, and we need to also prune duplicates as permutations of b generate abbcd and abbcd (same)
use List::MoreUtils 'uniq';
# build #res the same way as above ...
my #res = uniq #res;
Doing this during construction would not reduce complexity nor speed things up.
The permute is quoted as the fastest method in the module, by far. It is about an order of magnitude faster than the other modules I tested (below), taking about 1 second for 10 elements on my system. But note that this problem's complexity is factorial in size. It blows up really fast.
Two symbols, where one appears exactly once (variations)
This is different and the above module is not meant for it, nor would the exclusion criterion work. There are other modules, see at the end. However, the problem here is very simple.
Start from (1,0,0,...) and 'walk' 1 along the list, up to the "midpoint" – which is the half for even sized list (4 for 8-long), or next past half for odd sizes (5 for 9-long). All strings obtained this way, by moving 1 by one position up to midpoint, form the set. The second "half" are their inversions.
use warnings;
use strict;
my $size = shift || 4;
my #n = (1, map { 0 } 1..$size-1);
my #res = (join '', #n); # first element of the result
my $end_idx = ( #n % 2 == 0 ) ? #n/2 - 1 : int(#n/2);
foreach my $i (0..$end_idx-1) # stop one short as we write one past $i
{
#n[$i, $i+1] = (0, 1); # move 1 by one position from where it is
push #res, join '', #n;
}
print "$_\n" for #res;
We need to stop before the last index since it has been filled in the previous iteration.
This can be modified if both symbols (0,1) may appear repeatedly, but it is far simpler to use a module and then exclude inverses. The Algorithm::Combinatorics has routines for all needs here. For all variations of 0 and 1 of lenght $size, where both may repeat
use Algorithm::Combinatorics qw(variations_with_repetition);
my #rep_vars = variations_with_repetition([0, 1], $size);
Inverse elements can then be excluded by a brute-force search, with O(N2) complexity at worst.
Also note Math::Combinatorics.
The answer in the suggested duplicate Generating permutations which are not mirrors of each other doesn't deal with repeated elements (because that wasn't part of that question) so naively following it would include e.g. both 0100 and 0010. So this isn't an exact duplicate. But the idea applies.
Generate all the permutations but filter only for those with $_ le reverse $_. I think this is essentially what you suggest in the question, but there's no need to compute a map when a simple expression applied to each permutation will tell you whether to include it or not.

Finding the Minimum Window in S which Contains All Elements from T

I have a specific question about the code in the problem and its solution at http://articles.leetcode.com/finding-minimum-window-in-s-which
In the code below the figure (NOT the figure above the figure), 5th line of code from for loop
if (hasFound[S[end]] <= needToFind[S[end]]) **// WHY this condition is required???**
count++;
Based on my understanding
1) this if condition is not needed and just (whenever found a char just increase count which represents the # of chars found so far)
count++;
2) OR could be < (instead of <=) and equal doesn't seem to make sense for me
if (hasFound[S[end]] < needToFind[S[end]])
count++;
I tested 1) and 2) but neither of them give me the correct answer for all cases.
only (if condition with <=) gives me the correct solution for all cases.
I really don't understand why
if (hasFound[S[end]] <= needToFind[S[end]])
should be required to make this code work correctly for all cases.
Imagine that pattern T contains 3 chars A and 2 chars B.
So needToFind['A'] = 3
And you have to increment count, when hasFound['A'] becomes 1, 2 and 3
When hasFound['A'] becomes 2 only (you proposition about '<'), window contains only two A chars, it is impossible to make T, and count never reaches tLen=5
If remove this condition at all, 5 chars A give count=5=tlen, while window still doesn't contain any B

Minimum Character that needed to be deleted

Original Problem:
A word was K-good if for every two letters in the word, if the first appears x times and the second appears y times, then |x - y| ≤ K.
Given some word w, how many letters does he have to remove to make it K-good?
Problem Link.
I have solved the above problem and i not asking solution for the above
problem
I just misread the statement for first time and just thought how can we solve this problem in linear line time , which just give rise to a new problem
Modification Problem
A word was K-good if for every two consecutive letters in the word, if the first appears x times and the second appears y times, then |x - y| ≤ K.
Given some word w, how many letters does he have to remove to make it K-good?
Is this problem is solvable in linear time , i thought about it but could not find any valid solution.
Solution
My Approach: I could not approach my crush but her is my approach to this problem , try everything( from movie Zooptopia)
i.e.
for i range(0,1<<n): // n length of string
for j in range(0,n):
if(i&(1<<j) is not zero): delete the character
Now check if String is K good
For N in Range 10^5. Time Complexity: Time does not exist in that dimension.
Is there any linear solution to this problem , simple and sweet like people of stackoverflow.
For Ex:
String S = AABCBBCB and K=1
If we delete 'B' at index 5 so String S = AABCBCB which is good string
F[A]-F[A]=0
F[B]-F[A]=1
F[C]-F[B]=1
and so on
I guess this is a simple example there can me more complex example as deleting an I element makens (I-1) and (I+1) as consecutive
Is there any linear solution to this problem?
Consider the word DDDAAABBDC. This word is 3-good, becauseDandCare consecutive and card(D)-card(C)=3, and removing the lastDmakes it 1-good by makingDandCnon-consecutive.
Inversely if I consider DABABABBDC which is 2-good, removing the lastDmakes CandBconsecutive and increases the K-value of the word to 3.
This means that in the modified problem, the K-value of a word is determined by both the cardinals of each letter and the cardinals of each couple of consecutive letters.
By removing a letter, I reduce its cardinal of the letter as well as the cardinals of the pairs to which it belongs, but I also increase the cardinal of other pair (potentially creating new ones).
It is also important to notice that if in the original problem, all letters are equivalent (I can remove any indifferently), while it is no longer the case in the modified problem.
As a conclusion, I think we can safely assume that the "consecutive letters" constrain makes the problem not solvable in linear time for any alphabet/word.
Instead of finding the linear time solution, which i think doesn't exist (among others because there seem to be a multitude of alternative solutions to each K request), i'd like to preset the totally geeky solution.
Namely, take the parallel array processing language Dyalog APL and create these two tiny dynamic functions:
good←{1≥⍴⍵:¯1 ⋄ b←(⌈/a←(∪⍵)⍳⍵)⍴0 ⋄ b[a]+←1 ⋄ ⌈/|2-/b[a]}
make←{⍵,(good ⍵),a,⍺,(l-⍴a←⊃b),⍴b←(⍺=good¨b/¨⊂⍵)⌿(b←↓⍉~(l⍴2)⊤0,⍳2⊥(l←⍴⍵)⍴1)/¨⊂⍵}
good tells us the K-goodness of a string. A few examples below:
// fn" means the fn executes on each of the right args
good" 'AABCBBCB' 'DDDAAABBDC' 'DDDAAABBC' 'DABABABBDC' 'DABABABBC' 'STACKOVERFLOW'
2 3 1 2 3 1
make takes as arguments
[desired K] make [any string]
and returns
- original string
- K for original string
- reduced string for desired K
- how many characters were removed to achieve deired K
- how many possible solutions there are to achieve desired K
For example:
3 make 'DABABABBDC'
┌──────────┬─┬─────────┬─┬─┬──┐
│DABABABBDC│2│DABABABBC│3│1│46│
└──────────┴─┴─────────┴─┴─┴──┘
A little longer string:
1 make 'ABCACDAAFABBC'
┌─────────────┬─┬────────┬─┬─┬────┐
│ABCACDAAFABBC│4│ABCACDFB│1│5│3031│
└─────────────┴─┴────────┴─┴─┴────┘
It is possible to both increase and decrease the K-goodness.
Unfortunately, this is brute force. We generate the 2-base of all integers between 2^[lenght of string] and 1, for example:
0 1 0 1 1
Then we test the goodness of the substring, for example of:
0 1 0 1 1 / 'STACK' // Substring is now 'TCK'
We pick only those results (substrings) that match the desired K-good. Finally, out of the multitude of possible results, we pick the first one, which is the one with most characters left.
At least this was fun to code :-).

Check if string contains three same letters in Octave

I'm trying to make a function in Octave to check whether a string contains three consecutive same characters. That is, if my string is "asdf" it should return 0 and if it's like "asdfffg" it should return 1. What I did so far is this
if(length(findstr(word,"aaa",0)) > 1 || length(findstr(word,"bbb",0)) > 1 || ..
It's costly and I think not that really inefficient. Any suggestions?
Use a regular expression:
match = regexp(word, '(.)\1{2}', 'once');
This means: match any character ((.)), followed by that same character (\1) twice ({2}). It will return the starting index of the first match, or an empty array if there isn't any match. So your desired result would be
result = ~isempty(match);
Another possibility is to use convolution:
result = any(conv([1 1], +~diff(word))==2);
This works as follows: diff will give 0 when two consecutive characters are the same. So you want to detect if the output of diff contains two consecutive zeros. This is done by negating (~), converting to double (+), convolving with the sequence [1 1] (conv([1 1], ...)), and seeing if 2 is present in the output.

algorithms for fast string approximate matching

Given a source string s and n equal length strings, I need to find a quick algorithm to return those strings that have at most k characters that are different from the source string s at each corresponding position.
What is a fast algorithm to do so?
PS: I have to claim that this is a academic question. I want to find the most efficient algorithm if possible.
Also I missed one very important piece of information. The n equal length strings form a dictionary, against which many source strings s will be queried upon. There seems to be some sort of preprocessing step to make it more efficient.
My gut instinct is just to iterate over each String n, maintaining a counter of how many characters are different than s, but I'm not claiming it is the most efficient solution. However it would be O(n) so unless this is a known performance problem, or an academic question, I'd go with that.
Sedgewick in his book "Algorithms" writes that Ternary Search Tree allows "to locate all words within a given Hamming distance of a query word". Article in Dr. Dobb's
Given that the strings are fixed length, you can compute the Hamming distance between two strings to determine the similarity; this is O(n) on the length of the string. So, worst case is that your algorithm is O(nm) for comparing your string against m words.
As an alternative, a fast solution that's also a memory hog is to preprocess your dictionary into a map; keys are a tuple (p, c) where p is the position in the string and c is the character in the string at that position, values are the strings that have characters at that position (so "the" will be in the map at {(0, 't'), "the"}, {(1, 'h'), "the"}, {(2, 'e'), "the"}). To query the map, iterate through query string's characters and construct a result map with the retrieved strings; keys are strings, values are the number of times the strings have been retrieved from the primary map (so with the query string "the", the key "thx" will have a value of 2, and the key "tee" will have a value of 1). Finally, iterate through the result map and discard strings whose values are less than K.
You can save memory by discarding keys that can't possibly equal K when the result map has been completed. For example, if K is 5 and N is 8, then when you've reached the 4th-8th characters of the query string you can discard any retrieved strings that aren't already in the result map since they can't possibly have 5 matching characters. Or, when you've finished with the 6th character of the query string, you can iterate through the result map and remove all keys whose values are less than 3.
If need be you can offload the primary precomputed map to a NoSql key-value database or something along those lines in order to save on main memory (and also so that you don't have to precompute the dictionary every time the program restarts).
Rather than storing a tuple (p, c) as the key in the primary map, you can instead concatenate the position and character into a string (so (5, 't') becomes "5t", and (12, 'x') becomes "12x").
Without knowing where in each input string the match characters will be, for a particular string, you might need to check every character no matter what order you check them in. Therefore it makes sense to just iterate over each string character-by-character and keep a sum of the total number of mismatches. If i is the number of mismatches so far, return false when i == k and true when there are fewer than k-i unchecked characters remaining in the string.
Note that depending on how long the strings are and how many mismatches you'll allow, it might be faster to iterate over the whole string rather than performing these checks, or perhaps to perform them only after every couple characters. Play around with it to see how you get the fastest performance.
My method if we're thinking out loud :P I can't see a way to do this without going through each n string, but I'm happy to be corrected. On that it would begin with a pre-process to save a second set of your n strings so that the characters are in ascending order.
The first part of the comparison would then be to check each n string a character at a time say n' to each character in s say s'.
If s' is less than n' then not equal and move to the next s'. If n' is less than s' then go to next n'. Otherwise record a matching character. Repeat this until k miss matches are found or the alternate matches are found and mark n accordingly.
For further consideration, an added pre-processing could be done on each adjacent string in n to see the total number of characters that differ. This could then be used when comparing strings n to s and if sufficient difference exist between these and the adjacent n there may not be a need to compare it?

Resources