{"id":394108,"date":"2024-06-29T11:24:38","date_gmt":"2024-06-29T11:24:38","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=394108"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=394108","title":{"rendered":"<span>Solving coding problems with Kotlin: Collection functions<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/70f\/164\/46e\/70f16446e19e28bef57a52bd022e455c.jpg\" width=\"5000\" height=\"4000\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/70f\/164\/46e\/70f16446e19e28bef57a52bd022e455c.jpg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<p>(originally published on <a href=\"https:\/\/proandroiddev.com\/solving-coding-problems-with-kotlin-collection-functions-3d2b1ef7fe2c\" rel=\"noopener noreferrer nofollow\">Medium<\/a>)<\/p>\n<p>I have talked to many Android developers, and most of them are excited about Kotlin. So am I. When I just started learning Kotlin, I was solving\u00a0<a href=\"https:\/\/kotlinlang.org\/docs\/tutorials\/koans.html\" rel=\"noopener noreferrer nofollow\"><u>Kotlin Koans<\/u><\/a>, and along with other great features, I was impressed with the power of functions for performing operations on collections. Since then, I spent three years writing Kotlin code but rarely utilised all the potential of the language.<\/p>\n<p>During this year, I did more than a hundred coding problems on Leetcode in Java. I didn\u2019t switch to Kotlin because I know the syntax of Java 6 so well, that I could effortlessly write code without autocompletion and syntax highlighting. But I didn\u2019t keep track of new Java features, as Android support of Java SDK lagged many versions behind. I didn\u2019t switch to Kotlin for solving problems right away. <\/p>\n<p>Although I was writing Kotlin code for several years, I felt that I need to make an extra cognitive effort to get the syntax and the language constructions right. Solving algorithmic problems, especially under the time pressure, is very different from Android app development. Still, the more I learned about Kotlin, the more I realised how many powerful features I\u2019m missing, and how much boilerplate code I need to write.<\/p>\n<p>One day, I have decided that I need to move on, so I started a new session in Leetcode and switched the compiler to Kotlin. I solved just a few easy problems, but I already feel that I have something to share.<\/p>\n<h3>Loops<\/h3>\n<p>Let\u2019s start with loops. Let\u2019s say, you have an\u00a0<code>IntArray<\/code>\u00a0of 10 elements\u00a0<code>0, 1, 2, 3, 4, 5, 6, 7, 8, 9<\/code>\u00a0and you want to print\u00a0<code>123456789<\/code>.<\/p>\n<pre><code class=\"kotlin\">val array = intArrayOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) for(index in (1 until array.size)) {   print(array[index]) }<\/code><\/pre>\n<p><code>(1 until array.size)<\/code>\u00a0is an\u00a0<code>IntRange<\/code>, a class that represents a range of values of type\u00a0<code>Int<\/code>. The first element in this range is\u00a0<code>1<\/code>\u00a0and the last one is\u00a0<code>9<\/code>\u00a0as we used\u00a0<code>until<\/code>\u00a0to exclude the last value. We don\u2019t want to get\u00a0<code>ArrayIndexOutOfBoundsException<\/code>\u00a0right?<\/p>\n<p>But what if we want to print all the elements of the array, except the element at index 5? Like this\u00a0<code>012346789<\/code>. Let\u2019s get a bit more Kotliney then writing an\u00a0<code>if<\/code>\u00a0statement in the loop.<\/p>\n<pre><code class=\"kotlin\">val array = intArrayOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) for(index in array.indices - 5) {   print(array[index]) }<\/code><\/pre>\n<p><code>array.indices<\/code>\u00a0returns the range of valid indices for the array. In this case\u00a0<code>array.indices<\/code>\u00a0represent\u00a0<code>IntRange<\/code>\u00a0of\u00a0<code>(0..9)<\/code>. Making\u00a0<code>(0..9) - 5<\/code>\u00a0will result in\u00a0<code>[0, 1, 2, 3, 4, 6, 7, 8, 9]<\/code>. This is exactly what we need.<\/p>\n<p>Kotlin also provides an ability to iterate from the greater number down to the smaller number using\u00a0<code>downTo<\/code>. The iteration step size can also be changed using\u00a0<code>step<\/code>.<\/p>\n<pre><code class=\"kotlin\">val array = intArrayOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) for(index in array.size - 1 downTo 1 step 2) {   print(array[index]) }<\/code><\/pre>\n<p>The code above with result in\u00a0<code>97531<\/code>.<\/p>\n<h3>Remove Vowels from a String<\/h3>\n<p>It\u2019s a problem number\u00a0<a href=\"https:\/\/leetcode.com\/problems\/remove-vowels-from-a-string\/\" rel=\"noopener noreferrer nofollow\"><u>1119<\/u><\/a>\u00a0on Leetcode.<\/p>\n<blockquote>\n<p><em>Given a string\u00a0<\/em><code>S<\/code><em>, remove the vowels\u00a0<\/em><code>'a'<\/code><em>,\u00a0<\/em><code>'e'<\/code><em>,\u00a0<\/em><code>'i'<\/code><em>,\u00a0<\/em><code>'o'<\/code><em>, and\u00a0<\/em><code>'u'<\/code><em>\u00a0from it, and return the new string.<\/em><\/p>\n<\/blockquote>\n<p>Even in Java there is a 1 line regex solution, but my intuition was the following:<\/p>\n<ol>\n<li>\n<p>Create a StringBuilder.<\/p>\n<\/li>\n<li>\n<p>Iterate over characters, and if the current character is not a vowel, append it to the StringBuilder.<\/p>\n<\/li>\n<li>\n<p>Return String from the StringBuilder.<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"java\">public String removeVowels(String S) {   StringBuilder sb = new StringBuilder();     for(char s: S.toCharArray()) {     if(s != 'a' &amp;&amp; s != 'e' &amp;&amp; s != 'i' &amp;&amp; s !='o' &amp;&amp; s != 'u') {       sb.append(s);       }   }   return sb.toString(); }<\/code><\/pre>\n<p>What about Kotlin? More idiomatic way is to use\u00a0<code>filter()<\/code>\u00a0or\u00a0<code>filterNot()<\/code>.<\/p>\n<pre><code class=\"kotlin\">fun removeVowels(S: String): String {   val vowels = setOf('a', 'e', 'i', 'o', 'u')   return S.filter { it !in vowels } }<\/code><\/pre>\n<p><code>filter {predicate: (Char) -> Boolean}<\/code>\u00a0returns a string containing only those characters from the original string that match the given predicate.<\/p>\n<p>But instead of inverting\u00a0<code>!in<\/code>\u00a0let\u2019s use\u00a0<code>filterNot()<\/code><\/p>\n<pre><code class=\"kotlin\">fun removeVowels(S: String): String {   val vowels = setOf('a', 'e', 'i', 'o', 'u')   return S.filterNot { it in vowels } }<\/code><\/pre>\n<p>That was simple even for a beginner. Let\u2019s move on to something a bit more sophisticated.<\/p>\n<h3>Running Sum of 1d Array<\/h3>\n<p>It\u2019s another easy problem from Leetcode. Number\u00a0<a href=\"https:\/\/leetcode.com\/problems\/running-sum-of-1d-array\/\" rel=\"noopener noreferrer nofollow\"><u>1480<\/u><\/a>.<\/p>\n<blockquote>\n<p>Given an array\u00a0<code>nums<\/code>. We define a running sum of an array as\u00a0<code>runningSum[i] = sum(nums[0]\u2026nums[i])<\/code>. Return the running sum of\u00a0<code>nums<\/code>.<\/p>\n<p><strong>Input:<\/strong>\u00a0nums = [1,2,3,4]<br \/><strong>Output:<\/strong>\u00a0[1,3,6,10]<br \/><strong>Explanation:<\/strong>\u00a0Running sum is obtained as follows: [1, 1+2, 1+2+3, 1+2+3+4].<\/p>\n<\/blockquote>\n<p>So we need to iterate over the array, adding the value at the current index to the running sum, and put it to the same index in the result array.<\/p>\n<p>Is there something in Kotlin to help us with the running sum? Well, there\u2019s different variations of\u00a0<code>fold()<\/code>\u00a0and\u00a0<code>reduce()<\/code>\u00a0operations. Here\u2019s\u00a0<a href=\"https:\/\/stackoverflow.com\/questions\/44429419\/what-is-basic-difference-between-fold-and-reduce-in-kotlin-when-to-use-which\/44429568#44429568\" rel=\"noopener noreferrer nofollow\"><u>a good explanation<\/u><\/a>\u00a0of those functions. But since Kotlin 1.4 there\u2019s even more:\u00a0<code>runningFold()<\/code>\u00a0and\u00a0<code>runningReduce()<\/code>. As we want to start with the first element and return an array, it looks like\u00a0<code>runningReduce()<\/code>\u00a0is what we need. Let\u2019s check it\u2019s signature.<\/p>\n<pre><code class=\"kotlin\">\/**  * Returns a list containing successive accumulation values generated by applying [operation] from left to right  * to each element and current accumulator value that starts with the first element of this array.  *   * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value.  *   * @sample samples.collections.Collections.Aggregates.runningReduce  *\/ @SinceKotlin(\"1.4\") @kotlin.internal.InlineOnly public inline fun IntArray.runningReduce(operation: (acc: Int, Int) -> Int): List&lt;Int><\/code><\/pre>\n<p>Sounds a bit too complex, but it will make sense when you\u2019ll see an example.<\/p>\n<pre><code class=\"kotlin\">fun runningSum(nums: IntArray): IntArray {   return nums.runningReduce { sum, element -> sum + element }.toIntArray() }<\/code><\/pre>\n<p>This is the whole solution to the running sum problem using Kotlin\u00a0<code>runningReduce()<\/code>\u00a0function.\u00a0<code>sum<\/code>\u00a0starts with the first element in the array,\u00a0<code>element<\/code>\u00a0represens the current element. In lambda, we calculate the value of the next\u00a0<code>sum<\/code>. Oh\u2026 I guess my explanation isn\u2019t making it more clear that a doc. Let\u2019s just print out the values of the\u00a0<code>sum<\/code>\u00a0and the\u00a0<code>element<\/code>\u00a0at each step:<\/p>\n<p><code>sum: 1; element: 2; sum + element: 3sum: 3; element: 3; sum + element: 6sum: 6; element: 4; sum + element: 10sum: 10; element: 5; sum + element: 15<\/code><\/p>\n<p>And the array we return is\u00a0<code>[1, 3, 6, 10, 15]<\/code>. There is no\u00a0<code>sum + element: 1<\/code>, I didn\u2019t miss the line. The thing is that\u00a0<code>runningReduce<\/code>, as we see in the doc, takes the first value as the initial accumulator.<\/p>\n<p>Unfortunately, Leetcode doesn\u2019t support Kotlin 1.4 yet, so the code above might not compile.<\/p>\n<h3>Most Common Word<\/h3>\n<p>Easy Leetcode problem, number\u00a0<a href=\"https:\/\/leetcode.com\/problems\/most-common-word\/\" rel=\"noopener noreferrer nofollow\"><u>819<\/u><\/a>.<\/p>\n<blockquote>\n<p><em>Given a paragraph and a list of banned words, return the most frequent word that is not in the list of banned words. It is guaranteed there is at least one word that isn\u2019t banned, and that the answer is unique.<\/em><\/p>\n<p><strong><em>Input:<\/em><\/strong><em><br \/>paragraph = &#171;Bob hit a ball, the hit BALL flew far after it was hit.&#187;<br \/>banned = [&#171;hit&#187;]<br \/><\/em><strong><em>Output:<\/em><\/strong><em>\u00a0&#171;ball&#187;<\/em><\/p>\n<\/blockquote>\n<p>What are the steps to solve it?<\/p>\n<ol>\n<li>\n<p>Convert string to lower case and split by words.<\/p>\n<\/li>\n<\/ol>\n<p><code>[bob, hit, a, ball, the, hit, ball, flew, far, after, it, was, hit]<\/code><\/p>\n<p>2. Create a set of banned words.<\/p>\n<p><code>[hit]<\/code><\/p>\n<p>3. Create a map of words to their occurrence, excluding the banned words.<\/p>\n<p><code>{bob=1, a=1, ball=2, the=1, flew=1, far=1, after=1, it=1, was=1}<\/code><\/p>\n<p>4. Return word with the highest number of occurrences from the map.<\/p>\n<p><code>ball<\/code><\/p>\n<p>Let\u2019s implement those 4 steps in Java.<\/p>\n<pre><code class=\"java\">public String mostCommonWord(String paragraph, String[] banned) {   \/\/ 1. Covert string to lower case and split by words.   String[] words = paragraph.replaceAll(\"[^a-zA-Z0-9 ]\", \" \").toLowerCase().split(\"\\\\s+\");    \/\/ 2. Create a set of banned words.   Set&lt;String> bannedWords = new HashSet();   for (String word : banned)     bannedWords.add(word);    \/\/ 3. Create a map of words to their occurrence, excluding the banned words   Map&lt;String, Integer> wordCount = new HashMap();   for (String word : words) {     if (!bannedWords.contains(word))       wordCount.put(word, wordCount.getOrDefault(word, 0) + 1);   }    \/\/ 4. Return word with the highest number of occurrences from the map.   return Collections.max(wordCount.entrySet(), Map.Entry.comparingByValue()).getKey(); }<\/code><\/pre>\n<p>And the same 4 steps in Kotlin.<\/p>\n<pre><code class=\"kotlin\">fun mostCommonWord(paragraph: String, banned: Array&lt;String>): String {   \/\/ 1. Covert string to lower case and split by words.   val words = paragraph.toLowerCase().split(\"\\\\W+|\\\\s+\".toRegex())   \/\/ 2. Create a set of banned words.   val bannedSet = banned.toHashSet()   \/\/ 3. Create a map of words to their occurrence, excluding the banned words   val wordToCount = words.filterNot { it in bannedSet }.groupingBy { it }.eachCount()   \/\/ 4. Return word with the highest number of occurrences from the map.   return wordToCount.maxBy { it.value }!!.key }<\/code><\/pre>\n<p>Now let\u2019s go through the functions to see what is happening here.<\/p>\n<ol>\n<li>\n<p>We split the string into\u00a0<code>words: List&lt;String><\/code>. The type is inferred.<\/p>\n<\/li>\n<li>\n<p>Converting\u00a0<code>banned: Array&lt;String><\/code> to\u00a0<code>HashSet<\/code>\u00a0to make\u00a0<code>in<\/code>\u00a0checks in O(1) time<\/p>\n<\/li>\n<li>\n<p>In this step, we chain 3 function calls. First, we use\u00a0<code>filterNot()<\/code>\u00a0to filter out banned words.\u00a0<code>filterNot { it in banned }<\/code>\u00a0will return a\u00a0<code>List&lt;String><\/code>\u00a0that contains only those strings that are not in the\u00a0<code>banned<\/code>\u00a0array. Unlike\u00a0<code>groupBy()<\/code>\u00a0that returns a map,\u00a0<code>groupingBy()<\/code>\u00a0returns an object of\u00a0<code>Grouping<\/code>\u00a0type, that could be used later with one of group-and-fold operations. We use\u00a0<code>it<\/code>\u00a0in\u00a0<code>groupingBy()<\/code>\u00a0lambda. This means that we are grouping by the current element (word) in the collection. In other words \u2014 we create a map, where the key is a word, and the value is a count of occurrences of the word. To get the number of occurrences we use\u00a0<code>eachCount()<\/code>\u00a0on the\u00a0<code>Grouping.<\/code><\/p>\n<\/li>\n<li>\n<p>We use\u00a0<code>maxBy<\/code>\u00a0function to get the first largest element in the map, by\u00a0<code>value<\/code>. This returns us an object of\u00a0<code>Map.Entry&lt;String, Int>?<\/code>, e.g.\u00a0<code>ball = 2<\/code>. And we return a key, which is the most common word in the sentence.<\/p>\n<\/li>\n<\/ol>\n<h3>Order of elements<\/h3>\n<p>When you create a set <code>setOf(\u201ca\u201d, \u201cb\u201d, \u201cc\u201d)<\/code>\u00a0or converting array to set using\u00a0<code>arrayOf(\u201ca\u201d, \u201cb\u201d, \u201cc\u201d).toSet()<\/code>\u00a0the returned set is\u00a0<code>LinkedHashSet<\/code>\u00a0and therefore element iteration order is preserved.<\/p>\n<p>The same is true about maps<\/p>\n<p><code>mapOf(Pair(\u201ca\u201d, 1), Pair(\u201cb\u201d, 2))<\/code><\/p>\n<p><code>arrayOf&lt;\/em>(Pair(\u201ca\u201d, 1), Pair(\u201cb\u201d, 2)).toMap()<\/code><\/p>\n<p>Both functions will return an instance of\u00a0<code>LinkedHashMap<\/code>\u00a0that keeps preserves the original element order. Knowing it might be helpful when solving problems.<\/p>\n<p>I have covered just a few of all available collection functions in Kotlin. There\u2019s\u00a0<code>map<\/code>,\u00a0<code>flatMap<\/code>,\u00a0<code>count<\/code>,\u00a0<code>find<\/code>,\u00a0<code>sum<\/code>\u00a0and much more!<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/526384\/\"> https:\/\/habr.com\/ru\/articles\/526384\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>(originally published on <a href=\"https:\/\/proandroiddev.com\/solving-coding-problems-with-kotlin-collection-functions-3d2b1ef7fe2c\" rel=\"noopener noreferrer nofollow\">Medium<\/a>)<\/p>\n<p>I have talked to many Android developers, and most of them are excited about Kotlin. So am I. When I just started learning Kotlin, I was solving\u00a0<a href=\"https:\/\/kotlinlang.org\/docs\/tutorials\/koans.html\" rel=\"noopener noreferrer nofollow\"><u>Kotlin Koans<\/u><\/a>, and along with other great features, I was impressed with the power of functions for performing operations on collections. Since then, I spent three years writing Kotlin code but rarely utilised all the potential of the language.<\/p>\n<p>During this year, I did more than a hundred coding problems on Leetcode in Java. I didn\u2019t switch to Kotlin because I know the syntax of Java 6 so well, that I could effortlessly write code without autocompletion and syntax highlighting. But I didn\u2019t keep track of new Java features, as Android support of Java SDK lagged many versions behind. I didn\u2019t switch to Kotlin for solving problems right away. <\/p>\n<p>Although I was writing Kotlin code for several years, I felt that I need to make an extra cognitive effort to get the syntax and the language constructions right. Solving algorithmic problems, especially under the time pressure, is very different from Android app development. Still, the more I learned about Kotlin, the more I realised how many powerful features I\u2019m missing, and how much boilerplate code I need to write.<\/p>\n<p>One day, I have decided that I need to move on, so I started a new session in Leetcode and switched the compiler to Kotlin. I solved just a few easy problems, but I already feel that I have something to share.<\/p>\n<h3>Loops<\/h3>\n<p>Let\u2019s start with loops. Let\u2019s say, you have an\u00a0<code>IntArray<\/code>\u00a0of 10 elements\u00a0<code>0, 1, 2, 3, 4, 5, 6, 7, 8, 9<\/code>\u00a0and you want to print\u00a0<code>123456789<\/code>.<\/p>\n<pre><code class=\"kotlin\">val array = intArrayOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) for(index in (1 until array.size)) {   print(array[index]) }<\/code><\/pre>\n<p><code>(1 until array.size)<\/code>\u00a0is an\u00a0<code>IntRange<\/code>, a class that represents a range of values of type\u00a0<code>Int<\/code>. The first element in this range is\u00a0<code>1<\/code>\u00a0and the last one is\u00a0<code>9<\/code>\u00a0as we used\u00a0<code>until<\/code>\u00a0to exclude the last value. We don\u2019t want to get\u00a0<code>ArrayIndexOutOfBoundsException<\/code>\u00a0right?<\/p>\n<p>But what if we want to print all the elements of the array, except the element at index 5? Like this\u00a0<code>012346789<\/code>. Let\u2019s get a bit more Kotliney then writing an\u00a0<code>if<\/code>\u00a0statement in the loop.<\/p>\n<pre><code class=\"kotlin\">val array = intArrayOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) for(index in array.indices - 5) {   print(array[index]) }<\/code><\/pre>\n<p><code>array.indices<\/code>\u00a0returns the range of valid indices for the array. In this case\u00a0<code>array.indices<\/code>\u00a0represent\u00a0<code>IntRange<\/code>\u00a0of\u00a0<code>(0..9)<\/code>. Making\u00a0<code>(0..9) - 5<\/code>\u00a0will result in\u00a0<code>[0, 1, 2, 3, 4, 6, 7, 8, 9]<\/code>. This is exactly what we need.<\/p>\n<p>Kotlin also provides an ability to iterate from the greater number down to the smaller number using\u00a0<code>downTo<\/code>. The iteration step size can also be changed using\u00a0<code>step<\/code>.<\/p>\n<pre><code class=\"kotlin\">val array = intArrayOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) for(index in array.size - 1 downTo 1 step 2) {   print(array[index]) }<\/code><\/pre>\n<p>The code above with result in\u00a0<code>97531<\/code>.<\/p>\n<h3>Remove Vowels from a String<\/h3>\n<p>It\u2019s a problem number\u00a0<a href=\"https:\/\/leetcode.com\/problems\/remove-vowels-from-a-string\/\" rel=\"noopener noreferrer nofollow\"><u>1119<\/u><\/a>\u00a0on Leetcode.<\/p>\n<blockquote>\n<p><em>Given a string\u00a0<\/em><code>S<\/code><em>, remove the vowels\u00a0<\/em><code>'a'<\/code><em>,\u00a0<\/em><code>'e'<\/code><em>,\u00a0<\/em><code>'i'<\/code><em>,\u00a0<\/em><code>'o'<\/code><em>, and\u00a0<\/em><code>'u'<\/code><em>\u00a0from it, and return the new string.<\/em><\/p>\n<\/blockquote>\n<p>Even in Java there is a 1 line regex solution, but my intuition was the following:<\/p>\n<ol>\n<li>\n<p>Create a StringBuilder.<\/p>\n<\/li>\n<li>\n<p>Iterate over characters, and if the current character is not a vowel, append it to the StringBuilder.<\/p>\n<\/li>\n<li>\n<p>Return String from the StringBuilder.<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"java\">public String removeVowels(String S) {   StringBuilder sb = new StringBuilder();     for(char s: S.toCharArray()) {     if(s != 'a' &amp;&amp; s != 'e' &amp;&amp; s != 'i' &amp;&amp; s !='o' &amp;&amp; s != 'u') {       sb.append(s);       }   }   return sb.toString(); }<\/code><\/pre>\n<p>What about Kotlin? More idiomatic way is to use\u00a0<code>filter()<\/code>\u00a0or\u00a0<code>filterNot()<\/code>.<\/p>\n<pre><code class=\"kotlin\">fun removeVowels(S: String): String {   val vowels = setOf('a', 'e', 'i', 'o', 'u')   return S.filter { it !in vowels } }<\/code><\/pre>\n<p><code>filter {predicate: (Char) -> Boolean}<\/code>\u00a0returns a string containing only those characters from the original string that match the given predicate.<\/p>\n<p>But instead of inverting\u00a0<code>!in<\/code>\u00a0let\u2019s use\u00a0<code>filterNot()<\/code><\/p>\n<pre><code class=\"kotlin\">fun removeVowels(S: String): String {   val vowels = setOf('a', 'e', 'i', 'o', 'u')   return S.filterNot { it in vowels } }<\/code><\/pre>\n<p>That was simple even for a beginner. Let\u2019s move on to something a bit more sophisticated.<\/p>\n<h3>Running Sum of 1d Array<\/h3>\n<p>It\u2019s another easy problem from Leetcode. Number\u00a0<a href=\"https:\/\/leetcode.com\/problems\/running-sum-of-1d-array\/\" rel=\"noopener noreferrer nofollow\"><u>1480<\/u><\/a>.<\/p>\n<blockquote>\n<p>Given an array\u00a0<code>nums<\/code>. We define a running sum of an array as\u00a0<code>runningSum[i] = sum(nums[0]\u2026nums[i])<\/code>. Return the running sum of\u00a0<code>nums<\/code>.<\/p>\n<p><strong>Input:<\/strong>\u00a0nums = [1,2,3,4]<br \/><strong>Output:<\/strong>\u00a0[1,3,6,10]<br \/><strong>Explanation:<\/strong>\u00a0Running sum is obtained as follows: [1, 1+2, 1+2+3, 1+2+3+4].<\/p>\n<\/blockquote>\n<p>So we need to iterate over the array, adding the value at the current index to the running sum, and put it to the same index in the result array.<\/p>\n<p>Is there something in Kotlin to help us with the running sum? Well, there\u2019s different variations of\u00a0<code>fold()<\/code>\u00a0and\u00a0<code>reduce()<\/code>\u00a0operations. Here\u2019s\u00a0<a href=\"https:\/\/stackoverflow.com\/questions\/44429419\/what-is-basic-difference-between-fold-and-reduce-in-kotlin-when-to-use-which\/44429568#44429568\" rel=\"noopener noreferrer nofollow\"><u>a good explanation<\/u><\/a>\u00a0of those functions. But since Kotlin 1.4 there\u2019s even more:\u00a0<code>runningFold()<\/code>\u00a0and\u00a0<code>runningReduce()<\/code>. As we want to start with the first element and return an array, it looks like\u00a0<code>runningReduce()<\/code>\u00a0is what we need. Let\u2019s check it\u2019s signature.<\/p>\n<pre><code class=\"kotlin\">\/**  * Returns a list containing successive accumulation values generated by applying [operation] from left to right  * to each element and current accumulator value that starts with the first element of this array.  *   * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value.  *   * @sample samples.collections.Collections.Aggregates.runningReduce  *\/ @SinceKotlin(\"1.4\") @kotlin.internal.InlineOnly public inline fun IntArray.runningReduce(operation: (acc: Int, Int) -> Int): List&lt;Int><\/code><\/pre>\n<p>Sounds a bit too complex, but it will make sense when you\u2019ll see an example.<\/p>\n<pre><code class=\"kotlin\">fun runningSum(nums: IntArray): IntArray {   return nums.runningReduce { sum, element -> sum + element }.toIntArray() }<\/code><\/pre>\n<p>This is the whole solution to the running sum problem using Kotlin\u00a0<code>runningReduce()<\/code>\u00a0function.\u00a0<code>sum<\/code>\u00a0starts with the first element in the array,\u00a0<code>element<\/code>\u00a0represens the current element. In lambda, we calculate the value of the next\u00a0<code>sum<\/code>. Oh\u2026 I guess my explanation isn\u2019t making it more clear that a doc. Let\u2019s just print out the values of the\u00a0<code>sum<\/code>\u00a0and the\u00a0<code>element<\/code>\u00a0at each step:<\/p>\n<p><code>sum: 1; element: 2; sum + element: 3sum: 3; element: 3; sum + element: 6sum: 6; element: 4; sum + element: 10sum: 10; element: 5; sum + element: 15<\/code><\/p>\n<p>And the array we return is\u00a0<code>[1, 3, 6, 10, 15]<\/code>. There is no\u00a0<code>sum + element: 1<\/code>, I didn\u2019t miss the line. The thing is that\u00a0<code>runningReduce<\/code>, as we see in the doc, takes the first value as the initial accumulator.<\/p>\n<p>Unfortunately, Leetcode doesn\u2019t support Kotlin 1.4 yet, so the code above might not compile.<\/p>\n<h3>Most Common Word<\/h3>\n<p>Easy Leetcode problem, number\u00a0<a href=\"https:\/\/leetcode.com\/problems\/most-common-word\/\" rel=\"noopener noreferrer nofollow\"><u>819<\/u><\/a>.<\/p>\n<blockquote>\n<p><em>Given a paragraph and a list of banned words, return the most frequent word that is not in the list of banned words. It is guaranteed there is at least one word that isn\u2019t banned, and that the answer is unique.<\/em><\/p>\n<p><strong><em>Input:<\/em><\/strong><em><br \/>paragraph = &#171;Bob hit a ball, the hit BALL flew far after it was hit.&#187;<br \/>banned = [&#171;hit&#187;]<br \/><\/em><strong><em>Output:<\/em><\/strong><em>\u00a0&#171;ball&#187;<\/em><\/p>\n<\/blockquote>\n<p>What are the steps to solve it?<\/p>\n<ol>\n<li>\n<p>Convert string to lower case and split by words.<\/p>\n<\/li>\n<\/ol>\n<p><code>[bob, hit, a, ball, the, hit, ball, flew, far, after, it, was, hit]<\/code><\/p>\n<p>2. Create a set of banned words.<\/p>\n<p><code>[hit]<\/code><\/p>\n<p>3. Create a map of words to their occurrence, excluding the banned words.<\/p>\n<p><code>{bob=1, a=1, ball=2, the=1, flew=1, far=1, after=1, it=1, was=1}<\/code><\/p>\n<p>4. Return word with the highest number of occurrences from the map.<\/p>\n<p><code>ball<\/code><\/p>\n<p>Let\u2019s implement those 4 steps in Java.<\/p>\n<pre><code class=\"java\">public String mostCommonWord(String paragraph, String[] banned) {   \/\/ 1. Covert string to lower case and split by words.   String[] words = paragraph.replaceAll(\"[^a-zA-Z0-9 ]\", \" \").toLowerCase().split(\"\\\\s+\");    \/\/ 2. Create a set of banned words.   Set&lt;String> bannedWords = new HashSet();   for (String word : banned)     bannedWords.add(word);    \/\/ 3. Create a map of words to their occurrence, excluding the banned words   Map&lt;String, Integer> wordCount = new HashMap();   for (String word : words) {     if (!bannedWords.contains(word))       wordCount.put(word, wordCount.getOrDefault(word, 0) + 1);   }    \/\/ 4. Return word with the highest number of occurrences from the map.   return Collections.max(wordCount.entrySet(), Map.Entry.comparingByValue()).getKey(); }<\/code><\/pre>\n<p>And the same 4 steps in Kotlin.<\/p>\n<pre><code class=\"kotlin\">fun mostCommonWord(paragraph: String, banned: Array&lt;String>): String {   \/\/ 1. Covert string to lower case and split by words.   val words = paragraph.toLowerCase().split(\"\\\\W+|\\\\s+\".toRegex())   \/\/ 2. Create a set of banned words.   val bannedSet = banned.toHashSet()   \/\/ 3. Create a map of words to their occurrence, excluding the banned words   val wordToCount = words.filterNot { it in bannedSet }.groupingBy { it }.eachCount()   \/\/ 4. Return word with the highest number of occurrences from the map.   return wordToCount.maxBy { it.value }!!.key }<\/code><\/pre>\n<p>Now let\u2019s go through the functions to see what is happening here.<\/p>\n<ol>\n<li>\n<p>We split the string into\u00a0<code>words: List&lt;String><\/code>. The type is inferred.<\/p>\n<\/li>\n<li>\n<p>Converting\u00a0<code>banned: Array&lt;String><\/code> to\u00a0<code>HashSet<\/code>\u00a0to make\u00a0<code>in<\/code>\u00a0checks in O(1) time<\/p>\n<\/li>\n<li>\n<p>In this step, we chain 3 function calls. First, we use\u00a0<code>filterNot()<\/code>\u00a0to filter out banned words.\u00a0<code>filterNot { it in banned }<\/code>\u00a0will return a\u00a0<code>List&lt;String><\/code>\u00a0that contains only those strings that are not in the\u00a0<code>banned<\/code>\u00a0array. Unlike\u00a0<code>groupBy()<\/code>\u00a0that returns a map,\u00a0<code>groupingBy()<\/code>\u00a0returns an object of\u00a0<code>Grouping<\/code>\u00a0type, that could be used later with one of group-and-fold operations. We use\u00a0<code>it<\/code>\u00a0in\u00a0<code>groupingBy()<\/code>\u00a0lambda. This means that we are grouping by the current element (word) in the collection. In other words \u2014 we create a map, where the key is a word, and the value is a count of occurrences of the word. To get the number of occurrences we use\u00a0<code>eachCount()<\/code>\u00a0on the\u00a0<code>Grouping.<\/code><\/p>\n<\/li>\n<li>\n<p>We use\u00a0<code>maxBy<\/code>\u00a0function to get the first largest element in the map, by\u00a0<code>value<\/code>. This returns us an object of\u00a0<code>Map.Entry&lt;String, Int>?<\/code>, e.g.\u00a0<code>ball = 2<\/code>. And we return a key, which is the most common word in the sentence.<\/p>\n<\/li>\n<\/ol>\n<h3>Order of elements<\/h3>\n<p>When you create a set <code>setOf(\u201ca\u201d, \u201cb\u201d, \u201cc\u201d)<\/code>\u00a0or converting array to set using\u00a0<code>arrayOf(\u201ca\u201d, \u201cb\u201d, \u201cc\u201d).toSet()<\/code>\u00a0the returned set is\u00a0<code>LinkedHashSet<\/code>\u00a0and therefore element iteration order is preserved.<\/p>\n<p>The same is true about maps<\/p>\n<p><code>mapOf(Pair(\u201ca\u201d, 1), Pair(\u201cb\u201d, 2))<\/code><\/p>\n<p><code>arrayOf&lt;\/em>(Pair(\u201ca\u201d,<\/code><\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-394108","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/394108","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=394108"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/394108\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=394108"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=394108"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=394108"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}