How to get all possibilities for required and optional entries? - arrays

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 :)

Related

I'm trying to randomize 5 selections from a list of people

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.

Multidimensional Arrays and one of the fields

There is a multi-d array and I want to reach specific field in it. I have look around it but I was unable to find proper answer to my question.
My array is like that;
array-md
columns-- 0 | 1 | 2
index 0 - [1][John][Doe]
index 1 - [2][Sue][Allen]
index 2 - [3][Luiz][Guzman]
.
.
.
index n - [n+1][George][Smith]
My question is how can I reach only second column of the array? I tried name = array[loop][1]; but it says "Cannot access a property or method of a null object reference". What is the right way to do that?
Here is main part of the code.
get
var lpx:int;
var lpxi:int;
var arrLen:int = Info.endPageArray.length;
for(lpx = 0; lpx < arrLen; lpx++)
{
for(lpxi = Info.endPageArray[lpx][2]; lpxi < Info.endPageArray[lpx][1]; lpxi++)
{
if(Info._intervalSearch[lpxi] == "completed")
{
successCount++;
Info._unitIntervalSuccess.push([lpx, successCount / (Info._intervalSearch.length / 100)]);
}
}
}
set
for(lpix = 0; lpix < arrayLength; lpix++)
{
if(lpix + 1 <= arrayLength)
{
Info.endPageArray.push([lpix, Info._UnitsTriggers[lpix + 1], Info._UnitsTriggers[lpix]]);
}
else
{
Info.endPageArray.push([lpix, Info._UnitsTriggers[lpix], Info._UnitsTriggers[lpix - 1]]);
}
}
Try this:
var tempArr:Array = [];
function pushItem(itemName:String, itemSurname:String):void
{
var tempIndex:int = tempArr.length;
tempArr[tempIndex] = {};
tempArr[tempIndex][tempIndex + 1] = {};
tempArr[tempIndex][tempIndex + 1][name] = {};
tempArr[tempIndex][tempIndex + 1][name][itemSurname] = {};
}
function getNameObject(index:int):Object
{
var result:Object;
if(index < tempArr.length)
{
result = tempArr[index][index + 1];
}
return result;
}
pushItem("Max", "Payne");
pushItem("Lara", "Croft");
pushItem("Dart", "Vader");
//
trace(getNameObject(0));
trace(getNameObject(1));
trace(getNameObject(2));
Multidimensional array is an array of arrays, which you can create like this :
var persons:Array = [
['John', 'Doe'],
['Sue', 'Allen'],
['Luiz','Guzman']
];
var list:Array = [];
for(var i:int = 0; i < persons.length; i++)
{
list.push([i + 1, persons[i][0], persons[i][1]]);
}
trace(list);
// gives :
//
// 1, John, Doe
// 2, Sue, Allen
// 3, Luiz, Guzman
Then to get some data :
for(var j:int = 0; j < list.length; j++)
{
trace(list[j][1]); // gives for the 2nd line : Sue
}
For more about multidimensional arrays take a look here.
Hope that can help.

AS3 flash, Array objects are carrying over into next frame and causing null object error

//I commented out the section that I was trying, but so far nothing has been working. I know I need to set up a loop or something of that kind to get rid of the items in the array, but I'm not sure how to get the right outcome.
THANKS SO MUCH
import flash.utils.Timer;
import flash.display.MovieClip;
import flash.events.Event;
var loveXCounter: Number = 0;
healthLove_txt.text = "Wrong Words: 0";
var insideLoveXCount = new Timer(4000, 0)
insideLoveXCount.addEventListener(TimerEvent.TIMER, countLoveX);
insideLoveXCount.start();
var loveXList: Array = ["Hate", "Abhor", "Vile", "Dislike", "Enmity", "Illwill", "Loath", "Neglect", "Repulse", "Resent"];
function countLoveX(e: TimerEvent) {
var loveXName: String = loveXList[Math.floor(Math.random() * loveXList.length)];
var loveXReference: Class = getDefinitionByName(loveXName) as Class;
var myLoveX = new loveXReference;
myLoveX.x = Math.random() * 700;
myLoveX.y = -10;
myLoveX.speed = 5;
myLoveX.addEventListener(Event.ENTER_FRAME, fallingLoveX);
addChild(myLoveX);
loveXList.splice(loveXName, 1);
}
function fallingLoveX(e: Event): void {
if (e.target.hitTestObject(fb_mc)) {
e.target.visible = false;
loveXCounter = loveXCounter + 1;
e.target.removeEventListener(Event.ENTER_FRAME, fallingLoveX);
healthLove_txt.text = "Wrong Words: " + loveXCounter;
if (loveXCounter == 5) {
while( loveXList.length > 0 )
{
this.removeChild( loveXList[loveXList.length - 1] );
loveXList.pop();
}
MovieClip(root).gotoAndStop(137);
loseBook_mc.gotoAndStop("loseLove");
}
}
if (e.target.y < 800) {
e.target.y += e.target.speed;
if (e.target.y > 800) {
e.target.y = 800;
}
} else {
e.target.visible = false;
}
}
stop();
I can see that the line...
loveXList.splice(loveXName, 1);
...might be causing problems. Firstly, the first parameter of the Array .splice method should be of type int. You are passing in a String. To remedy that, store the randomly selected index of the loveXList Array in an int variable, use that get your loveXName String and use the int again to splice out the correct String from the loveXList Array, ie:
var randomIndex:int = Math.floor(Math.random() * loveXList.length);
var loveXName: String = loveXList[randomIndex];
...
loveXList.splice(randomIndex, 1);
Secondly, you will quickly run out of Strings to splice out of the loveXList Array so, at the start of the countLoveX function, check if loveXList.length>0. If loveXList.length==0 you may want to stop the timer.

Porting c code to actionscript 2

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.

Difficulty returning an array of indexes of each element from an array that matches search term

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.

Resources