diff --git a/src/main/java/iurii/job/interview/amazon/HeadsTailsOnlineAssessment.java b/src/main/java/iurii/job/interview/amazon/HeadsTailsOnlineAssessment.java new file mode 100644 index 0000000..33badfc --- /dev/null +++ b/src/main/java/iurii/job/interview/amazon/HeadsTailsOnlineAssessment.java @@ -0,0 +1,216 @@ +package iurii.job.interview.amazon; + +import java.util.Collections; + +/** + * A Amazon Shopping recently launched a new coin collection album. + * Each page has a coin pasted on it, with either the head or a tail side facing upwards, + * represented by H or T respectively. + * A sequence of coins is called beautiful if all the head-facing coins are pasted before all the tail-facing coins. + * More formally, a beautiful sequence is a sequence of the form HHTTT. + * One of the buyers has a hobby to collect and organize coins. + * The buyer pastes the end coins on end pages and then wishes to organize them into a beautiful sequence. + * Given the initial sequence of coins, find a minimum number of coins that must be flipped to obtain a beautiful sequence. + * + * The sequence of coins can be very long; + * THHHTH - 2 + * HHTT - 0 + * HHHH - 0 + * + * (H)*(T)* + * TTTTTT + * HTTTTT + * HHTTTT + * .. + * HHHHHH + * + * Algo: + * - Find count of H - count of flips to make TTTTTT.. + * TflipsCount = 0 + * - on i =0, 1.. + * - if on i pos H : HflipsCount = HflipsCount-1 + * - if on i pos T: TflipsCount = TflipsCount + 1 + * - if TflipsCount+HflipsCount < Result : Result = TflipsCount+HflipsCount + * + * You can see constraints; + * + * Variation : what if 2 coins are flipped at a time? => see + * + * We will use sliding window to find first T from the left and first H from right and flip them. + * Will this be optimal solution? It should be as we flip only coins that violate condition (H)*(T)* + * This is different from original question when each flip is separate operation and we are not sure + * if flipping in the beginning is better than flipping on the end. + * + * THTTTTTT + * i i + * + * HTTTTTTT + * + * TTTHHHH + * i i + * HTTHHHT + * i i + * HHTHHTT + * i i + * HHHHTTT + */ +public class HeadsTailsOnlineAssessment { + + /** + * Potential solution. We know how the end sequence should look like: + * a bunch of H follow by T. + * We can find number of flips for each of end sequence, starting all Tails and then + * making first character H, then HH, then HHH and count number of flips for each of them + * and take minimum. + * + * Note: we do not need to traverse sequence for each example. + * We can find number of heads in sequence then start traversing and check each character + * and depending on character correct number of flips. + * + * Complexity: O(N), N - sequence length / coin count; we need to go once to count heads + * and once from left to right to collect the answer + * Memory: O(1) - we need a couple of values to store results and a couple of current values, pointers; + * + * @param sequence - H or T , ex. HTHTHT + * @return minimum flips, for HTHTHT : 2 flips with ex. result : HTTTTT + */ + public HeadsTailsResult minFlipsForBeautifulSequence(String sequence) { + // skipping validation for sequence - only H and T + + // finding headCount + int totalHeadCount = 0; + int sequenceLength = sequence.length(); + for (char sequenceChar : sequence.toCharArray()) { + if ('H' == sequenceChar) { + totalHeadCount++; + } + } + + // finding the best number of flips and first T position + int headFlips = totalHeadCount; + int tailFlips = 0; + HeadsTailsResult result = new HeadsTailsResult(); + // all Tails + result.firstTailPosition = 0; + result.numberOfFlips = headFlips; + // Adding H (Head) in the beginning; we need to flip T to H or decrease head flips if we see Head + for (int i = 0; i < sequenceLength; i++) { + if (sequence.charAt(i) == 'H') { + headFlips--; + } else { + tailFlips++; + } + // if current number of flips is smaller this is our best solution found so far; + if (headFlips + tailFlips < result.numberOfFlips) { + result.numberOfFlips = headFlips + tailFlips; + result.firstTailPosition = i + 1; // Tails will start from next position + } + } + result.resultSequenceAfterFlips = + String.join("", Collections.nCopies(result.firstTailPosition,"H")) + + String.join("", Collections.nCopies(sequenceLength - result.firstTailPosition,"T")); + return result; + } + + /** + * This is variation with minimum 2 coin flips at a time. + * + * We will use sliding window to find first T from the left and first H from right and flip them. + * Will this be optimal solution? It should be as we flip only coins that violate condition (H)*(T)* + * This is different from original question when each flip is separate operation and we are not sure + * if flipping in the beginning is better than flipping on the end. + * + * THTTTTTT + * i i + * + * HTTTTTTT + * + * TTTHHHH + * i i + * HTTHHHT + * i i + * HHTHHTT + * i i + * HHHHTTT + * @param sequence + * @return + */ + public HeadsTailsResult minFlipsForBeautifulSequenceFlip2CoinsAtOnce(String sequence) { + int sequenceLength = sequence.length(); + int headPointer = findFromLeft(0, sequence, 'T'); + int tailPointer = findFromRight(sequenceLength - 1, sequence, 'H'); + char[] resSeq = sequence.toCharArray(); + HeadsTailsResult result = new HeadsTailsResult(); + while (headPointer < tailPointer) { + // flip + resSeq[headPointer] = 'H'; + resSeq[tailPointer] = 'T'; + result.numberOfFlips++; + + // next + headPointer = findFromLeft(headPointer + 1, sequence, 'T'); + tailPointer = findFromRight(tailPointer - 1, sequence, 'H'); + } + result.resultSequenceAfterFlips = String.valueOf(resSeq); + result.firstTailPosition = result.resultSequenceAfterFlips.indexOf('T'); + return result; + } + + // return position + private int findFromLeft(int initialPosition, String sequence, char character) { + int pos = initialPosition; + while (pos < sequence.length()) { + if (sequence.charAt(pos) == character) { + return pos; + } + pos++; + } + return pos; + } + + private int findFromRight(int initialPosition, String sequence, char character) { + int pos = initialPosition; + while (pos >= 0) { + if (sequence.charAt(pos) == character) { + return pos; + } + pos--; + } + return pos; + } + + // helper data classes + public static class HeadsTailsResult { + int firstTailPosition = -1; // by default not set + int numberOfFlips; + // should be in format (H)*(T)* + String resultSequenceAfterFlips = ""; // by default not set + + public HeadsTailsResult () { + + } + + public HeadsTailsResult (int firstTailPosition, int numberOfFlips, String resultSequenceAfterFlips) { + this.firstTailPosition = firstTailPosition; + this.numberOfFlips = numberOfFlips; + this.resultSequenceAfterFlips = resultSequenceAfterFlips; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof HeadsTailsResult)) { + return false; + } + HeadsTailsResult other = (HeadsTailsResult) obj; + return firstTailPosition == other.firstTailPosition + && numberOfFlips == other.numberOfFlips + && resultSequenceAfterFlips.equals(other.resultSequenceAfterFlips); + } + + @Override + public String toString() { + return String.format("firstTailPosition = %d numberOfFlips = %d resultSequenceAfterFlips = %s", + firstTailPosition, numberOfFlips, resultSequenceAfterFlips); + } + } +} diff --git a/src/main/java/iurii/job/interview/amazon/online_assesment/AmazonFreshPromotion.java b/src/main/java/iurii/job/interview/amazon/online_assesment/AmazonFreshPromotion.java new file mode 100644 index 0000000..b90f0de --- /dev/null +++ b/src/main/java/iurii/job/interview/amazon/online_assesment/AmazonFreshPromotion.java @@ -0,0 +1,74 @@ +package iurii.job.interview.amazon.online_assesment; + +import java.util.Objects; + +/** + * Question which is asked on Online interview assessments. + * Is a part of Amazon Code Review training. + * Links where I found that question and potential solutions : + * - Leetcode discussion : https://leetcode.com/discuss/interview-question/1008283/amazon-oa-sde-1-fresh-promotion + * - Youtube example of question and solution : https://www.youtube.com/watch?v=PBBEehnUW_8&ab_channel=crazydevelopers + * - Example of Youtube solution on Github with test cases : https://github.com/crazy-developers-dev/AmazonOA/blob/master/P1_AmazonFreshPromotion.java + */ +public class AmazonFreshPromotion { + + public boolean match(String[][] codeList, String[] shoppingCart) { + // check conditions ex. not empty + if (codeList == null || codeList.length == 0) { + return false; + } + if (shoppingCart == null || shoppingCart.length == 0) { + return false; + } + // scan while matching + int codeListSize = codeList.length; + int shoppingCartSize = shoppingCart.length; + + int codeListIndex = 0; + int shoppingCartIndex = 0; + + // algo in a couple of words - 2 pointer subarray check on matching + // one pointer - position in shopping cart + // second pointer current code to match from codeList + + while (shoppingCartIndex < shoppingCartSize && codeListIndex < codeListSize) { + String[] currentCode = codeList[codeListIndex]; + boolean isMatch = match(currentCode, shoppingCart, shoppingCartIndex); + if (!isMatch) { + // try match from next one + shoppingCartIndex++; + } else { + // if match - continue from next index after match + shoppingCartIndex += currentCode.length; + codeListIndex++; + } + + if (codeListIndex == codeListSize) { + // all codes are matched + return true; + } + } + + return false; + } + + private boolean match(String[] code, String[] shoppingCart, int shoppingCartStartIndex) { + // no left items to match + if (shoppingCartStartIndex + code.length > shoppingCart.length) { + return false; + } + for (int codeIndex= 0; codeIndex < code.length; codeIndex++) { + String codeValue = code[codeIndex]; + if ("anything".equals(codeValue)) { + // match - check next + continue; + } + if (!Objects.equals(shoppingCart[shoppingCartStartIndex + codeIndex], codeValue)) { + // no match + return false; + } + } + // all codes match + return true; + } +} diff --git a/src/main/java/iurii/job/interview/amazon/online_assesment/SearchSuggestionsSystem.java b/src/main/java/iurii/job/interview/amazon/online_assesment/SearchSuggestionsSystem.java new file mode 100644 index 0000000..de786cf --- /dev/null +++ b/src/main/java/iurii/job/interview/amazon/online_assesment/SearchSuggestionsSystem.java @@ -0,0 +1,311 @@ +package iurii.job.interview.amazon.online_assesment; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * Similar to Leetcode : https://leetcode.com/problems/search-suggestions-system/description/ + * just starting from index 2 + * + * Amazon + * Amazon is building a way to help customers search reviews quicker by providing real-time suggestions to search terms when the customer starts typing. When given a minimum of two characters into the search field the system will suggest at most three keywords from the review word repository. As the customer continues to type in the reviews search bar the relevant keyword suggestions will update automatically. + * + * Write an algorithm that will output a maximum of three keyword suggestions after each character is typed by the customer in the search field. + * + * If there are more than three acceptable keywords, return the keywords that are first in alphabetical order. + * Only return keyword suggestions after the customer has entered two characters. + * Keyword suggestions must start with the characters already typed + * + * Both the repository and the customerQuery should be compared in a case-insensitive way. + * + * Input + * The input to the method/function consists of two arguments: + * repository, a list of unique strings representing the various keywords from the Amazon review comment section; + * customerQuery, a string representing the full search query of the customer. + * + * Output + * Return a list of a list of strings in lower case, where each list represents the keyword suggestions made by the system as the customer types each character of the customerQuery. Assume the customer types characters in order without deleting or removing any characters. If an output is not possible, return an empty array ([]). + * + * Example + * Input: + * repository = [ "mobile", "mouse", "moneypot", "monitor", "mousepad" ] + * customerQuery = "mouse" + * + * Output: + * ["mobile", "moneypot", "monitor"] + * ["mouse", "mousepad"] + * ["mouse", "mousepad"] + * ["mouse", "mousepad"] + * + * Explanation: + * The chain of words that will generate in the search box will be + * mo, mou, mous, mouse + * and each line from output shows the suggestion of "mo", "mou", "mous", "mouse", respectively in each line. + * For the keyword suggestions made by the system that are generated for 'mo', the matches that will be generated are:["mobile", "mouse", "moneypot", "monitor", "mousepad"] + * Alphabetically, they will be reordered to [ "mobile", "moneypot", "monitor", "mouse", "mousepad" ]. + * Thus the keyword suggestions made by the system are [ "mobile", "moneypot", "monitor"]. + */ +public class SearchSuggestionsSystem { + + // almost bruteforce solution + public List> searchSuggestions(String[] products, String searchWord) { + List> result = new ArrayList<>(); + List lowercaseProducts = Arrays.stream(products).map(String::toLowerCase).collect(Collectors.toList()); + String lowercaseSearchWord = searchWord.toLowerCase(); + for(int ii = 2; ii < lowercaseSearchWord.length(); ii++) { + String partialQuery = lowercaseSearchWord.substring(0, ii); + + List partialResult = new ArrayList<>(); + for(String word : lowercaseProducts) { + if(partialQuery.equals(word.substring(0, ii))) { + partialResult.add(word); + if (partialResult.size() > 3) { + Collections.sort(partialResult); + partialResult.remove(3); + } + } + } + Collections.sort(partialResult); + result.add(partialResult); + } + return result; + } + + // similar to initial version, bit more bruteforce + public List> searchSuggestions2(String[] products, String searchWord) { + String queryString = ""; + List> result = new ArrayList<>(); + + // For each sub query string + for (int charIndex = 0; charIndex < searchWord.length(); charIndex++) { + queryString += Character.toLowerCase(searchWord.charAt(charIndex)); + + // Don't find suggestions if length is < 2 + if (queryString.length() < 2) + continue; + + // For each item in repository + List suggestionsForIndex = new ArrayList<>(); + for (int index = 0; index < products.length; index++) { + String item = products[index].toLowerCase(); + + if (item.startsWith(queryString)) { + suggestionsForIndex.add(item); + } + } + + // Sort and keep the top 3 + Collections.sort(suggestionsForIndex); + result.add(suggestionsForIndex.subList(0, 3)); + } + return result; + } + + private static final int MIN_QUERY_LENGTH = 2; + private static final int MAX_SUGGESTION_SIZE = 3; + private static final Comparator STRING_COMPARATOR = Comparator.reverseOrder(); + + public List> searchSuggestions3(String[] products, String searchWord) { + // pre conditions + if(products == null || searchWord == null || searchWord.length() < MIN_QUERY_LENGTH || products.length == 0) { + return Collections.emptyList(); + } + + List> suggestions = new ArrayList<>(); + + // this will separate the customer query into a list of lowercase prefixes + // ex: customerQuery = "aBc" will be prefixList = ["a","ab","abc"] + List prefixList = new ArrayList<>(); + String lowerCaseCustomerQuery = searchWord.toLowerCase(); + for (int i = MIN_QUERY_LENGTH; i <= lowerCaseCustomerQuery.length(); i++) { + prefixList.add(lowerCaseCustomerQuery.substring(0, i)); + } + + // process the entire repository once + for(String word : products) { + addWordAsSuggestionIfApplicable(word.toLowerCase(), prefixList, suggestions); + } + + return suggestions; + } + + /** + * converts a queue into a list, maybe a collections or stream operation could be used instead + **/ + public static List flattenQueueToList(Queue queue) { + List queueAsList = new ArrayList<>(); + while(!queue.isEmpty()) { + String item = queue.poll(); + queueAsList.add(item); + } + return queueAsList; + } + + /** + * Naming is hard. This method will take a given word from the repository, check against the first entry in the prefix list. If it + * matches, it will add it to the queue and process the next prefix in the list. If it does not match, it will not process the next + * prefix and return. + **/ + private static void addWordAsSuggestionIfApplicable(String word, List prefixList, List> suggestions) { + int index = 0; + String prefix = prefixList.get(index); + + while(word.startsWith(prefix)) { + PriorityQueue queue = new PriorityQueue<>(MAX_SUGGESTION_SIZE, STRING_COMPARATOR); + addWordToQueue(word, queue); + + // it matched last prefix so check next prefix if not at the end of the prefix list, otherwise exit loop + index++; + if (index == prefixList.size()) { + break; + } + prefix = prefixList.get(index); + } + + } + + /** + * add the suggested word to the queue. If the queue is less than max suggestion size just add the word, if the queue is full + * check word against value on top of queue, and if appropriate, pop value off and add new suggestion to queue. + **/ + private static void addWordToQueue(String word, Queue queue) { + if(queue.size() < MAX_SUGGESTION_SIZE) { + queue.add(word); + } else { + String peekValue = queue.peek(); + + if(peekValue.compareTo(word) > 0) { + queue.poll(); + queue.add(word); + } + } + } + + // The best solution using Trie + DFS + // Put all words into Trie + // Map should be sorted by key TreeMap = should sort on each put or afterward - does not matter + // Traverse Trie using search word and take first 3 words using DFS for current prefix in tries + // Time complexity : O(n * m) to form the trie + public List> searchSuggestionsTrieAndDfs(String[] products, String searchWord) { + List> result = new ArrayList<>(); + Trie root = new Trie(); + // next + for (String product : products) { + root.add(product); + } + Trie curTrie = root; + for(int i = 0; i < searchWord.length(); i++) { + char curChar = searchWord.charAt(i); + curTrie = curTrie.getNextOrDefault(curChar); + if (i < 1) { + // suggest after second char + continue; + } + // dfs to find top 3 answers + List answer = new ArrayList<>(); + findSuggestions(curTrie, answer); + result.add(answer); + } + return result; + } + + private void findSuggestions(Trie trie, List answer) { + if (answer.size() == 3) { + // return when first 3 sorted are returned + return; + } + // if exists terminal - add + if (trie.terminalValue != null) { + answer.add(trie.terminalValue); + } + for (char c : trie.next.keySet()) { + findSuggestions(trie.getNextOrDefault(c), answer); + } + } + + public static class Trie { + public static Trie EMPTY = new Trie(); + // available to query next and TreeMap To be sorted + Map next = new TreeMap<>(); + String terminalValue; + + public void add(String word) { + Trie curTrie = this; + for (int i = 0; i < word.length(); i++) { + char curChar = word.charAt(i); + if (curTrie.getNext(curChar) == null) { + curTrie.next.put(curChar, new Trie()); + } + curTrie = curTrie.getNext(curChar); + } + curTrie.terminalValue = word; + } + + public Trie getNext(char c) { + return next.get(c); + } + + public Trie getNextOrDefault(char c) { + return next.getOrDefault(c, EMPTY); + } + } + + // Time Complexity : O(n log(n)) + O(m log(n)) ; m - word length; n - number of products + // O(n log(n)) - sorting assuming O(1) string comparison based on hash + // O(m log(n)) -running binary sort m times on number of products n; + // O(m^2) because strings are immutable and need copy + // Space complexity: O(n*m) - products themselves + O(3*m) - result set + public List> searchSuggestionsWithBinarySearch(String[] products, String searchWord) { + // sorting + Arrays.sort(products); // nlog(n) + + // binary search first proper word: m log(n) + List> result = new ArrayList<>(); + + StringBuilder prefix = new StringBuilder(); + for(int i = 0; i < searchWord.length(); i++) { + char curChar = searchWord.charAt(i); + prefix.append(curChar); + if (i < 1) { + // suggest after second char + continue; + } + + int index = findIndex(prefix.toString(), products); + if (index == -1) { + // not found + continue; + } + List curResult = new ArrayList<>(); + // add up to 3 results from sorted if match + while (index < products.length && products[index].startsWith(prefix.toString()) && curResult.size() < 3) { + curResult.add(products[index]); + index++; + } + result.add(curResult); + } + return result; + } + + private int findIndex(String prefix, String[] products) { + int l = 0; + int h = products.length - 1; + while (l < h) { + int index = (h + l) / 2; + if (products[index].startsWith(prefix)) { + // find first index with starts with + while (index - 1 >= 0 && products[index - 1].startsWith(prefix)) { + index--; + } + return index; + } + if (products[index].compareTo(prefix) > 0) { + h = index - 1; + } else { + l = index + 1; + } + } + // not found + return -1; + } +} diff --git a/src/main/java/iurii/job/interview/google/FindRange.java b/src/main/java/iurii/job/interview/google/FindRange.java new file mode 100644 index 0000000..f8a8c3f --- /dev/null +++ b/src/main/java/iurii/job/interview/google/FindRange.java @@ -0,0 +1,50 @@ +package iurii.job.interview.google; + +import java.util.Set; +import java.util.TreeSet; + +/** + * This is google interview question I have heard. + * You have a set of int numbers, let`s say there are no duplicates. + * You need to implement function which accepts range [from to ] . for simplicity including both. + * You need to return - number of values exists in range; + * or even return all the numbers in the range. + * + * The solution should be based on Search in Tree - tree should be balanced, so probably red-black tree ? + * + */ +public class FindRange { + + /** + * Here solution is based on TreeSet, which sorts + */ + TreeSet values = new TreeSet<>(); + + void putValue(int value) { + values.add(value); + } + + + /** + * To insert new value into TreeSet operation is guaranteed to take O (log N) + * because tree is balanced and being rebalanced if not balanced yet; + * + * To get answer: + * Complexity: O(N) - for subset operation it is needed to go via all the nodes once; + * Memory: O(N) - to store maximum all the numbers or subset of numbers + * + * Important to note that on average operations needed will be O (log N) as you need to go into only one side of tree; + * + * @param from - first value from range. Can be configured inclusive/exclusive + * @param to - last value from the range. Can be configured inclusive/exclusive + * @return values from the range; + */ + Set findValues(int from, int to) { + return values.subSet(from, true, to, true); + } + + int findCount(int from, int to) { + return findValues(from, to).size(); + } + +} diff --git a/src/test/java/iurii/job/interview/amazon/HeadsTailsOnlineAssessmentTest.java b/src/test/java/iurii/job/interview/amazon/HeadsTailsOnlineAssessmentTest.java new file mode 100644 index 0000000..0ed0798 --- /dev/null +++ b/src/test/java/iurii/job/interview/amazon/HeadsTailsOnlineAssessmentTest.java @@ -0,0 +1,48 @@ +package iurii.job.interview.amazon; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Test; + +public class HeadsTailsOnlineAssessmentTest { + + @Test + public void minFlipsForBeautifulSequence() { + HeadsTailsOnlineAssessment assessment = new HeadsTailsOnlineAssessment(); + + // zero flips + assertThat(assessment.minFlipsForBeautifulSequence("HHHTTT")).isEqualTo( + new HeadsTailsOnlineAssessment.HeadsTailsResult(3, 0, "HHHTTT") + ); + + assertThat(assessment.minFlipsForBeautifulSequenceFlip2CoinsAtOnce("HHHTTT")).isEqualTo( + new HeadsTailsOnlineAssessment.HeadsTailsResult(3, 0, "HHHTTT") + ); + + // 2 flips + assertThat(assessment.minFlipsForBeautifulSequence("HTHTHT")).isEqualTo( + new HeadsTailsOnlineAssessment.HeadsTailsResult(1, 2, "HTTTTT") + ); + + assertThat(assessment.minFlipsForBeautifulSequenceFlip2CoinsAtOnce("HTHTHT")).isEqualTo( + new HeadsTailsOnlineAssessment.HeadsTailsResult(3, 1, "HHHTTT") + ); + + // 3 flips to head + assertThat(assessment.minFlipsForBeautifulSequence("TTTHHHH")).isEqualTo( + new HeadsTailsOnlineAssessment.HeadsTailsResult(7, 3, "HHHHHHH") + ); + + assertThat(assessment.minFlipsForBeautifulSequenceFlip2CoinsAtOnce("TTTHHHH")).isEqualTo( + new HeadsTailsOnlineAssessment.HeadsTailsResult(4, 3, "HHHHTTT") + ); + // 4 flips to Tails + assertThat(assessment.minFlipsForBeautifulSequence("TTTTHHHH")).isEqualTo( + new HeadsTailsOnlineAssessment.HeadsTailsResult(0, 4, "TTTTTTTT") + ); + + assertThat(assessment.minFlipsForBeautifulSequenceFlip2CoinsAtOnce("TTTTHHHH")).isEqualTo( + new HeadsTailsOnlineAssessment.HeadsTailsResult(4, 4, "HHHHTTTT") + ); + } +} \ No newline at end of file diff --git a/src/test/java/iurii/job/interview/amazon/online_assesment/AmazonFreshPromotionTest.java b/src/test/java/iurii/job/interview/amazon/online_assesment/AmazonFreshPromotionTest.java new file mode 100644 index 0000000..ea208dc --- /dev/null +++ b/src/test/java/iurii/job/interview/amazon/online_assesment/AmazonFreshPromotionTest.java @@ -0,0 +1,31 @@ +package iurii.job.interview.amazon.online_assesment; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class AmazonFreshPromotionTest { + + @Test + public void testMatch() { + AmazonFreshPromotion amazonFreshPromotion = new AmazonFreshPromotion(); + + String[][] codeList1 = { { "apple", "apple" }, { "banana", "anything", "banana" } }; + String[] shoppingCart1 = {"orange", "apple", "apple", "banana", "orange", "banana"}; + + String[][] codeList2 = { { "apple", "apple" }, { "banana", "anything", "banana" } }; + String[] shoppingCart2 = {"banana", "orange", "banana", "apple", "apple"}; + + String[][] codeList3 = { { "apple", "apple" }, { "banana", "anything", "banana" } }; + String[] shoppingCart3 = {"apple", "banana", "apple", "banana", "orange", "banana"}; + + String[][] codeList4 = { { "apple", "apple" }, { "apple", "apple", "banana" } }; + String[] shoppingCart4 = {"apple", "apple", "apple", "banana"}; + + + assertThat(amazonFreshPromotion.match(codeList1, shoppingCart1)).isTrue(); + assertThat(amazonFreshPromotion.match(codeList2, shoppingCart2)).isFalse(); + assertThat(amazonFreshPromotion.match(codeList3, shoppingCart3)).isFalse(); + assertThat(amazonFreshPromotion.match(codeList4, shoppingCart4)).isFalse(); + } +} \ No newline at end of file diff --git a/src/test/java/iurii/job/interview/amazon/online_assesment/SearchSuggestionsSystemTest.java b/src/test/java/iurii/job/interview/amazon/online_assesment/SearchSuggestionsSystemTest.java new file mode 100644 index 0000000..08c725c --- /dev/null +++ b/src/test/java/iurii/job/interview/amazon/online_assesment/SearchSuggestionsSystemTest.java @@ -0,0 +1,45 @@ +package iurii.job.interview.amazon.online_assesment; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +public class SearchSuggestionsSystemTest { + + @Test + public void searchSuggestionsTrieAndDfs() { + SearchSuggestionsSystem searchSuggestionsSystem = new SearchSuggestionsSystem(); + String[] products1 = new String[] {"mobile", "mouse", "moneypot", "monitor", "mousepad"}; + String searchWord1 = "mouse"; + + List> answer1 = searchSuggestionsSystem.searchSuggestionsTrieAndDfs(products1, searchWord1); + List> expected1 = new ArrayList<>(); + expected1.add(Arrays.asList("mobile", "moneypot", "monitor")); + expected1.add(Arrays.asList("mouse", "mousepad")); + expected1.add(Arrays.asList("mouse", "mousepad")); + expected1.add(Arrays.asList("mouse", "mousepad")); + + assertThat(answer1).isEqualTo(expected1); + + String[] products2 = new String[] {"havana"}; + String searchWord2 = "havana"; + + List> answer2 = searchSuggestionsSystem.searchSuggestionsTrieAndDfs(products2, searchWord2); + List> expected2 = new ArrayList<>(); + expected2.add(Arrays.asList("havana")); + expected2.add(Arrays.asList("havana")); + expected2.add(Arrays.asList("havana")); + expected2.add(Arrays.asList("havana")); + expected2.add(Arrays.asList("havana")); + + assertThat(answer2).isEqualTo(expected2); + + List> answerBinarySearch1 = searchSuggestionsSystem.searchSuggestionsWithBinarySearch(products1, searchWord1); + assertThat(answerBinarySearch1).isEqualTo(expected1); + + } +} \ No newline at end of file diff --git a/src/test/java/iurii/job/interview/google/FindRangeTest.java b/src/test/java/iurii/job/interview/google/FindRangeTest.java new file mode 100644 index 0000000..fb14978 --- /dev/null +++ b/src/test/java/iurii/job/interview/google/FindRangeTest.java @@ -0,0 +1,23 @@ +package iurii.job.interview.google; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Set; + +import org.junit.Test; + +public class FindRangeTest { + + @Test + public void simpleTest() { + FindRange findRange = new FindRange(); + findRange.putValue(1); + findRange.putValue(3); + findRange.putValue(5); + findRange.putValue(7); + + Set values = findRange.findValues(2, 6); + assertThat(values).containsExactly(3, 5); + } + +} \ No newline at end of file