Codility lithium2013 - Clocks


Codility
You are given N round clocks.
Every clock has M hands, and these hands can point to positions 1, 2, 3, ..., P (yes, these represent numbers around each face). The clocks are represented by the matrix A consisting of N rows and M columns of integers. The first row represents the hands of the first clock, and so on.
For example, you are given matrix A consisting of five rows and two columns, and P = 4:
A[0][0] = 1 A[0][1] = 2 A[1][0] = 2 A[1][1] = 4 A[2][0] = 4 A[2][1] = 3 A[3][0] = 2 A[3][1] = 3 A[4][0] = 1 A[4][1] = 3

You can rotate the clocks to obtain several clocks that look identical. For example, if you rotate the third, fourth and fifth clocks you can obtain the following clocks:

After rotation, the first, third and fourth clocks look the same, and the second clock looks the same as the fifth one. That means there are four pairs of clocks that look the same: (1, 3), (1, 4), (2, 5) and (3, 4).
Write a function:
class Solution { public int solution(int[][] A, int P); }
that, given a zero-indexed matrix A consisting of N rows and M columns of integers and integer P, returns the maximal number of pairs of clocks that can look the same after rotation.
For example, given the following array A and P = 4:
A[0][0] = 1 A[0][1] = 2 A[1][0] = 2 A[1][1] = 4 A[2][0] = 4 A[2][1] = 3 A[3][0] = 2 A[3][1] = 3 A[4][0] = 1 A[4][1] = 3
the function should return 4, as explained above.
Assume that:
  • N and M are integers within the range [1..500];
  • P is an integer within the range [1..1,000,000,000];
  • each element of matrix A is an integer within the range [1..P];
  • the elements of each row of matrix A are all distinct.
Complexity:
  • expected worst-case time complexity is O(N*M*log(N+M));
  • expected worst-case space complexity is O(N*M).
Brute-force solution
For every pair of clocks, we will check whether they can look identical or not. Let’s sort the
hands of each clock. After that, we can easily count the distances between consecutive hands.

Two clocks look identical if the first hands are aligned and the consecutive distances between
hands are the same. When we rotate a clock, some other hand can become the first one. So
to check whether two clocks can be rotated to look identically, we have to check every cyclic
rotation of the distances between consecutive hands.

Here is a program comparing all the pairs of clocks and checking whether they can be
rotated so that they look identically. Assume that matrix A contains distances between

consecutive hands.
However, the solution is inefficient. We have O(N^2 ) pairs of clocks, and every pair is compared in O(M2 ) time, so the whole algorithm may require O(N^2 · M^2 ) time.
1   def clocks(A):

2                N = len(A)

3          M = len(A[0])

4                result = 0

5                for i in xrange(N):

6                          for k in xrange(i + 1, N):

7                                     for l in xrange(M):


8
ok = True
9
for j in xrange(M):
10
if (A[i][j] != A[k][(j + l) % M]):
11
ok = False
12
break;
13
if ok:
14
result += 1
15
break;
16
return result


Slow solution
To find a better solution, we should be able to compare two clocks faster than in O(M2) time. There is a suitable algorithm called lexicographically minimal string rotation. For each clock, we find its canonical rotation. If two clocks can be rotated so that look identically, their canonical rotations should be identical. For this purpose we can choose such a rotation of distances between consecutive hands that is minimal in the lexicographical order. Finding the minimal rotation of a clock requires O(M) time, so the time complexity of the whole algorithm is O(N2 · M + N · M log M).
2: Slow solution.
1   def clocks(A):

2                N = len(A)

3                M = len(A[0])

4                for i in xrange(N):

5                 minimal_lexicographically_rotation(A[i])

6                result = 0

7                for i in xrange(N):

8                          for k in xrange(i + 1, N):

9                                     ok = True


10
for j in xrange(M):
11
if (A[i][j] != A[k][j]):
12
ok = False
13
break;
14
if ok:
15
result += 1
16
return result
With this approach, the time complexity is O(N · M ·(log M + log N)). This solution should achieve the maximum number of points.
Optimal solution

We can find an even faster solution to this task by simply sorting the clocks in the order of their lexicographically minimal rotations. That will cause identical clocks to be adjacent to each other in the array. Assume that matrix A contains distances between consecutive hands.
1   def clocks(A):

2                N = len(A)

3                for i in xrange(N):

4                          minimal_lexicographically_rotation(A[i])

5                A.sort()

6          result = 0

7                pairs = 0

8                for i in xrange(1, N):

9                          if (equal(A[i], A[i - 1])):

10                                     pairs += 1

11                          result += pairs

12                          else:

13                                     pairs = 0

14                return result

With this approach, the time complexity is O(N · M · (log M + log N)). This solution should achieve the maximum number of points.
Alternative solution

We can also solve this task in alternative way. Instead of looking for lexicographically minimal rotations, we can find the rotation in which we get the maximal (or minimal) hash. If the maximal hash for two clocks is the same, we claim that the two clocks look identical.

Finally, just sort the clocks by their maximal hashes and identical clocks will also be next to each other. The time complexity is O(N · M · log M + N · log N).
http://codesays.com/2014/solution-to-lithium2013-clocks-by-codility/
At the very beginning, I found this task is very similar with the string rotation question in CTCI. And I did transfer this question into a string rotation one. The string rotation solution worked, and gave the right answer. But I could only get 95/100, because of the TIMEOUT ERROR in the large_constantSpace test set. 

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def solution(A, P):
    columns = len(A[0])
    same_after_rotation = {}
 
    for row_index in xrange(len(A)):
        A[row_index].sort()
        signature = "-".join([str((A[row_index][column_index] -
                                A[row_index][column_index-1]) % P)
                                for column_index in xrange(columns)])
        for sig, count in same_after_rotation.items():
            if signature in sig:
                same_after_rotation[sig] += 1
                break
        else:
            same_after_rotation[signature+"-"+signature] = 1
 
    same_pairs = sum([item*(item-1)/2 for item in same_after_rotation.values()])
    return same_pairs

https://github.com/linjiyuan90/OJ_Code/blob/master/codility/challenges/Clocks.cc
https://github.com/xiongjunliang/codility/blob/master/lithium2013/clock.cpp
Read full article from Codility

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts