├── .gitignore ├── README.md ├── anagrams_group ├── README.md └── solutions │ ├── .gitkeep │ ├── ruijose │ └── ruby │ │ └── anagram.rb │ └── tdantas │ └── elixir │ └── anagram.ex ├── basket_checkout ├── README.md └── solutions │ └── .gitkeep ├── blind-prophet ├── README.md └── solutions │ └── .gitkeep ├── boogle_solver ├── README.md └── solutions │ └── .gitkeep ├── cache_lru ├── README.md └── solutions │ └── .gitkeep ├── cat_vs_dog ├── README.md └── solutions │ └── .gitkeep ├── circular_list ├── README.md └── solutions │ └── .gitkeep ├── cooking_the_books ├── README.md ├── input.txt └── solutions │ └── .gitkeep ├── cyclic_or_acyclic_list ├── README.md └── solutions │ └── .gitkeep ├── flat_tree ├── README.md └── solutions │ └── .gitkeep ├── huge_files_average_per_country ├── README.md └── solutions │ └── .gitkeep ├── international_phone_number ├── README.md └── solutions │ └── .gitkeep ├── largest_sum_of_integers ├── README.md └── solutions │ ├── .gitkeep │ └── ruijose │ └── ruby │ ├── max_sum.rb │ └── spec │ └── max_sum_spec.rb ├── mars_rovers ├── README.md └── solutions │ └── .gitkeep ├── matrix_prime_numbers ├── README.md └── solutions │ └── tdantas │ └── ruby │ ├── README.md │ ├── line.rb │ ├── prime_matrix.rb │ ├── printer.rb │ ├── solution.rb │ └── spec │ ├── line_spec.rb │ ├── matrix_spec.rb │ └── spec_helper.rb ├── maze ├── README.md ├── bin │ ├── challenge.jar │ └── challenge.sh └── solutions │ ├── axfcampos │ └── Java │ │ ├── README.md │ │ ├── src │ │ └── com │ │ │ └── company │ │ │ └── Main.java │ │ └── test │ │ ├── challenge.jar │ │ └── challenge.sh │ ├── diasdavid │ └── nodejs │ │ └── index.js │ ├── jxs │ └── elixir │ │ ├── README.md │ │ ├── config │ │ └── config.exs │ │ ├── lib │ │ ├── ExFollowerMaze │ │ │ ├── clients_server.ex │ │ │ └── source_server.ex │ │ └── ex_follower_maze.ex │ │ ├── mix.exs │ │ └── test │ │ ├── ex_follower_maze_test.exs │ │ └── test_helper.exs │ └── tdantas │ └── nodeJS │ ├── README.md │ ├── index.js │ ├── lib │ ├── event-dispatcher.js │ ├── events-server.js │ ├── events.js │ ├── index.js │ ├── parser.js │ ├── users-server.js │ └── users │ │ ├── entity.js │ │ └── repository.js │ └── package.json ├── remove_duplicate_char_from_string ├── README.md └── solutions │ ├── .gitkeep │ └── ruijose │ └── ruby │ └── remove_duplicates.rb ├── reverse_binary ├── README.md └── solutions │ └── .gitkeep ├── stack_data_structure_constant_time ├── README.md └── solutions │ ├── .gitkeep │ └── tdantas │ └── stack.ex ├── telegram_problem ├── README.md └── solutions │ ├── .gitkeep │ └── ruijose │ └── ruby │ ├── spec │ └── telegram_spec.rb │ └── telegram_problem.rb ├── trains ├── README.md └── solutions │ └── .gitkeep ├── word_sugestion_T9_based ├── README.md └── solutions │ └── .gitkeep └── wordsource ├── README.md └── solutions └── .gitkeep /.gitignore: -------------------------------------------------------------------------------- 1 | logs 2 | *.log 3 | pids 4 | *.pid 5 | *.seed 6 | lib-cov 7 | coverage 8 | .grunt 9 | build/Release 10 | node_modules 11 | .lock-wscript 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | This repository contains some IT Interviews that I heard, did and imagined. 3 | 4 | #### Submit your Solution 5 | 6 | Every question contains a solutions folder, your solution must have your github handler and inside the language that you chose. 7 | for example [matrix_prime_numbers](https://github.com/tdantas/it-interviews/tree/master/matrix_prime_numbers) 8 | 9 | #### Which programming language should I use ? 10 | Your best language :) 11 | -------------------------------------------------------------------------------- /anagrams_group/README.md: -------------------------------------------------------------------------------- 1 | You're given a list of strings, return a list of list of strings of anagrams, i.e. each element of the returned list is a list of words that are anagrams among them. 2 | 3 | For example, 4 | 5 | input [stars, mary, rats, tars, army, banana] 6 | output: [ [rats, tars], [army, mary], [stars], [banana] ]. -------------------------------------------------------------------------------- /anagrams_group/solutions/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdantas/it-interviews/882e3b52e8d0c653d76cb8782edda52a02a9675d/anagrams_group/solutions/.gitkeep -------------------------------------------------------------------------------- /anagrams_group/solutions/ruijose/ruby/anagram.rb: -------------------------------------------------------------------------------- 1 | def anagram_solver(possible_anagrams) 2 | all_anagrams = possible_anagrams.each_with_object(Hash.new []) do |word, hash| 3 | hash[word.chars.sort] += [word] 4 | end 5 | print_anagrams(all_anagrams) 6 | end 7 | 8 | def print_anagrams(anagrams_hash) 9 | anagrams_hash.each_with_object([]) do |(key,value), multi_array| 10 | multi_array << value 11 | end 12 | end 13 | 14 | p anagram_solver(["stars", "mary", "rats", "tars", "army", "banana"]) 15 | 16 | -------------------------------------------------------------------------------- /anagrams_group/solutions/tdantas/elixir/anagram.ex: -------------------------------------------------------------------------------- 1 | defmodule Anagramer do 2 | 3 | def run(words) do 4 | words 5 | |> Enum.map(&mapper/1) 6 | |> Enum.reduce(%{ }, &reducer/2) 7 | |> Dict.values 8 | end 9 | 10 | defp mapper(item) do 11 | item 12 | |> to_char_list 13 | |> Enum.sort 14 | |> to_string 15 | |> List.wrap 16 | |> Enum.concat([item]) 17 | end 18 | 19 | def reducer([key, value], acc) do 20 | case Dict.get(acc, key) do 21 | nil -> Dict.put(acc, key, [value]) 22 | values -> Dict.put(acc, key, [ value | values ]) 23 | end 24 | end 25 | end 26 | 27 | -------------------------------------------------------------------------------- /basket_checkout/README.md: -------------------------------------------------------------------------------- 1 | Amazon is an online marketplace, here is a 2 | sample of some of the products available on our site: 3 | 4 | ```` 5 | 6 | Product code | Name | Price 7 | ----------------------------------------------------- 8 | 001 | Lavender heart | £9.25 9 | 002 | Personalised cufflinks | £45.00 10 | 003 | Kids T-shirt | £19.95 11 | 12 | ```` 13 | Our marketing team want to offer promotions as an incentive 14 | for our customers to purchase these items. 15 | 16 | If you spend over £60, then you get 10% of your purchase 17 | If you buy 2 or more lavender hearts then the price drops 18 | to £8.50 19 | 20 | Our check-out can scan items in any order, and because our 21 | promotions will change, it needs to be flexible regarding 22 | our promotional rules. 23 | 24 | 25 | The interface to our checkout looks like this (shown in Ruby): 26 | 27 | ```` 28 | co = Checkout.new(promotional_rules) 29 | co.scan(item) 30 | co.scan(item) 31 | price = co.total 32 | ```` 33 | 34 | **** Implement a checkout system that fulfils these requirements.**** 35 | 36 | #### Test data 37 | 38 | ```` 39 | 40 | Basket: 001,002,003 41 | Total price expected: £66.78 42 | 43 | Basket: 001,003,001 44 | Total price expected: £36.95 45 | 46 | Basket: 001,002,001,003 47 | Total price expected: £73.76 48 | ```` -------------------------------------------------------------------------------- /basket_checkout/solutions/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdantas/it-interviews/882e3b52e8d0c653d76cb8782edda52a02a9675d/basket_checkout/solutions/.gitkeep -------------------------------------------------------------------------------- /blind-prophet/README.md: -------------------------------------------------------------------------------- 1 | #Problem 2 | 3 | A prophet (P) is lost in his way to the target (R). He is in a discrete space. 4 | 5 | _ | _ | _ | _ | _ | _ |_ 6 | _ | _ | _ | _ | T | _ |_ 7 | _ | _ | _ | _ | _ | _ |_ 8 | _ | P | _ | _ | _ | _ |_ 9 | _ | _ | _ | _ | _ | _ |_ 10 | | | | | | | 11 | 12 | The prophet can only 13 | 14 | move(direction) 15 | distance() 16 | 17 | When moving, the `direction` can only be `'up'`, `'down'`, `'down'` or `'left'`. 18 | The `distance()` returns the direct distance from the prophet to the target regardless of the direction. 19 | 20 | Write the algorith for the prophet to reach the target. 21 | 22 | ## [Live example](http://soarez.com/the-blind-prophet/) 23 | -------------------------------------------------------------------------------- /blind-prophet/solutions/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdantas/it-interviews/882e3b52e8d0c653d76cb8782edda52a02a9675d/blind-prophet/solutions/.gitkeep -------------------------------------------------------------------------------- /boogle_solver/README.md: -------------------------------------------------------------------------------- 1 | **You'll have to implement a Boggle solver.** 2 | 3 | Boggle is played on a 4x4 board (there are variants, 5x5, 6x6 but the size is irrelevant for this discussion) and the goal is to find words in the board. 4 | 5 | You can go in any of the 8 directions. Go online and look for an example of a Boggle board. 6 | 7 | The idea in this problem is given a list of words and a board, decide if you can find all those words in the board. 8 | 9 | boolean IsSolution(Board board, List words) 10 | 11 | 12 | Tell me the Board interface that you need for your implementation. 13 | -------------------------------------------------------------------------------- /boogle_solver/solutions/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdantas/it-interviews/882e3b52e8d0c653d76cb8782edda52a02a9675d/boogle_solver/solutions/.gitkeep -------------------------------------------------------------------------------- /cache_lru/README.md: -------------------------------------------------------------------------------- 1 | ## LRU Cache system 2 | ####Which data structures you choose to implement LRU Cache System ? 3 | 4 | #### Implement one cache system to validate your idea. 5 | 6 | ***Cache Interface:*** 7 | 8 | get(key) => [ object | null ] 9 | 10 | save(key, value) => [ old_value | null ] 11 | if the key exist, returns the last value bounded to with this key 12 | Otherwise null 13 | -------------------------------------------------------------------------------- /cache_lru/solutions/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdantas/it-interviews/882e3b52e8d0c653d76cb8782edda52a02a9675d/cache_lru/solutions/.gitkeep -------------------------------------------------------------------------------- /cat_vs_dog/README.md: -------------------------------------------------------------------------------- 1 | #Cat vs. Dog 2 | 3 | The latest reality show has hit the TV: “Cat vs. Dog”. In this show, a bunch of cats and dogs compete for the very prestigious Best Pet Ever title. In each episode, the cats and dogs get to show themselves off, after which the viewers vote on which pets should stay and which should be forced to leave the show. 4 | 5 | Each viewer gets to cast a vote on two things: one pet which should be kept on the show, and one pet which should be thrown out. Also, based on the universal fact that everyone is either a cat lover (i.e. a dog hater) or a dog lover (i.e. a cat hater), it has been decided that each vote must name exactly one cat and exactly one dog. 6 | 7 | Ingenious as they are, the producers have decided to use an advancement procedure which guarantees that as many viewers as possible will continue watching the show: the pets that get to stay will be chosen so as to maximize the number of viewers who get both their opinions satisfied. Write a program to calculate this maximum number of viewers. 8 | 9 | ###Input 10 | On the first line one positive number: the number of testcases, at most 100. After that per testcase: 11 | 12 | - One line with three integers c, d, v (1 ≤ c, d ≤ 100 and 0 ≤ v ≤ 500): the number of cats, dogs, and voters. 13 | - v lines with two pet identifiers each. The first is the pet that this voter wants to keep, the second is the pet that this voter wants to throw out. A pet identifier starts with one of the characters ‘C’ or ‘D’, indicating whether the pet is a cat or dog, respectively. The remaining part of the identifier is an integer giving the number of the pet (between 1 and c for cats, and between 1 and d for dogs). So for instance, “D42” indicates dog number 42. 14 | 15 | ###Output 16 | Per testcase: 17 | 18 | - One line with the maximum possible number of satisfied voters for the show. 19 | 20 | Sample input 1 21 | 22 | ```` 23 | 2 24 | 1 1 2 25 | C1 D1 26 | D1 C1 27 | 1 2 4 28 | C1 D1 29 | C1 D1 30 | C1 D2 31 | D2 C1 32 | Sample output 1 33 | 1 34 | 3 35 | ```` -------------------------------------------------------------------------------- /cat_vs_dog/solutions/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdantas/it-interviews/882e3b52e8d0c653d76cb8782edda52a02a9675d/cat_vs_dog/solutions/.gitkeep -------------------------------------------------------------------------------- /circular_list/README.md: -------------------------------------------------------------------------------- 1 | The Smallest Number in a Circular List in Ruby 2 | 3 | Given a circular list of integers (when you reach the end of the list you come back to the beginning), what is the most efficient algorithm to find the smallest integer in the list? 4 | 5 | For example: circular_list = [22, 52, 66, 82, 5, 8, 12, 19]. 6 | -------------------------------------------------------------------------------- /circular_list/solutions/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdantas/it-interviews/882e3b52e8d0c653d76cb8782edda52a02a9675d/circular_list/solutions/.gitkeep -------------------------------------------------------------------------------- /cooking_the_books/README.md: -------------------------------------------------------------------------------- 1 | #Cooking the Books 2 | 3 | 4 | Every business can make use of a good accountant and, if they're not big on following the law, sometimes a bad one. Bad accountants try to make more money for their employers by fudging numbers without getting caught. 5 | 6 | 7 | Sometimes a bad accountant wants to make a number larger, and sometimes smaller. It is widely known that tax auditors will fail to notice two digits being swapped in any given number, but any discrepancy more egregious will certainly be caught. It's also painfully obvious when a number has fewer digits than it ought to, so a bad accountant will never swap the first digit of a number with a 0. 8 | 9 | 10 | Given a number, how small or large can it be made without being found out? 11 | 12 | ###Input 13 | 14 | Input begins with an integer **T**, the number of numbers that need tweaking. Each of the next **T** lines contains a integer **N**. 15 | 16 | ###Output 17 | 18 | For the ith number, print a line containing "Case #i: " followed by the smallest and largest numbers that can be made from the original number **N**, using at most a single swap and following the rules above. 19 | 20 | 21 | ###Constraints 22 | 23 | 1 ≤ T ≤ 100 24 | 0 ≤ N ≤ 999999999 25 | N will never begin with a leading 0 unless N = 0 26 | 27 | 28 | 29 | #####Example Input 30 | 31 | ```` 32 | 5 33 | 31524 34 | 897 35 | 123 36 | 10 37 | 5 38 | ```` 39 | 40 | ##### Example Output 41 | 42 | ```` 43 | Case #1: 13524 51324 44 | Case #2: 798 987 45 | Case #3: 123 321 46 | Case #4: 10 10 47 | Case #5: 5 5 48 | ```` 49 | 50 | -------------------------------------------------------------------------------- /cooking_the_books/input.txt: -------------------------------------------------------------------------------- 1 | 20 2 | 623885686 3 | 32753219 4 | 764921681 5 | 364669874 6 | 519644114 7 | 497609663 8 | 393698191 9 | 820715607 10 | 926288077 11 | 218198062 12 | 10 13 | 906755308 14 | 9990999 15 | 731566438 16 | 999999999 17 | 0 18 | 621007349 19 | 724144391 20 | 444558727 21 | 763307818 22 | -------------------------------------------------------------------------------- /cooking_the_books/solutions/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdantas/it-interviews/882e3b52e8d0c653d76cb8782edda52a02a9675d/cooking_the_books/solutions/.gitkeep -------------------------------------------------------------------------------- /cyclic_or_acyclic_list/README.md: -------------------------------------------------------------------------------- 1 | # Problem 2 | 3 | ```` 4 | Write a function that takes a pointer to the head of a list and determines whether the list is cyclic or acyclic. 5 | 6 | Your function should return FALSE if the list is acyclic and TRUE if it is cyclic. 7 | 8 | You may NOT modify the list in any way. 9 | ```` 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /cyclic_or_acyclic_list/solutions/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdantas/it-interviews/882e3b52e8d0c653d76cb8782edda52a02a9675d/cyclic_or_acyclic_list/solutions/.gitkeep -------------------------------------------------------------------------------- /flat_tree/README.md: -------------------------------------------------------------------------------- 1 | Given the ***Tree*** 2 | 3 | ``` 4 | a 5 | / \ 6 | b c 7 | | /|\ 8 | d e f g 9 | 10 | 11 | ```` 12 | 13 | **Return the array** 14 | 15 | ```` 16 | [ a, b, c, d, e, f, g ] 17 | ```` 18 | 19 | -------------------------------------------------------------------------------- /flat_tree/solutions/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdantas/it-interviews/882e3b52e8d0c653d76cb8782edda52a02a9675d/flat_tree/solutions/.gitkeep -------------------------------------------------------------------------------- /huge_files_average_per_country/README.md: -------------------------------------------------------------------------------- 1 | Suppose you have some huge files, each 4GB, and you have to calculate the age average per country. 2 | 3 | The File Format is 4 | 5 | ```` 6 | id | country | age 7 | --------------------- 8 | 01 | Jamaica | 28 9 | 02 | Brazil | 47 10 | 03 | Portugal | 33 11 | 04 | Argentina | 56 12 | 05 | USA | 12 13 | 06 | Portugal | 82 14 | 07 | Brazil | 09 15 | 10 | Germany | 18 16 | … | … | … 17 | 18 | ```` 19 | 20 | ps: You are not allowed to use RDBMS to solve this question. 21 | 22 | Import all data and query 23 | 24 | select country ,AVG(age) from ImportedData group by country 25 | -------------------------------------------------------------------------------- /huge_files_average_per_country/solutions/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdantas/it-interviews/882e3b52e8d0c653d76cb8782edda52a02a9675d/huge_files_average_per_country/solutions/.gitkeep -------------------------------------------------------------------------------- /international_phone_number/README.md: -------------------------------------------------------------------------------- 1 | We deal with a lot of calls. Once a User has signed up for Talkdesk and have created their own account, they will then buy a new phone number. Using this number, a User is able to receive phone calls directly in their browser and optionally define a cellphone or office number which we'll use to forward the inbound call to. Users are also able to make outbound calls from their browser. 2 | 3 | Once an inbound/outbound call has finished, we need to charge the User's account depending on the duration. This is done by deducting the cost of the call from an Account's credits (which uses Dollars as the currency). The amount we charge depends on our service provider, Twilio, so we use Twilio's prices plus a little margin. 4 | 5 | For this challenge we'll just focus on the billing of inbound calls. 6 | 7 | ## The Problem 8 | 9 | There are various events that occur during the lifetime of a call. Upon received a call finished event we need to bill an Account's credits based on: 10 | 11 | * The call's duration 12 | * The type of the Talkdesk number that received the call 13 | * If the call was forwarded to a User's external number, then the price of the call to the specified country needs to be considered 14 | 15 | The price we must charge must be Twilio's price plus, for example, 5 cents (See Formula section). You can find a `.csv` file with the prices [here](https://www.twilio.com/resources/rates/international-rates.csv) 16 | 17 | In some cases, we might like to change the margin depending on our Client (for example, reduce the margin if they use a lot of minutes per month). 18 | 19 | Another important aspect of billing for calls is keeping a record of the charge made to a User's Account, as we would like to display the list of calls they've made including the amount we've charged for each one. 20 | 21 | When a call finishes, the information that's available when deciding how much to bill is: 22 | 23 | * The duration of the call (in seconds) 24 | * The Talkdesk Telephone's number that received the inbound call 25 | * The external phone number that was used to forward the call (only defined when the User answers a call on their cellphone or office landline rather than answering in the browser) 26 | * The corresponding Talkdesk account 27 | 28 | ### Formula 29 | 30 | To calculate the price per minute for inbounds is as follows: `Talkdesk_Number_Cost + External_Number_Cost + Profit_Margin` 31 | 32 | The `Talkdesk_Number_Cost` should be set to 1c except for two cases: US and UK Toll free numbers which should be set to 3c and 6c, respectively. 33 | 34 | The `External_Number_Cost` should be set to 1c if the call is answered in the web browser, otherwise the price to charge should be the same as Twilio charges for calls to that number. 35 | 36 | ### Background Information 37 | 38 | The way this is actually done in Talkdesk is by using RabbitMQ to send events. The types of events that are emitted for calls are: 39 | 40 | * **call_initiated** - When a Customer starts a call to a Talkdesk, before it actually starts to ring 41 | * **call_answered** - When an Agent picks up a call 42 | * **call_missed** - When a call wasn't answered by an Agent 43 | * **call_finished** - When an answered call finishes, either by the Agent closing the call or the Customer hanging up 44 | * **call_voicemail** - When a call resulted in a voicemail 45 | 46 | This problem is basically only dealing with a **call_finished** event. 47 | 48 | Here's an example of the data the event has (they come in JSON): 49 | 50 | ``` 51 | { 52 | "event":"call_finished", 53 | "type":"in", 54 | "duration":"91", 55 | "account_id":"4f4a37a201c642014200000c", 56 | "contact_id":"505de7e5f857d94a3d000001", 57 | "call_id":"9d036a18-0986-11e2-b2c6-3d435d81b7fd", 58 | "talkdesk_phone_number":"+14845348611", 59 | "customer_phone_number":"+351961918192", 60 | "forwarded_phone_number":null, 61 | "agent_id":"4f78ded32b0ac00001000001", 62 | "previous_agent_id":"5054d89ec7573f082a000c9e", 63 | "customer_id":"505de7e5f857d94a3d000001", 64 | "customer":null, 65 | "record":"http://s3.amazonaws.com/plivocloud/9ff87998-0986-11e2-aed8-002590513972.mp3", 66 | "timestamp":"2012-09-28T16:09:07Z" 67 | } 68 | ``` 69 | 70 | ## Other Requirements 71 | 72 | * To start, you can make a command-line program that can simulate an end of call and make a charge to the Account's credits. 73 | * As a bonus, make an HTTP interface that can accept requests notifying this system that a call has ended and that it needs to bill an account for the call. 74 | 75 | ## Environment 76 | 77 | We use MongoDB as our main database, so please do the same. (We have systems that use Mongoid (ORM) and others that use the MongoDB ruby driver directly, but use whichever you prefer). 78 | -------------------------------------------------------------------------------- /international_phone_number/solutions/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdantas/it-interviews/882e3b52e8d0c653d76cb8782edda52a02a9675d/international_phone_number/solutions/.gitkeep -------------------------------------------------------------------------------- /largest_sum_of_integers/README.md: -------------------------------------------------------------------------------- 1 | Return the largest sum of contiguous integers in the array. 2 | Example: if the input is (-10, 2, 3, -2, 0, 5, -15), the largest sum is 8. -------------------------------------------------------------------------------- /largest_sum_of_integers/solutions/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdantas/it-interviews/882e3b52e8d0c653d76cb8782edda52a02a9675d/largest_sum_of_integers/solutions/.gitkeep -------------------------------------------------------------------------------- /largest_sum_of_integers/solutions/ruijose/ruby/max_sum.rb: -------------------------------------------------------------------------------- 1 | def ranges(list_of_numbers) 2 | max_number = list_of_numbers.length 3 | (0..max_number).each_with_object([]) { |_, result| 4 | (0...max_number).each do |i| 5 | (i...max_number).each do |j| 6 | max_sum = 0 7 | current_sum = list_of_numbers[i..j].inject(:+) 8 | if current_sum > max_sum 9 | max_sum = current_sum 10 | result << max_sum 11 | end 12 | end 13 | end 14 | }.max 15 | end 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /largest_sum_of_integers/solutions/ruijose/ruby/spec/max_sum_spec.rb: -------------------------------------------------------------------------------- 1 | require_relative "max_sum" 2 | 3 | describe 'max sum integers' do 4 | it "should return 21" do 5 | expect(ranges([1,2,3,4,5,6])).to eql(21) 6 | end 7 | 8 | it "should return 8" do 9 | expect(ranges([-10, 2, 3, -2, 0, 5, -15])).to eql(8) 10 | end 11 | 12 | it "should return 6" do 13 | expect(ranges([-2, 1, -3, 4, -1, 2, 1, -5, 4])).to eql(6) 14 | end 15 | 16 | it "should return 12" do 17 | expect(ranges([10, -7, 8, -8, 6, -3, 6, -21, 5, -2, 1])).to eql(12) 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /mars_rovers/README.md: -------------------------------------------------------------------------------- 1 | #Problem 2 | 3 | A squad of robotic rovers are to be landed by NASA on a plateau on Mars. This plateau, which is curiously rectangular, must be navigated by the rovers so that their on-board cameras can get a complete view of the surrounding terrain to send back to Earth. 4 | 5 | A rover's position and location is represented by a combination of x and y co-ordinates and a letter representing one of the four cardinal compass points. The plateau is divided up into a grid to simplify navigation. An example position might be 0, 0, N, which means the rover is in the bottom left corner and facing North. 6 | 7 | In order to control a rover, NASA sends a simple string of letters. The possible letters are 'L', 'R' and 'M'. 'L' and 'R' makes the rover spin 90 degrees left or right respectively, without moving from its current spot. 'M' means move forward one grid point, and maintain the same heading. 8 | 9 | Assume that the square directly North from (x, y) is (x, y+1). 10 | 11 | ###INPUT: 12 | The first line of input is the upper-right coordinates of the plateau, the lower-left coordinates are assumed to be 0,0. 13 | 14 | The rest of the input is information pertaining to the rovers that have been deployed. Each rover has two lines of input. The first line gives the rover's position, and the second line is a series of instructions telling the rover how to explore the plateau. 15 | 16 | The position is made up of two integers and a letter separated by spaces, corresponding to the x and y co-ordinates and the rover's orientation. 17 | 18 | Each rover will be finished sequentially, which means that the second rover won't start to move until the first one has finished moving. 19 | 20 | 21 | ###OUTPUT 22 | The output for each rover should be its final co-ordinates and heading. 23 | 24 | INPUT AND OUTPUT 25 | 26 | **Test Input:** 27 | 28 | ```` 29 | 5 5 30 | 1 2 N 31 | LMLMLMLMM 32 | 3 3 E 33 | MMRMMRMRRM 34 | ````` 35 | **Expected Output:** 36 | 37 | ```` 38 | 1 3 N 39 | 5 1 E 40 | ```` -------------------------------------------------------------------------------- /mars_rovers/solutions/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdantas/it-interviews/882e3b52e8d0c653d76cb8782edda52a02a9675d/mars_rovers/solutions/.gitkeep -------------------------------------------------------------------------------- /matrix_prime_numbers/README.md: -------------------------------------------------------------------------------- 1 | 2 | Write a program that prints out a multiplication table of the first 10 prime numbers. 3 | 4 | The program must run from the command line and print to screen 1 table. 5 | 6 | Across the top and down the left side should be the 10 primes, and the body of the table should contain the product of multiplying these numbers. 7 | 8 | P.s. the prime numbers should be calculated by you, instead use some method from your language. -------------------------------------------------------------------------------- /matrix_prime_numbers/solutions/tdantas/ruby/README.md: -------------------------------------------------------------------------------- 1 | ### Enviroment 2 | 3 | ###### Language: 4 | Ruby 1.9.3 5 | 6 | ##### Test Framework 7 | RSpec 2.12.1 8 | 9 | #### Run 10 | ruby solution.rb 11 | 12 | #### Tests 13 | cd tdantas 14 | rspec 15 | 16 | #### Output 17 | 18 | ```` 19 | $ ruby solution.rb 20 | 21 | 4 |6 |10 |14 |22 |26 |34 |38 |46 |58 | 22 | 6 |9 |15 |21 |33 |39 |51 |57 |69 |87 | 23 | 10 |15 |25 |35 |55 |65 |85 |95 |115 |145 | 24 | 14 |21 |35 |49 |77 |91 |119 |133 |161 |203 | 25 | 22 |33 |55 |77 |121 |143 |187 |209 |253 |319 | 26 | 26 |39 |65 |91 |143 |169 |221 |247 |299 |377 | 27 | 34 |51 |85 |119 |187 |221 |289 |323 |391 |493 | 28 | 38 |57 |95 |133 |209 |247 |323 |361 |437 |551 | 29 | 46 |69 |115 |161 |253 |299 |391 |437 |529 |667 | 30 | 58 |87 |145 |203 |319 |377 |493 |551 |667 |841 | 31 | 32 | ```` -------------------------------------------------------------------------------- /matrix_prime_numbers/solutions/tdantas/ruby/line.rb: -------------------------------------------------------------------------------- 1 | class Line 2 | attr_accessor :primers 3 | attr_reader :factor 4 | 5 | def initialize(index, line) 6 | raise "Index Out of Range" unless valid? index, line 7 | @primers = line 8 | @factor = primers[index] 9 | end 10 | 11 | def value 12 | primers.map { |prime| prime * factor } 13 | end 14 | 15 | private 16 | def valid?(index, line) 17 | return false if index < 0 18 | return true if line.size == 0 19 | (0...line.size).cover?(index) 20 | end 21 | 22 | end -------------------------------------------------------------------------------- /matrix_prime_numbers/solutions/tdantas/ruby/prime_matrix.rb: -------------------------------------------------------------------------------- 1 | require './line' 2 | require './printer' 3 | 4 | class Fixnum 5 | def prime? 6 | (2..Math.sqrt(self).to_i).each do |number| 7 | return false if (self % number == 0) 8 | end 9 | true 10 | end 11 | end 12 | 13 | class PrimeMatrix 14 | attr_accessor :primers, :table 15 | attr_reader :size 16 | 17 | include Enumerable 18 | 19 | def initialize(size) 20 | @size = size 21 | @primers = [] 22 | populate_primers 23 | end 24 | 25 | def each(&block) 26 | return block.call([]) if size == 0 27 | 28 | (0...size).each do |index| 29 | block.call(Line.new(index, primers).value) 30 | end 31 | end 32 | 33 | def print 34 | self.each do |line| 35 | Printer.draw(line) 36 | end 37 | end 38 | 39 | 40 | private 41 | def populate_primers 42 | inc = 2 43 | until reach_size? do 44 | primers << inc if inc.prime? 45 | inc += 1 46 | end 47 | end 48 | 49 | def reach_size? 50 | primers.size == size 51 | end 52 | 53 | end -------------------------------------------------------------------------------- /matrix_prime_numbers/solutions/tdantas/ruby/printer.rb: -------------------------------------------------------------------------------- 1 | class Printer 2 | def self.draw(line) 3 | line.each do |element| 4 | print align(element.to_s, 4) + " |" 5 | end 6 | print "\n" 7 | end 8 | 9 | def self.align(str, alignment) 10 | ssize = str.size 11 | return str.to_s if ssize >= alignment 12 | [str, Array.new(alignment - ssize).join(" ")].join("") 13 | end 14 | 15 | end 16 | -------------------------------------------------------------------------------- /matrix_prime_numbers/solutions/tdantas/ruby/solution.rb: -------------------------------------------------------------------------------- 1 | $:.unshift File.dirname(__FILE__) 2 | 3 | require 'prime_matrix' 4 | require 'line' 5 | 6 | PrimeMatrix.new(10).print -------------------------------------------------------------------------------- /matrix_prime_numbers/solutions/tdantas/ruby/spec/line_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Line do 4 | describe "method#value" do 5 | 6 | it "should generate a new line based in the index" do 7 | line = Line.new 0, [2,3,4,5] 8 | line.value.should eq([4,6,8,10]) 9 | 10 | line = Line.new 1, [2,3,4,5] 11 | line.value.should eq([6,9,12,15]) 12 | 13 | line = Line.new 2, [2,3,4,5] 14 | line.value.should eq([8,12,16,20]) 15 | 16 | line = Line.new 3, [2,3,4,5] 17 | line.value.should eq([10,15,20,25]) 18 | end 19 | 20 | it "should raise one exception when initialize with invalid index" do 21 | expect { Line.new 2, [2,3] }.to raise_error 22 | end 23 | 24 | it "should raise one exception when initialize with out of range index" do 25 | expect { Line.new -1, [3,4] }.to raise_error 26 | end 27 | 28 | it "should generate a line with no elements when primers is empty" do 29 | Line.new(0, []).value.should eq([]) 30 | Line.new(10, []).value.should eq([]) 31 | end 32 | 33 | end 34 | end -------------------------------------------------------------------------------- /matrix_prime_numbers/solutions/tdantas/ruby/spec/matrix_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe PrimeMatrix do 4 | 5 | 6 | # x | 2 | 3 | 5 | 7 7 | # ---|------------------- 8 | # 2 | 4 | 6 | 10 | 14 9 | # 3 | 6 | 9 | 15 | 21 10 | # 5 | 10 | 15 | 25 | 35 11 | # 7 | 14 | 21 | 35 | 49 12 | 13 | it "Should generate the first 4 primers" do 14 | PrimeMatrix.new(4).primers.should eq([2,3,5,7]) 15 | end 16 | 17 | it "Should generate first 10 primers" do 18 | PrimeMatrix.new(10).primers.should eq([2, 3, 5, 7, 11, 13, 17, 19, 23, 29]) 19 | end 20 | 21 | it "should generate the first matrix line with 4 values" do 22 | PrimeMatrix.new(4).first.should eq([4,6,10,14]) 23 | end 24 | 25 | it "should generate matrix with one line" do 26 | PrimeMatrix.new(1).first.should eq([4]) 27 | end 28 | 29 | it "should generate matrix with no lines when invalid size" do 30 | PrimeMatrix.new(0).first.should eq([]) 31 | end 32 | 33 | end 34 | 35 | 36 | -------------------------------------------------------------------------------- /matrix_prime_numbers/solutions/tdantas/ruby/spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require_relative '../line' 2 | require_relative '../prime_matrix' -------------------------------------------------------------------------------- /maze/README.md: -------------------------------------------------------------------------------- 1 | # Follower Maze 2 | 3 | ## The Challenge 4 | The challenge here is to build a system which acts as a socket 5 | server, reading events from an *event source* and forwarding them when 6 | appropriate to *user clients*. 7 | 8 | Clients will connect through TCP and use the simple protocol described in a 9 | section below. There will be two types of clients connecting to your server: 10 | 11 | - **One** *event source*: It will send you a 12 | stream of events which may or may not require clients to be notified 13 | - **Many** *user clients*: Each one representing a specific user, 14 | these wait for notifications for events which would be relevant to the 15 | user they represent 16 | 17 | ### The Protocol 18 | The protocol used by the clients is string-based (i.e. a `CRLF` control 19 | character terminates each message). All strings are encoded in `UTF-8`. 20 | 21 | The *event souce* **connects on port 9090** and will start sending 22 | events as soon as the connection is accepted. 23 | 24 | The many *user clients* will **connect on port 9099**. As soon 25 | as the connection is accepted, they will send to the server the ID of 26 | the represented user, so that the server knows which events to 27 | inform them of. For example, once connected a *user client* may send down: 28 | `2932\r\n`, indicating that they are representing user 2932. 29 | 30 | After the identification is sent, the *user client* starts waiting for 31 | events to be sent to them. Events coming from *event source* should be 32 | sent to relevant *user clients* exactly like read, no modification is 33 | required or allowed. 34 | 35 | ### The Events 36 | There are five possible events. The table below describe payloads 37 | sent by the *event source* and what they represent: 38 | 39 | | Payload | Seq # | Type | From User Id | To User Id | 40 | |---------------------------|--------|--------------|--------------|------------| 41 | |666|F|60|50 | 666 | Follow | 60 | 50 | 42 | |1|U|12|9 | 1 | Unfollow | 12 | 9 | 43 | |542532|B | 542532 | Broadcast | - | - | 44 | |43|P|32|56 | 43 | Private Msg | 32 | 56 | 45 | |634|S|32 | 634 | Status Update| 32 | - | 46 | 47 | Using the [verification program](), you will receive exactly X events, 48 | with sequence number from 1 to X. **The events will arrive out of order**. 49 | 50 | Events may generate notifications for *user clients*. **If there is a 51 | *user client* ** connected for them, these are the users to be 52 | informed for different event types: 53 | 54 | * **Follow**: Only the `To User Id` should be notified 55 | * **Unfollow**: No clients should be notified 56 | * **Broadcast**: All connected *user clients* should be notified 57 | * **Private Message**: Only the `To User Id` should be notified 58 | * **Status Update**: All current followers of the `From User ID` should be notified 59 | 60 | If there are no *user client* connected for a user, any notifications 61 | for them must be silently ignored. *user clients* expect to be notified of 62 | events **in the correct order**, regardless of the order in which the 63 | *event source* sent them. 64 | 65 | ### Verification Program 66 | 67 | To run the clients, first make sure you have the server you wrote 68 | running and listening to ports 9090 and 9099, then run: 69 | 70 | ``` 71 | $ ./challenge.sh 72 | ``` 73 | 74 | This will start the clients, which will immediately start sending 75 | message to your server. You know it finished without errors when it 76 | outputs: 77 | 78 | ``` 79 | [INFO] ================================== 80 | [INFO] \o/ ALL NOTIFICATIONS RECEIVED \o/ 81 | [INFO] ================================== 82 | ``` 83 | 84 | ### Attention 85 | 86 | We expect you to write code you would consider **production-ready**. 87 | 88 | This means we want your code to be *well-factored*, *without needless duplication*, *follow good practices* and be *automatically verified*. 89 | What we will look at: 90 | - If your code fulfils the requirement, and runs against the verification Program 91 | - How clean is your design and implementation, how easy it is to understand and maintain your code 92 | - How you verified your software, if by automated tests or some other way. 93 | -------------------------------------------------------------------------------- /maze/bin/challenge.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdantas/it-interviews/882e3b52e8d0c653d76cb8782edda52a02a9675d/maze/bin/challenge.jar -------------------------------------------------------------------------------- /maze/bin/challenge.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | SEED=664 4 | EVENTS=1000 5 | CONCURRENCY=6 6 | 7 | time java -server -XX:-UseConcMarkSweepGC -Xmx2G -jar ./challenge.jar $SEED $EVENTS $CONCURRENCY 8 | -------------------------------------------------------------------------------- /maze/solutions/axfcampos/Java/README.md: -------------------------------------------------------------------------------- 1 | ### How to Run 2 | 3 | ```` 4 | cd src/ 5 | javac com/company/Main.java 6 | java com/company/Main 7 | 8 | ```` 9 | 10 | Now, run the challege.sh script from binary folder 11 | 12 | ``` 13 | cd maze/bin 14 | ./challenge.sh 15 | 16 | ``` 17 | 18 | Just wait for 19 | 20 | ```` 21 | 22 | 23 | [INFO] ======================================================== 24 | [INFO] \o/ ALL NOTIFICATIONS RECEIVED \o/ 25 | [INFO] ======================================================== 26 | 27 | ```` 28 | 29 | -------------------------------------------------------------------------------- /maze/solutions/axfcampos/Java/src/com/company/Main.java: -------------------------------------------------------------------------------- 1 | package com.company; 2 | 3 | 4 | import java.io.BufferedReader; 5 | import java.io.IOException; 6 | import java.io.InputStreamReader; 7 | import java.io.OutputStream; 8 | import java.net.ServerSocket; 9 | import java.net.Socket; 10 | import java.util.HashMap; 11 | import java.util.HashSet; 12 | import java.util.concurrent.ExecutorService; 13 | import java.util.concurrent.Executors; 14 | 15 | public class Main { 16 | 17 | public final HashMap> follows; 18 | public final HashMap jobs; 19 | public final HashMap connectedClients; 20 | public int orderedJobCounter; 21 | public final ExecutorService pool; 22 | public final ExecutorService event; 23 | 24 | public Main() { 25 | 26 | connectedClients = new HashMap<>(); 27 | jobs = new HashMap<>(); 28 | follows = new HashMap<>(); 29 | pool = Executors.newCachedThreadPool(); 30 | event = Executors.newSingleThreadExecutor(); 31 | orderedJobCounter = 1; 32 | EventHandlerThread et = new EventHandlerThread(); 33 | et.start(); 34 | ClientHandlerThread ct = new ClientHandlerThread(); 35 | ct.start(); 36 | JobHandlerThread jt = new JobHandlerThread(); 37 | jt.start(); 38 | 39 | } 40 | 41 | public class Client { 42 | 43 | private int cid; 44 | private Socket socket; 45 | 46 | public Client(int id, Socket s) { 47 | cid = id; 48 | socket = s; 49 | } 50 | 51 | public int getCid() { 52 | return cid; 53 | } 54 | 55 | public Socket getSocket() { 56 | return socket; 57 | } 58 | } 59 | 60 | public class Job { 61 | 62 | private String ogCmd; 63 | private int id; 64 | private JobType jobType; 65 | private int fromUserId; 66 | private int toUserId; 67 | 68 | public Job(int jobId, JobType jbt, int fuid, int tuid, String cmd) { 69 | id = jobId; 70 | jobType = jbt; 71 | fromUserId = fuid; 72 | toUserId = tuid; 73 | ogCmd = cmd; 74 | } 75 | 76 | public String getOgCmd() { 77 | return ogCmd; 78 | } 79 | 80 | public int getId() { 81 | return id; 82 | } 83 | 84 | public int getFromUserId() { 85 | return fromUserId; 86 | } 87 | 88 | public int getToUserId() { 89 | return toUserId; 90 | } 91 | 92 | public JobType getJobType() { 93 | return jobType; 94 | } 95 | } 96 | 97 | public enum JobType { 98 | FOLLOW, UNFOLLOW, BROADCAST, PRIVATE_MSG, STATUS_UPDATE 99 | } 100 | 101 | 102 | public class JobHandlerThread extends Thread { 103 | 104 | @Override 105 | public void run() { 106 | 107 | Job job; 108 | int execJobCounter = 1; 109 | while (true) { 110 | synchronized (jobs) { 111 | if (!jobs.containsKey(execJobCounter)) { 112 | try { 113 | jobs.wait(); 114 | } catch (InterruptedException e) { 115 | e.printStackTrace(); 116 | } 117 | continue; 118 | } else { 119 | job = jobs.get(execJobCounter); 120 | } 121 | } 122 | 123 | //execute job 124 | switch (job.getJobType()) { 125 | case BROADCAST: { 126 | for (Client c : connectedClients.values()) { 127 | sendNotification(c, job); 128 | } 129 | break; 130 | } 131 | case UNFOLLOW: { 132 | unfollow(job.getFromUserId(), job.getToUserId()); 133 | break; 134 | } 135 | case STATUS_UPDATE: { 136 | //notify 137 | HashSet l = follows.get(job.getFromUserId()); 138 | if (l != null) { 139 | for (int i : l) { 140 | Client c = connectedClients.get(i); 141 | sendNotification(c, job); 142 | } 143 | } 144 | break; 145 | } 146 | case FOLLOW: { 147 | follow(job.getFromUserId(), job.getToUserId()); 148 | //notify 149 | Client c = connectedClients.get(job.getToUserId()); 150 | sendNotification(c, job); 151 | break; 152 | } 153 | case PRIVATE_MSG: { 154 | //notify 155 | Client c = connectedClients.get(job.getToUserId()); 156 | sendNotification(c, job); 157 | break; 158 | } 159 | 160 | } 161 | execJobCounter++; 162 | } 163 | } 164 | 165 | public void unfollow(int unfollower, int followed) { 166 | follows.get(followed).remove(unfollower); 167 | } 168 | 169 | public void follow(int follower, int followed) { 170 | if (!follows.containsKey(followed)) { 171 | HashSet hs = new HashSet<>(); 172 | hs.add(follower); 173 | follows.put(followed, hs); 174 | } else { 175 | follows.get(followed).add(follower); 176 | } 177 | } 178 | 179 | public void sendNotification(Client c, Job job) { 180 | if (c != null) { 181 | try { 182 | OutputStream out = c.getSocket().getOutputStream(); 183 | out.write(job.getOgCmd().getBytes()); 184 | char r = '\r'; 185 | out.write(r); 186 | char n = '\n'; 187 | out.write(n); 188 | out.flush(); 189 | } catch (IOException e) { 190 | e.printStackTrace(); 191 | } 192 | } 193 | } 194 | 195 | 196 | } 197 | 198 | public class ClientHandlerThread extends Thread { 199 | ServerSocket serverSocket = null; 200 | 201 | public ClientHandlerThread() { 202 | try { 203 | serverSocket = new ServerSocket(9099); 204 | } catch (IOException e) { 205 | e.printStackTrace(); 206 | } 207 | } 208 | 209 | @Override 210 | public void run() { 211 | while (true) { 212 | try { 213 | Socket socket = serverSocket.accept(); 214 | pool.execute(new ClientIdSubmissionRunnable(socket)); 215 | } catch (IOException e) { 216 | e.printStackTrace(); 217 | } 218 | } 219 | } 220 | } 221 | 222 | public class ClientIdSubmissionRunnable implements Runnable { 223 | 224 | private final Socket socket; 225 | 226 | public ClientIdSubmissionRunnable(Socket s) { 227 | socket = s; 228 | } 229 | 230 | @Override 231 | public void run() { 232 | 233 | try { 234 | BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); 235 | StringBuilder sb = new StringBuilder(); 236 | 237 | int nl; 238 | while ((nl = br.read()) != (int) '\n') { 239 | sb.append(Integer.parseInt((new Character((char) nl)).toString())); 240 | } 241 | 242 | String sid = sb.toString(); 243 | int id = Integer.parseInt(sid); 244 | 245 | Client c = new Client(id, socket); 246 | connectedClients.put(id, c); 247 | 248 | } catch (IOException e) { 249 | e.printStackTrace(); 250 | } 251 | } 252 | } 253 | 254 | public class JobSubmissionRunnable implements Runnable { 255 | 256 | private final String command; 257 | 258 | public JobSubmissionRunnable(String cmd) { 259 | command = cmd; 260 | } 261 | 262 | @Override 263 | public void run() { 264 | String[] cmd = command.split("\\|"); 265 | Job job; 266 | switch (cmd[1]) { 267 | case "B": { 268 | job = new Job(Integer.parseInt(cmd[0]), JobType.BROADCAST, 0, 0, command); 269 | jobs.put(job.getId(), job); 270 | break; 271 | } 272 | case "F": { 273 | job = new Job(Integer.parseInt(cmd[0]), JobType.FOLLOW, Integer.parseInt(cmd[2]), Integer.parseInt(cmd[3]), command); 274 | jobs.put(job.getId(), job); 275 | break; 276 | } 277 | case "U": { 278 | job = new Job(Integer.parseInt(cmd[0]), JobType.UNFOLLOW, Integer.parseInt(cmd[2]), Integer.parseInt(cmd[3]), command); 279 | jobs.put(job.getId(), job); 280 | break; 281 | } 282 | case "P": { 283 | job = new Job(Integer.parseInt(cmd[0]), JobType.PRIVATE_MSG, Integer.parseInt(cmd[2]), Integer.parseInt(cmd[3]), command); 284 | jobs.put(job.getId(), job); 285 | break; 286 | } 287 | case "S": { 288 | job = new Job(Integer.parseInt(cmd[0]), JobType.STATUS_UPDATE, Integer.parseInt(cmd[2]), 0, command); 289 | jobs.put(job.getId(), job); 290 | break; 291 | } 292 | } 293 | 294 | synchronized (jobs) { 295 | jobs.notifyAll(); 296 | } 297 | 298 | } 299 | } 300 | 301 | public class EventHandlerThread extends Thread { 302 | 303 | public EventHandlerThread() { 304 | 305 | } 306 | 307 | @Override 308 | public void run() { 309 | 310 | ServerSocket serverSocket = null; 311 | Socket socket = null; 312 | 313 | 314 | while (true) { 315 | try { 316 | serverSocket = new ServerSocket(9090); 317 | 318 | socket = serverSocket.accept(); 319 | 320 | BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); 321 | StringBuilder sb = new StringBuilder(); 322 | 323 | int ch; 324 | while ((ch = br.read()) != -1) { 325 | 326 | if (ch == (int) '\n') { 327 | String command = sb.toString(); 328 | sb.setLength(0); 329 | 330 | event.execute(new JobSubmissionRunnable(command)); 331 | } else { 332 | sb.append((char) ch); 333 | } 334 | } 335 | 336 | } catch (IOException e) { 337 | e.printStackTrace(); 338 | } finally { 339 | //fechar sockets. 340 | try { 341 | if (serverSocket != null) serverSocket.close(); 342 | } catch (IOException e) { 343 | } 344 | try { 345 | if (socket != null) socket.close(); 346 | } catch (IOException e) { 347 | } 348 | } 349 | 350 | } 351 | 352 | } 353 | 354 | } 355 | 356 | public static void main(String[] args) { 357 | 358 | Main m = new Main(); 359 | } 360 | } 361 | -------------------------------------------------------------------------------- /maze/solutions/axfcampos/Java/test/challenge.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdantas/it-interviews/882e3b52e8d0c653d76cb8782edda52a02a9675d/maze/solutions/axfcampos/Java/test/challenge.jar -------------------------------------------------------------------------------- /maze/solutions/axfcampos/Java/test/challenge.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | SEED=664 4 | EVENTS=1000 5 | CONCURRENCY=6 6 | 7 | time java -server -XX:-UseConcMarkSweepGC -Xmx2G -jar ./challenge.jar $SEED $EVENTS $CONCURRENCY 8 | -------------------------------------------------------------------------------- /maze/solutions/diasdavid/nodejs/index.js: -------------------------------------------------------------------------------- 1 | var tcp = require('net'); 2 | 3 | tcp.createServer(eventHandler).listen(9090,'127.0.0.1'); 4 | tcp.createServer(clientHandler).listen(9099,'127.0.0.1'); 5 | 6 | var clients = {}; 7 | var seqNumber = 1; 8 | var events = []; 9 | var end = false; 10 | 11 | function eventHandler(socket) { 12 | socket.setEncoding('utf8'); 13 | socket.on('data', function(data){ 14 | data.split('\n').map(function(el){ 15 | if(el.length > 1) { 16 | events.push(el); 17 | } 18 | // console.log(data); 19 | }); 20 | }); 21 | 22 | socket.on('end', function (){ 23 | console.log('end'); 24 | end = true; 25 | }); 26 | } 27 | 28 | function clientHandler(socket) { 29 | socket.setEncoding('utf8'); 30 | socket.on('data', function(data){ 31 | clients[data.trim()] = { 32 | socket: socket, 33 | followers: [] 34 | } 35 | }); 36 | } 37 | 38 | function munch() { 39 | while(true) { 40 | 41 | if (end) { 42 | return process.exit(0); 43 | } 44 | 45 | if (events.length < 1) { 46 | continue; 47 | } 48 | 49 | var ev = events.shift(); 50 | 51 | var evSplit = ev.split('|'); 52 | if (parseInt(evSplit[0]) === seqNumber) { 53 | // console.log(ev); 54 | switch(evSplit[1]) { 55 | case 'F': follow(ev, evSplit); break; 56 | case 'U': unfollow(ev, evSplit); break; 57 | case 'B': broadcast(ev, evSplit); break; 58 | case 'P': privateMessage(ev, evSplit); break; 59 | case 'S': statusUpdate(ev, evSplit); break; 60 | // default: console.log('no event type match'); 61 | } 62 | seqNumber += 1; 63 | } else { 64 | events.push(ev); 65 | } 66 | 67 | } 68 | } 69 | 70 | // falta estas funcões 71 | 72 | function follow(ev, evSplit) { 73 | // evSplit[2] follower 74 | // evSplit[3] to follow 75 | // console.log('id: ', evSplit[2]); 76 | // console.log('id: ', evSplit[3]); 77 | // console.log('all:', ev, evSplit); 78 | if(!clients[evSplit[2]] || !clients[evSplit[3]]) { 79 | // console.log('does not exist - follow'); 80 | return; 81 | } 82 | 83 | clients[evSplit[3]].followers.push(evSplit[2]); 84 | clients[evSplit[3]].socket.write(ev + '\r\n'); 85 | 86 | } 87 | 88 | function unfollow(ev, evSplit) { 89 | // evSplit[2] follower 90 | // evSplit[3] to unfollow 91 | // console.log('ids: ', evSplit[2], evSplit[3]); 92 | // console.log('all:', ev, evSplit); 93 | 94 | if(!clients[evSplit[2]] || !clients[evSplit[3]]) { 95 | // console.log('does not exist - unfollow'); 96 | return; 97 | } 98 | 99 | clients[evSplit[3]] 100 | .followers 101 | .remove( 102 | clients[evSplit[3]].followers.indexOf(evSplit[3]) 103 | ); 104 | 105 | } 106 | 107 | function broadcast(ev, evSplit) { 108 | Object.keys(clients) 109 | .map(function(key) { 110 | // console.log('VOU BROADCAST: ', key); 111 | // console.log(clients[key]); 112 | // console.log('payload: ', ev); 113 | clients[key].socket.write(ev + '\r\n'); 114 | }); 115 | } 116 | 117 | function privateMessage(ev, evSplit) { 118 | // evSplit[3] destination 119 | // console.log('id: ', evSplit[3]); 120 | // console.log('all:', ev, evSplit); 121 | if(!clients[evSplit[3]]) { 122 | // console.log('does not exist - private'); 123 | return; 124 | } 125 | 126 | clients[evSplit[3]].socket.write(ev + '\r\n'); 127 | } 128 | 129 | function statusUpdate(ev, evSplit) { 130 | 131 | // evSplit[2] update followers 132 | // console.log('id: ', evSplit[2]); 133 | // console.log('all:', ev, evSplit); 134 | if(!!!clients[evSplit[2]]) { 135 | // console.log('does not exist - statusUpdate - ', clients[evSplit[2]], evSplit[2]); 136 | return; 137 | } 138 | 139 | if(clients[evSplit[2]].followers.length === 0) { 140 | // console.log('THERE IS : ', clients[evSplit[2]].followers, clients[evSplit[2]].followers.length); 141 | return; 142 | } 143 | 144 | 145 | clients[evSplit[2]].followers.map(function(flw){ 146 | clients[flw].socket.write(ev + '\r\n'); 147 | }); 148 | } 149 | 150 | function test() { 151 | if (events.length > 5) { 152 | munch(); 153 | } else { 154 | setTimeout(test,150); 155 | } 156 | } 157 | test(); 158 | // warmp up 159 | 160 | /// helper 161 | 162 | // eg. directions.remove(directions.indexOf(previousDirection)); 163 | 164 | Array.prototype.remove = function(from, to) { 165 | var rest = this.slice((to || from) + 1 || this.length); 166 | this.length = from < 0 ? this.length + from : from; 167 | return this.push.apply(this, rest); 168 | }; -------------------------------------------------------------------------------- /maze/solutions/jxs/elixir/README.md: -------------------------------------------------------------------------------- 1 | ExFollowerMaze 2 | ============== 3 | FollowerMaze solved using elixir 4 | 5 | instrunctions 6 | ------------ 7 | mix run --no-halt 8 | -------------------------------------------------------------------------------- /maze/solutions/jxs/elixir/config/config.exs: -------------------------------------------------------------------------------- 1 | # This file is responsible for configuring your application 2 | # and its dependencies with the aid of the Mix.Config module. 3 | use Mix.Config 4 | 5 | # This configuration is loaded before any dependency and is restricted 6 | # to this project. If another project depends on this project, this 7 | # file won't be loaded nor affect the parent project. For this reason, 8 | # if you want to provide default values for your application for third- 9 | # party users, it should be done in your mix.exs file. 10 | 11 | # Sample configuration: 12 | # 13 | # config :logger, :console, 14 | # level: :info, 15 | # format: "$date $time [$level] $metadata$message\n", 16 | # metadata: [:user_id] 17 | 18 | # It is also possible to import configuration files, relative to this 19 | # directory. For example, you can emulate configuration per environment 20 | # by uncommenting the line below and defining dev.exs, test.exs and such. 21 | # Configuration from the imported file will override the ones defined 22 | # here (which is why it is important to import them last). 23 | # 24 | # import_config "#{Mix.env}.exs" 25 | -------------------------------------------------------------------------------- /maze/solutions/jxs/elixir/lib/ExFollowerMaze/clients_server.ex: -------------------------------------------------------------------------------- 1 | defmodule ExFollowerMaze.ClientsServer do 2 | 3 | def accept(port) do 4 | Process.register(self, :clientsserver) 5 | {:ok, socket} = :gen_tcp.listen(port, [:binary, packet: :line, active: false]) 6 | IO.puts "Accepting clients on port #{port}" 7 | {:ok, clients_agent} = Agent.start_link(fn -> %{} end) 8 | Task.start_link(fn-> loop_acceptor(socket, clients_agent) end) 9 | handle_events(clients_agent, %{}) 10 | end 11 | 12 | defp loop_acceptor(socket, clients_list) do 13 | {status, client} = :gen_tcp.accept(socket) 14 | case {status, client } do 15 | {:ok, client} -> 16 | {:ok, data} = :gen_tcp.recv(client, 0) 17 | client_id = String.rstrip(data) 18 | Agent.update(clients_list, &Map.put(&1, client_id, client)) 19 | loop_acceptor(socket, clients_list) 20 | {status, _} -> 21 | IO.puts "no more clients" 22 | IO.inspect(status) 23 | loop_acceptor(socket, clients_list) 24 | end 25 | end 26 | 27 | defp handle_events(clients_agent, followers_map) do 28 | receive do 29 | event -> 30 | output = Enum.join(event, "|") <> "\n" 31 | case event do 32 | [_ , "B"] -> 33 | clients_list = Agent.get(clients_agent, fn list -> list end) 34 | Enum.each(clients_list, fn{_, client} -> :gen_tcp.send(client, output) end) 35 | handle_events(clients_agent, followers_map) 36 | [_ , "S", client_id] -> 37 | followers = Map.get(followers_map, client_id) || [] 38 | Enum.each followers, fn(follower) -> 39 | client = Agent.get(clients_agent, &Map.get(&1, follower)) 40 | if client, do: :gen_tcp.send(client, output) 41 | end 42 | handle_events(clients_agent, followers_map) 43 | [_, "F", follower, client_id] -> 44 | followers = Map.get(followers_map, client_id) || [] 45 | followers_map = Map.put(followers_map, client_id, [follower | followers]) 46 | client = Agent.get(clients_agent, &Map.get(&1, client_id)) 47 | if client, do: :gen_tcp.send(client, output) 48 | handle_events(clients_agent, followers_map) 49 | [_, "P", _, client_id] -> 50 | client = Agent.get(clients_agent, &Map.get(&1, client_id)) 51 | if client, do: :gen_tcp.send(client, output) 52 | handle_events(clients_agent, followers_map) 53 | _ -> 54 | handle_events(clients_agent, followers_map) 55 | end 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /maze/solutions/jxs/elixir/lib/ExFollowerMaze/source_server.ex: -------------------------------------------------------------------------------- 1 | defmodule ExFollowerMaze.SourceServer do 2 | 3 | def accept(port) do 4 | {:ok, socket} = :gen_tcp.listen(port, [:binary, packet: :line, active: false]) 5 | IO.puts "Accepting events source on port #{port}" 6 | {:ok, client} = :gen_tcp.accept(socket) 7 | loop_acceptor(client, %HashDict{}, 1) 8 | end 9 | 10 | defp parse_event(data) do 11 | data 12 | |> String.rstrip() 13 | |> String.split("|") 14 | end 15 | 16 | defp check_send_event(events, current_event) do 17 | case HashDict.get(events, Integer.to_string(current_event)) do 18 | nil -> 19 | {events, current_event} 20 | event -> 21 | send(:clientsserver, event) 22 | events = HashDict.delete(events, Integer.to_string(current_event)) 23 | current_event = current_event + 1 24 | check_send_event(events, current_event) 25 | end 26 | end 27 | 28 | defp loop_acceptor(client, events, current_event) do 29 | {status, data} = :gen_tcp.recv(client, 0) 30 | case {status, data} do 31 | {:ok, data} -> 32 | event = parse_event(data) 33 | events = HashDict.put(events, hd(event), event) 34 | {events, current_event} = check_send_event(events, current_event) 35 | loop_acceptor(client, events, current_event) 36 | {status, _} -> 37 | IO.inspect(status) 38 | IO.puts "Finished receiving events" 39 | end 40 | end 41 | 42 | end 43 | -------------------------------------------------------------------------------- /maze/solutions/jxs/elixir/lib/ex_follower_maze.ex: -------------------------------------------------------------------------------- 1 | defmodule ExFollowerMaze do 2 | use Application 3 | 4 | def start(_type, _args) do 5 | import Supervisor.Spec, warn: false 6 | children = [ 7 | worker(Task, [ExFollowerMaze.ClientsServer, :accept, [9099]], id: :clientsserver), 8 | worker(Task, [ExFollowerMaze.SourceServer, :accept, [9090]], id: :sourceserver) 9 | ] 10 | opts = [strategy: :one_for_one, name: ExFollowerMaze.Supervisor] 11 | Supervisor.start_link(children, opts) 12 | end 13 | 14 | end 15 | -------------------------------------------------------------------------------- /maze/solutions/jxs/elixir/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule ExFollowerMaze.Mixfile do 2 | use Mix.Project 3 | 4 | def project do 5 | [app: :ex_follower_maze, 6 | version: "0.0.1", 7 | elixir: "~> 1.0", 8 | deps: deps] 9 | end 10 | 11 | # Configuration for the OTP application 12 | # 13 | # Type `mix help compile.app` for more information 14 | def application do 15 | [mod: {ExFollowerMaze, []}, 16 | applications: [:logger]] 17 | end 18 | 19 | # Dependencies can be Hex packages: 20 | # 21 | # {:mydep, "~> 0.3.0"} 22 | # 23 | # Or git/path repositories: 24 | # 25 | # {:mydep, git: "https://github.com/elixir-lang/mydep.git", tag: "0.1.0"} 26 | # 27 | # Type `mix help deps` for more examples and options 28 | defp deps do 29 | [] 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /maze/solutions/jxs/elixir/test/ex_follower_maze_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ExFollowerMazeTest do 2 | use ExUnit.Case 3 | 4 | test "the truth" do 5 | assert 1 + 1 == 2 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /maze/solutions/jxs/elixir/test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | -------------------------------------------------------------------------------- /maze/solutions/tdantas/nodeJS/README.md: -------------------------------------------------------------------------------- 1 | ### How to Run 2 | 3 | 4 | ```` 5 | npm install # will install all dependencies 6 | npm start # start user server and event server 7 | 8 | ```` 9 | 10 | Now, run the challege.sh script from binary folder 11 | 12 | ``` 13 | cd maze/bin 14 | ./challenge.sh 15 | 16 | ``` 17 | 18 | Just wait for 19 | 20 | ```` 21 | 22 | 23 | [INFO] ======================================================== 24 | [INFO] \o/ ALL NOTIFICATIONS RECEIVED \o/ 25 | [INFO] ======================================================== 26 | 27 | ```` -------------------------------------------------------------------------------- /maze/solutions/tdantas/nodeJS/index.js: -------------------------------------------------------------------------------- 1 | require('./lib'); -------------------------------------------------------------------------------- /maze/solutions/tdantas/nodeJS/lib/event-dispatcher.js: -------------------------------------------------------------------------------- 1 | module.exports = EventDispatcher(); 2 | 3 | function EventDispatcher() { 4 | var next = 1; 5 | var backlog = { }; 6 | var report = []; 7 | 8 | return { process: process }; 9 | 10 | function process(event) { 11 | var curr; 12 | backlog[event.sequence] = event; 13 | 14 | while((curr = backlog[next])) { 15 | delete backlog[next]; 16 | next++; 17 | 18 | curr.process(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /maze/solutions/tdantas/nodeJS/lib/events-server.js: -------------------------------------------------------------------------------- 1 | var EE = require('events').EventEmitter; 2 | var net = require('net'); 3 | 4 | var CRLFParser = require('./parser'); 5 | var Events = require('./events'); 6 | 7 | module.exports = EventServer; 8 | 9 | function EventServer(port) { 10 | var server; 11 | var ee = new EE(); 12 | var parser = CRLFParser(); 13 | 14 | return { 15 | start: start, 16 | stop: stop, 17 | on: ee.on.bind(ee) 18 | }; 19 | 20 | function start(callback) { 21 | server = net.createServer(onConnection); 22 | 23 | server.listen(port, function(err) { 24 | 25 | parser.on('token', function(rawEvent) { 26 | var event = Events(rawEvent); 27 | ee.emit('event', event); 28 | }); 29 | 30 | callback(err, port); 31 | }); 32 | 33 | } 34 | 35 | function stop(callback) { 36 | callback = callback || function(){ }; 37 | server.close(callback); 38 | } 39 | 40 | function onConnection(eventStream) { 41 | eventStream.on('data', parser.parse); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /maze/solutions/tdantas/nodeJS/lib/events.js: -------------------------------------------------------------------------------- 1 | var debug = require('debug')('events.processor'); 2 | 3 | var usersRepository = require('./users/repository'); 4 | 5 | module.exports = Event; 6 | 7 | var Processors = { 8 | 'P': PVTEventProcessor, 9 | 'F': FollowEventProcessor, 10 | 'U': UnfollowEventProcessor, 11 | 'B': BroadcastEventProcessor, 12 | 'S': StatusEventProcessor 13 | }; 14 | 15 | function Event(payload) { 16 | var pieces = payload.split("|"); 17 | 18 | var _sequence = parseInt(pieces[0]); 19 | var _type = pieces[1].replace(/\r?\n/, ""); 20 | var _from = pieces[2]; 21 | var _to = pieces[3]; 22 | 23 | return { 24 | from: _from, 25 | to: _to, 26 | type: _type, 27 | sequence: _sequence, 28 | payload: payload, 29 | process: process, 30 | toString: toString 31 | }; 32 | 33 | function process(callback) { 34 | Processors[_type](this, callback); 35 | } 36 | 37 | function toString() { 38 | return [ 39 | 'Sequence: ' + _sequence, 40 | 'type: ' + _type, 41 | 'From:' + _from, 42 | 'To: ' + _to 43 | ].join(" "); 44 | } 45 | } 46 | 47 | function PVTEventProcessor(event, cb) { 48 | debug('PVTEventProcessor ' + event); 49 | 50 | var toUser = usersRepository.fetch(event.to); 51 | toUser.send(event.payload); 52 | } 53 | 54 | function FollowEventProcessor(event, cb) { 55 | debug('FollowEventProcessor ' + event); 56 | 57 | var from = usersRepository.fetch(event.from); 58 | var to = usersRepository.fetch(event.to); 59 | 60 | from.follow(to); 61 | to.send(event.payload, cb); 62 | } 63 | 64 | function UnfollowEventProcessor(event, cb) { 65 | debug('UnfollowEventProcessor ' + event); 66 | 67 | var from = usersRepository.fetch(event.from); 68 | var to = usersRepository.fetch(event.to); 69 | 70 | from.unfollow(to); 71 | } 72 | 73 | function BroadcastEventProcessor(event, cb) { 74 | debug('BroadcastEventProcessor ' + event); 75 | var allUsers = usersRepository.all(); 76 | 77 | allUsers.forEach(function(client) { 78 | client.send(event.payload, cb); 79 | }); 80 | } 81 | 82 | function StatusEventProcessor(event, cb) { 83 | debug('StatusEventProcessor ' + event); 84 | 85 | var fromUser = usersRepository.fetch(event.from); 86 | 87 | fromUser.followers().forEach(function(client) { 88 | client.send(event.payload, cb); 89 | }); 90 | } 91 | 92 | -------------------------------------------------------------------------------- /maze/solutions/tdantas/nodeJS/lib/index.js: -------------------------------------------------------------------------------- 1 | var EventsServer = require('./events-server'); 2 | var UsersServer = require('./users-server'); 3 | var UserRepository = require('./users/repository'); 4 | var EventDispatcher = require('./event-dispatcher'); 5 | 6 | var eventsServer = EventsServer(9090); 7 | var userServer = UsersServer(9099); 8 | 9 | userServer.on('user', function(socket, id) { 10 | UserRepository.create(id, socket); 11 | }); 12 | 13 | userServer.on("disconnect", function(userid) { 14 | UserRepository.delete(userid); 15 | }); 16 | 17 | eventsServer.on('event', function(event) { 18 | EventDispatcher.process(event); 19 | }); 20 | 21 | UserRepository.on('empty', function() { 22 | 23 | console.log("-----------------------------------------------") 24 | console.log(" All users disconnected, closing the server"); 25 | console.log("-----------------------------------------------") 26 | process.exit(0) 27 | 28 | }); 29 | 30 | eventsServer.start(function(err, port) { 31 | console.log("Events Server started on port: " + port) 32 | }); 33 | 34 | userServer.start(function(err, port) { 35 | console.log("User Server accepting data on port: " + port) 36 | }); -------------------------------------------------------------------------------- /maze/solutions/tdantas/nodeJS/lib/parser.js: -------------------------------------------------------------------------------- 1 | var EE = require('events').EventEmitter; 2 | 3 | module.exports = Parser; 4 | 5 | function Parser(matcher) { 6 | var ee = new EE(); 7 | var buf = ''; 8 | matcher = matcher || /\r?\n/; 9 | 10 | return { 11 | parse: toParse, 12 | on: ee.on.bind(ee) 13 | }; 14 | 15 | function toParse(data) { 16 | var pieces = (buf + data.toString()).split(matcher) 17 | 18 | buf = pieces.pop(); 19 | for (var i = 0; i < pieces.length; i++) { 20 | ee.emit('token', pieces[i] + '\n'); 21 | } 22 | } 23 | } 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /maze/solutions/tdantas/nodeJS/lib/users-server.js: -------------------------------------------------------------------------------- 1 | var EE = require('events').EventEmitter; 2 | var net = require('net'); 3 | 4 | var CRLFParser = require('./parser'); 5 | 6 | module.exports = UserServer; 7 | 8 | function UserServer(port) { 9 | var ee = new EE(); 10 | var server; 11 | 12 | return { 13 | start: start, 14 | stop: stop, 15 | on: ee.on.bind(ee) 16 | }; 17 | 18 | function start(callback) { 19 | server = net.createServer(onConnection); 20 | server.listen(port, function(err) { 21 | callback(err, port); 22 | }); 23 | } 24 | 25 | function stop(callback) { 26 | callback = callback || function(){ } 27 | server.close(callback); 28 | } 29 | 30 | function onConnection(userSocket) { 31 | userSocket._id = +new Date; 32 | var parser = CRLFParser(); 33 | 34 | userSocket.on('data', parser.parse); 35 | 36 | parser.on('token', function(userId) { 37 | userSocket.userId = userId; 38 | ee.emit('user', userSocket, userId); 39 | }); 40 | 41 | userSocket.on('close', function onDisconnect() { 42 | ee.emit('disconnect', userSocket.userId); 43 | }); 44 | } 45 | } -------------------------------------------------------------------------------- /maze/solutions/tdantas/nodeJS/lib/users/entity.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = User; 3 | 4 | function User(id, socket) { 5 | var _socket = socket; 6 | var _id = parseInt(id); 7 | var _followers = { }; 8 | 9 | var me = { 10 | id: _id, 11 | followers: followers, 12 | follow: follow, 13 | removeFollower: removeFollower, 14 | setFollower: setFollower, 15 | unfollow: unfollow, 16 | send: send, 17 | toString: toString 18 | }; 19 | 20 | return me; 21 | 22 | function followers() { 23 | return Object.keys(_followers).map(function(indice) { 24 | return _followers[indice]; 25 | }); 26 | } 27 | 28 | function follow(user) { 29 | user.setFollower(me); 30 | } 31 | 32 | function setFollower(user) { 33 | _followers[user.id] = user; 34 | } 35 | 36 | function unfollow(user) { 37 | user.removeFollower(me); 38 | } 39 | 40 | function removeFollower(user) { 41 | delete _followers[user.id]; 42 | } 43 | 44 | function send(payload) { 45 | _socket.write(payload); 46 | } 47 | 48 | function toString() { 49 | return [ _id ].join(" ") 50 | } 51 | 52 | } 53 | 54 | User.NULL = new User('N/A', { write: noop }); 55 | function noop(payload, cb) { 56 | if(typeof cb === 'function') cb(); 57 | } 58 | -------------------------------------------------------------------------------- /maze/solutions/tdantas/nodeJS/lib/users/repository.js: -------------------------------------------------------------------------------- 1 | var User = require('./entity') 2 | var EE = require('events').EventEmitter; 3 | 4 | 5 | var UserRepository = module.exports; 6 | 7 | var storage = { }; 8 | var ee = new EE(); 9 | 10 | UserRepository.on = ee.on.bind(ee); 11 | UserRepository.create = create; 12 | UserRepository.fetch = fetch; 13 | UserRepository.all = all; 14 | UserRepository['delete'] = deleteFn; 15 | 16 | function create(id, socket) { 17 | var user = new User(id, socket); 18 | storage[user.id] = user; 19 | } 20 | 21 | function fetch(id) { 22 | id = parseInt(id); 23 | var user = storage[id] || User.NULL; 24 | return user; 25 | } 26 | 27 | function all(){ 28 | return Object 29 | .keys(storage) 30 | .map(mapper); 31 | 32 | function mapper(key) { 33 | return storage[key]; 34 | } 35 | } 36 | 37 | function deleteFn(id) { 38 | var user = storage[id]; 39 | delete storage[id]; 40 | 41 | if(all().length === 0) ee.emit("empty"); 42 | return user; 43 | } 44 | 45 | -------------------------------------------------------------------------------- /maze/solutions/tdantas/nodeJS/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "solution", 3 | "version": "0.0.1", 4 | "description": "SoundCloud Interview", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "./node_modules/mocha/bin/mocha test/**", 8 | "start": "node index.js" 9 | }, 10 | "author": "Thiago T. Dantas", 11 | "license": "BSD-2-Clause", 12 | "dependencies": { 13 | "debug": "^2.0.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /remove_duplicate_char_from_string/README.md: -------------------------------------------------------------------------------- 1 | You're given a string, return a string without the duplicate characters. 2 | 3 | input: 'banana' 4 | output: 'ban' 5 | 6 | input: 'house' 7 | output: 'house' 8 | 9 | input: 'apple' 10 | output: 'aple' 11 | 12 | -------------------------------------------------------------------------------- /remove_duplicate_char_from_string/solutions/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdantas/it-interviews/882e3b52e8d0c653d76cb8782edda52a02a9675d/remove_duplicate_char_from_string/solutions/.gitkeep -------------------------------------------------------------------------------- /remove_duplicate_char_from_string/solutions/ruijose/ruby/remove_duplicates.rb: -------------------------------------------------------------------------------- 1 | def remove_duplicates_of(word) 2 | word.chars.uniq.join 3 | end 4 | 5 | puts remove_duplicates_of("banana") 6 | puts remove_duplicates_of("house") 7 | puts remove_duplicates_of("apple") 8 | -------------------------------------------------------------------------------- /reverse_binary/README.md: -------------------------------------------------------------------------------- 1 | # Reverse Binary 2 | 3 | ##Task 4 | 5 | Your task will be to write a program for reversing numbers in binary. For instance, the binary representation of 13 is 1101, and reversing it gives 1011, which corresponds to number 11. 6 | 7 | 8 | ###Input 9 | The input contains a single line with an integer N, 1 ≤ N ≤ 1000000000. 10 | 11 | ###Output 12 | Output one line with one integer, the number we get by reversing the binary representation of N. 13 | 14 | ```` 15 | Input: 13 16 | Output: 11 17 | 18 | Input: 47 19 | Output: 61 20 | ```` -------------------------------------------------------------------------------- /reverse_binary/solutions/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdantas/it-interviews/882e3b52e8d0c653d76cb8782edda52a02a9675d/reverse_binary/solutions/.gitkeep -------------------------------------------------------------------------------- /stack_data_structure_constant_time/README.md: -------------------------------------------------------------------------------- 1 | Lets modify the stack data structure to create a new one. 2 | 3 | This data structure has 3 methods 4 | All methods must respond in constant time O(1) 5 | 6 | ```` 7 | push(item) 8 | # => Pushes an item onto the top of this stack 9 | 10 | pop() 11 | # => Removes the object at the top of the stack and returns that object 12 | 13 | getMin() 14 | # => Return the minimal value in the stack 15 | 16 | ```` -------------------------------------------------------------------------------- /stack_data_structure_constant_time/solutions/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdantas/it-interviews/882e3b52e8d0c653d76cb8782edda52a02a9675d/stack_data_structure_constant_time/solutions/.gitkeep -------------------------------------------------------------------------------- /stack_data_structure_constant_time/solutions/tdantas/stack.ex: -------------------------------------------------------------------------------- 1 | defmodule Stack do 2 | defstruct items: [], min: [] 3 | 4 | def push(element) do 5 | %Stack{items: [element], min: [element] } 6 | end 7 | 8 | def push(%Stack{ items: [stack], min: [first | rest] }, element) do 9 | newMin = Enum.min([first, element]) 10 | %Stack{items: [element | stack], min: [newMin|[first|rest]]} 11 | end 12 | 13 | def pop(%Stack{items: [top | rest], min: [ _ | tail ] }) do 14 | {top, %Stack{items: rest, min: tail }} 15 | end 16 | 17 | def getMin(stack) do 18 | [ min| _ ] = stack.min; 19 | min 20 | end 21 | 22 | end 23 | 24 | -------------------------------------------------------------------------------- /telegram_problem/README.md: -------------------------------------------------------------------------------- 1 | Problem - 2 | 3 | Write a program that takes a number w, then accepts lines of text and outputs lines of text, where the output lines have as many words as possible but are never longer than w characters. Words may not be split, but you may assume that no single word is too long for a line. -------------------------------------------------------------------------------- /telegram_problem/solutions/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdantas/it-interviews/882e3b52e8d0c653d76cb8782edda52a02a9675d/telegram_problem/solutions/.gitkeep -------------------------------------------------------------------------------- /telegram_problem/solutions/ruijose/ruby/spec/telegram_spec.rb: -------------------------------------------------------------------------------- 1 | require_relative "../telegram_problem" 2 | 3 | describe Telegram do 4 | it 'should return 3 word for the next line' do 5 | Telegram.new(10, "tes1 a car ce cococo").output_lines.should eq(["tes1 a car ce"]) 6 | end 7 | 8 | it 'should return 3 word for each line' do 9 | Telegram.new(10, "ts1sssssk a car cenaspasd cococo", "ola cca c asd").output_lines.should eq(["ts1sssssk a", "ola cca c asd"]) 10 | end 11 | 12 | it 'should return 1 word for the next line' do 13 | Telegram.new(5, "tes1 a car cenaspasd cococo").output_lines.should eq(["tes1 a"]) 14 | end 15 | 16 | it 'should return the whole line' do 17 | Telegram.new(50, "tes1 a car cenaspasd cococo").output_lines.should eq(["tes1 a car cenaspasd cococo"]) 18 | end 19 | 20 | it 'should return stuff' do 21 | Telegram.new(5, "oi 2i o1").output_lines.should eq(["oi 2i"]) 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /telegram_problem/solutions/ruijose/ruby/telegram_problem.rb: -------------------------------------------------------------------------------- 1 | class Telegram 2 | def initialize(chars_limit, *lines_of_text) 3 | @chars_limit = chars_limit 4 | @lines_of_text = lines_of_text 5 | end 6 | 7 | def output_lines 8 | @lines_of_text.each_with_object([]) do |line, result| 9 | if line.length <= @chars_limit 10 | result << line 11 | else 12 | allowed_words = verify_words(count_lines(line)) 13 | result << line.split[0..allowed_words-1].join(" ") 14 | end 15 | end 16 | end 17 | 18 | private 19 | def count_lines(line) 20 | line.split.each_with_object(Hash.new) do |word, hash| 21 | hash[word] = word.length 22 | end 23 | end 24 | 25 | def verify_words(hash) 26 | n = 0 27 | hash.reduce(0) do |result, (key,value)| 28 | n += value 29 | result += 1 if n <= @chars_limit 30 | result 31 | end 32 | end 33 | end 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /trains/README.md: -------------------------------------------------------------------------------- 1 | #Problem 2 | 3 | The local commuter railroad services a number of towns in Kiwiland. 4 | Because of monetary concerns, all of the tracks are 'one-way.' That is, a route from Kaitaia to Invercargill does not imply the existence of a route from Invercargill to Kaitaia. In fact, even if both of these routes do happen to exist, they are distinct and are not necessarily the same distance! 5 | 6 | The purpose of this problem is to help the railroad provide its customers with information about the routes. In particular, you will compute the distance along a certain route, the number of different routes between two towns, and the shortest route between two towns. 7 | 8 | Input: A directed graph where a node represents a town and an edge represents a route between two towns. The weighting of the edge represents the distance between the two towns. A given route will never appear more than once, and for a given route, the starting and ending town will not be the same town. 9 | 10 | Output: For test input 1 through 5, if no such route exists, output 'NO SUCH ROUTE'. Otherwise, follow the route as given; do not make any extra stops! For example, the first problem means to start at city A, then travel directly to city B (a distance of 5), then directly to city C (a distance of 4). 11 | 12 | 1. The distance of the route A-B-C. 13 | 2. The distance of the route A-D. 14 | 3. The distance of the route A-D-C. 15 | 4. The distance of the route A-E-B-C-D. 16 | 5. The distance of the route A-E-D. 17 | 6. The number of trips starting at C and ending at C with a maximum of 3 stops. In the sample data below, there are two such trips: C-D-C (2 stops). and C-E-B-C (3 stops). 18 | 7. The number of trips starting at A and ending at C with exactly 4 stops. In the sample data below, there are three such trips: A to C (via B,C,D); A to C (via D,C,D); and A to C (via D,E,B). 19 | 8. The length of the shortest route (in terms of distance to travel) from A to C. 20 | 9. The length of the shortest route (in terms of distance to travel) from B to B. 21 | 10. The number of different routes from C to C with a distance of less than 30. In the sample data, the trips are: CDC, CEBC, CEBCDC, CDCEBC, CDEBC, CEBCEBC, CEBCEBCEBC. 22 | 23 | ###Test Input: 24 | 25 | For the test input, the towns are named using the first few letters of the alphabet from A to E. A route between two towns (A to B) with a distance of 5 is represented as AB5. 26 | 27 | Graph: AB5, BC4, CD8, DC8, DE6, AD5, CE2, EB3, AE7 28 | 29 | ###Output: 30 | ```` 31 | Output #1: 9 32 | Output #2: 5 33 | Output #3: 13 34 | Output #4: 22 35 | Output #5: NO SUCH ROUTE 36 | Output #6: 2 37 | Output #7: 3 38 | Output #8: 9 39 | Output #9: 9 40 | Output #10: 7 41 | ```` -------------------------------------------------------------------------------- /trains/solutions/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdantas/it-interviews/882e3b52e8d0c653d76cb8782edda52a02a9675d/trains/solutions/.gitkeep -------------------------------------------------------------------------------- /word_sugestion_T9_based/README.md: -------------------------------------------------------------------------------- 1 | Suppose you have to implement a system to give suggestions for words based on sequences of digits. 2 | 3 | Think of [T9][wikipedia_t9] where each digit maps to some characters. 4 | 5 | Your job will be to implement 2 functions: 6 | 7 | void PreProcess(Map map) 8 | List GetSuggestions(List sequence) 9 | 10 | **PreProcess** is called once at the beginning of the program, its parameter is a map of string to probability, i.e. what's the probability of that word show up if the integer sequence that maps to that word is input. 11 | 12 | **GetSuggestions** returns the 5 words with the highest probability for a particular integer sequence. 13 | 14 | Don't worry about optimizing PreProcess, just think about data structures and how your decisions will affect the implementation of both functions. 15 | 16 | 17 | [wikipedia_t9]: http://en.wikipedia.org/wiki/T9_(predictive_text -------------------------------------------------------------------------------- /word_sugestion_T9_based/solutions/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdantas/it-interviews/882e3b52e8d0c653d76cb8782edda52a02a9675d/word_sugestion_T9_based/solutions/.gitkeep -------------------------------------------------------------------------------- /wordsource/README.md: -------------------------------------------------------------------------------- 1 | ### Background 2 | 3 | A WordSource is a source of words and it keeps analytical information of each word that it has seen. 4 | 5 | 6 | ### Example 7 | 8 | ```` 9 | For the following string: "lorem ipsum ipsum" 10 | 11 | src = LoremIpsumWordSource.new 12 | src.next_word 13 | # => "lorem" 14 | src.next_word 15 | # => "ipsum" 16 | src.next_word 17 | # => "ipsum" 18 | src.top_5_words 19 | # => ["ipsum","lorem",nil,nil,nil] 20 | src.top_5_consonants 21 | # => ["m","p","s","l","r"] 22 | src.count 23 | # => 3 # total words seen 24 | ```` 25 | ### Assignment 26 | 27 | 1. Implement LoremIpsumWordSource 28 | 2. Get top 5 consonants from the words seen 29 | 3. Get top 5 words 30 | 4. Add callbacks on specific words e.g. every time "semper" is encountered, call those callbacks registered for "semper" 31 | 5. implement a WordSource that uses the twitter API -------------------------------------------------------------------------------- /wordsource/solutions/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdantas/it-interviews/882e3b52e8d0c653d76cb8782edda52a02a9675d/wordsource/solutions/.gitkeep --------------------------------------------------------------------------------