Sunday, March 27, 2016

HackerRank: Sherlock and anagrams (V)

March 27, 2016

Problem statement:

Difficulty: Moderate

More C# solution:

Solution 1:
Julia, here is code you  should study; more advanced than yours.

a person works for Box Inc.
https://www.hackerrank.com/__run
https://gist.github.com/jianminchen/576ecf2cd127a703cb7a

Learn C# coding: readonly, Equals, override, constructor, use byte instead of int. Take some time off, learn C#, OO design basics:

Here are the code, make some comments to read some articles to catch up:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SherlockAndAnagrams
{
    class CharCount
    {
        protected bool Equals(CharCount other)
        {
            return Equals(Array, other.Array);
        }

        /*
             Design concern:
             hashcode for anagram strings - same 
             
             use unchecked function
             figure out this design: 
             a                         b                c           ...   y               z
             3                         1                                   1               1
             3*(26*13)^25        1*(26*13)^24                 1*(26*13)    1
        */
        public override int GetHashCode()
        {
            int hc = Array.Length;
            for (int i = 0; i < Array.Length; ++i)
            {
                hc = unchecked(hc * 13 + Array[i]);  // Julia, figure out how this hashcode is working for anagram
            }
            return hc;
        }

        public readonly byte[] Array;   // Julia, readonly, why to use byte[] 

        public CharCount()
        {
            Array = new byte[26];
        }

        public CharCount(CharCount charCount)
        {
            Array = new byte[26];
            for (int i = 0; i < 26; i++)
            {
                Array[i] = charCount.Array[i];
            }
        }

        public void AddChar(char ch)  // 
        {
            Array[ch - 'a']++;
        }

        public override bool Equals(object obj)  // override Equals function 
        {
            CharCount other = obj as CharCount;
            if (obj == null)
            {
                return false;
            }

            for (int i = 0; i < 26; i++)
            {
                int val = Array[i].CompareTo(other.Array[i]);  // byte.CompareTo 
                if (val != 0)
                {
                    return false;
                }
            }

            return true;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            int t = int.Parse(Console.ReadLine());
            for (int i = 0; i < t; i++)
            {
                HandleTestCase();
            }
        }

        private static void HandleTestCase()
        {
            IDictionary<CharCount, int> dictionary = new Dictionary<CharCount, int>();
            string str = Console.ReadLine();

            for (int i = 0; i < str.Length; i++)
            {
                CharCount charCount = new CharCount();
                for (int j = i; j < str.Length; j++)
                {
                    charCount.AddChar(str[j]);
                    if (!dictionary.ContainsKey(charCount))
                    {
                        dictionary.Add(new CharCount(charCount), 1);
                    }
                    else
                    {
                        dictionary[charCount] = dictionary[charCount] + 1;
                    }
                }
            }

            Console.WriteLine(dictionary.Values.Sum(value => ((value * (value - 1)) / 2)));
        }
    }

}


HackerRank: Sherlock and Anagrams IV

March 27, 2016

Problem statement:

Difficulty: Moderate

More C# solution:

Solution 1:
Julia, here is code you  should study; more advanced than yours.

a person works for Box Inc.
https://www.hackerrank.com/__run
https://gist.github.com/jianminchen/576ecf2cd127a703cb7a

Learn C# coding: readonly, Equals, override, constructor, use byte instead of int.

Solution 2:
use Dictionary class, string key for anagram string, use getHashCode() call to turn key as Int.

https://gist.github.com/jianminchen/ffcca0582b5f0d1d6a9b

Read about getHashCode() webpage:
https://msdn.microsoft.com/en-us/library/system.object.gethashcode(v=vs.110).aspx

Solution 3:
https://gist.github.com/jianminchen/8f6bd4631f0b5f0bdee7


Solution 4.
use Dictionary class, sort the key string, then anagram strings will be the same.

https://gist.github.com/jianminchen/59e326cbd1d8910c01c7

solution 5:
Excellent code, written by a programmer in salesforce.com
https://www.hackerrank.com/rest/contests/w13/challenges/sherlock-and-anagrams/hackers/rosharyg/download_solution
Julia likes the code:

https://gist.github.com/jianminchen/d2ccf6532524d8751c73

Solution 6:   <-  simple and quick, it can be written in less than 20 minutes. But not time efficient! O(n^2 * string length)

Use brute force, 3 loops, and then define anagramChecking function, just basic array, simple and quick.

https://gist.github.com/jianminchen/9f381875942d468ccb00









HackerRank: Sherlock and anagrams (II)

March 27, 2016

Problem statement:

Difficulty: Moderate

Summary of practice

This problem solving gets hot. Julia found something she struggled a lot. When Julia spent more than 2 hours on a problem in the Saturday evening, she knew that she is in trouble. She needs to be trained, and she needs a mentor.

Time Spent: March 26, 2016  Saturday evening 9:30 - 11:30
                                               Sunday morning  9:00 - 12:00 

Julia's practice is here.

Code Study

Let us get ideas how other people solve the problems, study the code. Julia is training herself thinking in C# using HackerRank:

1. Hash function design 

code source is provided by a person 19 Gold, unbelievable smart and quick/ fast / great expressive code. 


Code study - code is here

The anagram string function is composed to the design of key in the Dictionary. 

Julia added some comment above the hash function 

/*
precondition:
if two string are anagram, then key of these two strings should be the same

"ab" and "ba" are the anagram, key should be the same
"ab" and "bc" are not the anagram, so keys should not be the same.

Julia's comment: 701 is confusing, why it has to be this big number?
*/

int Fun(string s, int l, int r)
    {
        var ret = new int[26];
        for (int i = l; i <= r; i++)
            ret[s[i] - 'a']++;

        int x = 0;                  // Julia's comment: should be 1  
        for (int i = 0; i < 26; i++)
            x = x * 701 + ret[i];

        return x;
    }

Julia goes over the detail to check: 

Key is designed using math formula polynomial expression:
string a -> key is integer:  0
string b -> key:   1
string ab -> key:  x = 1
                            x =  1* 701 + 1
string ba -> 11 ->  key:  x = 1 * 701 + 1
string bc -> 011-> key:  x = 0 ,  count of a is 0
                             x = 1,   count of b is 1
                             x = 1 * 701 + 1
"ba" and "bc" are not anagram, so the key should be different: both are 1 * 701 + 1

string ad -> 1001 -> key x  = 1,               count of a is 1
                                        x = 701 + 0 ,    count of b is 0
                                        x = 701 *701 + 0
                               key = 701^3 + 1

Math or computer science

Julia found out that the idea can save a lot of time, she likes to work hard. But she is also "lazy" and likes to write less code. 

Julia changed the key design, and ran the code in HackerRank, it also passed the test cases. In Julia's opinion, the code has a bug in theory but pass the HackerRank test; so, Julia fixed the code anyway. 


Just practice! It is not a science of math, it is computer science. 

C# practice code is here.

Further code review on other things

Julia is still interested in writing loops, more expressive. Let us review how the code does:

public object Solve()
{
        for (int tt = ReadInt(); tt > 0; tt--)  // Julia's comment: put ReadInt() into a loop
        {
            string s = ReadToken();
            int n     = s.Length;
            int ans = 0;
            var count = new Dictionary<int, int>();

            // Julia's comment: substring length from 1 to n-1,
            for (int i = 1; i < n; i++)  
            {
                // substring start position - j, end position: j+i-1, and check j+i <=n, easy to reason - avoid bug
                for (int j = 0; j + i <= n; j++) 
                {
                    var key = Fun(s, j, j + i - 1);
                    if ( !count.ContainsKey(key) )
                    {
                        count[key] = 0;
                    }

                    count[key]++;
                }
            }

            foreach (var p in count)
            {
                ans += p.Value * (p.Value - 1) / 2;
            }

            writer.WriteLine(ans);
        }

        return null;
    }

701 prime number vs 26

One more step, improvement:  Failed. Number from 701 to 26, it does not work. It depends on the length of string, which is <=100. Julia tried to figure out some math, algebra, but she is sure that the number should be coefficient, so, 
at least >100. 

Julia, the key design for anagram string can be modified:  
/*
precondition:
if two string are anagram, then key of these two string should be the same

"ab" and "ba" are the anagram, key should be the same

"ab" and "bc" are not the anagram, so key should not be the same.

*/
int keyForAnagramString(string s, int l, int r)
{
        var ret = new int[26];
        for (int i = l; i <= r; i++)
            ret[s[i] - 'a']++;

        int x = 1;                  // Julia's comment: should be 1  

        for (int i = 0; i < 26; i++)
        {
            x = x * 26 + ret[i];
        }

        return x;
}

Julia spent 5 hacko to buy the test case input/ output


One more try - 101 

Because the string length is <=100, so that coefficient is less than 100.

Key design can be changed to a small number 701 to 101, it passes the HackerRank test:

/*
precondition:
if two string are anagram, then key of these two string should be the same

"ab" and "ba" are the anagram, key should be the same
"ab" and "bc" are not the anagram, so key should not be the same.
*/
int keyForAnagramString(string s, int l, int r)
{
        var ret = new int[26];
        for (int i = l; i <= r; i++)
            ret[s[i] - 'a']++;

        int x = 1;                  // Julia's comment: should be 1  

        for (int i = 0; i < 26; i++)
        {
            x = x * 101 + ret[i];
        }

        return x;
}

January 8, 2017

Come back to visit the blog, and then spent 10 - 20 minutes to work on layout, fixed grammar errors. 

HackerRank: Sherlocks and Anagram (III)

March 27, 2016

Problem statement:

Difficulty: Moderate

This problem solving gets hot. Julia found something she struggled a lot. When Julia spent more than 2 hours on a problem in the Saturday evening, she knew that she is in trouble. She needs to be trained, and she needs a mentor.



Solution to study:

https://gist.github.com/jianminchen/68453786a6ea03774a16

Julia, you should warm up with C# Dictionary<string, int>, and also StringBuilder class, AppendFormat function.

Let us review how to design anagram key more efficient, more understandable way:

/*
Think about how smart and easy it is to design this key for anagram string.

Precondition:
if two strings are anagram, the key should be same.
if two strings are not anagram, the key should be different.

Test case:
ab, the key is {0}-1{1}-1
ba, the key is {0}-1{1}-1,
but
bc, the key is {0}-0{1}-1{2}-1

compare to the design of anagram key using integer, this one is much easy to understand and follow.

http://juliachencoding.blogspot.ca/2016/03/hackerrank-string-sherlock-and-anagrams.html
*/
static string GiveKey(int[] arr){
        StringBuilder sb = new StringBuilder();
        for(int i = 0 ; i < 26 ; i++){
            sb.AppendFormat("{0}-",arr[i]);
        }
        return sb.ToString();
    }




HackerRank: String - Sherlock and anagrams (I)

March 27, 2016

Problem statement:

Difficulty: Moderate

This problem solving gets hot. Julia found something she struggled a lot. When Julia spent more than 2 hours on a problem in the Saturday evening, she knew that she is in trouble. She needs to be trained, and she needs a mentor.

Time Spent: March 26, 2016 Saturday evening 9:30 - 11:30
                                               Sunday morning  9:00 - 12:00 
Several mistakes to fix:
1. Julia, improve your analysis on test cases from HackerRank
2. Julia, understand Anagram requirement.
3. loop index issues

Julia's practice:

Go over test case again:
1. abba,

Let's say S[i, j] denotes the substring(i, j-i+1)
S[0,1] = "ab",
S[0,2]="abb",
S[1,1] = "b"
S[4,4] = "b"
S[1,2] = "ab"
S[3,4] = "ba"

For S = abba, anagrammatic pairs are:

{S[1,1], S[4,4]},     //
{S[1,2], S[3,4]},
{S{2,2], S{3,3]},
{S[1,3], S[2,4]}

Notice that substring can be selected by first char of string, choice of n-m, n is string length, m is substring length.

substrings can be overlapped, but still are anagrammatic pairs.
S[1,3] and S[2,4] are overlapped, but are the anagrammatic pair.

Sample test case "abba", output should be 4, but Julia got 3. Spent time to fix index error.

2. sample case: ifailuhkqq
should be: 3
Julia got 4
Actually, Julia, you should simplify the test case first.
it is the same as ifailqq,
also it is the same as ifilqq

How many anagramammatic pairs in "ifilqq"
"i","i" - S[1, 1] and S[3,3]
"if","fi" - S[1, 2] and S[2,3] <- warm up anagram definition: same chars with same counts
"q", "q"
but 2 'i' char in the string "ifilq",
  1 'i' char in the string "filqq",

