By circular I mean a range can cross the max-value and loop back starting at 0. For example:
Given a max-value:
9
And two ranges (both of which can be "circular"):
0123456789
----range1 (a normal range)
ge2----ran (a circular range)
What is a good algorithm to calculate their intersection(s)?
In this case the intersection(s) would be:
7-9
789
ge1
ran
Bonus for an algorithm that can "delete" one from the other.
By delete I mean, one range is being completely extracted from another:
0123456789
----range1
ge2----ran
subtracting range2 from range 1 would yield:
3456
-ran
Update: the numbers are always integers. There are only ever two ranges being compared at once and they are always contiguous though, as noted, they may span 0.
Also note, it would be nice to output a boolean if one range fully contained another. I think I may have though of a nice way to do so.
Thanks!
It looks as though you can simply take each discrete element of your range and put it in a set. You can then perform an intersection of sets to get the output element.
This can be done in O(M+N) time by using a hash table.
Walk through your first range, creating an entry in the hash table for each element which is a member of the range.
Then walk through the second range and look each element up. If it is already in the hash table, then it is part of the intersection of the ranges.
With a little thought, you'll figure out how set differencing works.
If you need to intersect a third range, remove elements from the table that were not part of the second range.
here's an update about how I went about solving my above question. Basically the strategy is to divide and conquer.
Both ranges are split into two separate sections if need be. Then they are compared to each one at a time.
Hope this helps someone out, and tell me if you see any logical errors in this strategy. Later I'll post the "deletion" algorithm I mentioned above.
Also note, the ranges are 0-based.
var arePositiveIntegers = require('./arePositiveIntegers');
//returns an array of the overlaps between two potentially circular ranges
module.exports = function getOverlapsOfPotentiallyCircularRanges(rangeA, rangeB, maxLength) {
if (!arePositiveIntegers(rangeA.start, rangeA.end, rangeB.start, rangeB.end)) {
console.warn("unable to calculate ranges of inputs");
return [];
}
var normalizedRangeA = splitRangeIntoTwoPartsIfItIsCircular(rangeA, maxLength);
var normalizedRangeB = splitRangeIntoTwoPartsIfItIsCircular(rangeB, maxLength);
var overlaps = [];
normalizedRangeA.forEach(function(nonCircularRangeA) {
normalizedRangeB.forEach(function(nonCircularRangeB) {
var overlap = getOverlapOfNonCircularRanges(nonCircularRangeA, nonCircularRangeB);
if (overlap) {
overlaps.push(overlap);
}
});
});
return overlaps;
};
//takes a potentially circular range and returns an array containing the range split on the origin
function splitRangeIntoTwoPartsIfItIsCircular(range, maxLength) {
if (range.start <= range.end) {
//the range isn't circular, so we just return the range
return [{
start: range.start,
end: range.end
}];
} else {
//the range is cicular, so we return an array of two ranges
return [{
start: 0,
end: range.end
}, {
start: range.start,
end: maxLength - 1
}];
}
}
function getOverlapOfNonCircularRanges(rangeA, rangeB) {
if (!arePositiveIntegers(rangeA.start, rangeA.end, rangeB.start, rangeB.end)) {
console.warn("unable to calculate ranges of inputs");
return null;
}
if (rangeA.start < rangeB.start) {
if (rangeA.end < rangeB.start) {
//no overlap
} else {
if (rangeA.end < rangeB.end) {
return {
start: rangeB.start,
end: rangeA.end
};
} else {
return {
start: rangeB.start,
end: rangeB.end
};
}
}
} else {
if (rangeA.start > rangeB.end) {
//no overlap
} else {
if (rangeA.end < rangeB.end) {
return {
start: rangeA.start,
end: rangeA.end
};
} else {
return {
start: rangeA.start,
end: rangeB.end
};
}
}
}
}
Related
I try to implement a generation of a complex object based on a weighted elements list.
ListEnum.kt
enum class Elements(weighting:Int){
ELEM1(15),
ELEM2(20),
ELEM3(7),
ELEM4(18)
// function to get weighted random element
companion object{
fun getRandomElement(seed:Long): Elements{
var totalSum = 0
values().forEach {
totalSum += it.weighting
}
val index = Random(seed).nextInt(totalSum)
var sum = 0
var i = 0
while (sum < index) {
sum += values()[i++].weighting
}
return values()[max(0, i - 1)]
}
}
}
MyClass.kt
class MyClass{
fun getRandomElement():RandomElement{
val seed = Random.nextLong()
val element = Elements.getRandomElement(seed)
return RandomElement(element, seed)
}
}
I can persist the seed and recreate the same object with the same seed.
Now I want to modify the weighting in the Elements enum at runtime.
Elements.kt
enum class Elements(weighting:Int){
ELEM1(15),
ELEM2(20),
ELEM3(7),
ELEM4(18)
// function to get weighted random element
companion object{
fun getRandomElement(seed:Long, modifiers:Mods): Elements{
var totalSum = 0
values().forEach {
var modifiedWeighting =it.weighting
if(modifiers.modifier[it] != null){
modifiedWeighting= modifiers.modifier[it].times(modifiedWeighting).toInt()
}
totalSum += modifiedWeighting
}
val index = Random(seed).nextInt(totalSum)
var sum = 0
var i = 0
while (sum < index) {
var newSum = values()[i].weighting
if(modifiers.modifier[values()[i]] != null){
newSum = newSum.times(modifiers.modifier[values()[i]]).toInt()
}
sum += newSum
i++
}
return values()[max(0, i - 1)]
}
}
}
That works for generating random elements with modified weightings, but now I can't recreate the object because the seed does not consider the modifiers.
How can I generate such an object based on modified weightings that I can recreate just from the seed?
UPDATE:
To clarify by what I mean with modifiers. You can see them as a temporary modification of the weight of a specific element.
Modifiers are just float numbers like 1.0f -> keep weight as it is, 2.0f -> double the weight.
So after applying the modifiers, the element enum would look different. But like you can see, the modification is just temporary inside the calculation method.
One possible solution may be to create a static elements enum for every modification I need (they are limited, three or four), e.g.
ElementsModifiedByX, ElementsModifiedByY.
But that seems quiet a dirty solution to me.
I won't try to write Kotlin, but here is a simple strategy.
Instead of keeping your weights in the enum, move them into a structure like this:
{
start_weight: 0,
end_weight: 60,
choices: [(ELEM1, 15, 15), (ELEM2, 20, 35), (ELEM3, 7, 42), (ELEM4, 18, 60))],
}
And now to add weight, you just add onto the list and adjust the end_weight. To remove weight you move start_weight forward far enough then add in new entries for the weights that you accidentally erased. Your seeds are random numbers in the range from start_weight to end_weight. Making the choice can be done with a binary search. And, because you never erase entries, you can reliably reconstruct the same result every time from the same seed.
How can I check if all elements of vector_a also appear in the same order as vector_b?
vector_b could be very long, there is no assumption that it is sorted, but it does not have duplicate elements.
I could not find a method implemented for Vec or in itertools, so I tried implementing by doing:
Create a hashmap from vector_b mapping value -> index
Iterate over vector_b and check that:
Element exists in hashmap
Index is strictly greater than previous element's index
I am not really happy with this as it is not space efficient due to the creation of the hashmap.
Search for each element of the needle in the haystack in order. Each time you find a matching element, only continue the search in the remaining portion of the haystack. You can express this nicely by taking a new subslice of of the haystack each time you match an element.
fn is_subsequence<T: PartialEq>(needle: &[T], mut haystack: &[T]) -> bool {
for search in needle {
if let Some(index) = haystack.iter().position(|el| search == el) {
haystack = &haystack[index + 1..];
} else {
return false;
}
}
true
}
assert!(is_subsequence(b"", b"0123456789"));
assert!(is_subsequence(b"0", b"0123456789"));
assert!(is_subsequence(b"059", b"0123456789"));
assert!(is_subsequence(b"345", b"0123456789"));
assert!(is_subsequence(b"0123456789", b"0123456789"));
assert!(!is_subsequence(b"335", b"0123456789"));
assert!(!is_subsequence(b"543", b"0123456789"));
A slice is just a pointer and a size, stored on the stack, so this does no new allocations. It runs in O(n) time and should be close to the fastest possible implementation - or at least in the same ballpark.
Easiest way to do it is to iterate the two vectors jointly:
fn contains<T: PartialEq>(needle: &[T], haystack: &[T]) -> bool {
let mut idx = 0;
for it in needle {
while (idx < haystack.len()) && (&haystack[idx] != it) {
idx += 1;
}
if idx == haystack.len() {
return false;
}
}
return true;
}
I have a speed bottleneck in my code right now. The following function compares two arrays (position and size) and produces a new array of position elements that are smaller than size. This runs in O(n) time but is called many times. Is there anyway for me to do better for this very specific case?
code:
function findValidDimensions(positions, sizes) {
var forwardDimensions = [];
var backwardDimensions = [];
for (var i = 0; i < sizes.length; i++) {
if (positions[i] < sizes[i]) {
forwardDimensions.push(i);
}
if (positions[i] > 1) {
backwardDimensions.push(i);
}
}
// we can go forward or backward
return {
"forward": forwardDimensions,
"backward": backwardDimensions
}
}
Unless there are elements you can avoid looking at (which, from your spare description, sounds unlikely), looking at n elements will take O(n) time.
As i know that the complicity for your method is to large if you use a big array the best searching pattern is the heap or the B-Tree :)
Some ref :
https://en.wikipedia.org/wiki/Heap_%28data_structure%29
https://en.wikipedia.org/wiki/B-tree
Hey we are facing a space utilization problem or I am not clear what name I should give to problem.
Basically its a mesh problem.
I have tried to explain my problem using an image.
Problem statement is somewhat like below.
The box with the diagonal line is an item which has to be distributed in best proportion such as it should fit in all available container.
Containers are shown in different colors.
Now all containers will be in rectangle shape.
All containers has to be placed either in portrait mode or in landscape mode.
Both containers and item can be measured in width and height, for program they are pixels basically.
Based on comments of fellow members,Spektre and Lasse V. Karlsen here are the clarification on the same
It's a 2D arrangement
Yes we can rearrange the containers to achieve the best possible pattern.
No part of item should be in blank space. Item has to be a part of any container.
Item can overlap the container, and height and width can be vary from container to container. And Item's height width can also vary, but shape will remain rectangle always.
Location of Item is preferable if it sticks to top-left.
Yes it is somewhat like bin packing algorithm, but only problem with that algorithm is , in Bin packing items are more and container is one, in our case item is one and containers are more. So basically its a distribution problem.
Idea is the problem actually that we have the size of the container and need to place the containers so that we can create that rectangle.
The program should give following output
Position of the container
Part of item the container has inside.
And Arrangement pattern.
here something unsophisticated unoptimal but easy as a start point
Based on mine comments
exploiting common container size 480px
Algorithm:
rotate all containers (bins) to get 480 height
sort bins by width after rotation descending
need ceil(1080/480)=3 lines of 480px bins
use the widest bins to fill all the lines but never crossing 1920px
they are sorted so use the first ones
all used ones mark as used
use only unused bins
arrange rest of the bins to lines (goes to the shortest line)
so take unused bins
determine which line is shortest
if the shortest line is already 1920px wide or more then stop
if not move the bin to that line and mark it as used
C++ source code (ugly static allocation but simple and no lib used):
//---------------------------------------------------------------------------
struct _rec { int x,y,xs,ys,_used; };
_rec bin[128],item; int bins=0;
//---------------------------------------------------------------------------
void bin_generate(int n) // generate problem
{
int i;
Randomize();
item.x=0;
item.y=0;
item.xs=1920;
item.ys=1080;
for (bins=0;bins<n;bins++)
{
bin[bins].x=0;
bin[bins].y=0;
i=Random(2);
if (i==0) { bin[bins].xs=320; bin[bins].ys=480; }
else if (i==1) { bin[bins].xs=480; bin[bins].ys=800; }
else i=i;
// if (i==2) { bin[bins].xs=1920; bin[bins].ys=1080; }
}
}
//---------------------------------------------------------------------------
void bin_solve() // try to solve problem
{
int i,e,n,x,y,x0[128],y0[128],common=480;
_rec *r,*s,t;
// rotate bins to ys=480
for (r=bin,i=0;i<bins;i++,r++) if (r->xs==common) { x=r->xs; r->xs=r->ys; r->ys=x; }
// sort bins by xs desc
for (e=1;e;) for (e=0,r=bin,s=r+1,i=1;i<bins;i++,r++,s++) if (r->xs<s->xs) { t=*r; *r=*s; *s=t; e=1; }
// prepare lines needed ... n is num of lines, _rest is one common side height line is needed to add
n=item.ys/common; if (item.ys%common) n++; item.x=0; item.y=0;
for (i=0;i<n;i++) { x0[i]=0; y0[i]=common*i; }
for (r=bin,i=0;i<bins;i++,r++) r->_used=0;
// arrange wide bins to lines
for (e=0;e<n;e++)
for (r=bin,i=0;i<bins;i++,r++)
if (!r->_used)
if (x0[e]+r->xs<=item.xs)
{
r->x=x0[e];
r->y=y0[e];
r->_used=1;
x0[e]+=r->xs;
if (x0[e]>=item.xs) break;
}
// arrange rest bins to lines (goes to the shortest line)
for (r=bin,i=0;i<bins;i++,r++)
if (!r->_used)
{
// find shortest line
for (e=0,x=0;x<n;x++) if (x0[e]>x0[x]) e=x;
// stop if shortest line is already wide enough
if (x0[e]>=item.xs) break;
// fit the bin in it
r->x=x0[e];
r->y=y0[e];
r->_used=1;
x0[e]+=r->xs;
}
// arrange the unused rest below
for (x=0,y=n*common+40,r=bin,i=0;i<bins;i++,r++) if (!r->_used) { r->x=x; r->y=y; x+=r->xs; }
}
//---------------------------------------------------------------------------
Usage:
bin_generate(7); // generate n random devices to bin[bins] array of rectangles
bin_solve(); // try to solve problem ... just rearrange the bin[bins] values
this is not optimal but with some tweaks could be enough
for example last 2 lines need 600px of height together so if you have devices at that size or closely larger you can use them to fill the 2 last lines as 1 line ...
if not then may be some graph or tree approach will be better (due to low container count)
[Edit1] universal sizes
when you have not guarantied fixed common container size then you have to compute it instead...
//---------------------------------------------------------------------------
struct _rec { int x,y,xs,ys,_used; _rec(){}; _rec(_rec& a){ *this=a; }; ~_rec(){}; _rec* operator = (const _rec *a) { *this=*a; return this; }; /*_rec* operator = (const _rec &a) { ...copy... return this; };*/ };
List<_rec> bin,bintype;
_rec item;
//---------------------------------------------------------------------------
void bin_generate(int n) // generate problem
{
int i;
_rec r;
Randomize();
// target resolution
item.x=0; item.xs=1920;
item.y=0; item.ys=1080;
// all used device sizes in portrait start orientation
bintype.num=0; r.x=0; r.y=0; r._used=0;
r.xs= 320; r.ys= 480; bintype.add(r);
r.xs= 480; r.ys= 800; bintype.add(r);
r.xs= 540; r.ys= 960; bintype.add(r);
// r.xs=1080; r.ys=1920; bintype.add(r);
// create test case
bin.num=0; for (i=0;i<n;i++) bin.add(bintype[Random(bintype.num)]);
}
//---------------------------------------------------------------------------
void bin_solve() // try to solve problem
{
int i,j,k,e,x,y;
_rec *r,s;
List<int> hsiz,hcnt; // histogram of sizes
List< List<int> > lin; // line of bins with common size
// compute histogram of sizes
hsiz.num=0; hcnt.num=0;
for (r=bin.dat,i=0;i<bin.num;i++,r++)
{
x=r->xs; for (j=0;j<hsiz.num;j++) if (x==hsiz[j]) { hcnt[j]++; j=-1; break; } if (j>=0) { hsiz.add(x); hcnt.add(1); }
x=r->ys; for (j=0;j<hsiz.num;j++) if (x==hsiz[j]) { hcnt[j]++; j=-1; break; } if (j>=0) { hsiz.add(x); hcnt.add(1); }
}
// sort histogram by cnt desc (most occurent sizes are first)
for (e=1;e;) for (e=0,j=0,i=1;i<hsiz.num;i++,j++) if (hcnt[j]<hcnt[i])
{
x=hsiz[i]; hsiz[i]=hsiz[j]; hsiz[j]=x;
x=hcnt[i]; hcnt[i]=hcnt[j]; hcnt[j]=x; e=1;
}
// create lin[][]; with ys as common size (separate/rotate bins with common sizes from histogram)
lin.num=0;
for (r=bin.dat,i=0;i<bin.num;i++,r++) r->_used=0;
for (i=0;i<hsiz.num;i++)
{
lin.add(); lin[i].num=0; x=hsiz[i];
for (r=bin.dat,j=0;j<bin.num;j++,r++)
{
if ((!r->_used)&&(x==r->xs)) { lin[i].add(j); r->_used=1; y=r->xs; r->xs=r->ys; r->ys=y; }
if ((!r->_used)&&(x==r->ys)) { lin[i].add(j); r->_used=1; }
}
}
for (i=0;i<lin.num;i++) if (!lin[i].num) { lin.del(i); i--; }
// sort lin[][] by xs desc (widest bins are first)
for (i=0;i<lin.num;i++)
for (e=1;e;) for (e=0,k=0,j=1;j<lin[i].num;j++,k++)
if (bin[lin[i][k]].xs<bin[lin[i][j]].xs)
{ s=bin[lin[i][j]]; bin[lin[i][j]]=bin[lin[i][k]]; bin[lin[i][k]]=s; e=1; }
// arrange lines to visually check previous code (debug) ... and also compute the total line length (width)
for (y=item.ys+600,i=0;i<lin.num;i++,y+=r->ys) for (x=0,j=0;j<lin[i].num;j++) { r=&bin[lin[i][j]]; r->x=x; r->y=y; x+=r->xs; }
for (i=0;i<lin.num;i++)
{
j=lin[i][lin[i].num-1]; // last bin in line
hsiz[i]=bin[j].x+bin[j].xs; // total width
hcnt[i]=bin[j].ys; // line height
}
// now compute solution
for (r=bin.dat,i=0;i<bin.num;i++,r++) r->_used=0; // reset usage first
for (y=0,k=1,i=0;i<lin.num;i++) // process lines with common size
while(hsiz[i]>=item.xs) // stop if line shorter then needed
{
x=0;
// arrange wide bins to line
for (j=0;j<lin[i].num;j++)
{
r=&bin[lin[i][j]];
if ((!r->_used)&&(x+r->xs<=item.xs))
{
r->x=x; hsiz[i]-=x; x+=r->xs;
r->y=y; r->_used=k;
if (x>=item.xs) break;
}
}
// arrange short bins to finish line
if (x<item.xs)
for (j=lin[i].num-1;j>=0;j--)
{
r=&bin[lin[i][j]];
if (!r->_used)
{
r->x=x; hsiz[i]-=x; x+=r->xs;
r->y=y; r->_used=k;
if (x>=item.xs) break;
}
}
// remove unfinished line
if (x<item.xs)
{
for (j=0;j<lin[i].num;j++)
{
r=&bin[lin[i][j]];
if (r->_used==k)
{
r->x=0; r->y=0;
r->_used=0;
hsiz[i]+=r->xs;
}
}
break;
}
// next line
y+=hcnt[i];
if (y>=item.ys) break; // solution found already?
}
// rotate unused rest to have ys>=as needed but as wide as can be to form last line
e=item.ys-y; x=0;
if (e>0) for (r=bin.dat,i=0;i<bin.num;i++,r++)
if (!r->_used)
{
if ((r->xs<e)&&(r->ys<e)) continue; // skip too small bins
if (r->xs<r->ys) { j=r->xs; r->xs=r->ys; r->ys=j; }
if (r->ys< e) { j=r->xs; r->xs=r->ys; r->ys=j; }
r->x=x; x+=r->xs;
r->y=y; r->_used=1;
}
}
//---------------------------------------------------------------------------
it is almost the same as before but prior to solution histogram of container sizes is computed
choose most occurent ones and form groups of compatible bins (containers)
then apply the algorithm ...
I added usage of dynamic array template List<> because on static allocation I would go mad before writing this ...
List<int> x; is the same as int x[];
x.num is the number of items inside x[]
x.add() adds new item to end of x[]
x.add(q) adds new item = q to end of x[]
x.del(i) deletes i-th item from x[] ... indexing is from zero
so rewrite to what ever you use instead ...
List< List<int> > y; is 2D array y[][] ...
at last form last line from unused bins ...
This is not robust nor safe but it mostly works (it need some tweaking but I am too lazy for that)
the solution depends also on the input set order so you can find more solutions for the same input set if you shuffle it a bit ... (if some common sizes has the same count)
There are lots of questions discussing the fastest/best way to rotate a string or determine if one string is a rotation of another.
For example, neglecting sanitization of inputs, you'll see something like this for IsRotation:
public static bool IsRotation(string s1, string s2)
{
return (s1.Length == s2.Length && (s1 + s1).IndexOf(s2) != -1);
}
And something like this for Rotate:
public static string Rotate(string s, int index)
{
//Can't rotate. Return input.
if (s.Length < 2)
{
return s;
}
// Break input in half at rotation index
var s1 = s.Substring(0, index);
var s2 = s.Substring(index);
// Reverse the halves
var s1Reversed = Reverse(s1);
var s2Reversed = Reverse(s2);
// Join the reversed halves
var joined = s1Reversed + s2Reversed;
//Reverse and return the result.
var rotated = Reverse(joined);
return rotated;
}
For example, using "foo..."
Rotate("foo",1) == "ofo"
-and-
IsRotation("foo", "ofo") == true;
My question is is an extension of these questions.
Given an input string, s, determine how many rotations of that string are identical to the original string.
Considering the input string as a rotation, some sample input/output pairs:
IdenticalRotationCount("") == 1
IdenticalRotationCount("s") == 1
IdenticalRotationCount("sa") == 1
IdenticalRotationCount("ss") == 2
IdenticalRotationCount("ByeBye") == 2
IdenticalRotationCount("StackOverflow") == 0
I was told that there is a solution that will run in O(n) time. The beginner solution looks like this:
public static int IdenticalRotationCount(this string s)
{
//If length of s is less than two, we cannot rotate. Return 1.
if (s.Length < 2)
{
return 1;
}
//Get first char in s
var first = s[0];
//Consider input as first rotation that matches
var count = 1;
//Try each rotate position
for (var i = 1; i < s.Length; ++i)
{
var c = s[i];
//If current character doesn't start with same character as input
//we can skip the rotation
if (c != first)
{
continue;
}
//If the rotation at index i equals the input string, add 1 to result
if (StringExtensions.Rotate(s, i) == s)
{
++count;
}
}
return count;
}
However, if you choose an absurd input, like 200,000 consecutive 'a's, it will run for quite some time.
Can anybody provide a solution that runs in O(n) time? I can see N^2 by doing the actual comparison when breaking the input down into the two halves before rotation, instead of doing the actual rotation, but cannot see how to do O(n).
Thanks!
PS - If there is a more appropriate to post this sort of question, please say so in the comments. I'll gladly move it.
This sprung to mind - think about the question "if I concatenate the original string with itself, what's the first index of the original string within the concatenated result". With a little thought, it looks to me as though it'll answer the question O(n).
E.g.
Original string "ByeBye"
Concatenated string "ByeByeByeBye"
Original string appears at (0-based) index 2 within the concatenated string. This tells you something.
If a string is equal to a rotation of itself at offset k and at no smaller offset, then the string must be the repetition of its length k prefix. It will then also be equal to its rotation at all multiples of k, so there will be precisely n/k such rotations, where n is the length of the string. This is pretty easy to prove.
There is indeed an O(n) algorithm for determining the value of k. One way to do it is to use Duval's algorithm for Lyndon factorization (see Wikipedia). That's just a hint; I'll see if I can produce some actual pseudocode if desired.