Guidelines: The following exercise questions should take 1-2 hours, Put your answers after each question - try to give some short explanation for your
Candidate Name: Pery Date: 12/02/2020
Consider an array containing positive integers sorted in ascending order. A “Lead Number” of this array is an integer that repeats itself more than half of the array length Example: Example1 = [1,2,3,4,4,4,4,4,4,4,7,7,10] , the number ‘4’ repeats 7 times out of 13 hence it is the “Lead” Example2 = [1,4,4,6,6,6,6,9,9,13], the number ‘6’ repeats 4 times out of of 10 which is not enough - hence this array has no lead (-1)
Write a function that receives an array and returns the lead (or -1 if there is none), this should be as efficient as possible (time and memory), please add a short explanation and the claimed complexity. Can this be optimized to run in less than O(n)?
/**
Real-lead must be the value in the middle of the array (or one left or one right from the middle)
so we know the potenial lead from the begging. we just need to check the edges of that series
and understand if it long from arra.length or not. the faster way for found the edges is quick search ( jumping half every time )
so the complexity should be O(log(n))
**/
function getLead(sortedArr) {
const {length} = sortedArr;
var arrayMiddle = Math.floor(length / 2) // get the middle of the array
const pl = sortedArr[arrayMiddle] // the the potential lead
var leftEdge, rightEdge;
// find the left edge
let s = 0, e = arrayMiddle, m; // start, end
do {
m = s + Math.floor((e - s) / 2);
if (sortedArr[m] == pl) e = m;
else s = m;
} while (e - s > 1)
leftEdge = e;
s = arrayMiddle;
e = length - 1;
do {
m = s + Math.ceil((e - s) / 2);
if (sortedArr[m] == pl) s = m;
else e = m;
} while (e - s > 1);
rightEdge = s;
if ((rightEdge - leftEdge) + 1 > length / 2)
return pl;
return -1;
}
- What is the output of this code
Promise that resolve to
[1,4,9,16,25,36,49,64,81, 100]
note:new Array(10)
return empty array,[... new Array(10)]
return[10 x undefined]
- Write a function to replace ‘sampleFunction’ - that receives an object with 3 numbers and returns the minimal (this function should be typeScript valid!)
function sampleFunction(obj:{n1:number,n2:number, n3:number }){ return Promise.resolve(Object.values(obj).sort()[0]) }
- Refactor ‘doParallel’ to handle the ‘TODO’ comment properly
Note: consider that some task instances can be significantly slower than otherss
After considered with Yaeer, I Understand that the "slower" is just about IO operation so the code write right because if
sampleFunction()
return promise ( evenPromise.resolve
) The Code guaranteed to be async ( I should know, I implemented Promise ) And IO operation runs under the hood on different threads If we want REAL concurrency for intensive task in NodeJS we can do something like that:
Note from nodejs doc:
"Workers (threads) are useful for performing CPU-intensive JavaScript operations. They will not help much with I/O-intensive work. Node.js’s built-in asynchronous I/O operations are more efficient than Workers can be."
//concurrency.js
const { Worker, isMainThread, parentPort, workerData } = require('worker_threads');
if (isMainThread) {
async function doParallel<T, S>(
func: (args: T) => Promise<S>,
args: T[],
paralllelism = 10
): promise<S[]> {
const results = await AsyncQueue(args, paralllelism, async function (arg) {
return new Promise((res, rej) => {
var worker = new Worker(__filename, {
workerData: {
func: func.toString(),
arg
}
});
worker.once('message', res);
worker.once('exit', rej);
worker.postMessage(arg)
});
})
return results;
}
}else /** worker **/{
/** parsing the function **/
const func = new Function('return ' + workerData.func)();
func(workerData.arg)
.then(result => parentPort.postMessage(result))
.catch(err => parentPort.postMessage(err));
}
// should be in helper/async-queue.js
function AsyncQueue(args, maxNumOfWorkers, task) {
var numOfWorkers = 0;
var argIndex = 0;
var results = [];
return new Promise(done => {
const handleResult = index => result => {
results[index] = result;
numOfWorkers--;
getNextTask();
};
function getNextTask() {
if (numOfWorkers === 0 && argIndex === args.length) {
done(results);
return;
}
while (numOfWorkers < maxNumOfWorkers && argIndex < args.length) {
task(args[argIndex])
.then(handleResult(argIndex))
.catch(handleResult(argIndex));
argIndex++;
numOfWorkers++;
}
}
getNextTask();
});
}
shorter version, without need of Async Queue
//concurrency.js
const {Worker, isMainThread, parentPort, workerData} = require('worker_threads');
if (isMainThread) {
async function doParallel<T, S>(
func: (args: T) => Promise<S>,
args: T[],
paralllelism = 10
): promise<S[]> {
return new Promise(function (done, rej) {
args = [...Object.entries(args)];
var results = [];
var counterDown = args.length;
const workers = [];
maxNumOfWorkers = Math.min(maxNumOfWorkers, args.length)
Array.from(Array(maxNumOfWorkers), _ => {
let worker = new Worker(__filename, {workerData: func.toString()});
workers.push(worker);
worker.on('message', function ([i, result]) {
results[i] = result;
workers.push(worker)
if (--counterDown === 0)
return done(results)
runWorkers();
})
})
function runWorkers() {
while (args.length && workers.length) {
workers.pop().postMessage(args.pop())
}
}
runWorkers();
})
}
} else /** worker **/ {
/** parsing the function **/
const func = new Function('return ' + workerData)();
parentPort.on("message", function ([i, arg]) {
func(arg)
.then(result => parentPort.postMessage([i, result]))
.catch(err => parentPort.postMessage([i, err]));
})
}
SQL - Consider the following database schema containing 2 tables: user_cart
cart_id | user_id | created_at | closed_at |
---|---|---|---|
1 | 123 | 2020-10-01 13:10:05 | NULL |
2 | 125 | 2020-10-02 14:10:05 | NULL |
cart_items
item_id | cart_id | barcode | item_name | added_at 1 | 1 |12344242 | XXXX |2020-10-01 13:11:00 2 | 1 |12344242 | XXXX |2020-10-01 13:11:05 3 | 1 |542342331 | YYYY |2020-10-01 13:12:10
- Write a SQL query that returns all the user_cart rows that added item with barcode X on the last day (one row per cart!)
SELECT *
FROM cart_items
WHERE cart_id IN (
SELECT cart_id, item_name, added_at
FROM cart_items
WHERE item_name = "XXXX" AND
DATE(cart_items.added_at) > (NOW() - INTERVAL 1 DAY )
)
- Write a SQL query that returns all the items of the first 10 carts the took item with barcode X in the last week
-- items IN carts with XXXX in the last week sorted by `added_at`
SELECT *
FROM cart_items
WHERE cart_id IN (
SELECT DISTINCT cart_id
FROM cart_items
WHERE ( item_name = "XXXX"
AND DATE(added_at) > (NOW() - INTERVAL 7 DAY )
)
SORT BY added_at
LIMIT 10
)
Consider the following React Component: This implementation holds a potential performance issue, can you suggest improvements?
new UserAPI
create a new instance on every run of theUserList Componnect
souseEffect
will run every timeUserList Componnect
run (event if no change will be on the screen) then it firefetchUsers()
so beside the performance issue there is a race condition on the result.simple solution is take out the
cost userAPI = ...
out from the component factory; alsoreturn users.map( user=> <p>{user.name}</p> )
not containkey
onp
so there is potential of unnecessary render of the list to screen every time the list update.
Consider the following code: what will happen when the “Increment” (or “Decrement”) button is clicked? Please explain why that is and if there is a way to improve the code?
import React, {createContext, useState, useContext} from 'react';
interface CounterState {
count: number;
increment?: () => void;
decrement?: () => void;
hello: string;
}
const initialState: CounterState = {
count: 0,
increment: undefined,
decrement: undefined,
hello: 'Hello world',
};
const CounterContext = createContext<CounterState>(initialState);
const CounterProvider = ({children}) => {
const [count, setCount] = useState(0);
const [hello] = useState('Hello world');
const increment = () => setCount((counter) => counter + 1);
const decrement = () => setCount((counter) => counter - 1);
const value = {
count,
increment,
decrement,
hello,
};
return <CounterContext.Provider value = {value} > {children} < /CounterContext.Provider>;
};
const SayHello = () => {
const {hello} = useContext(CounterContext);
console.log('[SayHello] rendered');
return <h1>{hello} < /h1>;
};
const IncrementCounter = () => {
const {increment} = useContext(CounterContext);
console.log('[IncrementCounter] rendered');
return <button onClick = {increment} > Increment < /button>;
};
const DecrementCounter = () => {
console.log('[DecrementCounter] rendered');
const {decrement} = useContext(CounterContext);
return <button onClick = {decrement} > Decrement < /button>;
};
const ShowResult = () => {
console.log('[ShowResult] rendered');
const {count} = useContext(CounterContext);
return <h1>{count} < /h1>;
};
const App = () => (
<CounterProvider>
<SayHello / >
<ShowResult / >
<IncrementCounter / >
<DecrementCounter / >
</CounterProvider>
);
export default App;
Explanation:
Every timedecrement()
orincrement()
running, all the components that usedCounterContext
unnecessary render soSayHello Componnet
,IncrementCounter Componnet
,DecrementCounter Componnet
, will render again with the same result. the behaviour, why is that can found here: useContextOne solution is create separate context for
hello
andcount
.
That will save up from renderSayHello Componnet
Other solution is not use
contex
approach at all. look on the entire file as a module that provides a count and supplyuseCount
to bringcount
data to all components that need itOther solution is supply Our
Contex
with special methods to update the context values.Examples:
/** file : count.js **/
import React, {useEffect, useState} from 'react';
let setters = new Set();
function Setter(fn) {
return function (...args) {
for (let set of setters) {
set(fn)
}
}
}
export const increment = Setter((counter) => counter + 1);
export const decrement = Setter((counter) => counter - 1);
export function useCount(initValue = 0) {
const [count, setCount] = useState(initValue);
useEffect(_ => {
setters.add(setCount)
return () => setters.delete(setCount)
}, [setCount]);
return count;
}
/** file : helloContext.js **/
import React, {createContext, useState, useContext} from 'react';
/* separete context for Hello, with new approch of actions: */
interface HelloState {
hello: string;
}
export default
const HelloContext = ({children}) => {
const context = createContext<CounterState>(HelloState);
const [hello, setHello] = useState(HelloState);
const value = {
hello,
};
return {
setHello: setHello,
Provider: <context.Provider value = {value} > {children} < /context.Provider>;
}
};
import React, {useEffect, createContext, useState, useContext} from 'react';
import HelloContext from './helloContext'
import {useCount, increment, decrement} from './count'
const SayHello = () => {
const {hello} = useContext(HelloProvider);
console.log('[SayHello] rendered');
return <h1>{hello} < /h1>;
};
const IncrementCounter = () => {
console.log('[IncrementCounter] rendered');
return <button onClick = {increment} > Increment < /button>;
};
const DecrementCounter = () => {
console.log('[DecrementCounter] rendered');
return <button onClick = {decrement} > Decrement < /button>;
};
const UpdateHello = () => {
console.log('[UpdateHello] rendered');
return <button onClick = {HelloContext.setHello("Hello universe")} > Decrement < /button>;
}
const ShowResult = () => {
console.log('[ShowResult] rendered');
const {count} = useCount();
return <h1>{count} < /h1>;
};
const App = () => (
<HelloContext.Provider>
<SayHello / >
<ShowResult / >
<UpdateHello / >
<IncrementCounter / >
<DecrementCounter / >
</HelloContext.Provider>
);
export default App;