PassingCars at app.codility.com/programmers in PHP Explained: Count the number of passing cars on the road.
Task score : 100% - Correctness : 100% ; Performance : 100%
Detected time complexity : O(n)
Lesson 5 at app.codility.com/programmers
The solution and its explanation are given below.
Category of Article : Technology | Computers and Software | Algorithm
By: Chrysanthus Date Published: 28 May 2025
Problem
Title of Problem: PassingCars, for "Cars that cross in Opposite Directions".
A non-empty array A consisting of N integers is given. The consecutive elements of array A represent consecutive cars on a road.
Array A contains only 0s and/or 1s:
0 represents a car traveling east,
1 represents a car traveling west.
The goal is to count passing cars. We say that a pair of cars (P, Q), where 0 <= P < Q < N, is passing when P is traveling to the east and Q is traveling to the west.
For example, consider array A such that:
A[0] = 0 A[1] = 1 A[2] = 0 A[3] = 1 A[4] = 1
We have five pairs of passing cars: (0, 1), (0, 3), (0, 4), (2, 3), (2, 4).
Write a function:
function solution($A);
that, given a non-empty array A of N integers, returns the number of pairs of passing cars.
The function should return -1 if the number of pairs of passing cars exceeds 1,000,000,000.
For example, given:
A[0] = 0 A[1] = 1 A[2] = 0 A[3] = 1 A[4] = 1
the function should return 5, as explained above.
Write an efficient algorithm for the following assumptions:
N is an integer within the range [1..100,000];
each element of array A is an integer that can have one of the following values: 0, 1.
Note:
Assume that the cars to the east are using one lane, and the cars to the west are using the opposite lane. Then the cars in question are those that pass each other in opposite directions, and not in the same direction. The goal is to find the number of pairs that will finally cross (pass in opposite directions) one another. Assume that cars going in the same direction, never bypass; that is, such cars are all moving at the same speed. All cars going east will bypass all cars going west.
Brute Force Approach
The brute force approach is to scan the array in two for-loops, one nested; and for every zero, a 1 ahead in the array, makes a pair. In the following table, the pairs are counted (added) from left to right and from top to bottom:
| Index | 0 | 1 | 2 | 3 | 4 |
| Given array | 0 | 1 | 0 | 1 | 1 |
| 1st inner-loop iteration: pairs (with 1st 0) | 0 | 1 | 1 | 2 | 3 |
| 2nd inner-loop iteration: pairs (with no 0) | 3 | 3 | 3 | 3 | |
| 3rd inner-loop iteration: pairs (with 2nd 0) | 3 | 4 | 5 | ||
| 4th inner-loop iteration: pairs (with no 0) | 5 | 5 | |||
| 5th inner-loop iteration: pairs (with no 0) | 5 (answer) |
These are 15 operations, which are more than 5.log2(5), which is approximately 11.6. n is 5. So, this brute force approach gives, more than n.log2(n) time complexity. The code for this brute force-approach is not provided in this document.
Smart Approach in O(n) Time
The tutorial (lesson) for this task (problem) is Prefix Sums, so that should suggest to the candidate that prefix sums is needed somehow, to have an efficient algorithm for this task.
Observe from above that as the list (array) is scanned from left to right manually (with the eye), a 1 encountered ahead, makes pairs with all the preceding zeros. By adding (summing) all such pairs, in a prefix sums fashion, the total number of pairs for the task, will be obtained.
Strategy
- First, number of only zeros is being obtained (counting numbers of preceding zeros) as the given array is scanned.
- Next, number of pairs with each 1 encountered is obtained, involving the accumulating number of zeros.
- Next, as the number of pairs with each 1 encountered is obtained, the "prefix sum" (accumulating number of pairs) is also obtained. The table for this strategy is:
O(n) Solution (from left to right)
| O(n) Solution (from left to right) | ||||||
| Index | 0 | 1 | 2 | 3 | 4 | |
| Given array | 0 | 1 | 0 | 1 | 1 | |
| Accumulating number of zeros | 0 | 1 | 1 | 2 | 2 | 2 |
| Given array (re-typed) | 0 | 1 | 0 | 1 | 1 | |
| Accumulating number of pairs due to 1 encountered | 0 | 0 | 1 | 1 | 1+2 = 3 | 3+2 = 5 |
The solution for this O(n) approach, can be done using one for-loop, as in the following program (read the code and the comments):
<?php
function solution($A) {
$N = count($A);
$zerosOnlyPrefixs = 0; //equivalent new pairs, when 1 is encountered
$pairsPrefixs = 0;
for ($i=0; $i < $N; $i++) {
if ($A[$i]==0)
$zerosOnlyPrefixs++; //same as: zerosOnlyPrefixs = zerosOnlyPrefixs + 1
else if ($pairsPrefixs + $zerosOnlyPrefixs <= 1000000000){//no. of pairs so far, must not be > 1000000000
$pairsPrefixs = $pairsPrefixs + $zerosOnlyPrefixs; //A[i] == 1, prefix sum of pairs
}
else { // >= 1000000000 has been attained
return -1;
}
}
return $pairsPrefixs; //returns prefix sum of pairs at last index of given array
}
$v = [0, 1, 0, 1, 1];
$ret = solution($v);
echo $ret . "\n";
?>
The solution() function without the comments is:
function solution($A) {
$N = count($A);
$zerosOnlyPrefixs = 0;
$pairsPrefixs = 0;
for ($i=0; $i < $N; $i++) {
if ($A[$i]==0)
$zerosOnlyPrefixs++;
else if ($pairsPrefixs + $zerosOnlyPrefixs <= 1000000000){
$pairsPrefixs = $pairsPrefixs + $zerosOnlyPrefixs;
}
else {
return -1;
}
}
return $pairsPrefixs;
}
The "else if" segment is evaluated when 1 is encountered.
At app.codility.com/programmers, the scoring and detected time complexity for this smart approach is:
Detected time complexity: constant time, O(N)
Task score : 100% - Correctness : 100% ; Performance : 100%
Conclusion
As the given list (array) is scanned from left to right manually (with the eye), a 1 encountered ahead, makes pairs with all the preceding zeros. By adding (summing) all such pairs, in a prefix sum fashion, the total number of pairs for the task, will be obtained.
Strategy
- First, number of only zeros is being obtained (counting numbers of preceding zeros) as the given array is scanned.
- Next, number of pairs with each 1 encountered is obtained, involving the accumulating number of zeros.
- Next, as the number of pairs with each 1 encountered is obtained, the "prefix sum" (accumulating number of pairs) is also obtained. The table for this strategy is:
The efficient algorithm above, has been made from 1 looking backwards to the preceding zeros, for pairs. The algorithm can still be done from zero, looking ahead to the succeeding ones, for pairs. In other words, instead of doing prefix summing, suffix summing can be done.
The reader should register at app.codility.com/programmers, so that he/she should be testing his/her code.
The rest of the 17 lessons, with explanation of lessons, explanation of tasks, and explanation of solutions, can be found at (click): Explanations in PHP for the 17 Algorithm Lessons at https://app.codility.com/programmers with Problems and Solutions
Related Links
Basics of PHP with Security ConsiderationsWhite Space in PHP
PHP Data Types with Security Considerations
PHP Variables with Security Considerations
PHP Operators with Security Considerations
PHP Control Structures with Security Considerations
PHP String with Security Considerations
PHP Arrays with Security Considerations
PHP Functions with Security Considerations
PHP Return Statement
Exception Handling in PHP
Variable Scope in PHP
Constant in PHP
PHP Classes and Objects
Reference in PHP
PHP Regular Expressions with Security Considerations
Date and Time in PHP with Security Considerations
Files and Directories with Security Considerations in PHP
Writing a PHP Command Line Tool
PHP Core Number Basics and Testing
Validating Input in PHP
PHP Eval Function and Security Risks
PHP Multi-Dimensional Array with Security Consideration
Mathematics Functions for Everybody in PHP
PHP Cheat Sheet and Prevention Explained
More Related Links