I'm playing with BrainJS and looks awesome! However, I just came across a problem: how do I train my Neural Network to learn a general idea of how a phone number looks like (I guess feeding in a long list of phone numbers?) and after that, how do I actually run BrainJS to go through some text and find a phone number in it?
If I manage to do this I guess I can teach the NN to learn to find other meaningful information, all of this without using Regex!
I've checked all available features and I can't find what I need: Find a piece of specific data from the input based on what the neural network has been trained with.
Here a piece of code that I believe might be close to what I need, it understands there is a phone number(s) in the sentence based on training. What I want to achieve is get the phone number in the output, potentially on a piece of text it has never seen before.
var brain = require('brainjs');
const learnPhoneData = [
{
input: "Our phone number is 06545 294064 or 29495 195869",
output: {phone_number: 1}
},
{
input: "Our direct line is 36496 496743",
output: {phone_number: 1}
},
{
input: "Give us a call on our 02453 753425.",
output: {phone_number: 1}
}
// ... more of the above
]
const nonPhoneData = [
{
input: "Opening hours Monday to Friday - 9:00am to 5.00pm.",
output: {non_phone_number: 1}
},
{
input: "If you need help with your TV or radio broadcast licence please contact email#site.co.uk.",
output: {non_phone_number: 1}
},
{
input: "Welcome to our website!",
output: {non_phone_number: 1}
}
// ... more of the above
]
// of course the larger the datasets, the more accurate the AI.
var maxLengthInput = -1;
const normalizeArray = arr => {
while (arr.length < maxLengthInput) {
arr.push(0);
}
return arr;
}
const fixLengths = (data) => {
for (let i = 0; i < data.length; i++) {
if (data[i].input.length > maxLengthInput) {
maxLengthInput = data[i].input.length;
}
}
for (let i = 0; i < data.length; i++) {
data[i].input = normalizeArray(data[i].input);
}
return data;
}
const encode = d => {
const newArr = [];
d.split('').map(c => {
newArr.push((c.charCodeAt(0) / 255))
})
return newArr
}
const encodeData = data => {
return data.map( d => {
return {
input: encode(d.input),
output: d.output
}
})
}
const serializeAll = data => fixLengths(encodeData(data))
const serializeOne = data => normalizeArray(encode(data));
const trainData = [
...learnPhoneData,
...nonPhoneData
];
const net = new brain.NeuralNetwork({
activation: 'sigmoid', // activation function
hiddenLayers: [100, 100],
iterations: 2000,
learningRate: 0.002, // global learning rate, useful when training using streams
errorThresh: 0.005
});
net.train(serializeAll(trainData), {log: true})
//net.train(serializeAll(trainData))
// if entering only a phone number, it actually is very accurate :)
var output = net.run(serializeOne('07353 456357'))
console.log(output);
// {phone_number: 0.8490427059461814, non_phone_number: 0.149902567401934}
// when entering text and phone number, it is not accurate :-S
output = net.run(serializeOne('Call me on my 07353 456357 and I will get back ASAP.'))
console.log(output);
// {phone_number: 0.41922502546759033, non_phone_number: 0.5814407195666387}
Related
I want to update automatically the value of comments_list with the values in the comments JSON object
const tweet = JSON.stringify({"tweet_id":1,"created_at":"2022-06-28","comments_list":[]})
const comments = JSON.stringify({"tweet_id":1,"commenter_id": 2"commenter_first_name":"tito","commenter_username":"tito_lulu"})
The final output should look like this
{"tweet_id":1,"created_at":"2022-06-28","comments_list":[{"commenter_id": 2"commenter_first_name":"tito","commenter_username":"tito_lulu"}]}
I'd work with those strings in an object form, otherwise string-manipulation could be slow in some cases.
This is by no means the fastest solution but perhaps the idea behind it can be helpful.
const tweet = [{
"tweet_id": 1,
"created_at": "2022-06-28",
"comments_list": []
}]; // There could be many tweet objects so wrap it in an array
const comments = [{
"tweet_id": 1,
"commenter_id": 2,
"commenter_first_name": "tito",
"commenter_username": "tito_lulu"
},
{
"tweet_id": 1,
"commenter_id": 5,
"commenter_first_name": "me-too",
"commenter_username": "me294"
}
]; // Same here, could be many comments right?
let UpdatedTweets = [];
// There are faster ways to do this, but for your question
tweet.forEach((tweet, tweetIndex) => {
// Loop each tweet
let post = tweet;
comments.forEach((comment, commentIndex) => {
if (comment.tweet_id == tweet.tweet_id) {
// we have a match lets combine them
tweet.comments_list.push({
commenter_id: comment.comment_id,
commenter_first_name: comment.commenter_first_name,
commenter_username: comment.commenter_username
});
}
});
UpdatedTweets.push(post);
});
console.log(JSON.stringify(UpdatedTweets));
The general idea is:
Parse the JSON into JS objects
Update the target object with the complementary information
Stringify the target object into JSON (only if you need to, eg. send the data to some other machine)
In your case:
const tweet = JSON.stringify({"tweet_id":1,"created_at":"2022-06-28","comments_list":[]});
const comments = JSON.stringify({"tweet_id":1,"commenter_id": 2,
"commenter_first_name":"tito","commenter_username":"tito_lulu"});
let o_tweet = JSON.parse(tweet)
, o_comments = JSON.parse(comments)
;
if (Array.isArray(comments)) { // Test whether that is a single or multiple comments
comments.forEach( c => { o_tweet.comments_list.push(c); });
} else {
o_tweet.comments_list.push(o_comments);
}
console.log(o_tweet);
// Only if needed:
// let newtweet = JSON.stringify(o_tweet)
I am currently studying Vue and creating a personal account for the gazoline company.
I have an API IMG in console log
inside the data array there is also a transfer array, also u can see in below picture.
This data is output like this :
I want to get the amount of income in each tankfarme. How can I do it ?
somehow I was able to get the amount of the expense, but it receives the entire amount, and not in one tankfarm. Here is code
const getSumExpense = computed(() => {
let array = getTransfers.value.transfers.data;
let sum = 0;
array.forEach((element) => {
let arrayIncome = element.transfer;
arrayIncome.forEach((el) => {
sum = sum + el.expense;
});
});
return sum;
});
please help me, if you do not understand what I wrote, also tell me, I will try to write better
You can Array.prototype.reduce()
Code:
const arrayIncome = [{expense: 20}, {expense: 30}, {expense: 40}]
const sum = arrayIncome.reduce((a, { expense: e }) => a + e, 0)
console.log(sum)
If you want to get the sum of some specific tankfarm then you have to filter the array first and then with the help of reduce you can sum the records.
const data= [{tankfarm: 'cymma', transfer: [{expense: 10}, {expense: 20}]}]
const result = data.filter(element => element.tankfarm === 'cymma')[0].transfer.reduce((a, { expense: e }) => a + e, 0)
console.log("cymma expense", result)
I am having difficulties solving the following programming problem:
Write a function that keeps track of guests that are going
to a house party. You will be given an array of strings. Each string
will be one of the following:
{name} is going!
{name} is not going!
If you receive the first type of input, you have to add the person if
he/she is not in the list (If he/she is in the list print: {name} is
already in the list! If you receive the second type of input, you have
to remove the person if he/she is in the list (if not, print:{name} is
not in the list!).
At the end print all the guests each on a separate line.
The assignment is to solve it with array methods, for loops, for each, for of…anything that works.
I know it might be too simple for this website and I’m sorry but I have been struggling with it for too many hours and unfortunately this is as far as I can go with the code… My problem is that I can't seem to divide it into small steps and execute them with array methods and loops...
function houseParty(input) {
let guestsList = [];
let notComing = [];
for (let i = 0; i < input.length; i++) {
if (input[i].includes('not')) {
notComing.push(input[i]);
} else {
guestsList.push(input[i]);
}
}
}
houseParty(['Allie is going!',
'George is going!',
'John is not going!',
'George is not going!'
])
This is an example of an input:
[Tom is going!,
Annie is going!,
Tom is going!,
Garry is going!,
Jerry is going!]
And this is the expected output:
Tom is already in the list!
Tom
Annie
Garry
Jerry
I would be very happy if you could explain to me the logic behind the programming problem and how you guys 'translate' it into small steps so that the program does what needs to be done.
Your question is about the puzzle's logic and how to form steps to solve it. The ability to form the steps necessary is more of a way of thinking than anything else, it comes with practice. As for the logic, the solution can be implemented as follows:
create a collection (ie: array) of names that are going to the party
iterate over the input array
extrapolate from the message both the name of the person and if they are going or not.
if they are going and their name is not in the collection add their name to the collection
if they are not going and the name is in the collection then make sure their name is removed
after collecting your guests, iterate over your finalized collection and log your guests names to the console
**Are you looking this?**Please follow the explanation from the #foobar2k19's answer.
function houseParty(input) {
let guestsList = [];
for (let i = 0; i < input.length; i++) {
let nameOfThePerson = input[i].split(" ")[0];
if (input[i].includes('not')) {
if (guestsList.indexOf(nameOfThePerson) > -1) {
guestsList.splice(guestsList.indexOf(nameOfThePerson), 1);
}
} else if(guestsList.includes(nameOfThePerson)) {
guestsList.push(nameOfThePerson + ' is already in the list!');
} else {
guestsList.push(nameOfThePerson);
}
}
return guestsList;
}
const inputArr = ['Tom is going!',
'Annie is going!',
'Tom is going!',
'Garry is going!',
'Jerry is going!'];
console.log(houseParty(inputArr));
Try using Array#prototype#reduce to build a frequency list first, then mapping it to the response you want.
function houseParty(input) {
const res = Object.entries(input.reduce((acc, curr) => {
const name = curr.split(' ')[0];
if (!acc[name]) {
acc[name] = 1;
} else {
acc[name] += 1;
}
return acc;
}, {}))
.map(x => {
if (x[1] > 1) {
return `${x[0]} is already in the list`;
} else {
return x[0];
}
});
return res;
}
const result = houseParty(['Allie is going!',
'George is going!',
'John is not going!',
'George is not going!'
]);
console.log(result);
I'll give you more 'easy to understand' way.
Note 1:
better to check 'not going' match in string, because of the name may
contain 'not' - there are a lot of strange names around the world (For
example Knott).
Note 2:
You have to remove a person from the list if his/her name repeated in
input with different status.
function houseParty(input) {
let guestList = [];
let notComing = [];
let name, going;
//loop through input
for(let i = 0; i < input.length; i++) {
//get persons name
name = input[i].split(' ')[0];
//set going status
going = !input[i].includes('not going');
if (going) {
//check name in going list
if (guestList.indexOf(name) > -1) {
//this person is already in list
console.log(`${name} is in the list`);
}
else {
//add person in list
guestList.push(name);
}
//check if person was in not going list, remove from it
if (notComing.indexOf(name) > -1) {
//remove from not going list
notComing.splice(notComing.indexOf(name), 1);
}
}
else {
//check if name is in not going list
if (notComing.indexOf(name) > -1) {
console.log(`${name} is in the list`);
}
else {
notComing.push(name);
}
//check if person was in going list before
if (guestList.indexOf(name) > -1) {
guestList.splice(guestList.indexOf(name), 1);
}
}
}
//you have both lists filled now
console.log("Guests: ", guestList);
console.log("Not coming: ", notComing);
}
let input = [
'Allie is going!',
'George is going!',
'John is not going!',
'George is going!',
'George is not going!',
'Knott is going!'
];
//test
houseParty(input);
I'm brand new to programming so I apologize if this is a simple question.
I had a unique practice problem that I'm not quite sure how to solve:
I'm dealing with two arrays, both arrays are pulled from HTML elements on the page, one array is representing a bunch of states, and the next array is representing their populations. The point of the problem is to print the name of the states and their less than average populations.
To find and print all of the populations that are less than the average I used this code:
function code6() {
// clears screen.
clr();
// both variables pull data from HTML elements with functions.
var pop = getData2();
var states = getData();
var sum = 0;
for( var i = 0; i < pop.length; i++ ){
sum += parseInt( pop[i], 10 );
var avg = sum/pop.length;
if (pop[i] < avg) {
println(pop[i]);
// other functions used in the code to get data, print, and clear the screen.
function getData() {
var dataSource = getElement("states");
var numberArray = dataSource.value.split('\n');
// Nothing to split returns ['']
if (numberArray[0].length > 0) {
return(numberArray);
} else {
return [];
}
}
// Get the data from second data column
function getData2() {
var dataSource = getElement("pops");
var numberArray = dataSource.value.split('\n');
// Nothing to split returns ['']
if (numberArray[0].length > 0) {
return(numberArray);
} else {
return [];
}
}
// Clear the 'output' text area
function clr() {
var out = getElement("output");
out.value = "";
}
// Print to the 'output' HTML element and ADDS the line break
function println(x) {
if (arguments.length === 0) x = '';
print(x + '\n');
}
Now I just need to know how to get the value of these positions within the array so I can pull out the same positions from my states array and display them both side by side. Both arrays have the identical amount of items.
I hope this makes sense and thanks in advance to anyone who has time to take a look at this.
Best regards,
-E
Its a little hard to tell what you are trying to accomplish, but I guess you are going for something like:
'use strict'
function code6() {
const populations = ['39000000', '28000000', '21000000'];
const stateNames = ['california', 'texas', 'florida'];
const states = populations.map((population, i) => ({
'name': stateNames[i],
'population': Number(population),
}));
const sum = states.reduce((sum, state) => sum + state.population, 0);
const average = sum / populations.length;
states
.filter(state => state.population < average)
.forEach(state => {
const name = state.name;
const population = state.population;
console.log(`state name: ${name}, population: ${population}`);
});
}
// run the code
code6();
// state name: texas, population: 28000000
// state name: florida, population: 21000000
I took the liberty of refactoring your code to be a little more modern (es6) and Idiomatic. I hope its not to confusing for you. Feel free to ask any questions about it.
In short you should use:
'use strict' at the top of your files
const/let
use map/filter/forEach/reduce to iterate lists.
use meaningfull names
, and you should avoid:
classic indexed for-loop
parseInt
, and pretty much never ever use:
var
If your states array is built with corresponding indices to your pop one, like this:
states; //=> ['Alabama', 'Alaska', 'Arizona', ...]
pop; //=> [4863300, 741894, 6931071, ...]
then you could simply update your print statement to take that into account:
if (pop[i] < avg) {
println(state[i] + ': ' + pop[i]);
}
Or some such.
However, working with shared indices can be a very fragile way to use data. Could you rethink your getData and getData2 functions and combine them into one that returns a structure more like this the following?
states; //=> [
// {name: 'Alabama', pop: 4863300}
// {name: 'Alaska', pop: 741894},
// {name: 'Arizona', pop: 6931071},
// ...]
This would entail changes to the code above to work with the pop property of these objects, but it's probably more robust.
If your pop and state looks like:
var state = ['state1', 'state2', ...];
var pop = ['state1 pop', 'state2 pop', ...];
Then first of all, avg is already wrong. sum's value is running along with the loop turning avg's formula into sum as of iteration / array length instead of sum of all pops / array length. You should calculate the average beforehand. array.reduce will be your friend.
var average = pop.reduce(function(sum, val){return sum + val;}, 0) / pop.length;
Now for your filter operation, you can:
Zip up both arrays to one array using array.map.
Filter the resulting array with array.filter.
Finally, loop through the resulting array using array.forEach
Here's sample code:
var states = ['Alabama', 'Alaska'];
var pop = [4863300, 741894];
var average = pop.reduce(function(sum, val){return sum + val;}) / pop.length;
console.log('Average: ' + average);
states.map(function(state, index) {
// Convert 2 arrays to an array of objects representing state info
return { name: state, population: pop[index] };
}).filter(function(stateInfo) {
console.log(stateInfo);
// Filter each item by returning true on items you want to include
return stateInfo.population < average;
}).forEach(function(stateInfo) {
// Lastly, loop through your results
console.log(stateInfo.name + ' has ' + stateInfo.population + ' people');
});
Currently solving a puzzle and looking for some tips on sorting by events ordered. I would like to know what exactly is the procedure I should be following. Consider this
I input a number, then there n inputs
each input has two events, where of for event1 event2, and event1 happens before event2.
Consider the input
6
Eatfood Cuthair
Eatfood BrushTeeth
School EatFood
School DoHair
DoHair Meeting
Meeting Brushteeth
The output will be
school -> dohair-> eatfood -> meeting -> cuthair -> brushteeth
In that order. Since if we write everything down, school is indeed the first thing that occurs, and then dohair is second. If more than one possible ordering exists simply output one. You may assume that all events are connected in some way, and no circular dependencies exist.
What I am thinking about doing is making two arrays, one which has all eventOne's and all eventTwo's. I'm not really sure where to go from here though. I would like to do this in javascript. Thanks! Any hints or algorithms are suggested
Another Input
6
vote_140_prof announce_140_prof
vote_140_prof first_day_of_classes
dev_shed_algo vote_140_prof
dev_shed_algo do_hair
do_hair big_meeting
big_meeting first_day_of_classes
Output
dev_shed_algo do_hair vote_140_prof big_meeting announce_140_prof first_day_of_classes
I found the solution file on my computer, its in python which I don't know, but hopefully this will help others understand the problem
from collections import defaultdict
def toposort(graph, roots):
res = [i for i in roots]
queue = [i for i in roots]
while queue:
for i in graph[queue.pop(0)]:
if i not in res:
res.append(i)
queue.append(i)
return res
graph = defaultdict(set)
a_set = set()
b_set = set()
for i in range(int(input())):
a, b = input().split()
a_set.add(a)
b_set.add(b)
graph[a].add(b)
print(" ".join(i for i in toposort(graph, a_set - b_set)))
My attempt
var words =
'vote_140_prof announce_140_prof vote_140_prof first_day_of_classes devshed_algo vote_140_prof dev_shed_algo do_hair do_hair big_meeting big_meeting first_day_of_classes';
var events = words;
events = events.split(/\s+/);
console.log(events);
var obj = {};
for (var i = 0 ; i < events.length ; i++)
{
var name = events[i];
if(obj[name] === undefined )
{
obj[name] = [];
}
obj[name].push(events[i%2 === 1 ? i-1 : i+1]);
}
console.log(obj);
FORMATING
function sequenceEvents(pairs){
var edges = pairs.reduce(function(edges,pair){
edges.set(pair[0],[]).set(pair[1],[]);
new Map();
});
pairs.forEach(function(edges,pair){
edges.set(pair[0],[]).set(pair[1],[]);
});
var result = [];
while(edges.size){
var children = new Set([].concat.apply([],[...edges.value()]));
var roots = [...edges.keys()].filter(function(event){
!children.has(event);
});
if(!roots.length) throw "Cycle detected";
roots.forEach(function(root){
result.push(root);
edges.delete(root);
});
}
return result;
}
The Python algorithm is not correct. It will fail for this input:
3
A B
A C
C B
It will output:
A, B, C
...which conflicts with the last rule. This is because it wrongly assumes that the children of any root-event can be safely added to the result, and depend on no other events. In the above case, it will identify A as root, and B and C as its children. Then it will pop of C from that list, and add it to the result, without seeing that C depends on B, which is not in the result yet.
As others have noted, you need to make sure the capitalisation is consistent. Brushteeth and BrushTeeth are considered different events. The same is true for EatFood and Eatfood.
I provide here a solution. I hope the inline comments explain well enough what is happening:
function sequenceEvents(pairs) {
// Create a Map with a key for each(!) event,
// and add an empty array as value for each of them.
var edges = pairs.reduce(
// Set both the left and right event in the Map
// (duplicates get overwritten)
(edges, pair) => edges.set(pair[0], []).set(pair[1], []),
new Map() // Start with an empty Map
);
// Then add the children (dependent events) to those arrays:
pairs.forEach( pair => edges.get(pair[0]).push(pair[1]) );
var result = [];
// While there are still edges...
while (edges.size) {
// Get the end points of the edges into a Set
var children = new Set( [].concat.apply([], [...edges.values()]) );
// Identify the parents, which are not children, as roots
var roots = [...edges.keys()].filter( event => !children.has(event) );
// As we still have edges, we must find at least one root among them.
if (!roots.length) throw "Cycle detected";
roots.forEach(root => {
// Add the new roots to the result, all events they depend on
// are already in the result:
result.push(root);
// Delete the edges that start with these events, since the
// dependency they express has been fulfilled:
edges.delete(root);
});
}
return result;
}
// I/O
var input = document.querySelector('#input');
var go = document.querySelector('#go');
var output = document.querySelector('#output');
go.onclick = function() {
// Get lines from input, ignoring the initial number
// ... then split those lines in pairs, resulting in
// an array of pairs of events
var pairs = input.value.trim().split(/\n/).slice(1)
.map(line => line.split(/\s+/));
var sequence = sequenceEvents(pairs);
output.textContent = sequence.join(', ');
}
Input:<br>
<textarea id="input" rows=7>6
EatFood CutHair
EatFood BrushTeeth
School EatFood
School DoHair
DoHair Meeting
Meeting BrushTeeth
</textarea>
<button id="go">Sequence Events</button>
<div id="output"></div>
Without arrow functions nor apply
As in comments you indicated you like to have the code without arrow functions first:
function sequenceEvents(pairs) {
// Create a Map with a key for each(!) event,
// and add an empty array as value for each of them.
var edges = pairs.reduce(function (edges, pair) {
// Set both the left and right event in the Map
// (duplicates get overwritten)
return edges.set(pair[0], []).set(pair[1], []);
}, new Map() ); // Start with an empty Map
// Then add the children (dependent events) to those arrays:
pairs.forEach(function (pair) {
edges.get(pair[0]).push(pair[1]);
});
var result = [];
// While there are still edges...
while (edges.size) {
// Get the end points of the edges into a Set
var children = new Set(
[...edges.values()].reduce(function (children, value) {
return children.concat(value);
}, [] )
);
// Identify the parents, which are not children, as roots
var roots = [...edges.keys()].filter(function (event) {
return !children.has(event);
});
if (!roots.length) throw "Cycle detected";
roots.forEach(function (root) {
// Add the new roots to the result, all events they depend on
// are already in the result:
result.push(root);
// Delete the edges that start with these events, since the
// dependency they express has been fulfilled:
edges.delete(root);
});
}
return result;
}
Okay. Here's my shot at the problem.
var makePair = function(i0, i1) {
return {start: i0, end: i1};
};
var mp = makePair;
var makeBefores = function(pairs) {
var befores = {};
pairs.forEach(function(pair) {
if (befores[pair.end] == null) {
befores[pair.end] = [pair.start];
} else {
befores[pair.end].push(pair.start);
}
if (befores[pair.start] == null) {
befores[pair.start] = [];
}
});
for (var key in befores) {
console.log("after " + key + "there is:");
for (var i = 0; i < befores[key].length; i++) {
console.log(befores[key][i]);
}
}
return befores;
};
var shouldGoBefore = function(item, before) {
for (var i = 0; i < before.length; i++) {
if (item == before[i]) {
return true;
}
}
return false;
};
var sortEvents = function(pairs) {
if (pairs.length === 0) {
return [];
}
if (pairs.length === 1) {
return [pairs[0].start, pairs[0].end];
}
console.log(pairs);
var befores = makeBefores(pairs);
var sorted = [];
for (var key in befores) {
var added = false;
for (var i = 0; i < sorted.length; i++) {
console.log('checking if ' + sorted[i] + ' should go before ' + befores[key]);
if (shouldGoBefore(sorted[i], befores[key])) {
//console.log("splicing");
sorted.splice(i, 0, key);
added = true;
break;
}
}
if (!added) {
sorted.push(key);
}
}
return sorted.reverse();
}
var pairs = [mp('vote_140_prof','announce_140_prof'),mp('vote_140_prof','first_day_of_classes'),mp('dev_shed_algo','vote_140_prof'),mp('dev_shed_algo','do_hair'),mp('do_hair','big_meeting'),mp('big_meeting','first_day_of_classes'),mp('announce_140_prof','first_day_of_classes')];
console.log(sortEvents(pairs));
One reason things may not have been working is your test data had inconsistent capitalization. The results of this run are:
Array [ "School", "EatFood", "CutHair", "Meeting", "BrushTeeth", "DoHair" ]
I'm going to test it on your other data set but I believe this fulfills the prompt. I'm going to write up how it works in a minute.
Note that this doesn't do any file IO or reading of lines. It takes the input to sortEvents as an array of objects that have a start and end property, which I provided a helper method makePair to create.
The solution works by building a dictionary of what elements go before which others.
If you had an input like:
a->b
c->a
c->b
b->d
The dictionary would be like this:
a->[c],
c->[],
b->[a,c],
d->[b]
Then we use an array as a sort of linked list and we go through it seeing whether we have to insert something. So for example, if we are trying to see where a should be inserted and the list is c, then we would look at the dictionary for c, see that c is in it and then we know that before a there is supposed to be c, therefore we have to insert a after c
Take a hash map start with first event and put it's value to 0 than whenever you encounter event 2 check the value of event 1 in hash than put a smaller value for event 2. Once complete sort hash by value.
Bingo
line = input();
myMap = dict()
i=0
while i < line:
event1 = raw_input()
event2 = raw_input()
if event1 in myMap :
myMap[event2] = myMap[event1]+1
elif event2 in myMap:
myMap[event1] = myMap[event2]-1
else :
myMap[event1] = 0
myMap[event2] = 1
i=i+1
print i
print myMap
I don't know why some people downvoted but yes it's working, Atleast on both your samples
Sample input and output
6
eatfood
cuthair
1
{'eatfood': 0, 'cuthair': 1}
eatfood
brushteeth
2
{'brushteeth': 1, 'eatfood': 0, 'cuthair': 1}
school
eatfood
3
{'brushteeth': 1, 'eatfood': 0, 'school': -1, 'cuthair': 1}
school
dohair
4
{'brushteeth': 1, 'eatfood': 0, 'school': -1, 'cuthair': 1, 'dohair': 0}
dohair
meeting
5
{'school': -1, 'brushteeth': 1, 'cuthair': 1, 'dohair': 0, 'eatfood': 0, 'meeting': 1}
meeting
brushteeth
6
{'school': -1, 'brushteeth': 2, 'cuthair': 1, 'dohair': 0, 'eatfood': 0, 'meeting': 1}
The code is in python, feel free to convert in javascript