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] = 3You 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:
function solution(A, 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] = 3the function should return 4, as explained above.
Write an efficient algorithm for the following assumptions:
- 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.
// you can use console.log for debugging purposes, i.e.
// console.log('this is debug message');
// write your code in JavaScript (ECMA-262, 5th edition)
// compare 2 arrays - assumes they are the same length
function compareArrays( a1, a2 )
{
for( var i=0; i<a1.length; i++)
if( a1[i] != a2[i] ){
console.log("compareArrays: "+a1+" ... "+a2+" =false");
return false;
}
console.log("compareArrays: "+a1+" ... "+a2+" =true");
return true;
}
// compare newpos[] with positions[][]
// - rotates newpos[] to attempt match
// returns: index of match or -1 if no match
//
function comparePositions(positions,newpos)
{
for(var ipos=0; ipos<positions.length; ipos++){
for( i=0; i<newpos.length; i++){
if( compareArrays(positions[ipos],newpos))
return ipos;
newpos.push(newpos.shift()); //rotate array
}
}
return -1;
}
function solution(A, P) {
var idx,diff,halfP=P/2;
var highestCount=0;
var highestIndex=0;
var positions = [];
var counts=[];
A.forEach(function(clock) {
var position = [];
// sort 'hands' in ascending order
//clock.sort(function(a, b) { return a - b });
// duplicate start point on end
clock.push(clock[0]);
//console.log(clock);
// create array of distances between hands, wrapping around clock
for(idx=1; idx<clock.length;idx++){
diff= Math.abs(clock[idx] - clock[idx-1]);
position.push((diff>halfP)?P-diff:diff);
}
//console.log(position);
idx= comparePositions(positions,position);
if( idx < 0 ){
positions.push(position); // new pattern
counts.push(1);
}else{
counts[idx]++; // count old pattern
if( counts[idx] > highestCount){
highestCount= counts[idx];
highestIndex= idx;
}
}
});
positions.forEach(function(pos,idx){
console.log(idx+" "+positions[idx]);
});
// console.log( "Count="+highestCount+" patt="+positions[highestIndex]+" Counts="+counts);
// sum the combinations of counts for each position type
var sum=0;
for(idx=0; idx<counts.length; idx++){
count=counts[idx];
sum+= (count > 2) ? (count * (count-1))/2 : 1;
}
return sum;
}
WARNING: producing output may seriously slow down your code! compareArrays: 1,1 ... 2,2 =false compareArrays: 1,1 ... 2,2 =false compareArrays: 1,1 ... 1,1 =true compareArrays: 1,1 ... 1,1 =true compareArrays: 1,1 ... 2,2 =false compareArrays: 1,1 ... 2,2 =false compareArrays: 2,2 ... 2,2 =true 0 1,1 1 2,2
// you can use console.log for debugging purposes, i.e.
// console.log('this is debug message');
// write your code in JavaScript (ECMA-262, 5th edition)
// compare 2 arrays - assumes they are the same length
function compareArrays( a1, a2 )
{
for( var i=0; i<a1.length; i++)
if( a1[i] != a2[i] ){
console.log("compareArrays: "+a1+" ... "+a2+" =false");
return false;
}
console.log("compareArrays: "+a1+" ... "+a2+" =true");
return true;
}
// compare newpos[] with positions[][]
// - rotates newpos[] to attempt match
// returns: index of match or -1 if no match
//
function comparePositions(positions,newpos)
{
for(var ipos=0; ipos<positions.length; ipos++){
for( i=0; i<newpos.length; i++){
if( compareArrays(positions[ipos],newpos))
return ipos;
newpos.push(newpos.shift()); //rotate array
}
}
return -1;
}
function solution(A, P) {
var idx,diff,halfP=P/2;
var highestCount=0;
var highestIndex=0;
var positions = [];
var counts=[];
A.forEach(function(clock) {
var position = [];
// sort 'hands' in ascending order
//clock.sort(function(a, b) { return a - b });
// duplicate start point on end
clock.push(clock[0]);
//console.log(clock);
// create array of distances between hands, wrapping around clock
for(idx=1; idx<clock.length;idx++){
diff= Math.abs(clock[idx] - clock[idx-1]);
position.push((diff>halfP)?P-diff:diff);
}
//console.log(position);
idx= comparePositions(positions,position);
if( idx < 0 ){
positions.push(position); // new pattern
counts.push(1);
}else{
counts[idx]++; // count old pattern
}
});
positions.forEach(function(pos,idx){
console.log(idx+" "+positions[idx]);
});
// sum the combinations of counts for each position type
var sum=0;
for(idx=0; idx<counts.length; idx++){
count=counts[idx];
sum+= (count > 2) ? (count * (count-1))/2 : 1;
}
return sum;
}
WARNING: producing output may seriously slow down your code! compareArrays: 1,1 ... 2,2 =false compareArrays: 1,1 ... 2,2 =false compareArrays: 1,1 ... 1,1 =true compareArrays: 1,1 ... 1,1 =true compareArrays: 1,1 ... 2,2 =false compareArrays: 1,1 ... 2,2 =false compareArrays: 2,2 ... 2,2 =true 0 1,1 1 2,2
function result: 6
compareArrays: 1,3,1,3 ... 3,1,3,1 =false compareArrays: 1,3,1,3 ... 1,3,1,3 =true compareArrays: 1,3,1,3 ... 1,3,1,3 =true compareArrays: 1,3,1,3 ... 3,1,3,1 =false compareArrays: 1,3,1,3 ... 1,3,1,3 =true 0 1,3,1,3
// you can use console.log for debugging purposes, i.e.
// console.log('this is debug message');
// write your code in JavaScript (ECMA-262, 5th edition)
// compare 2 arrays - assumes they are the same length
function compareArrays( a1, a2 )
{
for( var i=0; i<a1.length; i++)
if( a1[i] != a2[i] ){
console.log("compareArrays: "+a1+" ... "+a2+" =false");
return false;
}
console.log("compareArrays: "+a1+" ... "+a2+" =true");
return true;
}
// compare newpos[] with positions[][]
// - rotates newpos[] to attempt match
// returns: index of match or -1 if no match
//
function comparePositions(positions,newpos)
{
for(var ipos=0; ipos<positions.length; ipos++){
for( i=0; i<newpos.length; i++){
if( compareArrays(positions[ipos],newpos))
return ipos;
newpos.push(newpos.shift()); //rotate array
}
}
return -1;
}
function solution(A, P) {
var idx,diff,halfP=P/2;
var highestCount=0;
var highestIndex=0;
var positions = [];
var counts=[];
A.forEach(function(clock) {
var position = [];
// sort 'hands' in ascending order
clock.sort(function(a, b) { return a - b });
// duplicate start point on end
clock.push(clock[0]);
//console.log(clock);
// create array of distances between hands, wrapping around clock
for(idx=1; idx<clock.length;idx++){
diff= Math.abs(clock[idx] - clock[idx-1]);
position.push((diff>halfP)?P-diff:diff);
}
//console.log(position);
idx= comparePositions(positions,position);
if( idx < 0 ){
positions.push(position); // new pattern
counts.push(1);
}else{
counts[idx]++; // count old pattern
}
});
positions.forEach(function(pos,idx){
console.log(idx+" "+positions[idx]);
});
// sum the combinations of counts for each position type
var sum=0;
for(idx=0; idx<counts.length; idx++){
count=counts[idx];
sum+= (count > 2) ? (count * (count-1))/2 : 1;
}
return sum;
}
WARNING: producing output may seriously slow down your code! compareArrays: 1,1 ... 2,2 =false compareArrays: 1,1 ... 2,2 =false compareArrays: 1,1 ... 1,1 =true compareArrays: 1,1 ... 1,1 =true compareArrays: 1,1 ... 2,2 =false compareArrays: 1,1 ... 2,2 =false compareArrays: 2,2 ... 2,2 =true 0 1,1 1 2,2
function result: 6
compareArrays: 1,3,1,3 ... 3,1,3,1 =false compareArrays: 1,3,1,3 ... 1,3,1,3 =true compareArrays: 1,3,1,3 ... 1,3,1,3 =true compareArrays: 1,3,1,3 ... 1,3,1,3 =true 0 1,3,1,3
// you can use console.log for debugging purposes, i.e.
// console.log('this is debug message');
// write your code in JavaScript (ECMA-262, 5th edition)
// compare 2 arrays - assumes they are the same length
function compareArrays( a1, a2 )
{
for( var i=0; i<a1.length; i++)
if( a1[i] != a2[i] ){
return false;
}
return true;
}
// compare newpos[] with positions[][]
// - rotates newpos[] to attempt match
// returns: index of match or -1 if no match
//
function comparePositions(positions,newpos)
{
for(var ipos=0; ipos<positions.length; ipos++){
for( i=0; i<newpos.length; i++){
if( compareArrays(positions[ipos],newpos))
return ipos;
newpos.push(newpos.shift()); //rotate array
}
}
return -1;
}
function solution(A, P) {
var idx,diff,halfP=P/2;
var highestCount=0;
var highestIndex=0;
var positions = [];
var counts=[];
A.forEach(function(clock) {
var position = [];
// sort 'hands' in ascending order
clock.sort(function(a, b) { return a - b });
// duplicate start point on end
clock.push(clock[0]);
//console.log(clock);
// create array of distances between hands, wrapping around clock
for(idx=1; idx<clock.length;idx++){
diff= Math.abs(clock[idx] - clock[idx-1]);
position.push((diff>halfP)?P-diff:diff);
}
//console.log(position);
idx= comparePositions(positions,position);
if( idx < 0 ){
positions.push(position); // new pattern
counts.push(1);
}else{
counts[idx]++; // count old pattern
}
});
positions.forEach(function(pos,idx){
console.log(idx+" "+positions[idx]);
});
// sum the combinations of counts for each position type
var sum=0;
for(idx=0; idx<counts.length; idx++){
count=counts[idx];
sum+= (count > 2) ? (count * (count-1))/2 : count-1;
}
return sum;
}
WARNING: producing output may seriously slow down your code! 0 1,1 1 2,2
// you can use console.log for debugging purposes, i.e.
// console.log('this is debug message');
// write your code in JavaScript (ECMA-262, 5th edition)
// compare 2 arrays - assumes they are the same length
function compareArrays( a1, a2 )
{
for( var i=0; i<a1.length; i++)
if( a1[i] != a2[i] ){
return false;
}
return true;
}
// compare newpos[] with positions[][]
// - rotates newpos[] to attempt match
// returns: index of match or -1 if no match
//
function comparePositions(positions,newpos)
{
for(var ipos=0; ipos<positions.length; ipos++){
for( i=0; i<newpos.length; i++){
if( compareArrays(positions[ipos],newpos))
return ipos;
newpos.push(newpos.shift()); //rotate array
}
}
return -1;
}
function solution(A, P) {
var idx,diff,halfP=P/2;
var highestCount=0;
var highestIndex=0;
var positions = [];
var counts=[];
A.forEach(function(clock) {
var position = [];
// sort 'hands' in ascending order
clock.sort(function(a, b) { return a - b });
// duplicate start point on end
clock.push(clock[0]);
// create array of distances between hands, wrapping around clock
for(idx=1; idx<clock.length;idx++){
diff= Math.abs(clock[idx] - clock[idx-1]);
position.push((diff>halfP)?P-diff:diff);
}
idx= comparePositions(positions,position);
if( idx < 0 ){
positions.push(position); // new pattern
counts.push(1);
}else{
counts[idx]++; // count old pattern
}
});
// sum the combinations of counts for each position type
var sum=0;
for(idx=0; idx<counts.length; idx++){
count=counts[idx];
sum+= (count > 2) ? (count * (count-1))/2 : count-1;
}
return sum;
}
// you can use console.log for debugging purposes, i.e.
// console.log('this is debug message');
// write your code in JavaScript (ECMA-262, 5th edition)
// compare 2 arrays - assumes they are the same length
function compareArrays( a1, a2 )
{
for( var i=0; i<a1.length; i++)
if( a1[i] != a2[i] ){
return false;
}
return true;
}
// compare newpos[] with positions[][]
// - rotates newpos[] to attempt match
// returns: index of match or -1 if no match
//
function comparePositions(positions,newpos)
{
for(var ipos=0; ipos<positions.length; ipos++){
for( i=0; i<newpos.length; i++){
if( compareArrays(positions[ipos],newpos))
return ipos;
newpos.push(newpos.shift()); //rotate array
}
}
return -1;
}
function solution(A, P) {
var idx,diff,halfP=P/2;
var highestCount=0;
var highestIndex=0;
var positions = [];
var counts=[];
A.forEach(function(clock) {
var position = [];
// sort 'hands' in ascending order
clock.sort(function(a, b) { return a - b });
// duplicate start point on end
clock.push(clock[0]);
// create array of distances between hands, wrapping around clock
for(idx=1; idx<clock.length;idx++){
diff= Math.abs(clock[idx] - clock[idx-1]);
position.push((diff>halfP)?P-diff:diff);
}
idx= comparePositions(positions,position);
if( idx < 0 ){
positions.push(position); // new pattern
counts.push(1);
}else{
counts[idx]++; // count old pattern
}
});
// sum the combinations of counts for each position type
var sum=0;
for(idx=0; idx<counts.length; idx++){
count=counts[idx];
sum+= (count > 2) ? (count * (count-1))/2 : count-1;
}
return sum;
}
The following issues have been detected: timeout errors.
all the same space except two, number of clocks = 500
running time: >2.04 sec., time limit: 1.76 sec.
shuffled range spaces, clocks = 500
running time: >2.04 sec., time limit: 1.60 sec.