Should be easy array situation - arrays

My question shouldn't be too difficult but I haven't solved it yet. Basically, what I'm trying to do is to take a message (like this one), preserve each letter in the message, but generate a random message using each letter. So, I can currently read into a textbox (say) "Hello!", but I need to take the message in that textbox and (on the click of a button) have something like "lolH!e". There's got to be a simple way to read each letter into an array (or list, or whatever), and spit them out at random, but while using each letter only once as in the original message. Any thoughts?

In JavaScript you can do something like this:
function randomize(s){
var a = Array.from(s);
for(var j, x, i = a.length; i; j = parseInt(Math.random() * i), x = a[--i], a[i] = a[j], a[j] = x);
return a.join("");
}
Then use it like:
randomize("Hello!")
There are some other good solutions here: How do I shuffle the characters in a string in JavaScript?

Related

C# WinForm: Select specific words and change colour

I have a program that allows the user to enter text, and it will highlight any repeat words. It already adds repeated words to one list and all the words to another. I want the program to print out the words, and if a repeat word is used, to highlight it.
I have tried using outputBox.Find(repeatList[i]) with a loop, but this only finds the first word used in the text. I also tried marking the current number for the last letter typed, selecting that point, finding the coordinates after the word.Length was typed, and then changing the colour of that, which didn't work.
for (int h = 0; h < repeatList.Count; h++)
{
for (int c = 0; c < repeatList.Count; c++)
{
outputBox.Find(repeatList[h]);
outputBox.SelectionColor = Color.Red;
}
}
At this point in the code, the outputBox already contains the users input, I just want to know how to compare words and select them for colouring. I've only just started Winforms and have only been coding for a few weeks, so I am sorry - I have looked at other answers but was not able to implement them. Thank you in advance for any responses.
EDIT: I would just like to add that my prefered method for colouring the text would be as it prints each word out, this was my original intention as I'm much more used to console applications where I can just change the colour and print more. If that method is easier to do than checking afterwards, I'm find to do that.
I would use the start index and keep a copy of it.
int startFrom = 0
...
startFrom = outputBox.Find(repeatList[h], startFrom)
You could then use the 'startFrom' index with the text word length to select the text.
Here is an example:
var findText = "test";
int index = 0;
do
{
index = richTextBox1.Find(findText, index, RichTextBoxFinds.WholeWord);
if (index > -1)
{
richTextBox1.Select(index, findText.Length);
richTextBox1.SelectionColor = Color.Red;
index++;
}
} while (index > -1);

Feasibility of non-self-intersecting path according to array constraints

