Hi, recently I had a job interview. I had two tasks:
1) to refactor a JavaScript code
// The library 'jsUtil' has a public function that compares 2 arrays, returning true if
// they're the same. Refactor it so it's more robust, performs better and is easier to maintain.
/**
@name jsUtil.arraysSame
@description Compares 2 arrays, returns true if both are comprised of the same items, in the same order
@param {Object[]} a Array to compare with
@param {Object[]} b Array to compare to
@returns {boolean} true if both contain the same items, otherwise false
@example
if ( jsUtil.arraysSame( [1, 2, 3], [1, 2, 3] ) ) {
alert('Arrays are the same!');
}
*/
// assume jsUtil is an object
jsUtil.arraysSame = function(a, b) {
var r = 1;
for (i in a) if ( a[i] != b[i] ) r = 0;
else continue;
return r;
}
2) To refactor a PHP function that checks for a leap year
<?php
/*
The class 'DateUtil' defines a method that takes a date in the format DD/MM/YYYY, extracts the year
and works out if it is a leap year. The code is poorly written. Refactor it so that it is more robust
and easier to maintain in the future.
Hint: a year is a leap year if it is evenly divisible by 4, unless it is also evenly
divisible by 100 and not by 400.
*/
class DateUtil {
function notLeapYear ($var) {
$var = substr($var, 6, 4);
if (! ($var % 100) && $var % 400) {
return 1;
}
return $var % 4;
}
}
$testDates = array('03/12/2000', '01/04/2001', '28/01/2004', '29/11/2200');
/* the expected result is
* 03/12/2000 falls in a leap year
* 01/04/2001 does not fall in a leap year
* 28/01/2004 falls in a leap year
* 29/11/2200 does not fall in a leap year
*/
?>
<? $dateUtil = new DateUtil(); ?>
<ul>
<? foreach ($testDates as $date) { ?>
<li><?= $date ?> <?= ($dateUtil->notLeapYear($date) ? 'does not fall' : 'falls') ?> in a leap year</li>
<? } ?>
</ul>
I think I cope with the task but I am not quite sure, I still don't have an answer from them and it's been about a week. Could you give an example of your approach to this tasks? I'd really appreciate. Later I can post my solutions/code.
OK here are my answers to the questions.
<?php // Always use full/long openning tags not
$start = microtime(true);
class DateUtil {
/**
* The date could be used in other
* class methods in the future.
* Use just internally.
**/
var $_date;
/**
* The constructor of the class takes
* 1 argument, date, as a string and sets
* the object parameter _date to be used
* internally. This is compatable only in PHP5
* for PHP4 should be replaced with function DateUtil(...)
*/
public function __construct( $date = '' ) {
$this->_date = $date;
}
/**
* Setter for the date. Currently not used.
* Also we could use _set magical function.
* for PHP5.
**/
public function setDate( $date = '' ) {
$this->_date = $date;
}
/**
* Gettre of the date. Currently not used.
* Also we could use _get magical function.
* for PHP5.
**/
public function getDate() {
return $this->_date;
}
public function isLeapYear( $year = '' ) {
// all leap years can be divided through 4
if (($year % 4) != 0) {
return false;
}
// all leap years can be divided through 400
if ($year % 400 == 0) {
return true;
} else if ($year % 100 == 0) {
return false;
}
return true;
}
}
$dates = array('03/12/2000', '01/04/2001', '30/01/2004', '29/11/2200');
$dateUtil = new DateUtil();
foreach($dates as $date) {
/**
* This processing is not done in the class
* because the date format could be different in
* other cases so we cannot assume this will allways
* be the format of the date
*
* The php function strtotime() was not used due to
* a bug called 2K38, more specifically dates after and 2038
* are not parsed correctly due to the format of the UNIX
* timestamp which is 32bit integer.
* If the years we use are higher than 1970 and lower
* than 2038 we can use date('L', strtotime($date));
**/
$year = explode('/', $date);
$year = $year[2];
$isLeap = $dateUtil->isLeapYear($year);
echo '<pre>' . $date . ' - ';
echo ($isLeap)? 'Is leap year': 'Is not leap year';
echo '</pre>';
}
echo 'The execution took: ' . (microtime(true) - $start) . ' sec';
?>
JavaScript
/***************************************************/
jsUtil = new Object();
jsUtil.arraysSame = function(a, b) {
if( typeof(a) != 'object') {
// Check if tepes of 'a' is object
return false;
} else if(typeof(a) != typeof(b)) {
// Check if tepes of 'a' and 'b' are same
return false;
} else if(a.length != b.length) {
// Check if arrays have different length if yes return false
return false;
}
for(var i in a) {
// We compare each element not only by value
// but also by type so 3 != '3'
if(a[i] !== b[i]) {
return false;
}
}
return true;
}
// It will work with associative arrays too
var a = {a:1, b:2, c:3};
var b = {a:1, b:2, c:3}; // true
var c = {a:1, b:2, g:3}; // false
var d = {a:1, b:2, c:'3'}; // false
var output = '';
output += 'Arrays a==b is: ' + jsUtil.arraysSame( a, b );
output += '\n';
output += 'Arrays a==c is: ' + jsUtil.arraysSame( a, c );
output += '\n';
output += 'Arrays a==d is: ' + jsUtil.arraysSame( a, d );
alert(output);