Actually, the test case can be simplified using:
"abacdd", the pairs are (a,a), (ab, ba), (d,  d). That is very simple and understandable! 
"abacd" and "bacdd" are not anagrams, because two 'a' in first string, but 1 a in second string
so two strings are not anagram.

Julia, what you spent time on:
1. List<int> constructor issue - 10 minutes, List<int>(i)
2. 10 minutes to figure out that you should work on anagrams strings 
3. 10 minutes to write, 15 minutes to debug - Wrote a wrong anagram function
"ifilq" is not an anagram of "filqq", sample test case No. 2 should be 3

Julia is not very strong on testing software, she writes the software and puts it on. The software 
she writes can be improved tremendously, but she needs to find out what to improve. 

To be continued. 

Friday, March 25, 2016

HackerRank: Two string - thinking in Java

March 25, 2016

Read other people's ideas. Understand other people by reading their code. Julia likes to read some Java programming language code for 1-2 hours, she came cross people's code, amazed by ideas from people working in Facebook, Amazon, and amazed that people have GOLD prize on HackerRank.

Julia likes to be able to write very readable, most understandable code with shortest time as possible.

problem statement:

https://www.hackerrank.com/challenges/two-strings

Here are a few Java solution she likes:

Solution 1:
https://gist.github.com/jianminchen/6f029bb909ed7d85c012

Solution 2:
source code reference: 
https://www.hackerrank.com/winger

People like to use bit operation, most likely they are expert and then have some Gold in HackerRank. 

bit operation
https://gist.github.com/jianminchen/3d2acf64725cd73c79db


use one integer to store 26 characters, 1 bit one char from a to z.

private static int f(String a) {
        int r = 0;
        for (char c : a.toCharArray()) {
            r |= 1 << (c - 'a');    // Julia's comment: 1 left shift (c-'a') times 
        }
        return r;
    }

Solution 3:

https://gist.github.com/jianminchen/ff846e884ef9e9e2856a

Solution 4:

It is interesting to read InputStream, need to warm up on Java class

https://gist.github.com/jianminchen/21ffc64093fd5952647c

Solution 5:
use HashSet, Set, Character, String classes
https://gist.github.com/jianminchen/1eb02a940f7fa4b6a3f7


Leetcode 33: Search in sorted rotated array

March 23, 2016

understand the algorithm - good analysis graph in the following blog:
http://fisherlei.blogspot.ca/2013/01/leetcode-search-in-rotated-sorted-array.html


using this analysis in the blog:
First, Julia, you have to find out which half is sorted; only one of them;
Second, use sorted half to determine if the search is in the sorted half or not;
Then, you go to sorted half/ unsorted half.

Code can be optimized, if it is in sorted half, then, go to normal binary search
otherwise, go to unsorted - modified binary search - use recursive to write a solution first.

http://bangbingsyb.blogspot.ca/2014/11/leetcode-search-in-rotated-sorted-array.html


Julia, in your practice, you discuss that the middle point is a peak element/ valley element or not; and then, both halves are sorted, which is the special case.

Lesson learned:

1. In your analysis, you have to make the test case as simple as possible, as you see in the above blog:
use 0 -7,
原数组:0 1 2 4 5 6 7
情况1:  6 7 0 1 2 4 5    起始元素0在中间元素的左边
情况2:  2 4 5 6 7 0 1    起始元素0在中间元素的右边

2. And then, you have to be careful, how many cases are then discussed. The above, two cases, using 0 as search element

3. 两种情况都有半边是完全sorted的。根据这半边,当target != A[mid]时,可以分情况判断:
Actually, you should add one more restriction, search half is sorted in ascending order. 

because the half of 6 7 0 1, 6 > 1, in the descending half, it must include going up and then going down. but, 
in the ascending half, 1 2 4 5, just pure ascending. <- you can argue that, it is a fact! 



Thursday, March 24, 2016

HackerRank: Two string - thinking in C++ over 15 ways

March 24, 2016

Julia likes to get idea how to write modern C++, she started to read at least 50 C++ solutions a week.

Always look for brilliant ideas to solve a simple problem. Take time to read other people's code, and then, find really excellent ideas.

Algorithm problem solving -> More ideas -> Good thinker -> Confidence.

