Yahoo Interview Question for Software Engineer / Developers


Country: United States
Interview Type: In-Person




Comment hidden because of low score. Click to expand.
3
of 3 vote

Use a ring buffer (circular queue) of type Message of size 5000*60*10 which is 3000000B or 3MB. The memory footprint will be 3MB*sizeof(Message) so that gives us upper limit of 100MB (string ticker are no more than 4B and fixed length for int64/double).
Maintain a rolling sum (type double) and every time adding a stock price, add it to sum and subtract the last purged value.
Simply return sum/Total entries

- Mithya March 22, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Correction: String ticker will be 8B (unicode) assuming max 4 byte of ticker

- Mithya March 22, 2014 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

I think u will return the average aff all stocks during the last 10 min, the question is to return the average for only a given stock symbol.
So instead of keeping a rolling sum, I suggest keeping a hash map <String(symbol), double (rolling sum / stock)>

- Bibo May 17, 2014 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

I think it will look something like this, please let me know if we can save memory further

public enum StockPriceMath {
    INSTANCE;
    private long INTERVAL = 600000000; // microseconds since each second we get 50000 updates, we can't do it in miliseconds
    private volatile HashMap<String, Queue> priceMap = new ConcurrentHashMap<String, Queue<Message>>();
    private volatile HashMap<String, Long> sumMap = new ConcurrentHashMap<String, Integer>();
    public void updatePrice(Message message) {
        Queue<Message> tickerQueue;
        // if we have seen the ticker before
        if priceMap.contains(message.ticker) {
            tickerQueue = priceMap.get(ticker);
        }
        else {
            // new ticker
            tickerQueue = new ConcurentLinkedQueue<Message>(600000000);
            tickerQueue.insert(message);
            priceMap.set(message.ticker, tickerQueue)
            sumMap.set(message.ticker, 0)
        }
        long sum = sumMap.get(message.ticker);
        while (message.timestamp - tickerQueue.peek().timestamp > INTERVAL) {
            sum = sum - tickerQueue.pop().price;
        }
        sum += message.price;
        sumMap.set(message.ticker, sum);
    }
    
    public long get10minuteAverage(String ticker) {
        Queue<Message> tickerQueue = priceMap.get(ticker);
        long sum = sumMap.get(message.ticker);
        return sum / tickerQueue.size();
    }
}

I used Enum istead of class to make it singleton since this will be used in a high frequency environment and singleton will help us to maintain concurrency.

Also I do not know if something like concurrentLinkedQueue exists, i just assumed it did.

- byteattack May 31, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Looks like the implementation of Observer design pattern

- arsragavan March 21, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

They were more concerned about how to store it in the memory and calculating the average of last 10 minutes. 5000 requests a second, we are looking at about 3 million + records stored in memory

- budsiya March 21, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

To budsiya: Can we use something like a priority queue which maintains the records by time so that we can get the records stored in the last 10 minutes easily.

- arsragavan March 21, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

We can do a custom solution based on the average stock price for this symbol ie if the stock price is between $1-10
I would keep a longlong variable each time new price comes in multiple by 1000 so we keep four decimal places then add it to longlong variable. At the end divide it by 3M this will give us average with decimal place moved right by 4. Now divide it double 1000.0 this will give us average with correct decimal place.

- Mat March 22, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

You can use the observer pattern and bucketize the processed messages. And put these buckets in a Fixed length Map. The length of the Map depends on the time resolution. The key of the map is the time rounded off to time resolution. For example, if we take a time resolution of 1 minutes, then we will have a Map of size 10 and the key is number of minutes from epoch.

Processed_Message {
double priceSum;
int numMessage;
};

Map<Long, ProcessedMessage> eventMap;

void addEvent(Message msg) {
    long minute = getMinutes(msg.timeStamp);
    ProcessedMessage cur = eventMap.get(minute);
    if ( cur == null) {
        //check for size and remove element if greater then 10
       //Add the element as processedMessage
    }
    else {
       //Add this element to processMessage
   }
}

long getAverage() {
    //Get the max 10 elements from the map
    //Get the total price sum and total elements by adding them
    // Divide them and return averge
}

To get better results, increase the time resolution, say to seconds.

- xdeepak81 March 22, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

new_avg = (old_avg*n + number)/(n+1)

- Anonymous March 23, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

I don't know if I get it right. Basically, we can store the first value of the price we have, and for the rest, we can calculate p(i) - p(first) and cumulate them. Then we won't get a very large number. And the final result can be aquired by calculating first_price + total / times since the first price we get is used as the benchmark.

- ravio March 26, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

average = ((average * count) + price) / (count + 1);

- chapooty March 31, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

no need to store all msg, just calculate average for each second and the number of counts for that second, store 600 of them. Way less memory

- kingpotter1990 September 17, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

no need to store all msg, just calculate average for each second and the number of counts for that second, store 600 of them. Way less memory

- kingpotter1990 September 17, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Have a circular queue of size 600 slots so that we just store average values of per second in each slot ( or we can go very fine(5000*60*10) = 3 million) slots for each symbol.

And another buffer of all incoming messages for each symbol for 1 second.
Now every time a message comes for a particular symbol, then we just keep collecting the prices and count the number of times it has come in this second and store both. So store as a tuple:
(sum_price: sum(prices),
num_times: N )

After each second just take this tuple and put it in the circular queue for that symbol. And purge the last bucket (10mins + 1st sec).

When asked for the average price, just return the sum of all the sum_price values and divide that by sum of all the num_times value. That will give you the average price.

If we want better accuracy, then just make the circular queue of size 3 million rather than 600.

- dhirendra.sinha January 18, 2016 | Flag Reply


Add a Comment
Name:

Writing Code? Surround your code with {{{ and }}} to preserve whitespace.

Books

is a comprehensive book on getting a job at a top tech company, while focuses on dev interviews and does this for PMs.

Learn More

Videos

CareerCup's interview videos give you a real-life look at technical interviews. In these unscripted videos, watch how other candidates handle tough questions and how the interviewer thinks about their performance.

Learn More

Resume Review

Most engineers make critical mistakes on their resumes -- we can fix your resume with our custom resume review service. And, we use fellow engineers as our resume reviewers, so you can be sure that we "get" what you're saying.

Learn More

Mock Interviews

Our Mock Interviews will be conducted "in character" just like a real interview, and can focus on whatever topics you want. All our interviewers have worked for Microsoft, Google or Amazon, you know you'll get a true-to-life experience.

Learn More