I have two arrays, each containing a different ordering of the same set of integers. Each integer is a label for a point in which two closed paths intersect in the plane. The two arrays are interpreted as giving the circular ordering (in clockwise order) of points along each of two closed paths in the plane, with no particular starting point. The two paths intersect with each other as many times as there are points in the arrays, but a path may not self-intersect at all. How do I determine, from these two arrays, whether it is possible to draw the two paths in the plane without self-crossings? (The integer labels have no inherent meaning.)
Example 1: A = {3,4,2,1,10,7} and B = {1,2,4,10,7,3}: it is possible
Example 2: A = {2,3,0,10,8,11} and B = {10,2,3,8,11,0}: it is not possible.
Try it by drawing a circle, with 6 points labelled around it according to A, then attempt to connect the 6 points in a second closed path, according to the ordering in B, without crossing the new line you are drawing. (I believe it makes no difference to the possibility/impossibility of drawing the line whether you start by exiting or entering the first loop.) You will be able to do it for example 1, but not for example 2.
I am currently using a very elaborate method where I look at adjacent pairs in one array, e.g. in Example 1, array A is divided into {3,4}, {2,1}, {10,7}, then I find the groupings in the array B as partitioned by the two members listed in each case:
{3,4} --> {{1,2}, {10,7}}
{2,1} --> {{4,10,7,3}, {}}
{10,7} --> {{3,1,2,4}, {}}
and check that each pair on the left-hand-side finds itself in the same grouping of the right-hand-side partition in each of the other 2 rows. Then I do the same, offset by one position:
{4,2} --> {{10,7,3,1}, {}}
{1,10} --> {{2,4}, {7,3}}
{7,3} --> {{1,2,4,10}, {}}
Everything checks out here.
In Example 2, though, the method shows that it is impossible to draw the path. Among the "offset by 1" pairs from array A we find {10,8} causes a partition of array B into {{2,3}, {11,0}}. But we need 11 and 2 to be in the same grouping, as they are the next pair of points in array A.
This idea is unwieldy, and my implementation is even more unwieldy. I'm not even 100% convinced it always works. Could anyone suggest an algorithm for deciding? Target language is C, if that matters.
EDIT: I've added an illustration here: http://imgur.com/TS8xDIk. Here the paths to be reconciled share points 0, 1, 2 and 3. On the black path they are visited in order (A = {0,1,2,3}). On the blue path we have B = {0,2,1,3}. You can see on the left-hand side that this is impossible--the blue path will have to self-intersect in order to do it (or have additional intersections with the black path, which is also not allowed).
On the right-hand side is an illustration of the same problem interpreted as a graph with edges, responding to the suggestion that the problem boils down to a check for planarity. Well, as you can see, it's quite possible to form a planar graph from this collection of edges, but we cannot read the graph as two closed paths with n intersections--the blue path has "intersections" with the other path that don't actually cross. The paths are required to cross from inside to outside or vice-versa at each node, they cannot simply kiss and turn back.
I hope this clarifies the problem and I apologise for any lack of clarity the first time around.
By the way introducing coordinates would be a complete red herring: any point can be given any coordinates, and the problem remains the same. In a sense it is topological more than geometrical. Thanks for any additional suggestions on how to accomplish this feasibility check.
SECOND EDIT to show my current code. Like in the suggestion below by svinja, I first reduced the two arrays to a permutation of 0..2n-1. The input to the function is two arrays (which contain different orderings of the same 2n integers) and the length of these arrays. I am a hobbyist with no training in programming so I expect you will find several infelicities in the approach to coding. The idea is to return 1 if the arrays A and B are in a permutational relationship that allows the path to be drawn, and 0 if not.
int isGoodPerm(int A[], int B[], int len)
{
int i,j,a,b;
int P[max_len];
for (i=0; i<len; i++)
for (j=0; j<len; j++)
if (B[j] == A[i])
{
P[i] = j;
break;
}
for (i=0; i<len; i++)
{
if (P[i] < P[(i+1)%len])
{
a = P[i];
b = P[(i+1)%len];
}
else
{
a = P[(i+1)%len];
b = P[i];
}
for (j=i+2; j<i+len; j+=2)
if ((P[j%len] > a && P[j%len] < b) != (P[(j+1)%len] > a && P[(j+1)%len] < b))
return 0;
}
return 1;
}
I'm actually still testing another part of this project, and have only tested this part in isolation. I tweaked a couple of things when pasting it into the larger codebase and have copied that version--I hope I didn't introduce any errors.
I think the long question is hiding the true intent. I might be missing something, but it looks like the only thing you really need to check is if the points in an array can be drawn without self-intersecting. I'm assuming you can map the integers to the actual coordinates. If so, you might find the solution posed by the related math.statckexchange site here describing either the determinant-based method or the Bentley-Ottman algorithm for crossings to be helpful.
I am not sure if this is correct, but as nobody is posting an answer, here it is:
We can convert any instance of this problem to one where the first path is (0, 1, 2, ... N). In your example 2, this would be (0, 1, 2, 3, 4, 5) and (3, 0, 1, 4, 5, 2). I only mention this because I do this conversion in my code to simplify further code.
Now, imagine the first path are points on a circle. I think we can assume this without loss of generality. I also assume we can start the second path either inside or outside of the circle, if one works the other should, too. If I am wrong about either, the algorithm is certainly wrong.
So we always start by connecting the first and second point of the second path on the, let's say, outside. If we connect 2 points X and Y which are not right next to each other on the circle, we divide the remaining points into group A - the ones from X to Y clockwise, and group B - the ones from Y to X clockwise. Now we remember that points from group A can no longer be connected to points from group B on the outside part.
After this, we continue connecting the second and third point of the second path, but we are now on the inside. So we check "can we connect X and Y on the inside?" if we can't, we return false. If we can, we again find groups A and B and remember that none of them can be connected to each other, but now on the inside.
Now we're back on the outside, and we connect the third and fourth point of the second path... And so on.
Here is an image that shows how it works, for your examples 1 and 2:
And here is the code (in C#, but should be easy to translate):
static bool Check(List<int> path1, List<int> path2)
{
// Translate into a problem where the first path is (0, 1, 2, ... N}
var path = new List<int>();
foreach (var path2Element in path2)
path.Add(path1.IndexOf(path2Element));
var N = path.Count;
var blocked = new bool[N, N, 2];
var subspace = 0;
var currentElementIndex = 0;
var nextElementIndex = 1;
for (int step = 1; step <= N; step++)
{
var currentElement = path[currentElementIndex];
var nextElement = path[nextElementIndex];
// If we're blocked before finishing, return false
if (blocked[currentElement, nextElement, subspace])
return false;
// Mark appropriate pairs as blocked
for (int i = (currentElement + 1) % N; i != nextElement; i = (i + 1) % N)
for (int j = (nextElement + 1) % N; j != currentElement; j = (j + 1) % N)
blocked[i, j, subspace] = blocked[j, i, subspace] = true;
// Move to the next edge
currentElementIndex = (currentElementIndex + 1) % N;
nextElementIndex = (nextElementIndex + 1) % N;
// Outside -> Inside, or Inside -> Outside
subspace = (2 - subspace) / 2;
}
return true;
}
Old answer:
I am not sure I understood this problem correctly, but if I have, I think this can be reduced to planarity testing. I will use your example 2 for the numbers:
Create graph G1 from the first array; it has edges 2-3, 3-0, 10-8, 8-11, 11-2
Create graph G2 from the second array; 10-2, 2-3, 3-8, 8-11, 11-0, 0-10
Create graph G whose set of edges is the union of the sets of edges of G1 and G2: 2-3, 3-0, 10-8, 8-11, 11-2, 10-2, 3-8, 11-0, 0-10
Check if G is planar.
This is if I correctly interpreted the question in the sense that the second path must not cross itself but must not cross the first path either (except for the unavoidable 1 intersection per vertex due to shared vertices). If this is not the case, then Example 2 does have solutions (note how the 11-2 and 8-10 edges are crossed by the second path).

AS3 putting each element of an array on a separate line

I'm working on a game which contains the following code; what it's meant to do is pick 8 random names from an array and enter them into some text onscreen, so that each element is on a separate line. Here's the summary of my code:
var a:Array
for (var i:Number=1; i<=packQ; i++)
{
shuffle(packShuffler);
//Note: this function randomly reorganizes the array "packShuffler", it's a pretty complicated function so lets leave it at that.
a.push(packShuffler[0])
a.push(packShuffler[1])
a.push(packShuffler[2])
a.push(packShuffler[3])
a.push(packShuffler[4])
a.push(packShuffler[5])
a.push(packShuffler[6])
a.push(packShuffler[7])
}
cardGet.text=""+a
//textbox looks something like this:
//blue,white,dragon,beast,great,black,Sword,Circle
I know it looks very very awkward, especially the push part, but it's the only way I know at the moment :/
Well, my problem is, at the last line {cardGet.text=""+a}, the text appears as a big block of elements with commas between them, what I want is to make each element appear on a separate line. How do I do this?
Part of the problem is that a.toString() is getting called implicitly, on the line that says cardGet.text=""+a. That being said, an Array's toString() method will, by definition, return element1 + ", " + element2 + ", " + ... + elementn.
But why are you pushing them onto a new array? Why not simply shuffle the old one, as you have, and then just build your own string out of it? Kind of like this:
shuffle(packShuffler);
cardGet.text = "";
// takes every element, except for the last, and adds it and a newline
// to the string
for (var j:int = 0; j < packShuffler.length - 1; j++)
{
cardGet.text += packShuffler[j] + "\n";
}
// adds the very last element to the string without a newline
cardGet.text += packShuffler[packShuffler.length - 1];

Issue with managed array in C++/CLI

I'm a c++ programmer and I'm having some issue with managed array. I'll explain what i mean. I'm using Visual Studio to code a Windows Form to handle a device.
I need to plot datas from a MCU connected to my PC thru a serial port. To save the values incoming from serial port, I'm using an array like that:
array<double, 1>^ datas = gcnew array<double, 1>(ndatas);
array<Byte, 1>^ byteDatas = gcnew array<Byte, 1>(2*ndatas);
where ndatas is the number of values of my series and byteDatas is the array where I will save the bytes that compose every value. Every value is made by 2 bytes.
After that, I will fill this array like this:
for(int i = 0; <=ndatas; ) {
if(bytes = serialPort1->BytesToRead>=2) {
datas[i] = getData(serialPort1, byteDatas, i);
}
i++;
}
The funcion getData is this one:
double getData(serialPort^ sp, array<Byte,1> data, int i) {
union Level {
char L[2];
signed short level;
} lvl;
sp->Read(data, i, 2);
for(int j = 0; j<=2; j++) {
lvl.L[j]= data[i+j];
}
return safe_cast<double>(lvl.level/100.00);
}
This function is on another .cpp file, so I had to use the variable SerialPort.
Everything goes like charm. If I try to use a MessageBox to display my datas, I can see how my array is correctly filled with the right values.
My next step to do, is to plot this data on a pictureBox using drawLine. But I really can't cause half of the values of the array datas are set to 0. For istance, if my series has 100 values, I can draw only the first values with the right amplitude. The other are represented, of course, as a horizontal line of zeroes.
To find this out, I have used a for cycle like that.
for(int i = 0; i<=datas->Length; i++) {
MessageBox::Show(Convert::ToString(datas[i]+" " + Convert::ToString(i+1));
}
just to be sure from when I will find the problem.
The strange part of this one is that, if I put the same MessageBox line of code under
datas[i] = getData(serialPort1, byteDatas, i);
I can display all of values without zeroes.
I'm stuck, and I don't know how to get rid of this problem. I hope I can find a little help to overcome this annoying issue.
I wish everything is crystal clear and I would like to thank everyone will give me a feedback.
Cheers,
Emiliano
When you do call getData, you're getting a valid value.
But BytesToRead goes down as you read data. At some point it drops below 2, and the rest of the for loop does nothing.
You might need to save where you are in the array when you run out of data, and when more serial data arrives, continue filling in the array from where you left off.
Plus, of course, right now you appear to be putting every data value into element 0 of the array, because you never increment i.
Also, you're reading each data point at index i, which means that you overwrite the second byte from the previous sample.
There's no need for safe_cast, the result of the division is already a double. And even if you needed a conversion, safe_cast isn't appropriate, since none of these data types are polymorphic.
Furthermore, your use of the union causes undefined behavior.
Finally, you're in C++. So why are you using what is probably the worst designed serial port API Microsoft ever made? This is C++. Calling Win32 APIs is easy, just #include <windows.h> and go, no p/invoke needed.

AS3 make an array of movieclip moves constantly. (this array constantly increases in size)

ActionScript 3.0
I got this bullet_array.
and it pushes new bullet everytime I pressed spacebar.
There's this "for loop", which works - only when I pressed spacebar.
but I wanted the bullets to constantly move.
the 'for loop' is inside update(), which is from Event.ENTER_FRAME
so technically, the for loop should constantly be looping (i think), but it only went through ONCE, and only after the array increases in size. And it only worked on the new object, and didn't touch the old object.
public function update(evt:Event = null)
{
stage.focus = stage;
//fire = true is set by spacebar
if (fire == true)
{
var snowball:MovieClip = new Snowball;
snowball.x = (mcPlayer.x);
snowball.y = (mcPlayer.y - 5);
snowballArray.push(snowball);
SBAlength = +1; //stands for snowballArray's length
addChild(snowball);
fire = false;
}
for (var i = SBAlength - 1; i >= 0; i--)
{
snowballArray[i].y -= snowballSpd; //snowballSpd is already declared as 5
for (var j = snowmanArray.length - 1; j>=0; j--)
{
for (var k = numberArray.length -1; k>0; k--)
{
if (snowballArray[i].hitTestObject(snowmanArray[j]))
{
if (snowmanArray[j].hitTestObject(numberArray[k]))
{
bosslife -= numberArray[k];
numberArray[k].splice(k,1);
}
snowballArray[i].gotoAndPlay("hit");
snowmanArray[j].splice(j,1);
break;
}
if(numberArray[k] >= 0)
{
numberArray[k].splice(k,1);
randomNo= Math.floor(Math.random()*(max-min+1))+min;
numberArray[k].push(randomNo);
}
snowmanArray[j].txtNumber.text = numberArray[j];
}
}
There may be other issues here, but:
Maintaining the array length
SBAlength = +1; // Sets your length to 1
Instead use:
SBAlength += 1; // Increases your length by 1
But really, you might as well use the array's length property in the loop, instead of maintaining SBALength (and risking it getting out of sync due to some future code):
for (var i = snowballArray.length - 1; i >= 0; i--)
Manipulating arrays
Also (don't think this is related to your problem, but it will certainly cause errors), in your inner loop, you're constantly doing things like this:
snowmanArray[j].splice(j,1);
numberArray[k].push(randomNo);
// etc.
That would only work if the items in numberArray and snowmanArray are themselves arrays - not sure if they are, but doesn't seem like it, since you're also using the items as numbers:
bosslife -= numberArray[k];
The first statement is asking to remove an item from an array stored in snowmanArray[j] - not removing an item from snowmanArray itself. If you want to remove an item from snowmanArray, you'd do snowmanArray.splice(j, 1).
In the same way, to add an item to numberArray, you'd do numberArray.push(randomNo), rather than numberArray[k].push(randomNo).
Manipulating arrays inside loops etc.
It's fine to e.g. remove the current array item while iterating over that array - but only as long as you do it in the way you do, starting from the end and going backwards. However...
After doing (or rather, intending to do) this if the snowman was hit:
snowmanArray.splice(j,1);
... you're later doing:
snowmanArray[j].txtNumber.text = numberArray[j];
I.e. you remove the snowman from the array, but then later on, you try to get the array item you just removed. You need to be sure that snowmanArray[j] still exists before you address it.
Array item types
You're mostly using numberArray as an array of int (or Number). Except here:
snowmanArray[j].hitTestObject(numberArray[k])
You can't hitTestObject against an int/Number. Not sure what the line is supposed to do, but the object you hit test against needs to be a DisplayObject (e.g. a MovieClip).
Erm... after lots of tracing around and stuff,
i figure that the main problem isn't with the array nor the splicing (though my codes is wrong -but it didn't work even if i commented away those codes), but that i place > instead of < to check bosslife, so it keep resetting the level, so snowballArray keeps becoming a new Array, hence the array.length didn't work, and using SBAlength gives some kinda weird error while inside the for loop.

Resources