Julia, think in C++ - solve problems using the following:
1. bit operation
2. array int[26]
3. class set
4. class unordered_set, functions: reserve, insert, count
5. class bitset, size_t
5. cin vs gets, pointer - some calculation

Problem statement is here.


Solution 1:
Here it is, namespace std, >>, string class, set<char>, auto, &x, for(auto &x: A), modern C++ style

C++ code is here


Solution 2: using bit operation - beautiful code, genius!
source code reference:

https://problemsolvingnotes.wordpress.com/page/2/
https://www.hackerrank.com/MarioYC
ACM ICPC World Finalist 2012, 2013
count - reference:
http://www.cplusplus.com/reference/algorithm/count/

sync with stdio
http://www.cplusplus.com/reference/ios/ios_base/sync_with_stdio/

using | inclusive OR
http://www.cplusplus.com/doc/tutorial/operators/
solution in C++:
https://gist.github.com/jianminchen/a0724f1fbbe5c621cd63

using namespace std;

int main(){
    ios::sync_with_stdio(0);

    string A,B;

    int T;

    cin >> T;

    int cont[26];

    while(T--){
        cin >> A >> B;    
   
        memset(cont,0,sizeof cont);
   
        for(int i = 0;i < A.size();++i)
            cont[ A[i] - 'a'] |= 1;   // Julia's comment: set first bit as 1, using | - inclusive OR
   
        for(int i = 0;i < B.size();++i)
            cont[ B[i] - 'a'] |= 2;  //  Julia's comment: set second bit as 1, using | - inclusive OR
   
        if(count(cont,cont + 26,3) > 0) cout << "YES\n";
// check array cont - if there is any number is 3, if found, return true
        else cout << "NO\n";
    }

    return 0;
}

Solution 3:
https://gist.github.com/jianminchen/6b443714e61f1c8c1382

Solution 4:
https://gist.github.com/jianminchen/dcfc885d390939a08ae2

Solution 5:
https://gist.github.com/jianminchen/13c2d3832f1cbd53433c

Solution 6: set class, insert, find, end functions
read set class end function:
http://www.cplusplus.com/reference/set/set/find/
set class insert function:
http://www.cplusplus.com/reference/set/set/insert/

https://gist.github.com/jianminchen/1fd8c8e9acdc72f18d10

Solution 7:
https://gist.github.com/jianminchen/f4b6dcea9936347192e9

Solution 8: unordered_set class, reserved function, insert, count function
unordered_set class reserve function:  http://www.cplusplus.com/reference/unordered_set/unordered_set/reserve/

https://gist.github.com/jianminchen/a3865ec039c092476492

Solution 9: cin vs gets, scanf, pointer - calculation
warm up with some concepts:
C++ gets:
http://www.cplusplus.com/reference/cstdio/gets/

compare two solutions - difference
https://gist.github.com/jianminchen/f35171b0c2ddcd403c2b

code is better! - https://www.hackerrank.com/avolchek 24 Gold
https://gist.github.com/jianminchen/d9c0d7a25ca2e24ca17b

Solution 11:
warm up with std::fill function template:
http://www.cplusplus.com/reference/algorithm/fill/
very strong C++ coder:
https://www.hackerrank.com/Informatimukas
https://gist.github.com/jianminchen/ff3fd27b8c1245322adf

Solution 12: bitset, size_t
https://gist.github.com/jianminchen/765ba74888057b887cac

Solution 13: vector class template
https://gist.github.com/jianminchen/c0e3a44edc31b3804331

Solution 14: 
very readable - two functions
https://gist.github.com/jianminchen/43f23e82ee04076c7496

Wednesday, March 23, 2016

Pluralsight: C++ Advanced Topics

March 23, 2016

Pluralsight:
C++ Adavanced Topics
https://www.pluralsight.com/courses/adv-cpp

Avoid Manual Memory Management
Use Lambdas
Use Standard Containers
Use Standard Algorithms
Embrace Move Semantics
Follow Style Rules
Consider the Plmpl Idiom
Stop Writing C with Classes

Julia is still trying to figure out ways to know best teachers in C++/ C#. Where to find them? Julia, stay focus, find several articles from stackOverFlow about C++, related to Lambdas, Move semantics, have some serious reading, then, come back to the video.

Watch some videos:
https://www.youtube.com/playlist?list=PL_AKIMJc4roXG7rOmqsb_wDG1btCzhS8F