please look at the following link.
Permutation of String letters: How to remove repeated permutations?
I would like to port this to actionscript 2. Here is what i have so far:
var str:String = "AAC";
var arr:Array = str.split("");
permute(0,2);
function swap(i:Number, j:Number)
{
var temp;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
function permute(i:Number, n:Number)
{
var k:Number;
if (i == n)
trace(arr);
else
{
for (k = i; k <= n; k++)
{
swap(i, k);
permute(i+1, n);
swap(i, k);
}
}
}
This is working fine to list all permutations with duplicates, but i would like to remove those and have unique values. So far i haven't managed to port the ticked solution from the above link. Thank You for your help.
Below are two versions, the first is for AS3, the second is for AS2. It is a slightly different algorithm (it is a bit less efficient then the one you have, but I think it will do as an illustration). It is essentially the same algorithmic complexity, so it's OK, the redundancy is in generating intermediate results (shorter arrays), which are later discarded (but you could modify it to reuse those arrays, if this concerns you).
AS3
private function permuteRecursively(input:Array,
hash:Object = null):Array
{
var first:String;
var oldResult:Array;
var newResult:Array;
var times:int;
var current:Array;
var test:String;
if (input.length > 1)
{
first = input.shift();
if (!hash) hash = { };
oldResult = this.permuteRecursively(input, hash);
newResult = [];
for each (var result:Array in oldResult)
{
times = result.length;
while (times >= 0)
{
current = result.concat();
if (times == result.length) current.push(first);
else current.splice(times, 0, first);
test = current.join("");
if (!(test in hash))
{
newResult.push(current);
hash[test] = 1;
}
times--;
}
}
}
else newResult = [input];
return newResult;
}
AS2:
private function permuteRecursively(input:Array,
hash:Object):Array
{
var first:String;
var oldResult:Array;
var newResult:Array;
var times:Number;
var current:Array;
var test:String;
var result:Array;
if (input.length > 1)
{
first = input.shift();
if (!hash) hash = { };
oldResult = this.permuteRecursively(input, hash);
newResult = [];
for (var i:Number = 0; i < oldResult.length; i++)
{
result = oldResult[i];
times = result.length;
while (times >= 0)
{
current = result.concat();
if (times == result.length) current.push(first);
else current.splice(times, 0, first);
test = current.join("");
if (!(test in hash))
{
newResult.push(current);
hash[test] = 1;
}
times--;
}
}
}
else newResult = [input];
return newResult;
}
EDIT:
Actually, now that I think of it, I'm not sure what kind of duplicates you were trying to avoid. The above code treats the permutations of AAC such as AAC and ACA as if they were distinct (even though A is "duplicated" in them), but AAC and AAC are considered the same (even though the first A and the second A may come from different sources in the original array).
If what you wanted to remove duplicated elements of generated arrays, then, obviously, the best strategy would be to remove them from the source first.
Related
The title is not very explicit :')
So there is an example to understand what I want to do :
I have to put a string (as input) which have to look like:
(Hey) (how are you) !
This have to create this string array:
!
Hey !
how are you !
Hey how are you !
Based on the parentheses that have to made all possibilities of string, considering that parenthesis is "optional"
function combs(arr, depth) {
var resp = [], len = arr.length, total = (1 << len);
for (var i = 1; i < total; i++) {
var tmp = [], good = true;
for (var k = 0; k < len; k++) {
if ((i & (1 << k))) {
tmp.push(arr[k]);
}
if (depth && tmp.length > depth) {
good = false;
continue;
}
}
good && resp.push(tmp);
}
return resp;
}
const entries = [{c:"hey",r:false}, {c:" how are you",r:false}, {c:"!",r:true}];
entries.forEach((v,i)=>entries[i].i=i);
const req = entries.filter(v=>v.r);
const opt = entries.filter(v=>!v.r);
const result = [req.map(v=>v.c).join("")];
combs(opt).forEach(v=>{
result.push(req.concat(v).sort((a,b)=>a.i-b.i).map(v=>v.c).join(""))
})
console.log(result)
Firstly, I have to calculate the possibility of having only required elements,
after I calculate all possibility for optional elements only, and I merge each optional possibilities with the only required possibility.
I sort by the index in the origin array.
And I get:
[ '!', 'hey!', ' how are you!', 'hey how are you!' ]
As wanted :)
This might be less difficult than I'm making it out to be, but I'm trying to make a Discord.JS bot command, that will take however many arguments I have. For example: !randomize 1,2,3,4,5,6,7,8,9,10
And the bot would respond with something like: "I have chosen: 4,2,7,3,9!" Any help?
Current attempt: Not exactly sure what I'm doing.
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}`
`bot.on('message', async msg => {
if(msg.content === "!add") {
//message.member.user.tag
var msgArray = msg.content.split(" ");
var args = msgArray.slice(1);
var user = args[1];
//if(!args[1]) return msg.channel.send("Please specify an argument!");
if(nameList.includes(user)) {
msg.reply("You're already on the list.")
} else {
nameList.push(args[1]);
msg.channel.send(`${args[1]} has been added to the list!\n Current List:` + nameList);
}
}
if(msg.content === "!bonus") {
if(nameList.length === 0) {
msg.reply("Either the list is empty, or I'm not in the mood!");
} else {
shuffleArray(nameList);
var chosenOne = nameList.pop();
nameList = [];
msg.reply(chosenOne + ' has been chosen! Good luck!');
}
}
if(msg.content === "!list") {
if(nameList.length === 0) {
msg.channel.send("Either the list is empty, or I'm not in the mood!");
} else {
msg.channel.send('The current list:' + nameList);
}
});```
Here's some simple steps to select 5 random elements from an array...
Construct an array of possible selections. In this example I've used names for the first 10 letters of the alphabet. In your code, it'll be the command arguments or predefined nameList.
Make a new array to hold the elements picked.
At some point before #3, you should check to make sure the pool the user has provided is large enough to make 5 selections (Array.length).
Use a for loop to execute the next code multiple times.
Generate a random number representing the index of a selected element (Math.random(), Math.floor()/double NOT bitwise operator).
Push the selection into the array.
Remove the chosen element from the original pool (Array.splice()).
Return the results.
const pool = ['Albert', 'Bob', 'Charlie', 'David', 'Edward', 'Francis', 'George', 'Horacio', 'Ivan', 'Jim'];
const selected = [];
for (let i = 0; i < 5; i++) {
const num = ~~(Math.random() * pool.length);
selected.push(pool[num]);
pool.splice(num, 1);
}
console.log(`I have chosen: ${selected.join(', ')}`);
Take this example and manipulate it within your code to suit your purpose.
I have two code snippets . which one is better.
var texts:Array = new Array(1,2,3,4,5,6,7,8,9,10);
texts.reverse();
for(var index:int=0; index < texts.length; index++) {
trace(texts[index]);
}
Or
var texts:Array = new Array(1,2,3,4,5,6,7,8,9,10);
for( var index:int = texts.length; --index;) {
trace(texts[index]);
}
In former we have reverse operation and then print it and in latter we start from the length and start printing the array. The goal is to traverse the array from last.
I wrote a script which evaluates time elapsed between for loops. After running the application numerous of times, it appears that the 2nd for loop is fastest.
Averaging: 4.168000000000001 | 4.163000000000002 seconds respectively for 100 iterations of each for loop.
The script is as follows:
import flash.events.Event;
var _t:int = getTimer();
var dt:Number;
var started:Boolean = false;
var iteration:int = 0;
var timer1:Number = 0;
var timer2:Number = 0;
var numberOfIterations = 100;
var texts1:Array = new Array(1,2,3,4,5,6,7,8,9,10);
var texts2:Array = new Array(1,2,3,4,5,6,7,8,9,10);
texts2.reverse();
addEventListener(Event.ENTER_FRAME, onEnterFrame);
addEventListener(Event.EXIT_FRAME, onExitFrame);
function onEnterFrame(e:Event):void {
var t:int = getTimer();
dt = (t - _t) * 0.001;
_t = t;
iteration++;
// small FLA load buffer
if(iteration == 50 && !started)
{
iteration = 0;
started = true;
}
}
function onExitFrame(e:Event):void {
if(started)
{
if(iteration < numberOfIterations)
{
for(var index:int=0; index < texts1.length; index++) {}
timer2 += dt;
trace("Time Elapsed Alg 2: " + (timer2));
}
else
{
for( var index:int = texts2.length; --index;) {}
timer1 += dt;
trace("Time Elapsed Alg 1: " + (timer1));
}
if(iteration == ((numberOfIterations*2)-1))
{
trace("________________________________________");
trace("FINAL: " + timer1 + " | " + timer2);
removeEventListener(Event.EXIT_FRAME, onExitFrame);
removeEventListener(Event.ENTER_FRAME, onEnterFrame);
}
}
}
I am interested to see what others get using the following script, as it seems reliable on my PC as if I switch the for loop positions, the results still indicate that the fastest is:
var texts:Array = new Array(1,2,3,4,5,6,7,8,9,10);
for( var index:int = texts.length; --index;) {
trace(texts[index]);
}
The first one doesn't trace the last item in the array ie 1
The second one does.
So I say the second is better.
I'm curious though - what's the correct way to code the first one so that it traces all the items in the array?
How can I splice an array within another array?
I'm trying to create a game for kids in my class. Some kind of a trivia history question creator. How to splice the MasterArray so that I would get rid of sub-arrays (Hard-England and Medium-England) within the allEnglandArray. Because the "MasterArray.splice()" seem to be affecting - splicing only the allEngland array, or the allFrance array. But I need to get rid of those sub-arrays...
My code:
var Easy-England:Array = ["item1","item2","item3","item4","item5"];
var Medium-England:Array = ["item6","item7","item8"];
var Hard-England:Array = ["item9","item10"];
var allEngland:Array = [Easy-England,Medium-England,Hard-England];
var Easy-France:Array = ["item11","item12","item13","item14","item15"];
var Medium-France:Array = ["item16","item17","item18"];
var Hard-France:Array = ["item19","item20"];
var allFrance:Array = [Easy-France,Medium-France,Hard-France];
// the list of countries goes on and on and on... (Italy, Hungary, etc.)
var allStuff:Array = [allEngland, allFrance, etc.];
var MasterArray:Array;
// FUNCTIONS
// clear MasterArray - first I clear out completely the MasterArray
function clearMasterArray():void
{
MasterArray.splice(0);
}
// update MasterArray - than I fill the MasterArray with data according to checkBoxes
function updateMasterArray():void
{
for (var i:int = 0; i<checkBoxBlock.myCheckBoxes.length; i++)
{
if (checkBoxBlock.myCheckBoxes[i].selected)
{
MasterArray.push(allStuff[i]);
}
}
}
// splice MasterArray - last thing I do is splice the items according to student's proficiency level, referred to as "studentPL".
function spliceMasterArray():void
{
if (studentPL == 1)
{
for (var i:int = 0; i<allStuff.length; i++)
{
allStuff[i].splice(5,5);
}
}
if (studentPL == 2)
{
for (var i:int = 0; i<allStuff.length; i++)
{
allStuff[i].splice(8,2);
}
}
if (studentPL == 3)
{
for (var i:int = 0; i<allStuff.length; i++)
{
trace("no need to splice");
}
}
}
And after this I call those functions in another function in this order...
function creatorFunction():void
{
clearMasterArray();
updateMasterArray();
spliceMasterArray();
}
Instead of:
var allEngland:Array = [Easy-England,Medium-England,Hard-England];
try this:
var allEngland:Array = Easy-England.concat(Medium-England, Hard-England);
This way you will have a 'flat' array (no sub-arrays), so it will be easier to deal with.
Hi I am really struggling making code for a function that 'returns an array of indexes from an already populated array containing strings, when it matches the search term'.
So if the search term matches a word or characters in the element of the array regardless of its order, it should return the indexes in which those words are apparent in the array. Not using jquery grep feature.
Here is some code to illustrate what I mean.
array_test = ["Today was hot","Tomorrow will be hot aswell", "Yesterday the weather was not so good","o1234 t12345"]
function locateSearch(array_test,searchTerm){
var myArray = [];
for(i=0;i<array_test.length;i++){
if(...) // what should i be testing here, this is where i have been going wrong...
myArray[myArray.length] = i;
}
return myArray;
}
document.write(locateSearch,'ot') //this should return indexes [0,1,2,3]
Sorry If I have not explained this so well, appreciate your help. Thank you.
array_test = ["Today was hot","Tomorrow will be hot aswell", "Yesterday the weather was not so good","o1234 t12345"];
function locateSearch(array_test,searchTerm){
searchTerm = searchTerm.toLowerCase();
var myArray = [];
for(var i = 0; i < array_test.length; i++){
for(var j = 0; j < searchTerm.length; j++) {
if(array_test[i].toLowerCase().indexOf(searchTerm[j]) >= 0) {
myArray.push(i);
break;
}
}
}
return myArray;
}
alert(locateSearch(array_test, 'To').toString());
Also see this jsfiddle.
=== UPDATE ===
If every char has to be in the same string:
array_test = ["Today was hot","Tomorrow will be hot aswell", "Yesterday the weather was not so good","o1234 t12345"];
function locateSearch(array_test,searchTerm){
searchTerm = searchTerm.toLowerCase();
var myArray = [];
var bFound;
for(var i = 0; i < array_test.length; i++){
bFound = true;
for(var j = 0; j < searchTerm.length; j++) {
if(array_test[i].toLowerCase().indexOf(searchTerm[j]) == -1) {
bFound = false;
break;
}
}
if (bFound) {
myArray.push(i);
}
}
return myArray;
}
alert(locateSearch(array_test, 'es').toString());
Also see my updated jsfiddle.
if I understood your question correctly...
if(array_test[i].indexOf(searchTerm).toLowercase() != -1)
myArray.push(i);
You didn't mention if the search was case sensitive, but assuming it is I threw it in there
if you need your test to be case insensitive use the regEx match method instead of indexOf()
so... if(array[i].match(/searchTerm/i) != null){ myArray.push(i) }
Try this:
array_test = ["Today was hot","Tomorrow will be hot aswell", "Yesterday the weather was not so good","o1234 t12345"]
function locateSearch(array_test,searchTerm) {
var myArray = [];
for(i=0;i<array_test.length;i++) {
if(array_test[i].indexOf(searchTerm) != -1) // what should i be testing here, this is where i have been going wrong...
myArray.push(i);
}
return myArray;
}
document.write(locateSearch,'ot') //this should return indexes [0,1,2,3]
This will return indexes of all elements in array_test that contain the search term.