I'm creating a program that will ask a question and give 5 choices for answers.
One is pre-defined and is correct, the others I want to be random selections from a bank of answers and the entire array is to be shuffled too.
I've written something, but it has some inconsistencies.
For one, sometimes the pre-defined choice appears twice in the list (it appears to skip over my if check).
Another is that sometimes, the editor crashes when I run it.
I use for in loops and I'm worried the crash is caused by a never-ending loop.
Here's my code:
private var numberOfComponents:int;
private var maxComponents:int = 5;
//numberOfComponents returns the length property of my 'components' answer bank
componentsSelection = buildComponentSelectionList(0); //0 is the index of my correct answer
function buildComponentSelectionList(correctItemIndex){
var theArray:Array = new Array();
var indicesOfSelection:Array = getIndicesByIncluding(correctItemIndex);
Debug.Log(indicesOfSelection);
for (var i=0;i<indicesOfSelection.length;i++)
theArray.Push(components[indicesOfSelection[i]]);
return theArray;
}
function getIndicesByIncluding(correctItem){
var indicesArray:Array = new Array();
var numberOfChoices = maxComponents-1;
for(var i=0;i<numberOfChoices;i++){
var number = Mathf.Round(Random.value*(numberOfComponents-1));
addToRandomNumberSelection(indicesArray, number,correctItem);
}
indicesArray.Push(correctItem);
RandomizeArray(indicesArray);
return indicesArray;
}
function addToRandomNumberSelection(indicesArray:Array,number,correctItem){
if(indicesArray.length == 0){
indicesArray.Push(number);
} else {
var doesntExist = true;
for(var i=0;i<indicesArray.length;i++){
if(indicesArray[i] == correctItem)
doesntExist = false;
if (indicesArray[i] == number)
doesntExist = false;
}
if(doesntExist) {
indicesArray.Push(number);
} else {
addToRandomNumberSelection(indicesArray, Mathf.Round(Random.value*(numberOfComponents-1)),correctItem);
}
}
}
function RandomizeArray(arr : Array)
{
for (var i = arr.length - 1; i > 0; i--) {
var r = Random.Range(0,i);
var tmp = arr[i];
arr[i] = arr[r];
arr[r] = tmp;
}
}
The editor is Unity3D, and the code is a version of JavaScript; I think my error is a logic one, rather than a syntactical one.
I feel I've been staring at this code for too long now and I'm missing something obvious.
Can anybody help me?
You can loop through the options and determine the probability that it should be included, then shuffle the included options:
function getRandomOptions(allOptions, correctIndex, count){
var result = [allOptions[correctIndex]];
count--;
var left = allOptions.length;
for (var i = 0; count > 0; i++) {
if (i != correctIndex && Math.floor(Math.random() * left) < count) {
result.push(allOptions[i]);
count--;
}
left--;
}
shuffleArray(result);
return result;
}
function shuffleArray(arr) {
for (var i = arr.length - 1; i > 0; i--) {
var r = Math.floor(Math.random() * i);
var tmp = arr[i];
arr[i] = arr[r];
arr[r] = tmp;
}
}
Demo: http://jsfiddle.net/Guffa/wXsjz/
Related
I am newbie in machine learning, but decided to make own js library for neural networks, everything went perfect until i tryed to train my NN. In My Mini Library i created some functions...
1) A Function That Creates My Neuron-Object:
this.Node = function (conns) {
var output = {};
output.b = hyth.Random({type: "TanH"});
output.w = [];
for (var a = 0; a < conns; a++){
output.w[a] = hyth.Random({type: "TanH"});
}
output.Value = function (i) {
if (i.length == conns) {
var sum = 0;
for (var a = 0; a < conns; a++){
sum += i[a] * output.w[a];
}
sum += output.b;
return myMath.Activate(sum, {type: "Sigmoid"});
}
}
return output;
}
This function has one argument , which is the amount of wanted weights from neuron, and it returns an object with two properties - "b" the float (bias), and "w" the 1D Array which contains floats, and one method - which calculates the activation of neuron-object.
2) A Function That Creates My Neural Net
this.Network = function () {
var p = arguments;
var arr = [];
for (var a = 0; a < p.length-1; a++){
arr[a] = [];
for (var b = 0; b < p[a+1]; b++){
arr[a][b] = this.Node(p[a]);
}
}
return arr;
}
This Function Returns A 2D Array with Neuron-Object as It's final value, using argument array as settings for layer count and node count for each layer.
3) A Function That Feeds Forward The NN
this.Forward = function (network, input) {
if (network[0][0].w.length == input.length) {
var activations = [];
for (var a = 0; a < network.length; a++){
activations[a] = [];
for (var c = 0; c < network[a].length; c++){
if (a == 0){
activations[0][c] = network[0][c].Value(input);
continue;
}
activations[a][c] = network[a][c].Value(activations[a-1]);
}
}
return activations;
}
}
This Function Returns 2D array with an activation float for every neuron as it's final value. It uses 2 agruments - the output of 2nd function, input array.
4) And Final Function That Backpropagates
this.Backward = function (network, input, target) {
if (network[0][0].w.length == input.length && network[network.length-1].length == target.length) {
var activations = this.Forward(network, input, true);
var predictions = activations[activations.length-1];
var errors = [];
for (var v = 0; v < network.length; v++) {
errors[v] = [];
}
for (var a = network.length-1; a > -1; a--){
for (var x = 0; x < network[a].length; x++) {
var deract = hyth.Deractivate(activations[a][x]);
if (a == network.length-1) {
errors[a][x] = (predictions[x] - target[x]) * deract;
} else {
errors[a][x] = 0;
for (var y = 0; y < network[a+1].length; y++) {
errors[a][x] += network[a+1][y].w[x] * errors[a+1][y];
}
errors[a][x] *= deract;
}
}
}
return errors;
}
}
This Function Returns 2D array with the rror float for every neuron as it's final value. Arguments are 3 - the nnet , input and wanted output.
So I can make a neural network, feed forward and and backpropagate, receive activations and errors, but i always fail to train my net with my errors and activations to work perfect , last time it was outputing same result for every type of input. I want to understand training algorithm from zero , so i need someone's help.
P.S. - i dont want someone say that i need to use famous libraries , i want to understand and make it myself.
ic is my input array and cbList is my internal array that im checking agaist. I want to check the whole array and return the highest value in based on the cbList. I have some ugly code already tried but i dont want to use it, can someone basically make this better and more efficient. I've been searching and cant find anything in my situation.
So basically just want to check ic and if highest pops up, break out and return that value, if no highest is found, then go on to check high value, and so on...
function hcbin(inv){
var fh;
var ic = ['low','med','low','high'];
var cbList = [ 'low', 'med', 'high','highest'];
for( var i = 0; i < ic.length; i++) {
if (ic[i] === cbList[3]) {
$scope.hdc = ic[i];
fh = true;
}
}
if (!fh){
for( var ii = 0; ii < ic.length; ii++) {
if (ic[ii] === cbList[2]) {
$scope.hdc = ic[ii];
fh = true;
}
}
}
if (!fh){
for( var iii = 0; iii < ic.length; iii++) {
if (ic[iii] === cbList[1]) {
$scope.hdc = ic[iii];
fh = true;
}
}
}
if (!fh){
for( var iiii = 0; iiii < ic.length; iiii++) {
if (ic[iiii] === cbList[0]) {
$scope.hdc = ic[iiii];
fh = true;
}
}
}
};
Try this snippet:
var ic = ['low','med','low', 'high'];
var cbList = [ 'low', 'med', 'high','highest'];
var result = null;
for (var i = (cbList.length - 1); i >=0; i--) {
if (ic.indexOf(cbList[i]) > -1) {
result = cbList[i];
break;
}
}
console.log(result);
Make sure cbList keeps the priority order(from low to highest importance) because the for is based upon that.
I must be doing something stupid. The array newArea needs to add up data from all regions, i.e. be global. Regions are represented by variable p. But when I try to get newArea array to add to itself, e.g. newArea[p] += otherArray, it outputs NaNs. Even newArea[p] += 1 outputs NaNs.
Can anyone spot what I'm doing wrong? It's driving me mad and I'm working to a deadline.
mm=0
var maxVolume = 0;
var tempCAGR = 0;
var maxCAGR = 0;
var newArray = [];
var newRegions = [];
var newConsValues = [];
var newArea = [];
for (var p=0; p<arrayRef[mm].length; p++) {//9 regions
newArray[p] = [];
for (var q=0; q<arrayRef[mm][p].length; q++) {//4 scenarios
newArea[q] = [];
if (q==0) {
newRegions.push(arrayRef[mm][p][q][0]);
newConsValues.push(arrayRef[mm][p][q][1]);
}
for (var r=0; r<dates.length; r++) {//time
//console.log('p: '+p+', q: '+q+', r: '+r);
if (p==0) {
newArea[q][r] = 1;
} else {
newArea[q][r] += 1;
}
}
arrayRef[mm][p][q].shift();
tempCAGR = Math.pow(( arrayRef[mm][p][q][len] / arrayRef[mm][p][q][1] ),(1/len))-1;
//console.log(newRegions[p]+', num: '+arrayRef[mm][p][q][len-1]+', denom: '+arrayRef[mm][p][q][0]+', len: '+len+', cagr: '+tempCAGR);
newArray[p][q] = tempCAGR;
maxCAGR = Math.max(maxCAGR,tempCAGR);
}
}
console.log(newArea);
You are cleaning the array in newArea everytime you loop through it:
...loop q ...
newArea[q] = []; // <-- resets the array at q pos
... loop r ...
if (p==0) {
newArea[q][r] = 1;
} else {
newArea[q][r] += 1;
}
So when p === 0 it will fill an array at q pos of your newArea array. However, next iteration of p will clear them out, so there's nothing there to sum.
You probably want to keep the old array or create a new one if there isn't one.
newArea[q] = newArea[q] || [];
It looks like you do not have the variable initialised. With adding something to undefined, you get NaN.
You can change the art of incrementing with a default value:
if (p == 0) {
newArea[q][r] = 1;
} else {
newArea[q][r] = (newArea[q][r] || 0) + 1;
}
I'e been trying to write one and it's getting messy!
Suppose I have two strings textStart, textTarget and I want to keep track of the characters I would need to add and remove from textStart in order to product textTarget.
For instance, if textStart = "dude" and textTarget = "deck", then characters that would need to be added would be 'c' and 'k' and the characters that would need to be substracted would be the 'u' and one of the 'd's.
I'm thinking that I first need to create maps that represent the number of each character in textStart and textTarget.
So I wrote this:
var startChars = {};
for (var k = 0, n = textStart.length; k < n; ++k)
{
if (textStart[k] in startChars)
++startChars[textStart[k]];
else
startChars[textStart[k]] = 1;
}
var targetChars = {};
for (var k = 0, n = textTarget.length; k < n; ++k)
{
if (textTarget[k] in startChars)
++targetChars[textTarget[k]];
else
map1[targetChars[k]] = 1;
}
Which would give me
startChars['d']=2,
startChars['u']=1,
startChars['e']=1
and
targetChars['d']=1,
targetChars['e']=1,
targetChars['c']=1,
targetChars['k']=1
Then I can make create maps needAdded and needRemoved that look at the difference in the above two maps:
var needAdded = {};
var needRemoved = {};
I'm not sure how to fill those maps as intended, because I don't know how to iterate through the keys of a map using JavaScript. I somehow need to end up with
needAdded['c']=1,
needAdded['k']=1,
needRemoved['u']=1,
needRemoved['d']=1
That's where you guys come in and help me.
I hope I've done a good job describing what I'm trying to do and how I've tried to do it so far. My programming intuition tells me that I'm writing too many lines of code and that I need to consult StackOverflow for help. Any way to do this elegantly without JQuery or Regex? I know someone's going to come in this thread and write a 1-line Regex solution or something like that.
var s = 'dude',
t = 'deck',
finalOutput = '';
for (var i = 0; i < s.length; i++){
if ( typeof t[i] != 'undefined' ){
if ( s[i] != t[i] ){
console.log(s[i] + ' changed to ' + t[i]);
s[i] = t[i];
finalOutput += t[i];
} else{
finalOutput += s[i];
}
}
}
console.log('FINAL: ' + finalOutput);
Here's a jsfiddle I just spent way too much time on... hopefully it makes sense :)
var textStart = 'dude';
var textTarget = 'deck';
var startChars = {};
for (var k = 0, n = textStart.length; k < n; ++k)
{
if (textStart[k] in startChars)
++startChars[textStart[k]];
else
startChars[textStart[k]] = 1;
}
var targetChars = {};
for (var k = 0, n = textTarget.length; k < n; ++k)
{
if (textTarget[k] in targetChars)
++targetChars[textTarget[k]];
else
targetChars[textTarget[k]] = 1;
}
console.log('start: ' + JSON.stringify(startChars));
console.log('target: ' + JSON.stringify(targetChars));
var needAdded = {};
var needRemoved = {};
for (var c in startChars) {
// If target does not contain letter, remove all, otherwise remove excess
if (targetChars[c] > 0) {
if (startChars[c] > targetChars[c])
needRemoved[c] = startChars[c] - targetChars[c];
else if (startChars[c] < targetChars[c])
needAdded[c] = targetChars[c] - startChars[c];
} else {
needRemoved[c] = startChars[c];
}
}
for (var c in targetChars) {
// If start does not contain letter, add all, otherwise add excess
if (startChars[c] > 0) {
if (startChars[c] > targetChars[c])
needRemoved[c] = startChars[c] - targetChars[c];
else if (startChars[c] < targetChars[c])
needAdded[c] = targetChars[c] - startChars[c];
} else {
needAdded[c] = targetChars[c];
}
}
console.log('needAdded: ' + JSON.stringify(needAdded));
console.log('needRemoved: ' + JSON.stringify(needRemoved));
The output is as follows:
start: {"d":2,"u":1,"e":1}
target: {"d":1,"e":1,"c":1,"k":1}
needAdded: {"c":1,"k":1}
needRemoved: {"d":1,"u":1}
Ok, also too much time on this:
var textStart = "dude";
var textTarget = "duck";
var map = {};
MapCharacters(textStart, map, 1);
MapCharacters(textTarget, map, -1);
console.log(map);
var toDelete = [];
var toAdd = [];
for (var prop in map) {
if (map.hasOwnProperty(prop)) {
while (map[prop] > 0) {
toDelete.push(prop);
map[prop]--;
}
while (map[prop] < 0) {
toAdd.push(prop);
map[prop]++;
}
}
}
console.log(toDelete);
console.log(toAdd);
function MapCharacters(string, map, add) {
for (var k = 0, n = string.length; k < n; ++k) {
if (string[k] in map) {
map[string[k]] += add;
} else {
map[string[k]] = add;
}
}
}
http://jsfiddle.net/nSV2J/1/
It could probably be done more efficiently, but as I said - too much time!
I realized that the best way to do this is not to make two maps, but just one. In the first case you increment the count for each letter and in the second case you decrease it. Now it's easy to find which ones need to be removed (the ones that end up > 0) and which ones need to be added (the ones that end up < 0)
This is a challenge for coderbyte I thought I'd try to do it using a different method for solving it than loops, objects. It passed but it isn't perfect. The directions for the challenge are:
Have the function LetterCountI(str) take the str parameter being passed and return the first word with the greatest number of repeated letters. For example: "Today, is the greatest day ever!" should return greatest because it has 2 e's (and 2 t's) and it comes before ever which also has 2 e's. If there are no words with repeating letters return -1. Words will be separated by spaces.
function LetterCountI(str){
var wordsAndLetters = {};
var count = 0;
var finalword;
str = str.split(" ");
for(var i = 0; i < str.length; i++){
wordsAndLetters[str[i]] = wordsAndLetters[str[i]] || 0;
}
function countWordLetters(strs){
strs = strs.split("");
var lettercount = {};
for(var i = 0; i <strs.length; i++){
lettercount[strs[i]] = lettercount[strs[i]] || 0;
lettercount[strs[i]]++;
}
return lettercount;
}
for(var words in wordsAndLetters){
wordsAndLetters[words] = countWordLetters(words);
var highestLetterFrequency = wordsAndLetters[words];
for(var values in highestLetterFrequency){
if(highestLetterFrequency[values] > count){
count = highestLetterFrequency[values];
finalword = words;
}
if(count !== 1){
return finalword;
}
}
}
return -1;
}
LetterCountI("today is the greatest day ever!");
Sorry if some of the variable names are confusing I've been up for far too long trying to figure out what I did wrong. If you use the parameters at the bottom of the code it returns 'greatest' like it should however change the parameters to
LetterCountI("toddday is the greatttttest day ever!");
and it logs 'toddday' when it should log 'greatttttest'. Is my code completely wrong? I realize if the parameters were ("caatt dooog") it should log 'caatt' since there are 4 recurring letters but I'm not worried about that I just am concerned about it finding the most recurrence of one letter(but by all means if you have a solution I would like to hear it!). Any changes to the variables if needed to make this code more readable would be appreciated!
The problem with your code is the positioning of the following section of code:
if(count !== 1){
return finalword;
}
Move it from where it currently is to just before the return -1, like so:
for(var words in wordsAndLetters){
wordsAndLetters[words] = countWordLetters(words);
var highestLetterFrequency = wordsAndLetters[words];
for(var values in highestLetterFrequency){
if(highestLetterFrequency[values] > count){
count = highestLetterFrequency[values];
finalword = words;
}
}
}
if(count !== 1){
return finalword;
}
return -1;
The problem with your original code is that your were returning the first word that had repeating characters, which meant your code didn't get far enough to check if any subsequent words had more repeating characters.
Also, just for fun, here is my alternative solution.
Here you go
Array.prototype.getUnique = function(){
var u = {}, a = [];
for(var i = 0, l = this.length; i < l; ++i){
if(u.hasOwnProperty(this[i])) {
continue;
}
a.push(this[i]);
u[this[i]] = 1;
}
return a;
}
function LetterCountI(str){
var temp = str.split(" ");
var final = '', weight = 0;
for(var i = 0; i < temp.length; ++i) {
var word = temp[i].split("");
if(word.getUnique().length < word.length) {
var diff = word.length - word.getUnique().length;
if(diff > weight){
weight = diff;
final = temp[i];
}
}
}
return final;
}
console.log(LetterCountI("Catt dooog"));
console.log(LetterCountI("toddday is the greatttttest day ever!"));
Viva LinQ !!!!!
var resultPerWord = new Dictionary<string, int>();
var S = "toddday is the greatttttest day ever!";
foreach(var s in S.Split(' '))
{
var theArray =
from w in s
group w by w into g
orderby g.Count() descending
select new { Letter = g.Key, Occurrence = g.Count() };
resultPerWord.Add(s, theArray.First().Occurrence);
}
var r = "-1";
if (resultPerWord.Any(x => x.Value >1))
{
r = resultPerWord.OrderByDescending(x => x.Value).First().Key;
}